diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..2996d286d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,20 @@ +/.github +/.husky +/packages/datagateway-*/cypress +/packages/datagateway-*/cypress.json +/packages/datagateway-*/server +/packages/datagateway-*/README.md +**/build +**/coverage +**/lib +**/node_modules +.gitignore +.prettierrc +codecov.yml +CODEOWNERS +LICENSE.md +README.md +Dockerfile +**/*.test.* +**/setupTests* +**/testData* diff --git a/.github/add_doi_datapublicationtype.py b/.github/add_doi_datapublicationtype.py new file mode 100644 index 000000000..47dd28a4d --- /dev/null +++ b/.github/add_doi_datapublicationtype.py @@ -0,0 +1,13 @@ +from icat.client import Client + +client = Client( + "https://localhost:8181", + checkCert=False, +) +client.login("simple", {"username": "root", "password": "pw"}) + +data_publication_type = client.new("dataPublicationType") +data_publication_type.name = "User-defined" +data_publication_type.description = "User-defined" +data_publication_type.facility = client.get("Facility", 1) +data_publication_type.create() diff --git a/.github/add_icat_rules.py b/.github/add_icat_rules.py new file mode 100644 index 000000000..f1702563e --- /dev/null +++ b/.github/add_icat_rules.py @@ -0,0 +1,50 @@ +from icat.client import Client + +client = Client( + "https://localhost:8181", + checkCert=False, +) +client.login("simple", {"username": "root", "password": "pw"}) + +public_tables = [ + "Instrument", + "ParameterType", + "InvestigationType", + "DatasetType", + "SampleType", + "DatafileFormat", + "Facility", + "FacilityCycle", +] + +client.createRules("R", public_tables) + +public_steps = [ + ("Datafile", "dataset"), + ("Dataset", "investigation"), + ("Sample", "investigation"), + ("Instrument", "instrumentScientists"), + ("Investigation", "investigationFacilityCycles"), + ("InstrumentScientist", "user"), + ("Investigation", "publications"), + ("Sample", "type"), + ("InvestigationUser", "user"), + ("Investigation", "investigationUsers"), + ("Investigation", "investigationInstruments"), + ("Dataset", "sample"), + ("Dataset", "datafiles"), + ("Investigation", "datasets"), + ("Investigation", "samples"), + ("Sample", "parameters"), + ("Investigation", "parameters"), + ("Dataset", "parameters"), + ("Datafile", "parameters"), +] + +public_step_objects = [] + +for step in public_steps: + ps = client.new("PublicStep", origin=step[0], field=step[1]) + public_step_objects.append(ps) + +client.createMany(public_step_objects) diff --git a/.github/config.env b/.github/config.env new file mode 100644 index 000000000..1e5012ea5 --- /dev/null +++ b/.github/config.env @@ -0,0 +1,18 @@ +ICAT_URL=https://host.docker.internal:8181 +FACILITY=LILS +ICAT_USERNAME=root +ICAT_PASSWORD=pw +PUBLISHER=test +MINTER_ROLE=PI +VERSION=0.01 + +ICAT_DOI_BASE_URL=https://example.stfc.ac.uk/ +ICAT_SESSION_PATH=/icat/session/ +ICAT_AUTHENTICATOR_NAME=simple +ICAT_CHECK_CERT=False +SSL_CERT_VERIFICATION=False + +DATACITE_PREFIX=10.5286 +DATACITE_URL=https://api.test.datacite.org/dois +DATACITE_USERNAME=BL.STFC + diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index be5436cd5..000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,141 +0,0 @@ -version: 2 -updates: -- package-ecosystem: npm - directory: "/" - schedule: - interval: daily - time: "00:00" - timezone: Europe/London - open-pull-requests-limit: 10 - versioning-strategy: increase - ignore: - - dependency-name: "*" - update-types: ["version-update:semver-patch"] - - dependency-name: "@date-io/date-fns" - versions: - - ">= 2.a, < 3" - - dependency-name: eslint-plugin-react - versions: - - "> 7.20.0, < 7.21" - - dependency-name: eslint-plugin-react-hooks - versions: - - "> 4.0.4, < 4.1" - - dependency-name: i18next - versions: - - ">= 19.7.a, < 19.8" - - dependency-name: i18next - versions: - - "> 19.9.0, < 19.10" - - dependency-name: i18next-browser-languagedetector - versions: - - "> 6.0.0, < 6.1" - - dependency-name: i18next-http-backend - versions: - - "> 1.0.15, < 1.1" - - dependency-name: jsrsasign - versions: - - "> 8.0.20, < 8.1" - - dependency-name: jsrsasign - versions: - - "> 9.0.0, < 9.1" - - dependency-name: react-i18next - versions: - - "> 11.7.0, < 11.8" - - dependency-name: react-redux - versions: - - "> 7.2.0, < 7.3" - - dependency-name: single-spa-react - versions: - - "> 3.0.0, < 3.1" - - dependency-name: typescript - versions: - - "> 3.9.6, < 3.10" - - dependency-name: typescript - versions: - - "> 4.2.2, < 4.3" - - dependency-name: "@types/jest" - versions: - - "> 26.0.4, < 26.1" - - dependency-name: "@types/jsrsasign" - versions: - - "> 8.0.3, < 8.1" - - dependency-name: "@types/node" - versions: - - "> 14.0.20, < 14.1" - - dependency-name: "@types/node" - versions: - - "> 14.14.31, < 14.15" - - dependency-name: "@types/react" - versions: - - "> 16.9.41, < 16.10" - - dependency-name: "@types/react-virtualized" - versions: - - "> 9.21.10, < 9.22" - - dependency-name: "@welldone-software/why-did-you-render" - versions: - - "> 4.2.5, < 4.3" - - dependency-name: i18next-http-backend - versions: - - 1.2.1 - - dependency-name: eslint - versions: - - 7.21.0 - - 7.22.0 - - 7.23.0 - - 7.24.0 - - dependency-name: date-fns - versions: - - 2.16.1 - - 2.18.0 - - 2.19.0 - - 2.20.2 - - 2.21.0 - - dependency-name: cypress - versions: - - 6.6.0 - - 6.7.1 - - 6.8.0 - - 7.0.1 - - 7.1.0 - - dependency-name: "@typescript-eslint/parser" - versions: - - 4.17.0 - - 4.18.0 - - 4.19.0 - - 4.20.0 - - 4.21.0 - - dependency-name: jsrsasign - versions: - - 10.1.13 - - dependency-name: "@welldone-software/why-did-you-render" - versions: - - 6.0.5 - - 6.1.0 - - dependency-name: react - versions: - - 17.0.1 - - dependency-name: typescript - versions: - - 4.1.3 - - 4.1.5 - - dependency-name: "@types/node" - versions: - - 14.14.22 - - 14.14.25 - - 14.14.26 - - 14.14.28 - - 14.14.29 - - dependency-name: "@typescript-eslint/eslint-plugin" - versions: - - 4.14.0 - - 4.14.2 - - 4.15.0 - - dependency-name: eslint-config-react-app - versions: - - 6.0.0 - - dependency-name: lint-staged - versions: - - 10.5.3 - - dependency-name: "@material-ui/core" - versions: - - 4.11.2 diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 000000000..dfd7337f8 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,11 @@ +changelog: + categories: + - title: Features + labels: + - '*' + exclude: + labels: + - dependencies + - title: Dependencies + labels: + - dependencies \ No newline at end of file diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 82e27ecad..f2ee6a3fe 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -2,7 +2,7 @@ name: CI Build on: workflow_dispatch: pull_request: - # By default, the pull_request event type is not triggered when a PR is merged into main + # By default, the pull_request event type is not triggered when a PR is merged into main or develop push: branches: - main @@ -14,30 +14,18 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Setup Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4 with: - node-version: '14.x' - - # Cache yarn dependencies/ restore the cached dependencies during future workflows - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: Cache yarn dependencies - uses: actions/cache@v2 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- + node-version: 20 + cache: 'yarn' + - name: Install dependencies # Ubuntu 16+ does not install libgconf-2-4 by default, so we need to install it ourselves (for Cypress) run: | - npm config set scripts-prepend-node-path true sudo apt-get install libgconf-2-4 - yarn --frozen-lockfile + yarn --immutable # Linting and unit testing - name: Run linting @@ -48,55 +36,60 @@ jobs: # Test coverage upload - name: Upload unit test coverage for the Common package if: success() - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4 with: directory: ./packages/datagateway-common/ flags: common fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} - name: Upload unit test coverage for the DataView package if: success() - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4 with: directory: ./packages/datagateway-dataview/ flags: dataview fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} - name: Upload unit test coverage for the Search package if: success() - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4 with: directory: ./packages/datagateway-search/ flags: search fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} - name: Upload unit test coverage for the Download package if: success() - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4 with: directory: ./packages/datagateway-download/ flags: download fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} dataview-e2e-tests: name: DataGateway DataView End to End Tests runs-on: ubuntu-20.04 steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Add apt repo run: sudo add-apt-repository universe - name: Setup Java - uses: actions/setup-java@v1 + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4 with: + distribution: 'zulu' java-version: 8 java-package: jdk - name: Setup Python - uses: actions/setup-python@v2 + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 with: python-version: 3.6 architecture: x64 # ICAT Ansible clone and install dependencies - name: Checkout icat-ansible - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: icatproject-contrib/icat-ansible ref: master @@ -146,72 +139,51 @@ jobs: cd /home/runner/install/icat.server/ && ./setup -vv install - name: Checkout datagateway-api - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: ral-facilities/datagateway-api path: datagateway-api - ref: v1.0.1 + ref: v9.0.2 # DataGateway API file setup + - name: Create search_api_mapping.json + run: cp datagateway-api/datagateway_api/search_api_mapping.json.example datagateway-api/datagateway_api/search_api_mapping.json - name: Create log file - run: touch logs.log - - name: Configure log file location - run: echo "`jq -r --arg REPO_DIR "$GITHUB_WORKSPACE/logs.log" \ - '.log_location=$REPO_DIR' datagateway-api/datagateway_api/config.json.example`" > datagateway-api/datagateway_api/config.json.example - - name: Configure API backend - run: echo "`jq -r --arg BACKEND "python_icat" \ - '.backend=$BACKEND' datagateway-api/datagateway_api/config.json.example`" > datagateway-api/datagateway_api/config.json.example - - name: Set debug mode to true - run: | - sed -i -e "s/\"debug_mode\": false,/\"debug_mode\": true,/" datagateway-api/datagateway_api/config.json.example - - name: Set log level to DEBUG - run: | - sed -i -e "s/\"log_level\": \"WARN\",/\"log_level\": \"DEBUG\",/" datagateway-api/datagateway_api/config.json.example - - name: Create config.json - run: cp datagateway-api/datagateway_api/config.json.example datagateway-api/datagateway_api/config.json + run: touch datagateway-api/datagateway_api/logs.log + + - name: Create config.yaml + run: cp datagateway-api/datagateway_api/config.yaml.example datagateway-api/datagateway_api/config.yaml # DataGateway API dependencies - name: Install Poetry run: pip install poetry - name: Install dependencies - run: cd datagateway-api; poetry install + run: cd datagateway-api/; poetry install - name: Add dummy data to icatdb run: | - cd datagateway-api; poetry run python -m util.icat_db_generator + cd datagateway-api/; poetry run python -m util.icat_db_generator - name: Start API - run: cd datagateway-api; nohup poetry run python -m datagateway_api.src.main > api-output.txt & + run: cd datagateway-api/; nohup poetry run python -m datagateway_api.src.main > api-output.txt & # E2E tests - - name: Checkout repo - uses: actions/checkout@v2 - name: Setup Node.js - uses: actions/setup-node@v1 - with: - node-version: '14.x' - # Cache yarn dependencies/ restore the cached dependencies during future workflows - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: Cache yarn dependencies - uses: actions/cache@v2 - id: yarn-cache + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4 with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- + node-version: 20 + cache: 'yarn' + - name: Install dependencies # Ubuntu 16+ does not install libgconf-2-4 by default, so we need to install it ourselves (for Cypress) run: | - npm config set scripts-prepend-node-path true sudo apt-get install libgconf-2-4 - yarn --frozen-lockfile + yarn --immutable + - name: Run datagateway-dataview e2e tests run: yarn workspace datagateway-dataview run e2e - name: Upload Cypress screenshots if: failure() - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 with: name: DataView-Screenshots path: packages/datagateway-dataview/cypress/screenshots @@ -221,23 +193,24 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Add apt repo run: sudo add-apt-repository universe - name: Setup Java - uses: actions/setup-java@v1 + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4 with: + distribution: 'zulu' java-version: 8 java-package: jdk - name: Setup Python - uses: actions/setup-python@v2 + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 with: python-version: 3.6 architecture: x64 # ICAT Ansible clone and install dependencies - name: Checkout icat-ansible - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: icatproject-contrib/icat-ansible ref: master @@ -276,9 +249,21 @@ jobs: ansible-playbook icat-ansible/icat_test_hosts.yml -i icat-ansible/hosts --vault-password-file icat-ansible/vault_pass.txt -vv # Fixes on ICAT components needed for e2e tests - - name: Add anon user to rootUserNames + - name: Removing authenticator prefix for simple auth run: | - awk -F" =" '/rootUserNames/{$2="= simple/root anon/anon";print;next}1' /home/runner/install/icat.server/run.properties > /home/runner/install/icat.server/run.properties.tmp + sed -i 's/mechanism = simple/!mechanism = simple/' /home/runner/install/authn.simple/run.properties + - name: Adding Chris481 user + run: | + sed -i '/user\.list/ s/$/ Chris481/' /home/runner/install/authn.simple/run.properties + - name: Adding Chris481 user password + run: | + echo "user.Chris481.password = pw" >> /home/runner/install/authn.simple/run.properties + - name: Reinstall authn.simple + run: | + cd /home/runner/install/authn.simple/ && ./setup -vv install + - name: Add anon, root (simple without prefix) and Chris481 users to rootUserNames + run: | + awk -F" =" '/rootUserNames/{$2="= root Chris481 anon/anon";print;next}1' /home/runner/install/icat.server/run.properties > /home/runner/install/icat.server/run.properties.tmp - name: Apply rootUserNames change run: | mv -f /home/runner/install/icat.server/run.properties.tmp /home/runner/install/icat.server/run.properties @@ -291,6 +276,15 @@ jobs: - name: Reinstall IDS Server run: | cd /home/runner/install/ids.server/ && python2 ./setup -vv install + - name: Add root (simple without prefix) to datagateway-download-api adminUserNames + run: | + awk -F" =" '/adminUserNames/{$2="= root";print;next}1' /home/runner/install/datagateway-download-api/run.properties > /home/runner/install/datagateway-download-api/run.properties.tmp + - name: Apply adminUserNames change + run: | + mv -f /home/runner/install/datagateway-download-api/run.properties.tmp /home/runner/install/datagateway-download-api/run.properties + - name: Reinstall datagateway-download-api + run: | + cd /home/runner/install/datagateway-download-api/ && python2 ./setup -vv install # Disable Globus for Download e2e tests - name: Login to ICAT @@ -303,72 +297,61 @@ jobs: run: rm -f login_output - name: Checkout datagateway-api - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: ral-facilities/datagateway-api path: datagateway-api - ref: v1.0.1 + ref: v9.0.2 # DataGateway API file setup + - name: Create search_api_mapping.json + run: cp datagateway-api/datagateway_api/search_api_mapping.json.example datagateway-api/datagateway_api/search_api_mapping.json - name: Create log file - run: touch logs.log - - name: Configure log file location - run: echo "`jq -r --arg REPO_DIR "$GITHUB_WORKSPACE/logs.log" \ - '.log_location=$REPO_DIR' datagateway-api/datagateway_api/config.json.example`" > datagateway-api/datagateway_api/config.json.example - - name: Configure API backend - run: echo "`jq -r --arg BACKEND "python_icat" \ - '.backend=$BACKEND' datagateway-api/datagateway_api/config.json.example`" > datagateway-api/datagateway_api/config.json.example - - name: Set debug mode to true - run: | - sed -i -e "s/\"debug_mode\": false,/\"debug_mode\": true,/" datagateway-api/datagateway_api/config.json.example - - name: Set log level to DEBUG - run: | - sed -i -e "s/\"log_level\": \"WARN\",/\"log_level\": \"DEBUG\",/" datagateway-api/datagateway_api/config.json.example - - name: Create config.json - run: cp datagateway-api/datagateway_api/config.json.example datagateway-api/datagateway_api/config.json + run: touch datagateway-api/datagateway_api/logs.log + + - name: Create config.yaml + run: cp datagateway-api/datagateway_api/config.yaml.example datagateway-api/datagateway_api/config.yaml # DataGateway API dependencies - name: Install Poetry run: pip install poetry - name: Install dependencies - run: cd datagateway-api; poetry install + run: cd datagateway-api/; poetry install - name: Add dummy data to icatdb run: | - cd datagateway-api; poetry run python -m util.icat_db_generator + cd datagateway-api/; poetry run python -m util.icat_db_generator - name: Start API - run: cd datagateway-api; nohup poetry run python -m datagateway_api.src.main > api-output.txt & + run: cd datagateway-api/; nohup poetry run python -m datagateway_api.src.main > api-output.txt & + + # DOI minter setup + - name: Adding 'User-defined' DataPublicationType (needed for DOI minting api) + run: cd datagateway-api/; poetry run python ../.github/add_doi_datapublicationtype.py + + - name: 'Add password to env file' + run: echo DATACITE_PASSWORD=${{ secrets.DATACITE_PASSWORD }} >> ./.github/config.env + + - name: Run minting api + run: docker run --env-file ./.github/config.env -p 8000:8000 --add-host host.docker.internal:host-gateway -d harbor.stfc.ac.uk/icat/doi-mint-api # E2E tests - - name: Checkout repo - uses: actions/checkout@v2 - name: Setup Node.js - uses: actions/setup-node@v1 - with: - node-version: '14.x' - # Cache yarn dependencies/ restore the cached dependencies during future workflows - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: Cache yarn dependencies - uses: actions/cache@v2 - id: yarn-cache + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4 with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- + node-version: 20 + cache: 'yarn' + - name: Install dependencies # Ubuntu 16+ does not install libgconf-2-4 by default, so we need to install it ourselves (for Cypress) run: | - npm config set scripts-prepend-node-path true sudo apt-get install libgconf-2-4 - yarn --frozen-lockfile + yarn --immutable + - name: Run datagateway-download e2e tests run: yarn workspace datagateway-download run e2e - name: Upload Cypress screenshots if: failure() - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 with: name: Download-Screenshots path: packages/datagateway-download/cypress/screenshots @@ -378,23 +361,24 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Add apt repo run: sudo add-apt-repository universe - name: Setup Java - uses: actions/setup-java@v1 + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4 with: + distribution: 'zulu' java-version: 8 java-package: jdk - name: Setup Python - uses: actions/setup-python@v2 + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 with: python-version: 3.6 architecture: x64 # ICAT Ansible clone and install dependencies - name: Checkout icat-ansible - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: icatproject-contrib/icat-ansible ref: master @@ -412,6 +396,12 @@ jobs: - name: Replace default payara user with Actions user run: | sed -i -e "s/^payara_user: \"glassfish\"/payara_user: \"runner\"/" icat-ansible/group_vars/all/vars.yml + - name: Change icat.server version + run: | + echo "icat_server_version: '6.1.0-SNAPSHOT'" >> icat-ansible/group_vars/all/vars.yml + - name: Change icat.lucene version + run: | + echo "icat_lucene_version: '3.0.0-SNAPSHOT'" >> icat-ansible/group_vars/all/vars.yml - name: Amending roles run: | sed -i 's/role: authn_uows_isis/role: authn_anon/' icat-ansible/icat_test_hosts.yml @@ -442,90 +432,90 @@ jobs: cd /home/runner/install/icat.server/ && ./setup -vv install - name: Checkout datagateway-api - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: ral-facilities/datagateway-api path: datagateway-api - ref: v1.0.1 + ref: v9.0.2 # DataGateway API file setup + - name: Create search_api_mapping.json + run: cp datagateway-api/datagateway_api/search_api_mapping.json.example datagateway-api/datagateway_api/search_api_mapping.json - name: Create log file - run: touch logs.log - - name: Configure log file location - run: echo "`jq -r --arg REPO_DIR "$GITHUB_WORKSPACE/logs.log" \ - '.log_location=$REPO_DIR' datagateway-api/datagateway_api/config.json.example`" > datagateway-api/datagateway_api/config.json.example - - name: Configure API backend - run: echo "`jq -r --arg BACKEND "python_icat" \ - '.backend=$BACKEND' datagateway-api/datagateway_api/config.json.example`" > datagateway-api/datagateway_api/config.json.example - - name: Set debug mode to true - run: | - sed -i -e "s/\"debug_mode\": false,/\"debug_mode\": true,/" datagateway-api/datagateway_api/config.json.example - - name: Set log level to DEBUG - run: | - sed -i -e "s/\"log_level\": \"WARN\",/\"log_level\": \"DEBUG\",/" datagateway-api/datagateway_api/config.json.example - - name: Create config.json - run: cp datagateway-api/datagateway_api/config.json.example datagateway-api/datagateway_api/config.json + run: touch datagateway-api/datagateway_api/logs.log + + - name: Create config.yaml + run: cp datagateway-api/datagateway_api/config.yaml.example datagateway-api/datagateway_api/config.yaml # DataGateway API dependencies - name: Install Poetry run: pip install poetry - name: Install dependencies - run: cd datagateway-api; poetry install + run: cd datagateway-api/; poetry install - name: Add dummy data to icatdb run: | - cd datagateway-api; poetry run python -m util.icat_db_generator + cd datagateway-api/; poetry run python -m util.icat_db_generator + - name: Add ICAT rules & public steps + run: cd datagateway-api/; poetry run python ../.github/add_icat_rules.py # Recreate Lucene indexes - - name: Login to ICAT - run: | - curl -k --request POST 'https://localhost:8181/icat/session' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'json={"plugin":"simple", "credentials": [{"username":"root"}, {"password":"pw"}]}' > login_output - - name: Recreate Datafile index - run: | - curl -k --request POST 'https://localhost:8181/icat/lucene/db/Datafile/0' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'sessionId='`jq -r '.sessionId' login_output` - - name: Recreate Dataset index - run: | - curl -k --request POST 'https://localhost:8181/icat/lucene/db/Dataset/1' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'sessionId='`jq -r '.sessionId' login_output` - - name: Recreate Investigation index - run: | - curl -k --request POST 'https://localhost:8181/icat/lucene/db/Investigation/1' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'sessionId='`jq -r '.sessionId' login_output` + - name: Use icatadmin to reindex all indexes + run: ~/bin/icatadmin https://localhost:8181 simple username root password pw -- populate --delete - name: Let reindexes complete run: sleep 30 - - name: Remove session ID data - run: rm -f login_output - name: Start API - run: cd datagateway-api; nohup poetry run python -m datagateway_api.src.main > api-output.txt & + run: cd datagateway-api/; nohup poetry run python -m datagateway_api.src.main > api-output.txt & # E2E tests - - name: Checkout repo - uses: actions/checkout@v2 - name: Setup Node.js - uses: actions/setup-node@v1 - with: - node-version: '14.x' - # Cache yarn dependencies/ restore the cached dependencies during future workflows - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: Cache yarn dependencies - uses: actions/cache@v2 - id: yarn-cache + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4 with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- + node-version: 20 + cache: 'yarn' + - name: Install dependencies # Ubuntu 16+ does not install libgconf-2-4 by default, so we need to install it ourselves (for Cypress) run: | - npm config set scripts-prepend-node-path true sudo apt-get install libgconf-2-4 - yarn --frozen-lockfile + yarn --immutable + - name: Run datagateway-search e2e tests run: yarn workspace datagateway-search run e2e - name: Upload Cypress screenshots if: failure() - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 with: name: Search-Screenshots path: packages/datagateway-search/cypress/screenshots + + docker: + # This job triggers only if all the other jobs succeed. It builds the Docker image and if successful, + # it pushes it to Harbor. + needs: [lint-and-unit-test, dataview-e2e-tests, download-e2e-tests, search-e2e-tests] + name: Docker + runs-on: ubuntu-20.04 + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + + - name: Login to Harbor + uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0 + with: + registry: ${{ secrets.HARBOR_URL }} + username: ${{ secrets.HARBOR_USERNAME }} + password: ${{ secrets.HARBOR_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@818d4b7b91585d195f67373fd9cb0332e31a7175 # v4.6.0 + with: + images: ${{ secrets.HARBOR_URL }}/plugins + + - name: Build and push Docker image to Harbor + uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 # v4.2.1 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index f14bd8877..19ec46b3c 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -4,7 +4,8 @@ on: branches: - main - develop - tags: '*' + tags: + - '*' jobs: build: @@ -13,33 +14,19 @@ jobs: steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Setup Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4 with: - node-version: '14.x' - - # Cache yarn dependencies/ restore the cached dependencies during future workflows - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - - name: Cache yarn dependencies - uses: actions/cache@v2 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- + node-version: 20 + cache: 'yarn' - name: Install dependencies # Ubuntu 16+ does not install libgconf-2-4 by default, so we need to install it ourselves (for Cypress) run: | - npm config set scripts-prepend-node-path true sudo apt-get install libgconf-2-4 - yarn --frozen-lockfile + yarn --immutable - name: Determine tag name run: | @@ -78,7 +65,7 @@ jobs: tar -czf ../../datagateway-search-$TAG_NAME.tar.gz datagateway-search-$TAG_NAME - name: Update snapshot tag - uses: richardsimko/update-tag@v1 + uses: richardsimko/update-tag@e173a8ef8f54ab526a91dad6139a25efed62424c # v1 with: tag_name: ${{ env.TAG_NAME }} env: @@ -86,11 +73,15 @@ jobs: if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop' }} - name: Create/update release - uses: johnwbyrd/update-release@v1.0.0 + uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8 with: token: ${{ secrets.GITHUB_TOKEN }} - files: ./datagateway-dataview-${{ env.TAG_NAME }}.tar.gz ./datagateway-download-${{ env.TAG_NAME }}.tar.gz ./datagateway-search-${{ env.TAG_NAME }}.tar.gz - release: Release ${{ env.TAG_NAME }} - tag: ${{ env.TAG_NAME }} + files: | + ./datagateway-dataview-${{ env.TAG_NAME }}.tar.gz + ./datagateway-download-${{ env.TAG_NAME }}.tar.gz + ./datagateway-search-${{ env.TAG_NAME }}.tar.gz + name: ${{ env.TAG_NAME }} + tag_name: ${{ env.TAG_NAME }} prerelease: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop' }} draft: false + generate_release_notes: true diff --git a/.gitignore b/.gitignore index 678ed6de8..75007c98b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,15 @@ node_modules/ /.pnp .pnp.js +# yarn 2 +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + # testing coverage/ screenshots/ @@ -29,3 +38,4 @@ yarn-error.log* **/public/*settings*.json !**/public/*settings.example.json +.vscode/ diff --git a/.husky/pre-commit b/.husky/pre-commit index a94c6b198..2d833c641 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -2,4 +2,4 @@ . "$(dirname "$0")/_/husky.sh" . "$(dirname "$0")/common.sh" -yarn lerna run --concurrency 1 --stream pre-commit \ No newline at end of file +yarn workspaces foreach --interlaced --verbose --jobs 1 run pre-commit \ No newline at end of file diff --git a/.yarn/plugins/@yarnpkg/plugin-version.cjs b/.yarn/plugins/@yarnpkg/plugin-version.cjs new file mode 100644 index 000000000..16113269f --- /dev/null +++ b/.yarn/plugins/@yarnpkg/plugin-version.cjs @@ -0,0 +1,523 @@ +/* eslint-disable */ +//prettier-ignore +module.exports = { +name: "@yarnpkg/plugin-version", +factory: function (require) { +var plugin=(()=>{var fU=Object.create;var ky=Object.defineProperty;var cU=Object.getOwnPropertyDescriptor;var dU=Object.getOwnPropertyNames;var pU=Object.getPrototypeOf,hU=Object.prototype.hasOwnProperty;var Kn=(u=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(u,{get:(l,c)=>(typeof require<"u"?require:l)[c]}):u)(function(u){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+u+'" is not supported')});var re=(u,l)=>()=>(l||u((l={exports:{}}).exports,l),l.exports),gS=(u,l)=>{for(var c in l)ky(u,c,{get:l[c],enumerable:!0})},_S=(u,l,c,p)=>{if(l&&typeof l=="object"||typeof l=="function")for(let _ of dU(l))!hU.call(u,_)&&_!==c&&ky(u,_,{get:()=>l[_],enumerable:!(p=cU(l,_))||p.enumerable});return u};var pu=(u,l,c)=>(c=u!=null?fU(pU(u)):{},_S(l||!u||!u.__esModule?ky(c,"default",{value:u,enumerable:!0}):c,u)),vU=u=>_S(ky({},"__esModule",{value:!0}),u);var iD=re((fee,ES)=>{function mU(u,l){for(var c=-1,p=u==null?0:u.length,_=Array(p);++c{function yU(){this.__data__=[],this.size=0}DS.exports=yU});var oD=re((dee,SS)=>{function gU(u,l){return u===l||u!==u&&l!==l}SS.exports=gU});var ah=re((pee,TS)=>{var _U=oD();function EU(u,l){for(var c=u.length;c--;)if(_U(u[c][0],l))return c;return-1}TS.exports=EU});var xS=re((hee,CS)=>{var DU=ah(),wU=Array.prototype,SU=wU.splice;function TU(u){var l=this.__data__,c=DU(l,u);if(c<0)return!1;var p=l.length-1;return c==p?l.pop():SU.call(l,c,1),--this.size,!0}CS.exports=TU});var AS=re((vee,RS)=>{var CU=ah();function xU(u){var l=this.__data__,c=CU(l,u);return c<0?void 0:l[c][1]}RS.exports=xU});var OS=re((mee,kS)=>{var RU=ah();function AU(u){return RU(this.__data__,u)>-1}kS.exports=AU});var NS=re((yee,MS)=>{var kU=ah();function OU(u,l){var c=this.__data__,p=kU(c,u);return p<0?(++this.size,c.push([u,l])):c[p][1]=l,this}MS.exports=OU});var sh=re((gee,LS)=>{var MU=wS(),NU=xS(),FU=AS(),LU=OS(),bU=NS();function k2(u){var l=-1,c=u==null?0:u.length;for(this.clear();++l{var PU=sh();function IU(){this.__data__=new PU,this.size=0}bS.exports=IU});var BS=re((Eee,IS)=>{function BU(u){var l=this.__data__,c=l.delete(u);return this.size=l.size,c}IS.exports=BU});var jS=re((Dee,US)=>{function UU(u){return this.__data__.get(u)}US.exports=UU});var qS=re((wee,zS)=>{function jU(u){return this.__data__.has(u)}zS.exports=jU});var uD=re((See,HS)=>{var zU=typeof global=="object"&&global&&global.Object===Object&&global;HS.exports=zU});var ra=re((Tee,WS)=>{var qU=uD(),HU=typeof self=="object"&&self&&self.Object===Object&&self,WU=qU||HU||Function("return this")();WS.exports=WU});var O2=re((Cee,VS)=>{var VU=ra(),GU=VU.Symbol;VS.exports=GU});var XS=re((xee,KS)=>{var GS=O2(),YS=Object.prototype,YU=YS.hasOwnProperty,KU=YS.toString,fh=GS?GS.toStringTag:void 0;function XU(u){var l=YU.call(u,fh),c=u[fh];try{u[fh]=void 0;var p=!0}catch{}var _=KU.call(u);return p&&(l?u[fh]=c:delete u[fh]),_}KS.exports=XU});var JS=re((Ree,QS)=>{var QU=Object.prototype,JU=QU.toString;function ZU(u){return JU.call(u)}QS.exports=ZU});var t1=re((Aee,eT)=>{var ZS=O2(),$U=XS(),ej=JS(),tj="[object Null]",nj="[object Undefined]",$S=ZS?ZS.toStringTag:void 0;function rj(u){return u==null?u===void 0?nj:tj:$S&&$S in Object(u)?$U(u):ej(u)}eT.exports=rj});var vf=re((kee,tT)=>{function ij(u){var l=typeof u;return u!=null&&(l=="object"||l=="function")}tT.exports=ij});var lD=re((Oee,nT)=>{var oj=t1(),uj=vf(),lj="[object AsyncFunction]",aj="[object Function]",sj="[object GeneratorFunction]",fj="[object Proxy]";function cj(u){if(!uj(u))return!1;var l=oj(u);return l==aj||l==sj||l==lj||l==fj}nT.exports=cj});var iT=re((Mee,rT)=>{var dj=ra(),pj=dj["__core-js_shared__"];rT.exports=pj});var lT=re((Nee,uT)=>{var aD=iT(),oT=function(){var u=/[^.]+$/.exec(aD&&aD.keys&&aD.keys.IE_PROTO||"");return u?"Symbol(src)_1."+u:""}();function hj(u){return!!oT&&oT in u}uT.exports=hj});var sD=re((Fee,aT)=>{var vj=Function.prototype,mj=vj.toString;function yj(u){if(u!=null){try{return mj.call(u)}catch{}try{return u+""}catch{}}return""}aT.exports=yj});var fT=re((Lee,sT)=>{var gj=lD(),_j=lT(),Ej=vf(),Dj=sD(),wj=/[\\^$.*+?()[\]{}|]/g,Sj=/^\[object .+?Constructor\]$/,Tj=Function.prototype,Cj=Object.prototype,xj=Tj.toString,Rj=Cj.hasOwnProperty,Aj=RegExp("^"+xj.call(Rj).replace(wj,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function kj(u){if(!Ej(u)||_j(u))return!1;var l=gj(u)?Aj:Sj;return l.test(Dj(u))}sT.exports=kj});var dT=re((bee,cT)=>{function Oj(u,l){return u==null?void 0:u[l]}cT.exports=Oj});var sc=re((Pee,pT)=>{var Mj=fT(),Nj=dT();function Fj(u,l){var c=Nj(u,l);return Mj(c)?c:void 0}pT.exports=Fj});var Oy=re((Iee,hT)=>{var Lj=sc(),bj=ra(),Pj=Lj(bj,"Map");hT.exports=Pj});var ch=re((Bee,vT)=>{var Ij=sc(),Bj=Ij(Object,"create");vT.exports=Bj});var gT=re((Uee,yT)=>{var mT=ch();function Uj(){this.__data__=mT?mT(null):{},this.size=0}yT.exports=Uj});var ET=re((jee,_T)=>{function jj(u){var l=this.has(u)&&delete this.__data__[u];return this.size-=l?1:0,l}_T.exports=jj});var wT=re((zee,DT)=>{var zj=ch(),qj="__lodash_hash_undefined__",Hj=Object.prototype,Wj=Hj.hasOwnProperty;function Vj(u){var l=this.__data__;if(zj){var c=l[u];return c===qj?void 0:c}return Wj.call(l,u)?l[u]:void 0}DT.exports=Vj});var TT=re((qee,ST)=>{var Gj=ch(),Yj=Object.prototype,Kj=Yj.hasOwnProperty;function Xj(u){var l=this.__data__;return Gj?l[u]!==void 0:Kj.call(l,u)}ST.exports=Xj});var xT=re((Hee,CT)=>{var Qj=ch(),Jj="__lodash_hash_undefined__";function Zj(u,l){var c=this.__data__;return this.size+=this.has(u)?0:1,c[u]=Qj&&l===void 0?Jj:l,this}CT.exports=Zj});var AT=re((Wee,RT)=>{var $j=gT(),ez=ET(),tz=wT(),nz=TT(),rz=xT();function M2(u){var l=-1,c=u==null?0:u.length;for(this.clear();++l{var kT=AT(),iz=sh(),oz=Oy();function uz(){this.size=0,this.__data__={hash:new kT,map:new(oz||iz),string:new kT}}OT.exports=uz});var FT=re((Gee,NT)=>{function lz(u){var l=typeof u;return l=="string"||l=="number"||l=="symbol"||l=="boolean"?u!=="__proto__":u===null}NT.exports=lz});var dh=re((Yee,LT)=>{var az=FT();function sz(u,l){var c=u.__data__;return az(l)?c[typeof l=="string"?"string":"hash"]:c.map}LT.exports=sz});var PT=re((Kee,bT)=>{var fz=dh();function cz(u){var l=fz(this,u).delete(u);return this.size-=l?1:0,l}bT.exports=cz});var BT=re((Xee,IT)=>{var dz=dh();function pz(u){return dz(this,u).get(u)}IT.exports=pz});var jT=re((Qee,UT)=>{var hz=dh();function vz(u){return hz(this,u).has(u)}UT.exports=vz});var qT=re((Jee,zT)=>{var mz=dh();function yz(u,l){var c=mz(this,u),p=c.size;return c.set(u,l),this.size+=c.size==p?0:1,this}zT.exports=yz});var fD=re((Zee,HT)=>{var gz=MT(),_z=PT(),Ez=BT(),Dz=jT(),wz=qT();function N2(u){var l=-1,c=u==null?0:u.length;for(this.clear();++l{var Sz=sh(),Tz=Oy(),Cz=fD(),xz=200;function Rz(u,l){var c=this.__data__;if(c instanceof Sz){var p=c.__data__;if(!Tz||p.length{var Az=sh(),kz=PS(),Oz=BS(),Mz=jS(),Nz=qS(),Fz=VT();function F2(u){var l=this.__data__=new Az(u);this.size=l.size}F2.prototype.clear=kz;F2.prototype.delete=Oz;F2.prototype.get=Mz;F2.prototype.has=Nz;F2.prototype.set=Fz;GT.exports=F2});var XT=re((tte,KT)=>{function Lz(u,l){for(var c=-1,p=u==null?0:u.length;++c{var bz=sc(),Pz=function(){try{var u=bz(Object,"defineProperty");return u({},"",{}),u}catch{}}();QT.exports=Pz});var dD=re((rte,ZT)=>{var JT=cD();function Iz(u,l,c){l=="__proto__"&&JT?JT(u,l,{configurable:!0,enumerable:!0,value:c,writable:!0}):u[l]=c}ZT.exports=Iz});var pD=re((ite,$T)=>{var Bz=dD(),Uz=oD(),jz=Object.prototype,zz=jz.hasOwnProperty;function qz(u,l,c){var p=u[l];(!(zz.call(u,l)&&Uz(p,c))||c===void 0&&!(l in u))&&Bz(u,l,c)}$T.exports=qz});var L2=re((ote,eC)=>{var Hz=pD(),Wz=dD();function Vz(u,l,c,p){var _=!c;c||(c={});for(var t=-1,O=l.length;++t{function Gz(u,l){for(var c=-1,p=Array(u);++c{function Yz(u){return u!=null&&typeof u=="object"}rC.exports=Yz});var oC=re((ate,iC)=>{var Kz=t1(),Xz=fc(),Qz="[object Arguments]";function Jz(u){return Xz(u)&&Kz(u)==Qz}iC.exports=Jz});var hD=re((ste,aC)=>{var uC=oC(),Zz=fc(),lC=Object.prototype,$z=lC.hasOwnProperty,eq=lC.propertyIsEnumerable,tq=uC(function(){return arguments}())?uC:function(u){return Zz(u)&&$z.call(u,"callee")&&!eq.call(u,"callee")};aC.exports=tq});var cc=re((fte,sC)=>{var nq=Array.isArray;sC.exports=nq});var cC=re((cte,fC)=>{function rq(){return!1}fC.exports=rq});var vD=re((ph,b2)=>{var iq=ra(),oq=cC(),hC=typeof ph=="object"&&ph&&!ph.nodeType&&ph,dC=hC&&typeof b2=="object"&&b2&&!b2.nodeType&&b2,uq=dC&&dC.exports===hC,pC=uq?iq.Buffer:void 0,lq=pC?pC.isBuffer:void 0,aq=lq||oq;b2.exports=aq});var mC=re((dte,vC)=>{var sq=9007199254740991,fq=/^(?:0|[1-9]\d*)$/;function cq(u,l){var c=typeof u;return l=l==null?sq:l,!!l&&(c=="number"||c!="symbol"&&fq.test(u))&&u>-1&&u%1==0&&u{var dq=9007199254740991;function pq(u){return typeof u=="number"&&u>-1&&u%1==0&&u<=dq}yC.exports=pq});var _C=re((hte,gC)=>{var hq=t1(),vq=mD(),mq=fc(),yq="[object Arguments]",gq="[object Array]",_q="[object Boolean]",Eq="[object Date]",Dq="[object Error]",wq="[object Function]",Sq="[object Map]",Tq="[object Number]",Cq="[object Object]",xq="[object RegExp]",Rq="[object Set]",Aq="[object String]",kq="[object WeakMap]",Oq="[object ArrayBuffer]",Mq="[object DataView]",Nq="[object Float32Array]",Fq="[object Float64Array]",Lq="[object Int8Array]",bq="[object Int16Array]",Pq="[object Int32Array]",Iq="[object Uint8Array]",Bq="[object Uint8ClampedArray]",Uq="[object Uint16Array]",jq="[object Uint32Array]",qi={};qi[Nq]=qi[Fq]=qi[Lq]=qi[bq]=qi[Pq]=qi[Iq]=qi[Bq]=qi[Uq]=qi[jq]=!0;qi[yq]=qi[gq]=qi[Oq]=qi[_q]=qi[Mq]=qi[Eq]=qi[Dq]=qi[wq]=qi[Sq]=qi[Tq]=qi[Cq]=qi[xq]=qi[Rq]=qi[Aq]=qi[kq]=!1;function zq(u){return mq(u)&&vq(u.length)&&!!qi[hq(u)]}gC.exports=zq});var My=re((vte,EC)=>{function qq(u){return function(l){return u(l)}}EC.exports=qq});var Ny=re((hh,P2)=>{var Hq=uD(),DC=typeof hh=="object"&&hh&&!hh.nodeType&&hh,vh=DC&&typeof P2=="object"&&P2&&!P2.nodeType&&P2,Wq=vh&&vh.exports===DC,yD=Wq&&Hq.process,Vq=function(){try{var u=vh&&vh.require&&vh.require("util").types;return u||yD&&yD.binding&&yD.binding("util")}catch{}}();P2.exports=Vq});var CC=re((mte,TC)=>{var Gq=_C(),Yq=My(),wC=Ny(),SC=wC&&wC.isTypedArray,Kq=SC?Yq(SC):Gq;TC.exports=Kq});var gD=re((yte,xC)=>{var Xq=nC(),Qq=hD(),Jq=cc(),Zq=vD(),$q=mC(),eH=CC(),tH=Object.prototype,nH=tH.hasOwnProperty;function rH(u,l){var c=Jq(u),p=!c&&Qq(u),_=!c&&!p&&Zq(u),t=!c&&!p&&!_&&eH(u),O=c||p||_||t,M=O?Xq(u.length,String):[],A=M.length;for(var T in u)(l||nH.call(u,T))&&!(O&&(T=="length"||_&&(T=="offset"||T=="parent")||t&&(T=="buffer"||T=="byteLength"||T=="byteOffset")||$q(T,A)))&&M.push(T);return M}xC.exports=rH});var Fy=re((gte,RC)=>{var iH=Object.prototype;function oH(u){var l=u&&u.constructor,c=typeof l=="function"&&l.prototype||iH;return u===c}RC.exports=oH});var _D=re((_te,AC)=>{function uH(u,l){return function(c){return u(l(c))}}AC.exports=uH});var OC=re((Ete,kC)=>{var lH=_D(),aH=lH(Object.keys,Object);kC.exports=aH});var NC=re((Dte,MC)=>{var sH=Fy(),fH=OC(),cH=Object.prototype,dH=cH.hasOwnProperty;function pH(u){if(!sH(u))return fH(u);var l=[];for(var c in Object(u))dH.call(u,c)&&c!="constructor"&&l.push(c);return l}MC.exports=pH});var ED=re((wte,FC)=>{var hH=lD(),vH=mD();function mH(u){return u!=null&&vH(u.length)&&!hH(u)}FC.exports=mH});var Ly=re((Ste,LC)=>{var yH=gD(),gH=NC(),_H=ED();function EH(u){return _H(u)?yH(u):gH(u)}LC.exports=EH});var PC=re((Tte,bC)=>{var DH=L2(),wH=Ly();function SH(u,l){return u&&DH(l,wH(l),u)}bC.exports=SH});var BC=re((Cte,IC)=>{function TH(u){var l=[];if(u!=null)for(var c in Object(u))l.push(c);return l}IC.exports=TH});var jC=re((xte,UC)=>{var CH=vf(),xH=Fy(),RH=BC(),AH=Object.prototype,kH=AH.hasOwnProperty;function OH(u){if(!CH(u))return RH(u);var l=xH(u),c=[];for(var p in u)p=="constructor"&&(l||!kH.call(u,p))||c.push(p);return c}UC.exports=OH});var by=re((Rte,zC)=>{var MH=gD(),NH=jC(),FH=ED();function LH(u){return FH(u)?MH(u,!0):NH(u)}zC.exports=LH});var HC=re((Ate,qC)=>{var bH=L2(),PH=by();function IH(u,l){return u&&bH(l,PH(l),u)}qC.exports=IH});var KC=re((mh,I2)=>{var BH=ra(),YC=typeof mh=="object"&&mh&&!mh.nodeType&&mh,WC=YC&&typeof I2=="object"&&I2&&!I2.nodeType&&I2,UH=WC&&WC.exports===YC,VC=UH?BH.Buffer:void 0,GC=VC?VC.allocUnsafe:void 0;function jH(u,l){if(l)return u.slice();var c=u.length,p=GC?GC(c):new u.constructor(c);return u.copy(p),p}I2.exports=jH});var QC=re((kte,XC)=>{function zH(u,l){var c=-1,p=u.length;for(l||(l=Array(p));++c{function qH(u,l){for(var c=-1,p=u==null?0:u.length,_=0,t=[];++c{function HH(){return[]}$C.exports=HH});var Py=re((Nte,t6)=>{var WH=ZC(),VH=DD(),GH=Object.prototype,YH=GH.propertyIsEnumerable,e6=Object.getOwnPropertySymbols,KH=e6?function(u){return u==null?[]:(u=Object(u),WH(e6(u),function(l){return YH.call(u,l)}))}:VH;t6.exports=KH});var r6=re((Fte,n6)=>{var XH=L2(),QH=Py();function JH(u,l){return XH(u,QH(u),l)}n6.exports=JH});var Iy=re((Lte,i6)=>{function ZH(u,l){for(var c=-1,p=l.length,_=u.length;++c{var $H=_D(),eW=$H(Object.getPrototypeOf,Object);o6.exports=eW});var wD=re((Pte,u6)=>{var tW=Iy(),nW=By(),rW=Py(),iW=DD(),oW=Object.getOwnPropertySymbols,uW=oW?function(u){for(var l=[];u;)tW(l,rW(u)),u=nW(u);return l}:iW;u6.exports=uW});var a6=re((Ite,l6)=>{var lW=L2(),aW=wD();function sW(u,l){return lW(u,aW(u),l)}l6.exports=sW});var SD=re((Bte,s6)=>{var fW=Iy(),cW=cc();function dW(u,l,c){var p=l(u);return cW(u)?p:fW(p,c(u))}s6.exports=dW});var c6=re((Ute,f6)=>{var pW=SD(),hW=Py(),vW=Ly();function mW(u){return pW(u,vW,hW)}f6.exports=mW});var TD=re((jte,d6)=>{var yW=SD(),gW=wD(),_W=by();function EW(u){return yW(u,_W,gW)}d6.exports=EW});var h6=re((zte,p6)=>{var DW=sc(),wW=ra(),SW=DW(wW,"DataView");p6.exports=SW});var m6=re((qte,v6)=>{var TW=sc(),CW=ra(),xW=TW(CW,"Promise");v6.exports=xW});var g6=re((Hte,y6)=>{var RW=sc(),AW=ra(),kW=RW(AW,"Set");y6.exports=kW});var E6=re((Wte,_6)=>{var OW=sc(),MW=ra(),NW=OW(MW,"WeakMap");_6.exports=NW});var Uy=re((Vte,R6)=>{var CD=h6(),xD=Oy(),RD=m6(),AD=g6(),kD=E6(),x6=t1(),B2=sD(),D6="[object Map]",FW="[object Object]",w6="[object Promise]",S6="[object Set]",T6="[object WeakMap]",C6="[object DataView]",LW=B2(CD),bW=B2(xD),PW=B2(RD),IW=B2(AD),BW=B2(kD),n1=x6;(CD&&n1(new CD(new ArrayBuffer(1)))!=C6||xD&&n1(new xD)!=D6||RD&&n1(RD.resolve())!=w6||AD&&n1(new AD)!=S6||kD&&n1(new kD)!=T6)&&(n1=function(u){var l=x6(u),c=l==FW?u.constructor:void 0,p=c?B2(c):"";if(p)switch(p){case LW:return C6;case bW:return D6;case PW:return w6;case IW:return S6;case BW:return T6}return l});R6.exports=n1});var k6=re((Gte,A6)=>{var UW=Object.prototype,jW=UW.hasOwnProperty;function zW(u){var l=u.length,c=new u.constructor(l);return l&&typeof u[0]=="string"&&jW.call(u,"index")&&(c.index=u.index,c.input=u.input),c}A6.exports=zW});var M6=re((Yte,O6)=>{var qW=ra(),HW=qW.Uint8Array;O6.exports=HW});var jy=re((Kte,F6)=>{var N6=M6();function WW(u){var l=new u.constructor(u.byteLength);return new N6(l).set(new N6(u)),l}F6.exports=WW});var b6=re((Xte,L6)=>{var VW=jy();function GW(u,l){var c=l?VW(u.buffer):u.buffer;return new u.constructor(c,u.byteOffset,u.byteLength)}L6.exports=GW});var I6=re((Qte,P6)=>{var YW=/\w*$/;function KW(u){var l=new u.constructor(u.source,YW.exec(u));return l.lastIndex=u.lastIndex,l}P6.exports=KW});var q6=re((Jte,z6)=>{var B6=O2(),U6=B6?B6.prototype:void 0,j6=U6?U6.valueOf:void 0;function XW(u){return j6?Object(j6.call(u)):{}}z6.exports=XW});var W6=re((Zte,H6)=>{var QW=jy();function JW(u,l){var c=l?QW(u.buffer):u.buffer;return new u.constructor(c,u.byteOffset,u.length)}H6.exports=JW});var G6=re(($te,V6)=>{var ZW=jy(),$W=b6(),eV=I6(),tV=q6(),nV=W6(),rV="[object Boolean]",iV="[object Date]",oV="[object Map]",uV="[object Number]",lV="[object RegExp]",aV="[object Set]",sV="[object String]",fV="[object Symbol]",cV="[object ArrayBuffer]",dV="[object DataView]",pV="[object Float32Array]",hV="[object Float64Array]",vV="[object Int8Array]",mV="[object Int16Array]",yV="[object Int32Array]",gV="[object Uint8Array]",_V="[object Uint8ClampedArray]",EV="[object Uint16Array]",DV="[object Uint32Array]";function wV(u,l,c){var p=u.constructor;switch(l){case cV:return ZW(u);case rV:case iV:return new p(+u);case dV:return $W(u,c);case pV:case hV:case vV:case mV:case yV:case gV:case _V:case EV:case DV:return nV(u,c);case oV:return new p;case uV:case sV:return new p(u);case lV:return eV(u);case aV:return new p;case fV:return tV(u)}}V6.exports=wV});var X6=re((ene,K6)=>{var SV=vf(),Y6=Object.create,TV=function(){function u(){}return function(l){if(!SV(l))return{};if(Y6)return Y6(l);u.prototype=l;var c=new u;return u.prototype=void 0,c}}();K6.exports=TV});var J6=re((tne,Q6)=>{var CV=X6(),xV=By(),RV=Fy();function AV(u){return typeof u.constructor=="function"&&!RV(u)?CV(xV(u)):{}}Q6.exports=AV});var $6=re((nne,Z6)=>{var kV=Uy(),OV=fc(),MV="[object Map]";function NV(u){return OV(u)&&kV(u)==MV}Z6.exports=NV});var rx=re((rne,nx)=>{var FV=$6(),LV=My(),ex=Ny(),tx=ex&&ex.isMap,bV=tx?LV(tx):FV;nx.exports=bV});var ox=re((ine,ix)=>{var PV=Uy(),IV=fc(),BV="[object Set]";function UV(u){return IV(u)&&PV(u)==BV}ix.exports=UV});var sx=re((one,ax)=>{var jV=ox(),zV=My(),ux=Ny(),lx=ux&&ux.isSet,qV=lx?zV(lx):jV;ax.exports=qV});var hx=re((une,px)=>{var HV=YT(),WV=XT(),VV=pD(),GV=PC(),YV=HC(),KV=KC(),XV=QC(),QV=r6(),JV=a6(),ZV=c6(),$V=TD(),eG=Uy(),tG=k6(),nG=G6(),rG=J6(),iG=cc(),oG=vD(),uG=rx(),lG=vf(),aG=sx(),sG=Ly(),fG=by(),cG=1,dG=2,pG=4,fx="[object Arguments]",hG="[object Array]",vG="[object Boolean]",mG="[object Date]",yG="[object Error]",cx="[object Function]",gG="[object GeneratorFunction]",_G="[object Map]",EG="[object Number]",dx="[object Object]",DG="[object RegExp]",wG="[object Set]",SG="[object String]",TG="[object Symbol]",CG="[object WeakMap]",xG="[object ArrayBuffer]",RG="[object DataView]",AG="[object Float32Array]",kG="[object Float64Array]",OG="[object Int8Array]",MG="[object Int16Array]",NG="[object Int32Array]",FG="[object Uint8Array]",LG="[object Uint8ClampedArray]",bG="[object Uint16Array]",PG="[object Uint32Array]",Fi={};Fi[fx]=Fi[hG]=Fi[xG]=Fi[RG]=Fi[vG]=Fi[mG]=Fi[AG]=Fi[kG]=Fi[OG]=Fi[MG]=Fi[NG]=Fi[_G]=Fi[EG]=Fi[dx]=Fi[DG]=Fi[wG]=Fi[SG]=Fi[TG]=Fi[FG]=Fi[LG]=Fi[bG]=Fi[PG]=!0;Fi[yG]=Fi[cx]=Fi[CG]=!1;function zy(u,l,c,p,_,t){var O,M=l&cG,A=l&dG,T=l&pG;if(c&&(O=_?c(u,p,_,t):c(u)),O!==void 0)return O;if(!lG(u))return u;var P=iG(u);if(P){if(O=tG(u),!M)return XV(u,O)}else{var U=eG(u),z=U==cx||U==gG;if(oG(u))return KV(u,M);if(U==dx||U==fx||z&&!_){if(O=A||z?{}:rG(u),!M)return A?JV(u,YV(O,u)):QV(u,GV(O,u))}else{if(!Fi[U])return _?u:{};O=nG(u,U,M)}}t||(t=new HV);var Q=t.get(u);if(Q)return Q;t.set(u,O),aG(u)?u.forEach(function(ye){O.add(zy(ye,l,c,ye,u,t))}):uG(u)&&u.forEach(function(ye,le){O.set(le,zy(ye,l,c,le,u,t))});var v=T?A?$V:ZV:A?fG:sG,de=P?void 0:v(u);return WV(de||u,function(ye,le){de&&(le=ye,ye=u[le]),VV(O,le,zy(ye,l,c,le,u,t))}),O}px.exports=zy});var yh=re((lne,vx)=>{var IG=t1(),BG=fc(),UG="[object Symbol]";function jG(u){return typeof u=="symbol"||BG(u)&&IG(u)==UG}vx.exports=jG});var yx=re((ane,mx)=>{var zG=cc(),qG=yh(),HG=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,WG=/^\w*$/;function VG(u,l){if(zG(u))return!1;var c=typeof u;return c=="number"||c=="symbol"||c=="boolean"||u==null||qG(u)?!0:WG.test(u)||!HG.test(u)||l!=null&&u in Object(l)}mx.exports=VG});var Ex=re((sne,_x)=>{var gx=fD(),GG="Expected a function";function OD(u,l){if(typeof u!="function"||l!=null&&typeof l!="function")throw new TypeError(GG);var c=function(){var p=arguments,_=l?l.apply(this,p):p[0],t=c.cache;if(t.has(_))return t.get(_);var O=u.apply(this,p);return c.cache=t.set(_,O)||t,O};return c.cache=new(OD.Cache||gx),c}OD.Cache=gx;_x.exports=OD});var wx=re((fne,Dx)=>{var YG=Ex(),KG=500;function XG(u){var l=YG(u,function(p){return c.size===KG&&c.clear(),p}),c=l.cache;return l}Dx.exports=XG});var Tx=re((cne,Sx)=>{var QG=wx(),JG=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,ZG=/\\(\\)?/g,$G=QG(function(u){var l=[];return u.charCodeAt(0)===46&&l.push(""),u.replace(JG,function(c,p,_,t){l.push(_?t.replace(ZG,"$1"):p||c)}),l});Sx.exports=$G});var Ox=re((dne,kx)=>{var Cx=O2(),eY=iD(),tY=cc(),nY=yh(),rY=1/0,xx=Cx?Cx.prototype:void 0,Rx=xx?xx.toString:void 0;function Ax(u){if(typeof u=="string")return u;if(tY(u))return eY(u,Ax)+"";if(nY(u))return Rx?Rx.call(u):"";var l=u+"";return l=="0"&&1/u==-rY?"-0":l}kx.exports=Ax});var Nx=re((pne,Mx)=>{var iY=Ox();function oY(u){return u==null?"":iY(u)}Mx.exports=oY});var qy=re((hne,Fx)=>{var uY=cc(),lY=yx(),aY=Tx(),sY=Nx();function fY(u,l){return uY(u)?u:lY(u,l)?[u]:aY(sY(u))}Fx.exports=fY});var bx=re((vne,Lx)=>{function cY(u){var l=u==null?0:u.length;return l?u[l-1]:void 0}Lx.exports=cY});var MD=re((mne,Px)=>{var dY=yh(),pY=1/0;function hY(u){if(typeof u=="string"||dY(u))return u;var l=u+"";return l=="0"&&1/u==-pY?"-0":l}Px.exports=hY});var Bx=re((yne,Ix)=>{var vY=qy(),mY=MD();function yY(u,l){l=vY(l,u);for(var c=0,p=l.length;u!=null&&c{function gY(u,l,c){var p=-1,_=u.length;l<0&&(l=-l>_?0:_+l),c=c>_?_:c,c<0&&(c+=_),_=l>c?0:c-l>>>0,l>>>=0;for(var t=Array(_);++p<_;)t[p]=u[p+l];return t}Ux.exports=gY});var qx=re((_ne,zx)=>{var _Y=Bx(),EY=jx();function DY(u,l){return l.length<2?u:_Y(u,EY(l,0,-1))}zx.exports=DY});var Wx=re((Ene,Hx)=>{var wY=qy(),SY=bx(),TY=qx(),CY=MD();function xY(u,l){return l=wY(l,u),u=TY(u,l),u==null||delete u[CY(SY(l))]}Hx.exports=xY});var Yx=re((Dne,Gx)=>{var RY=t1(),AY=By(),kY=fc(),OY="[object Object]",MY=Function.prototype,NY=Object.prototype,Vx=MY.toString,FY=NY.hasOwnProperty,LY=Vx.call(Object);function bY(u){if(!kY(u)||RY(u)!=OY)return!1;var l=AY(u);if(l===null)return!0;var c=FY.call(l,"constructor")&&l.constructor;return typeof c=="function"&&c instanceof c&&Vx.call(c)==LY}Gx.exports=bY});var Xx=re((wne,Kx)=>{var PY=Yx();function IY(u){return PY(u)?void 0:u}Kx.exports=IY});var $x=re((Sne,Zx)=>{var Qx=O2(),BY=hD(),UY=cc(),Jx=Qx?Qx.isConcatSpreadable:void 0;function jY(u){return UY(u)||BY(u)||!!(Jx&&u&&u[Jx])}Zx.exports=jY});var n5=re((Tne,t5)=>{var zY=Iy(),qY=$x();function e5(u,l,c,p,_){var t=-1,O=u.length;for(c||(c=qY),_||(_=[]);++t0&&c(M)?l>1?e5(M,l-1,c,p,_):zY(_,M):p||(_[_.length]=M)}return _}t5.exports=e5});var i5=re((Cne,r5)=>{var HY=n5();function WY(u){var l=u==null?0:u.length;return l?HY(u,1):[]}r5.exports=WY});var u5=re((xne,o5)=>{function VY(u,l,c){switch(c.length){case 0:return u.call(l);case 1:return u.call(l,c[0]);case 2:return u.call(l,c[0],c[1]);case 3:return u.call(l,c[0],c[1],c[2])}return u.apply(l,c)}o5.exports=VY});var s5=re((Rne,a5)=>{var GY=u5(),l5=Math.max;function YY(u,l,c){return l=l5(l===void 0?u.length-1:l,0),function(){for(var p=arguments,_=-1,t=l5(p.length-l,0),O=Array(t);++_{function KY(u){return function(){return u}}f5.exports=KY});var p5=re((kne,d5)=>{function XY(u){return u}d5.exports=XY});var m5=re((One,v5)=>{var QY=c5(),h5=cD(),JY=p5(),ZY=h5?function(u,l){return h5(u,"toString",{configurable:!0,enumerable:!1,value:QY(l),writable:!0})}:JY;v5.exports=ZY});var g5=re((Mne,y5)=>{var $Y=800,eK=16,tK=Date.now;function nK(u){var l=0,c=0;return function(){var p=tK(),_=eK-(p-c);if(c=p,_>0){if(++l>=$Y)return arguments[0]}else l=0;return u.apply(void 0,arguments)}}y5.exports=nK});var E5=re((Nne,_5)=>{var rK=m5(),iK=g5(),oK=iK(rK);_5.exports=oK});var w5=re((Fne,D5)=>{var uK=i5(),lK=s5(),aK=E5();function sK(u){return aK(lK(u,void 0,uK),u+"")}D5.exports=sK});var T5=re((Lne,S5)=>{var fK=iD(),cK=hx(),dK=Wx(),pK=qy(),hK=L2(),vK=Xx(),mK=w5(),yK=TD(),gK=1,_K=2,EK=4,DK=mK(function(u,l){var c={};if(u==null)return c;var p=!1;l=fK(l,function(t){return t=pK(t,u),p||(p=t.length>1),t}),hK(u,yK(u),c),p&&(c=cK(c,gK|_K|EK,vK));for(var _=l.length;_--;)dK(c,l[_]);return c});S5.exports=DK});var Eh=re((Wne,A5)=>{"use strict";var R5=Object.getOwnPropertySymbols,AK=Object.prototype.hasOwnProperty,kK=Object.prototype.propertyIsEnumerable;function OK(u){if(u==null)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(u)}function MK(){try{if(!Object.assign)return!1;var u=new String("abc");if(u[5]="de",Object.getOwnPropertyNames(u)[0]==="5")return!1;for(var l={},c=0;c<10;c++)l["_"+String.fromCharCode(c)]=c;var p=Object.getOwnPropertyNames(l).map(function(t){return l[t]});if(p.join("")!=="0123456789")return!1;var _={};return"abcdefghijklmnopqrst".split("").forEach(function(t){_[t]=t}),Object.keys(Object.assign({},_)).join("")==="abcdefghijklmnopqrst"}catch{return!1}}A5.exports=MK()?Object.assign:function(u,l){for(var c,p=OK(u),_,t=1;t{"use strict";var jD=Eh(),Pa=typeof Symbol=="function"&&Symbol.for,Dh=Pa?Symbol.for("react.element"):60103,NK=Pa?Symbol.for("react.portal"):60106,FK=Pa?Symbol.for("react.fragment"):60107,LK=Pa?Symbol.for("react.strict_mode"):60108,bK=Pa?Symbol.for("react.profiler"):60114,PK=Pa?Symbol.for("react.provider"):60109,IK=Pa?Symbol.for("react.context"):60110,BK=Pa?Symbol.for("react.forward_ref"):60112,UK=Pa?Symbol.for("react.suspense"):60113,jK=Pa?Symbol.for("react.memo"):60115,zK=Pa?Symbol.for("react.lazy"):60116,k5=typeof Symbol=="function"&&Symbol.iterator;function wh(u){for(var l="https://reactjs.org/docs/error-decoder.html?invariant="+u,c=1;cYy.length&&Yy.push(u)}function ID(u,l,c,p){var _=typeof u;(_==="undefined"||_==="boolean")&&(u=null);var t=!1;if(u===null)t=!0;else switch(_){case"string":case"number":t=!0;break;case"object":switch(u.$$typeof){case Dh:case NK:t=!0}}if(t)return c(p,u,l===""?"."+PD(u,0):l),1;if(t=0,l=l===""?".":l+":",Array.isArray(u))for(var O=0;O{"use strict";var YK="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";z5.exports=YK});var GD=re((Yne,G5)=>{"use strict";var VD=function(){};process.env.NODE_ENV!=="production"&&(H5=q5(),Ky={},W5=Function.call.bind(Object.prototype.hasOwnProperty),VD=function(u){var l="Warning: "+u;typeof console<"u"&&console.error(l);try{throw new Error(l)}catch{}});var H5,Ky,W5;function V5(u,l,c,p,_){if(process.env.NODE_ENV!=="production"){for(var t in u)if(W5(u,t)){var O;try{if(typeof u[t]!="function"){var M=Error((p||"React class")+": "+c+" type `"+t+"` is invalid; it must be a function, usually from the `prop-types` package, but received `"+typeof u[t]+"`.");throw M.name="Invariant Violation",M}O=u[t](l,t,p,c,null,H5)}catch(T){O=T}if(O&&!(O instanceof Error)&&VD((p||"React class")+": type specification of "+c+" `"+t+"` is invalid; the type checker function must return `null` or an `Error` but returned a "+typeof O+". You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument)."),O instanceof Error&&!(O.message in Ky)){Ky[O.message]=!0;var A=_?_():"";VD("Failed "+c+" type: "+O.message+(A!=null?A:""))}}}}V5.resetWarningCache=function(){process.env.NODE_ENV!=="production"&&(Ky={})};G5.exports=V5});var Y5=re(mi=>{"use strict";process.env.NODE_ENV!=="production"&&function(){"use strict";var u=Eh(),l=GD(),c="16.13.1",p=typeof Symbol=="function"&&Symbol.for,_=p?Symbol.for("react.element"):60103,t=p?Symbol.for("react.portal"):60106,O=p?Symbol.for("react.fragment"):60107,M=p?Symbol.for("react.strict_mode"):60108,A=p?Symbol.for("react.profiler"):60114,T=p?Symbol.for("react.provider"):60109,P=p?Symbol.for("react.context"):60110,U=p?Symbol.for("react.concurrent_mode"):60111,z=p?Symbol.for("react.forward_ref"):60112,Q=p?Symbol.for("react.suspense"):60113,v=p?Symbol.for("react.suspense_list"):60120,de=p?Symbol.for("react.memo"):60115,ye=p?Symbol.for("react.lazy"):60116,le=p?Symbol.for("react.block"):60121,ae=p?Symbol.for("react.fundamental"):60117,Me=p?Symbol.for("react.responder"):60118,fe=p?Symbol.for("react.scope"):60119,pe=typeof Symbol=="function"&&Symbol.iterator,Z="@@iterator";function Ae(W){if(W===null||typeof W!="object")return null;var he=pe&&W[pe]||W[Z];return typeof he=="function"?he:null}var Fe={current:null},He={suspense:null},ot={current:null},st=/^(.*)[\\\/]/;function qe(W,he,Se){var we="";if(he){var tt=he.fileName,Cn=tt.replace(st,"");if(/^index\./.test(Cn)){var cn=tt.match(st);if(cn){var In=cn[1];if(In){var Ur=In.replace(st,"");Cn=Ur+"/"+Cn}}}we=" (at "+Cn+":"+he.lineNumber+")"}else Se&&(we=" (created by "+Se+")");return` + in `+(W||"Unknown")+we}var Xe=1;function Ie(W){return W._status===Xe?W._result:null}function kt(W,he,Se){var we=he.displayName||he.name||"";return W.displayName||(we!==""?Se+"("+we+")":Se)}function Kt(W){if(W==null)return null;if(typeof W.tag=="number"&&et("Received an unexpected object in getComponentName(). This is likely a bug in React. Please file an issue."),typeof W=="function")return W.displayName||W.name||null;if(typeof W=="string")return W;switch(W){case O:return"Fragment";case t:return"Portal";case A:return"Profiler";case M:return"StrictMode";case Q:return"Suspense";case v:return"SuspenseList"}if(typeof W=="object")switch(W.$$typeof){case P:return"Context.Consumer";case T:return"Context.Provider";case z:return kt(W,W.render,"ForwardRef");case de:return Kt(W.type);case le:return Kt(W.render);case ye:{var he=W,Se=Ie(he);if(Se)return Kt(Se);break}}return null}var Ye={},V=null;function oe(W){V=W}Ye.getCurrentStack=null,Ye.getStackAddendum=function(){var W="";if(V){var he=Kt(V.type),Se=V._owner;W+=qe(he,V._source,Se&&Kt(Se.type))}var we=Ye.getCurrentStack;return we&&(W+=we()||""),W};var ve={current:!1},ee={ReactCurrentDispatcher:Fe,ReactCurrentBatchConfig:He,ReactCurrentOwner:ot,IsSomeRendererActing:ve,assign:u};u(ee,{ReactDebugCurrentFrame:Ye,ReactComponentTreeHook:{}});function Oe(W){{for(var he=arguments.length,Se=new Array(he>1?he-1:0),we=1;we1?he-1:0),we=1;we0&&typeof Se[Se.length-1]=="string"&&Se[Se.length-1].indexOf(` + in`)===0;if(!we){var tt=ee.ReactDebugCurrentFrame,Cn=tt.getStackAddendum();Cn!==""&&(he+="%s",Se=Se.concat([Cn]))}var cn=Se.map(function(Pi){return""+Pi});cn.unshift("Warning: "+he),Function.prototype.apply.call(console[W],console,cn);try{var In=0,Ur="Warning: "+he.replace(/%s/g,function(){return Se[In++]});throw new Error(Ur)}catch{}}}var Lt={};function Xt(W,he){{var Se=W.constructor,we=Se&&(Se.displayName||Se.name)||"ReactClass",tt=we+"."+he;if(Lt[tt])return;et("Can't call %s on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the %s component.",he,we),Lt[tt]=!0}}var pn={isMounted:function(W){return!1},enqueueForceUpdate:function(W,he,Se){Xt(W,"forceUpdate")},enqueueReplaceState:function(W,he,Se,we){Xt(W,"replaceState")},enqueueSetState:function(W,he,Se,we){Xt(W,"setState")}},Nn={};Object.freeze(Nn);function Wt(W,he,Se){this.props=W,this.context=he,this.refs=Nn,this.updater=Se||pn}Wt.prototype.isReactComponent={},Wt.prototype.setState=function(W,he){if(!(typeof W=="object"||typeof W=="function"||W==null))throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,W,he,"setState")},Wt.prototype.forceUpdate=function(W){this.updater.enqueueForceUpdate(this,W,"forceUpdate")};{var Ot={isMounted:["isMounted","Instead, make sure to clean up subscriptions and pending requests in componentWillUnmount to prevent memory leaks."],replaceState:["replaceState","Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236)."]},Wn=function(W,he){Object.defineProperty(Wt.prototype,W,{get:function(){Oe("%s(...) is deprecated in plain JavaScript React classes. %s",he[0],he[1])}})};for(var w in Ot)Ot.hasOwnProperty(w)&&Wn(w,Ot[w])}function Ct(){}Ct.prototype=Wt.prototype;function wn(W,he,Se){this.props=W,this.context=he,this.refs=Nn,this.updater=Se||pn}var ir=wn.prototype=new Ct;ir.constructor=wn,u(ir,Wt.prototype),ir.isPureReactComponent=!0;function sr(){var W={current:null};return Object.seal(W),W}var Ln=Object.prototype.hasOwnProperty,Er={key:!0,ref:!0,__self:!0,__source:!0},zt,p0,B0;B0={};function Do(W){if(Ln.call(W,"ref")){var he=Object.getOwnPropertyDescriptor(W,"ref").get;if(he&&he.isReactWarning)return!1}return W.ref!==void 0}function wl(W){if(Ln.call(W,"key")){var he=Object.getOwnPropertyDescriptor(W,"key").get;if(he&&he.isReactWarning)return!1}return W.key!==void 0}function Sl(W,he){var Se=function(){zt||(zt=!0,et("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://fb.me/react-special-props)",he))};Se.isReactWarning=!0,Object.defineProperty(W,"key",{get:Se,configurable:!0})}function Tl(W,he){var Se=function(){p0||(p0=!0,et("%s: `ref` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://fb.me/react-special-props)",he))};Se.isReactWarning=!0,Object.defineProperty(W,"ref",{get:Se,configurable:!0})}function ua(W){if(typeof W.ref=="string"&&ot.current&&W.__self&&ot.current.stateNode!==W.__self){var he=Kt(ot.current.type);B0[he]||(et('Component "%s" contains the string ref "%s". Support for string refs will be removed in a future major release. This case cannot be automatically converted to an arrow function. We ask you to manually fix this case by using useRef() or createRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref',Kt(ot.current.type),W.ref),B0[he]=!0)}}var Rt=function(W,he,Se,we,tt,Cn,cn){var In={$$typeof:_,type:W,key:he,ref:Se,props:cn,_owner:Cn};return In._store={},Object.defineProperty(In._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:!1}),Object.defineProperty(In,"_self",{configurable:!1,enumerable:!1,writable:!1,value:we}),Object.defineProperty(In,"_source",{configurable:!1,enumerable:!1,writable:!1,value:tt}),Object.freeze&&(Object.freeze(In.props),Object.freeze(In)),In};function Kr(W,he,Se){var we,tt={},Cn=null,cn=null,In=null,Ur=null;if(he!=null){Do(he)&&(cn=he.ref,ua(he)),wl(he)&&(Cn=""+he.key),In=he.__self===void 0?null:he.__self,Ur=he.__source===void 0?null:he.__source;for(we in he)Ln.call(he,we)&&!Er.hasOwnProperty(we)&&(tt[we]=he[we])}var Pi=arguments.length-2;if(Pi===1)tt.children=Se;else if(Pi>1){for(var t0=Array(Pi),n0=0;n01){for(var Ii=Array(n0),jr=0;jr is not supported and will be removed in a future major release. Did you mean to render instead?")),Se.Provider},set:function(cn){Se.Provider=cn}},_currentValue:{get:function(){return Se._currentValue},set:function(cn){Se._currentValue=cn}},_currentValue2:{get:function(){return Se._currentValue2},set:function(cn){Se._currentValue2=cn}},_threadCount:{get:function(){return Se._threadCount},set:function(cn){Se._threadCount=cn}},Consumer:{get:function(){return we||(we=!0,et("Rendering is not supported and will be removed in a future major release. Did you mean to render instead?")),Se.Consumer}}}),Se.Consumer=Cn}return Se._currentRenderer=null,Se._currentRenderer2=null,Se}function xt(W){var he={$$typeof:ye,_ctor:W,_status:-1,_result:null};{var Se,we;Object.defineProperties(he,{defaultProps:{configurable:!0,get:function(){return Se},set:function(tt){et("React.lazy(...): It is not supported to assign `defaultProps` to a lazy component import. Either specify them where the component is defined, or create a wrapping component around it."),Se=tt,Object.defineProperty(he,"defaultProps",{enumerable:!0})}},propTypes:{configurable:!0,get:function(){return we},set:function(tt){et("React.lazy(...): It is not supported to assign `propTypes` to a lazy component import. Either specify them where the component is defined, or create a wrapping component around it."),we=tt,Object.defineProperty(he,"propTypes",{enumerable:!0})}}})}return he}function Li(W){return W!=null&&W.$$typeof===de?et("forwardRef requires a render function but received a `memo` component. Instead of forwardRef(memo(...)), use memo(forwardRef(...))."):typeof W!="function"?et("forwardRef requires a render function but was given %s.",W===null?"null":typeof W):W.length!==0&&W.length!==2&&et("forwardRef render functions accept exactly two parameters: props and ref. %s",W.length===1?"Did you forget to use the ref parameter?":"Any additional parameter will be undefined."),W!=null&&(W.defaultProps!=null||W.propTypes!=null)&&et("forwardRef render functions do not support propTypes or defaultProps. Did you accidentally pass a React component?"),{$$typeof:z,render:W}}function di(W){return typeof W=="string"||typeof W=="function"||W===O||W===U||W===A||W===M||W===Q||W===v||typeof W=="object"&&W!==null&&(W.$$typeof===ye||W.$$typeof===de||W.$$typeof===T||W.$$typeof===P||W.$$typeof===z||W.$$typeof===ae||W.$$typeof===Me||W.$$typeof===fe||W.$$typeof===le)}function z0(W,he){return di(W)||et("memo: The first argument must be a component. Instead received: %s",W===null?"null":typeof W),{$$typeof:de,type:W,compare:he===void 0?null:he}}function ti(){var W=Fe.current;if(W===null)throw Error(`Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: +1. You might have mismatching versions of React and the renderer (such as React DOM) +2. You might be breaking the Rules of Hooks +3. You might have more than one copy of React in the same app +See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.`);return W}function bu(W,he){var Se=ti();if(he!==void 0&&et("useContext() second argument is reserved for future use in React. Passing it is not supported. You passed: %s.%s",he,typeof he=="number"&&Array.isArray(arguments[2])?` + +Did you call array.map(useContext)? Calling Hooks inside a loop is not supported. Learn more at https://fb.me/rules-of-hooks`:""),W._context!==void 0){var we=W._context;we.Consumer===W?et("Calling useContext(Context.Consumer) is not supported, may cause bugs, and will be removed in a future major release. Did you mean to call useContext(Context) instead?"):we.Provider===W&&et("Calling useContext(Context.Provider) is not supported. Did you mean to call useContext(Context) instead?")}return Se.useContext(W,he)}function Ko(W){var he=ti();return he.useState(W)}function Dr(W,he,Se){var we=ti();return we.useReducer(W,he,Se)}function ro(W){var he=ti();return he.useRef(W)}function Pu(W,he){var Se=ti();return Se.useEffect(W,he)}function xo(W,he){var Se=ti();return Se.useLayoutEffect(W,he)}function xl(W,he){var Se=ti();return Se.useCallback(W,he)}function Tn(W,he){var Se=ti();return Se.useMemo(W,he)}function tl(W,he,Se){var we=ti();return we.useImperativeHandle(W,he,Se)}function io(W,he){{var Se=ti();return Se.useDebugValue(W,he)}}var Ro;Ro=!1;function mu(){if(ot.current){var W=Kt(ot.current.type);if(W)return` + +Check the render method of \``+W+"`."}return""}function Ao(W){if(W!==void 0){var he=W.fileName.replace(/^.*[\\\/]/,""),Se=W.lineNumber;return` + +Check your code at `+he+":"+Se+"."}return""}function it(W){return W!=null?Ao(W.__source):""}var Dt={};function mn(W){var he=mu();if(!he){var Se=typeof W=="string"?W:W.displayName||W.name;Se&&(he=` + +Check the top-level render call using <`+Se+">.")}return he}function vr(W,he){if(!(!W._store||W._store.validated||W.key!=null)){W._store.validated=!0;var Se=mn(he);if(!Dt[Se]){Dt[Se]=!0;var we="";W&&W._owner&&W._owner!==ot.current&&(we=" It was passed a child from "+Kt(W._owner.type)+"."),oe(W),et('Each child in a list should have a unique "key" prop.%s%s See https://fb.me/react-warning-keys for more information.',Se,we),oe(null)}}}function ni(W,he){if(typeof W=="object"){if(Array.isArray(W))for(var Se=0;Se",tt=" Did you accidentally export a JSX literal instead of a component?"):cn=typeof W,et("React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s",cn,tt)}var In=Kr.apply(this,arguments);if(In==null)return In;if(we)for(var Ur=2;Ur{"use strict";process.env.NODE_ENV==="production"?YD.exports=j5():YD.exports=Y5()});var X5=re((Qne,K5)=>{var KK=ra(),XK=function(){return KK.Date.now()};K5.exports=XK});var J5=re((Jne,Q5)=>{var QK=/\s/;function JK(u){for(var l=u.length;l--&&QK.test(u.charAt(l)););return l}Q5.exports=JK});var $5=re((Zne,Z5)=>{var ZK=J5(),$K=/^\s+/;function eX(u){return u&&u.slice(0,ZK(u)+1).replace($K,"")}Z5.exports=eX});var r9=re(($ne,n9)=>{var tX=$5(),e9=vf(),nX=yh(),t9=0/0,rX=/^[-+]0x[0-9a-f]+$/i,iX=/^0b[01]+$/i,oX=/^0o[0-7]+$/i,uX=parseInt;function lX(u){if(typeof u=="number")return u;if(nX(u))return t9;if(e9(u)){var l=typeof u.valueOf=="function"?u.valueOf():u;u=e9(l)?l+"":l}if(typeof u!="string")return u===0?u:+u;u=tX(u);var c=iX.test(u);return c||oX.test(u)?uX(u.slice(2),c?2:8):rX.test(u)?t9:+u}n9.exports=lX});var u9=re((ere,o9)=>{var aX=vf(),KD=X5(),i9=r9(),sX="Expected a function",fX=Math.max,cX=Math.min;function dX(u,l,c){var p,_,t,O,M,A,T=0,P=!1,U=!1,z=!0;if(typeof u!="function")throw new TypeError(sX);l=i9(l)||0,aX(c)&&(P=!!c.leading,U="maxWait"in c,t=U?fX(i9(c.maxWait)||0,l):t,z="trailing"in c?!!c.trailing:z);function Q(Z){var Ae=p,Fe=_;return p=_=void 0,T=Z,O=u.apply(Fe,Ae),O}function v(Z){return T=Z,M=setTimeout(le,l),P?Q(Z):O}function de(Z){var Ae=Z-A,Fe=Z-T,He=l-Ae;return U?cX(He,t-Fe):He}function ye(Z){var Ae=Z-A,Fe=Z-T;return A===void 0||Ae>=l||Ae<0||U&&Fe>=t}function le(){var Z=KD();if(ye(Z))return ae(Z);M=setTimeout(le,de(Z))}function ae(Z){return M=void 0,z&&p?Q(Z):(p=_=void 0,O)}function Me(){M!==void 0&&clearTimeout(M),T=0,p=A=_=M=void 0}function fe(){return M===void 0?O:ae(KD())}function pe(){var Z=KD(),Ae=ye(Z);if(p=arguments,_=this,A=Z,Ae){if(M===void 0)return v(A);if(U)return clearTimeout(M),M=setTimeout(le,l),Q(A)}return M===void 0&&(M=setTimeout(le,l)),O}return pe.cancel=Me,pe.flush=fe,pe}o9.exports=dX});var a9=re((tre,l9)=>{var pX=u9(),hX=vf(),vX="Expected a function";function mX(u,l,c){var p=!0,_=!0;if(typeof u!="function")throw new TypeError(vX);return hX(c)&&(p="leading"in c?!!c.leading:p,_="trailing"in c?!!c.trailing:_),pX(u,l,{leading:p,maxWait:l,trailing:_})}l9.exports=mX});var QD=re((nre,XD)=>{"use strict";var Fr=XD.exports;XD.exports.default=Fr;var yi="\x1B[",Sh="\x1B]",G2="\x07",Xy=";",s9=process.env.TERM_PROGRAM==="Apple_Terminal";Fr.cursorTo=(u,l)=>{if(typeof u!="number")throw new TypeError("The `x` argument is required");return typeof l!="number"?yi+(u+1)+"G":yi+(l+1)+";"+(u+1)+"H"};Fr.cursorMove=(u,l)=>{if(typeof u!="number")throw new TypeError("The `x` argument is required");let c="";return u<0?c+=yi+-u+"D":u>0&&(c+=yi+u+"C"),l<0?c+=yi+-l+"A":l>0&&(c+=yi+l+"B"),c};Fr.cursorUp=(u=1)=>yi+u+"A";Fr.cursorDown=(u=1)=>yi+u+"B";Fr.cursorForward=(u=1)=>yi+u+"C";Fr.cursorBackward=(u=1)=>yi+u+"D";Fr.cursorLeft=yi+"G";Fr.cursorSavePosition=s9?"\x1B7":yi+"s";Fr.cursorRestorePosition=s9?"\x1B8":yi+"u";Fr.cursorGetPosition=yi+"6n";Fr.cursorNextLine=yi+"E";Fr.cursorPrevLine=yi+"F";Fr.cursorHide=yi+"?25l";Fr.cursorShow=yi+"?25h";Fr.eraseLines=u=>{let l="";for(let c=0;c[Sh,"8",Xy,Xy,l,G2,u,Sh,"8",Xy,Xy,G2].join("");Fr.image=(u,l={})=>{let c=`${Sh}1337;File=inline=1`;return l.width&&(c+=`;width=${l.width}`),l.height&&(c+=`;height=${l.height}`),l.preserveAspectRatio===!1&&(c+=";preserveAspectRatio=0"),c+":"+u.toString("base64")+G2};Fr.iTerm={setCwd:(u=process.cwd())=>`${Sh}50;CurrentDir=${u}${G2}`,annotation:(u,l={})=>{let c=`${Sh}1337;`,p=typeof l.x<"u",_=typeof l.y<"u";if((p||_)&&!(p&&_&&typeof l.length<"u"))throw new Error("`x`, `y` and `length` must be defined when `x` or `y` is defined");return u=u.replace(/\|/g,""),c+=l.isHidden?"AddHiddenAnnotation=":"AddAnnotation=",l.length>0?c+=(p?[u,l.length,l.x,l.y]:[l.length,u]).join("|"):c+=u,c+G2}}});var c9=re((rre,JD)=>{"use strict";var f9=(u,l)=>{for(let c of Reflect.ownKeys(l))Object.defineProperty(u,c,Object.getOwnPropertyDescriptor(l,c));return u};JD.exports=f9;JD.exports.default=f9});var p9=re((ire,Jy)=>{"use strict";var yX=c9(),Qy=new WeakMap,d9=(u,l={})=>{if(typeof u!="function")throw new TypeError("Expected a function");let c,p=0,_=u.displayName||u.name||"",t=function(...O){if(Qy.set(t,++p),p===1)c=u.apply(this,O),u=null;else if(l.throw===!0)throw new Error(`Function \`${_}\` can only be called once`);return c};return yX(t,u),Qy.set(t,p),t};Jy.exports=d9;Jy.exports.default=d9;Jy.exports.callCount=u=>{if(!Qy.has(u))throw new Error(`The given function \`${u.name}\` is not wrapped by the \`onetime\` package`);return Qy.get(u)}});var h9=re((ore,Zy)=>{Zy.exports=["SIGABRT","SIGALRM","SIGHUP","SIGINT","SIGTERM"];process.platform!=="win32"&&Zy.exports.push("SIGVTALRM","SIGXCPU","SIGXFSZ","SIGUSR2","SIGTRAP","SIGSYS","SIGQUIT","SIGIOT");process.platform==="linux"&&Zy.exports.push("SIGIO","SIGPOLL","SIGPWR","SIGSTKFLT","SIGUNUSED")});var e3=re((ure,X2)=>{var $i=global.process,o1=function(u){return u&&typeof u=="object"&&typeof u.removeListener=="function"&&typeof u.emit=="function"&&typeof u.reallyExit=="function"&&typeof u.listeners=="function"&&typeof u.kill=="function"&&typeof u.pid=="number"&&typeof u.on=="function"};o1($i)?(v9=Kn("assert"),Y2=h9(),m9=/^win/i.test($i.platform),Th=Kn("events"),typeof Th!="function"&&(Th=Th.EventEmitter),$i.__signal_exit_emitter__?Eo=$i.__signal_exit_emitter__:(Eo=$i.__signal_exit_emitter__=new Th,Eo.count=0,Eo.emitted={}),Eo.infinite||(Eo.setMaxListeners(1/0),Eo.infinite=!0),X2.exports=function(u,l){if(!o1(global.process))return function(){};v9.equal(typeof u,"function","a callback must be provided for exit handler"),K2===!1&&ZD();var c="exit";l&&l.alwaysLast&&(c="afterexit");var p=function(){Eo.removeListener(c,u),Eo.listeners("exit").length===0&&Eo.listeners("afterexit").length===0&&$y()};return Eo.on(c,u),p},$y=function(){!K2||!o1(global.process)||(K2=!1,Y2.forEach(function(l){try{$i.removeListener(l,eg[l])}catch{}}),$i.emit=tg,$i.reallyExit=$D,Eo.count-=1)},X2.exports.unload=$y,u1=function(l,c,p){Eo.emitted[l]||(Eo.emitted[l]=!0,Eo.emit(l,c,p))},eg={},Y2.forEach(function(u){eg[u]=function(){if(!!o1(global.process)){var c=$i.listeners(u);c.length===Eo.count&&($y(),u1("exit",null,u),u1("afterexit",null,u),m9&&u==="SIGHUP"&&(u="SIGINT"),$i.kill($i.pid,u))}}}),X2.exports.signals=function(){return Y2},K2=!1,ZD=function(){K2||!o1(global.process)||(K2=!0,Eo.count+=1,Y2=Y2.filter(function(l){try{return $i.on(l,eg[l]),!0}catch{return!1}}),$i.emit=g9,$i.reallyExit=y9)},X2.exports.load=ZD,$D=$i.reallyExit,y9=function(l){!o1(global.process)||($i.exitCode=l||0,u1("exit",$i.exitCode,null),u1("afterexit",$i.exitCode,null),$D.call($i,$i.exitCode))},tg=$i.emit,g9=function(l,c){if(l==="exit"&&o1(global.process)){c!==void 0&&($i.exitCode=c);var p=tg.apply(this,arguments);return u1("exit",$i.exitCode,null),u1("afterexit",$i.exitCode,null),p}else return tg.apply(this,arguments)}):X2.exports=function(){return function(){}};var v9,Y2,m9,Th,Eo,$y,u1,eg,K2,ZD,$D,y9,tg,g9});var E9=re((lre,_9)=>{"use strict";var gX=p9(),_X=e3();_9.exports=gX(()=>{_X(()=>{process.stderr.write("\x1B[?25h")},{alwaysLast:!0})})});var t3=re(Q2=>{"use strict";var EX=E9(),ng=!1;Q2.show=(u=process.stderr)=>{!u.isTTY||(ng=!1,u.write("\x1B[?25h"))};Q2.hide=(u=process.stderr)=>{!u.isTTY||(EX(),ng=!0,u.write("\x1B[?25l"))};Q2.toggle=(u,l)=>{u!==void 0&&(ng=u),ng?Q2.show(l):Q2.hide(l)}});var T9=re(Ch=>{"use strict";var S9=Ch&&Ch.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(Ch,"__esModule",{value:!0});var D9=S9(QD()),w9=S9(t3()),DX=(u,{showCursor:l=!1}={})=>{let c=0,p="",_=!1,t=O=>{!l&&!_&&(w9.default.hide(),_=!0);let M=O+` +`;M!==p&&(p=M,u.write(D9.default.eraseLines(c)+M),c=M.split(` +`).length)};return t.clear=()=>{u.write(D9.default.eraseLines(c)),p="",c=0},t.done=()=>{p="",c=0,l||(w9.default.show(),_=!1)},t};Ch.default={create:DX}});var C9=re((fre,wX)=>{wX.exports=[{name:"AppVeyor",constant:"APPVEYOR",env:"APPVEYOR",pr:"APPVEYOR_PULL_REQUEST_NUMBER"},{name:"Azure Pipelines",constant:"AZURE_PIPELINES",env:"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI",pr:"SYSTEM_PULLREQUEST_PULLREQUESTID"},{name:"Bamboo",constant:"BAMBOO",env:"bamboo_planKey"},{name:"Bitbucket Pipelines",constant:"BITBUCKET",env:"BITBUCKET_COMMIT",pr:"BITBUCKET_PR_ID"},{name:"Bitrise",constant:"BITRISE",env:"BITRISE_IO",pr:"BITRISE_PULL_REQUEST"},{name:"Buddy",constant:"BUDDY",env:"BUDDY_WORKSPACE_ID",pr:"BUDDY_EXECUTION_PULL_REQUEST_ID"},{name:"Buildkite",constant:"BUILDKITE",env:"BUILDKITE",pr:{env:"BUILDKITE_PULL_REQUEST",ne:"false"}},{name:"CircleCI",constant:"CIRCLE",env:"CIRCLECI",pr:"CIRCLE_PULL_REQUEST"},{name:"Cirrus CI",constant:"CIRRUS",env:"CIRRUS_CI",pr:"CIRRUS_PR"},{name:"AWS CodeBuild",constant:"CODEBUILD",env:"CODEBUILD_BUILD_ARN"},{name:"Codeship",constant:"CODESHIP",env:{CI_NAME:"codeship"}},{name:"Drone",constant:"DRONE",env:"DRONE",pr:{DRONE_BUILD_EVENT:"pull_request"}},{name:"dsari",constant:"DSARI",env:"DSARI"},{name:"GitLab CI",constant:"GITLAB",env:"GITLAB_CI"},{name:"GoCD",constant:"GOCD",env:"GO_PIPELINE_LABEL"},{name:"Hudson",constant:"HUDSON",env:"HUDSON_URL"},{name:"Jenkins",constant:"JENKINS",env:["JENKINS_URL","BUILD_ID"],pr:{any:["ghprbPullId","CHANGE_ID"]}},{name:"Magnum CI",constant:"MAGNUM",env:"MAGNUM"},{name:"Netlify CI",constant:"NETLIFY",env:"NETLIFY_BUILD_BASE",pr:{env:"PULL_REQUEST",ne:"false"}},{name:"Sail CI",constant:"SAIL",env:"SAILCI",pr:"SAIL_PULL_REQUEST_NUMBER"},{name:"Semaphore",constant:"SEMAPHORE",env:"SEMAPHORE",pr:"PULL_REQUEST_NUMBER"},{name:"Shippable",constant:"SHIPPABLE",env:"SHIPPABLE",pr:{IS_PULL_REQUEST:"true"}},{name:"Solano CI",constant:"SOLANO",env:"TDDIUM",pr:"TDDIUM_PR_ID"},{name:"Strider CD",constant:"STRIDER",env:"STRIDER"},{name:"TaskCluster",constant:"TASKCLUSTER",env:["TASK_ID","RUN_ID"]},{name:"TeamCity",constant:"TEAMCITY",env:"TEAMCITY_VERSION"},{name:"Travis CI",constant:"TRAVIS",env:"TRAVIS",pr:{env:"TRAVIS_PULL_REQUEST",ne:"false"}}]});var A9=re(Dl=>{"use strict";var R9=C9(),Ds=process.env;Object.defineProperty(Dl,"_vendors",{value:R9.map(function(u){return u.constant})});Dl.name=null;Dl.isPR=null;R9.forEach(function(u){var l=Array.isArray(u.env)?u.env:[u.env],c=l.every(function(p){return x9(p)});if(Dl[u.constant]=c,c)switch(Dl.name=u.name,typeof u.pr){case"string":Dl.isPR=!!Ds[u.pr];break;case"object":"env"in u.pr?Dl.isPR=u.pr.env in Ds&&Ds[u.pr.env]!==u.pr.ne:"any"in u.pr?Dl.isPR=u.pr.any.some(function(p){return!!Ds[p]}):Dl.isPR=x9(u.pr);break;default:Dl.isPR=null}});Dl.isCI=!!(Ds.CI||Ds.CONTINUOUS_INTEGRATION||Ds.BUILD_NUMBER||Ds.RUN_ID||Dl.name);function x9(u){return typeof u=="string"?!!Ds[u]:Object.keys(u).every(function(l){return Ds[l]===u[l]})}});var O9=re((dre,k9)=>{"use strict";k9.exports=A9().isCI});var N9=re((pre,M9)=>{"use strict";var SX=u=>{let l=new Set;do for(let c of Reflect.ownKeys(u))l.add([u,c]);while((u=Reflect.getPrototypeOf(u))&&u!==Object.prototype);return l};M9.exports=(u,{include:l,exclude:c}={})=>{let p=_=>{let t=O=>typeof O=="string"?_===O:O.test(_);return l?l.some(t):c?!c.some(t):!0};for(let[_,t]of SX(u.constructor.prototype)){if(t==="constructor"||!p(t))continue;let O=Reflect.getOwnPropertyDescriptor(_,t);O&&typeof O.value=="function"&&(u[t]=u[t].bind(u))}return u}});var U9=re(ei=>{"use strict";Object.defineProperty(ei,"__esModule",{value:!0});var Z2,Ah,lg,ag,a3;typeof window>"u"||typeof MessageChannel!="function"?(J2=null,n3=null,r3=function(){if(J2!==null)try{var u=ei.unstable_now();J2(!0,u),J2=null}catch(l){throw setTimeout(r3,0),l}},F9=Date.now(),ei.unstable_now=function(){return Date.now()-F9},Z2=function(u){J2!==null?setTimeout(Z2,0,u):(J2=u,setTimeout(r3,0))},Ah=function(u,l){n3=setTimeout(u,l)},lg=function(){clearTimeout(n3)},ag=function(){return!1},a3=ei.unstable_forceFrameRate=function(){}):(rg=window.performance,i3=window.Date,L9=window.setTimeout,b9=window.clearTimeout,typeof console<"u"&&(P9=window.cancelAnimationFrame,typeof window.requestAnimationFrame!="function"&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),typeof P9!="function"&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")),typeof rg=="object"&&typeof rg.now=="function"?ei.unstable_now=function(){return rg.now()}:(I9=i3.now(),ei.unstable_now=function(){return i3.now()-I9}),xh=!1,Rh=null,ig=-1,o3=5,u3=0,ag=function(){return ei.unstable_now()>=u3},a3=function(){},ei.unstable_forceFrameRate=function(u){0>u||125ug(O,c))A!==void 0&&0>ug(A,O)?(u[p]=A,u[M]=c,p=M):(u[p]=O,u[t]=c,p=t);else if(A!==void 0&&0>ug(A,c))u[p]=A,u[M]=c,p=M;else break e}}return l}return null}function ug(u,l){var c=u.sortIndex-l.sortIndex;return c!==0?c:u.id-l.id}var Ia=[],pc=[],TX=1,Nu=null,hu=3,fg=!1,l1=!1,kh=!1;function cg(u){for(var l=ia(pc);l!==null;){if(l.callback===null)sg(pc);else if(l.startTime<=u)sg(pc),l.sortIndex=l.expirationTime,s3(Ia,l);else break;l=ia(pc)}}function f3(u){if(kh=!1,cg(u),!l1)if(ia(Ia)!==null)l1=!0,Z2(c3);else{var l=ia(pc);l!==null&&Ah(f3,l.startTime-u)}}function c3(u,l){l1=!1,kh&&(kh=!1,lg()),fg=!0;var c=hu;try{for(cg(l),Nu=ia(Ia);Nu!==null&&(!(Nu.expirationTime>l)||u&&!ag());){var p=Nu.callback;if(p!==null){Nu.callback=null,hu=Nu.priorityLevel;var _=p(Nu.expirationTime<=l);l=ei.unstable_now(),typeof _=="function"?Nu.callback=_:Nu===ia(Ia)&&sg(Ia),cg(l)}else sg(Ia);Nu=ia(Ia)}if(Nu!==null)var t=!0;else{var O=ia(pc);O!==null&&Ah(f3,O.startTime-l),t=!1}return t}finally{Nu=null,hu=c,fg=!1}}function B9(u){switch(u){case 1:return-1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var CX=a3;ei.unstable_ImmediatePriority=1;ei.unstable_UserBlockingPriority=2;ei.unstable_NormalPriority=3;ei.unstable_IdlePriority=5;ei.unstable_LowPriority=4;ei.unstable_runWithPriority=function(u,l){switch(u){case 1:case 2:case 3:case 4:case 5:break;default:u=3}var c=hu;hu=u;try{return l()}finally{hu=c}};ei.unstable_next=function(u){switch(hu){case 1:case 2:case 3:var l=3;break;default:l=hu}var c=hu;hu=l;try{return u()}finally{hu=c}};ei.unstable_scheduleCallback=function(u,l,c){var p=ei.unstable_now();if(typeof c=="object"&&c!==null){var _=c.delay;_=typeof _=="number"&&0<_?p+_:p,c=typeof c.timeout=="number"?c.timeout:B9(u)}else c=B9(u),_=p;return c=_+c,u={id:TX++,callback:l,priorityLevel:u,startTime:_,expirationTime:c,sortIndex:-1},_>p?(u.sortIndex=_,s3(pc,u),ia(Ia)===null&&u===ia(pc)&&(kh?lg():kh=!0,Ah(f3,_-p))):(u.sortIndex=c,s3(Ia,u),l1||fg||(l1=!0,Z2(c3))),u};ei.unstable_cancelCallback=function(u){u.callback=null};ei.unstable_wrapCallback=function(u){var l=hu;return function(){var c=hu;hu=l;try{return u.apply(this,arguments)}finally{hu=c}}};ei.unstable_getCurrentPriorityLevel=function(){return hu};ei.unstable_shouldYield=function(){var u=ei.unstable_now();cg(u);var l=ia(Ia);return l!==Nu&&Nu!==null&&l!==null&&l.callback!==null&&l.startTime<=u&&l.expirationTime{"use strict";process.env.NODE_ENV!=="production"&&function(){"use strict";Object.defineProperty(Lr,"__esModule",{value:!0});var u=!1,l=!1,c=!0,p,_,t,O,M;if(typeof window>"u"||typeof MessageChannel!="function"){var A=null,T=null,P=function(){if(A!==null)try{var it=Lr.unstable_now(),Dt=!0;A(Dt,it),A=null}catch(mn){throw setTimeout(P,0),mn}},U=Date.now();Lr.unstable_now=function(){return Date.now()-U},p=function(it){A!==null?setTimeout(p,0,it):(A=it,setTimeout(P,0))},_=function(it,Dt){T=setTimeout(it,Dt)},t=function(){clearTimeout(T)},O=function(){return!1},M=Lr.unstable_forceFrameRate=function(){}}else{var z=window.performance,Q=window.Date,v=window.setTimeout,de=window.clearTimeout;if(typeof console<"u"){var ye=window.requestAnimationFrame,le=window.cancelAnimationFrame;typeof ye!="function"&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),typeof le!="function"&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")}if(typeof z=="object"&&typeof z.now=="function")Lr.unstable_now=function(){return z.now()};else{var ae=Q.now();Lr.unstable_now=function(){return Q.now()-ae}}var Me=!1,fe=null,pe=-1,Z=5,Ae=0,Fe=300,He=!1;if(l&&navigator!==void 0&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0){var ot=navigator.scheduling;O=function(){var it=Lr.unstable_now();return it>=Ae?He||ot.isInputPending()?!0:it>=Fe:!1},M=function(){He=!0}}else O=function(){return Lr.unstable_now()>=Ae},M=function(){};Lr.unstable_forceFrameRate=function(it){if(it<0||it>125){console.error("forceFrameRate takes a positive int between 0 and 125, forcing framerates higher than 125 fps is not unsupported");return}it>0?Z=Math.floor(1e3/it):Z=5};var st=function(){if(fe!==null){var it=Lr.unstable_now();Ae=it+Z;var Dt=!0;try{var mn=fe(Dt,it);mn?Xe.postMessage(null):(Me=!1,fe=null)}catch(vr){throw Xe.postMessage(null),vr}}else Me=!1;He=!1},qe=new MessageChannel,Xe=qe.port2;qe.port1.onmessage=st,p=function(it){fe=it,Me||(Me=!0,Xe.postMessage(null))},_=function(it,Dt){pe=v(function(){it(Lr.unstable_now())},Dt)},t=function(){de(pe),pe=-1}}function Ie(it,Dt){var mn=it.length;it.push(Dt),Ye(it,Dt,mn)}function kt(it){var Dt=it[0];return Dt===void 0?null:Dt}function Kt(it){var Dt=it[0];if(Dt!==void 0){var mn=it.pop();return mn!==Dt&&(it[0]=mn,V(it,mn,0)),Dt}else return null}function Ye(it,Dt,mn){for(var vr=mn;;){var ni=Math.floor((vr-1)/2),mr=it[ni];if(mr!==void 0&&oe(mr,Dt)>0)it[ni]=Dt,it[vr]=mr,vr=ni;else return}}function V(it,Dt,mn){for(var vr=mn,ni=it.length;vrLn){if(Ln*=2,Ln>sr){console.error("Scheduler Profiling: Event log exceeded maximum size. Don't forget to call `stopLoggingProfilingEvents()`."),Xn();return}var mn=new Int32Array(Ln*4);mn.set(zt),Er=mn.buffer,zt=mn}zt.set(it,Dt)}}function br(){Ln=ir,Er=new ArrayBuffer(Ln*4),zt=new Int32Array(Er),p0=0}function Xn(){var it=Er;return Ln=0,Er=null,zt=null,p0=0,it}function Fu(it,Dt){c&&(Ot[wn]++,zt!==null&&Ai([B0,Dt*1e3,it.id,it.priorityLevel]))}function wo(it,Dt){c&&(Ot[Wn]=ve,Ot[w]=0,Ot[wn]--,zt!==null&&Ai([Do,Dt*1e3,it.id]))}function h0(it,Dt){c&&(Ot[wn]--,zt!==null&&Ai([Sl,Dt*1e3,it.id]))}function So(it,Dt){c&&(Ot[Wn]=ve,Ot[w]=0,Ot[wn]--,zt!==null&&Ai([wl,Dt*1e3,it.id]))}function hr(it,Dt){c&&(Xt++,Ot[Wn]=it.priorityLevel,Ot[w]=it.id,Ot[Ct]=Xt,zt!==null&&Ai([Tl,Dt*1e3,it.id,Xt]))}function To(it,Dt){c&&(Ot[Wn]=ve,Ot[w]=0,Ot[Ct]=0,zt!==null&&Ai([ua,Dt*1e3,it.id,Xt]))}function Co(it){c&&(pn++,zt!==null&&Ai([Rt,it*1e3,pn]))}function U0(it){c&&zt!==null&&Ai([Kr,it*1e3,pn])}var xi=1073741823,Wr=-1,Cl=250,Lu=5e3,F0=1e4,S0=xi,or=[],Pr=[],j0=1,Ir=!1,Ft=null,hn=et,Br=!1,Tr=!1,xt=!1;function Li(it){for(var Dt=kt(Pr);Dt!==null;){if(Dt.callback===null)Kt(Pr);else if(Dt.startTime<=it)Kt(Pr),Dt.sortIndex=Dt.expirationTime,Ie(or,Dt),c&&(Fu(Dt,it),Dt.isQueued=!0);else return;Dt=kt(Pr)}}function di(it){if(xt=!1,Li(it),!Tr)if(kt(or)!==null)Tr=!0,p(z0);else{var Dt=kt(Pr);Dt!==null&&_(di,Dt.startTime-it)}}function z0(it,Dt){c&&U0(Dt),Tr=!1,xt&&(xt=!1,t()),Br=!0;var mn=hn;try{if(c)try{return ti(it,Dt)}catch(mr){if(Ft!==null){var vr=Lr.unstable_now();So(Ft,vr),Ft.isQueued=!1}throw mr}else return ti(it,Dt)}finally{if(Ft=null,hn=mn,Br=!1,c){var ni=Lr.unstable_now();Co(ni)}}}function ti(it,Dt){var mn=Dt;for(Li(mn),Ft=kt(or);Ft!==null&&!(u&&Ir)&&!(Ft.expirationTime>mn&&(!it||O()));){var vr=Ft.callback;if(vr!==null){Ft.callback=null,hn=Ft.priorityLevel;var ni=Ft.expirationTime<=mn;hr(Ft,mn);var mr=vr(ni);mn=Lr.unstable_now(),typeof mr=="function"?(Ft.callback=mr,To(Ft,mn)):(c&&(wo(Ft,mn),Ft.isQueued=!1),Ft===kt(or)&&Kt(or)),Li(mn)}else Kt(or);Ft=kt(or)}if(Ft!==null)return!0;var bi=kt(Pr);return bi!==null&&_(di,bi.startTime-mn),!1}function bu(it,Dt){switch(it){case ee:case Oe:case et:case ct:case Lt:break;default:it=et}var mn=hn;hn=it;try{return Dt()}finally{hn=mn}}function Ko(it){var Dt;switch(hn){case ee:case Oe:case et:Dt=et;break;default:Dt=hn;break}var mn=hn;hn=Dt;try{return it()}finally{hn=mn}}function Dr(it){var Dt=hn;return function(){var mn=hn;hn=Dt;try{return it.apply(this,arguments)}finally{hn=mn}}}function ro(it){switch(it){case ee:return Wr;case Oe:return Cl;case Lt:return S0;case ct:return F0;case et:default:return Lu}}function Pu(it,Dt,mn){var vr=Lr.unstable_now(),ni,mr;if(typeof mn=="object"&&mn!==null){var bi=mn.delay;typeof bi=="number"&&bi>0?ni=vr+bi:ni=vr,mr=typeof mn.timeout=="number"?mn.timeout:ro(it)}else mr=ro(it),ni=vr;var v0=ni+mr,Xr={id:j0++,callback:Dt,priorityLevel:it,startTime:ni,expirationTime:v0,sortIndex:-1};return c&&(Xr.isQueued=!1),ni>vr?(Xr.sortIndex=ni,Ie(Pr,Xr),kt(or)===null&&Xr===kt(Pr)&&(xt?t():xt=!0,_(di,ni-vr))):(Xr.sortIndex=v0,Ie(or,Xr),c&&(Fu(Xr,vr),Xr.isQueued=!0),!Tr&&!Br&&(Tr=!0,p(z0))),Xr}function xo(){Ir=!0}function xl(){Ir=!1,!Tr&&!Br&&(Tr=!0,p(z0))}function Tn(){return kt(or)}function tl(it){if(c&&it.isQueued){var Dt=Lr.unstable_now();h0(it,Dt),it.isQueued=!1}it.callback=null}function io(){return hn}function Ro(){var it=Lr.unstable_now();Li(it);var Dt=kt(or);return Dt!==Ft&&Ft!==null&&Dt!==null&&Dt.callback!==null&&Dt.startTime<=it&&Dt.expirationTime{"use strict";process.env.NODE_ENV==="production"?d3.exports=U9():d3.exports=j9()});var z9=re((yre,Oh)=>{Oh.exports=function u(l){"use strict";var c=Eh(),p=fi(),_=dg();function t(y){for(var m="https://reactjs.org/docs/error-decoder.html?invariant="+y,C=1;Cj0||(y.current=Pr[j0],Pr[j0]=null,j0--)}function Ft(y,m){j0++,Pr[j0]=y.current,y.current=m}var hn={},Br={current:hn},Tr={current:!1},xt=hn;function Li(y,m){var C=y.type.contextTypes;if(!C)return hn;var N=y.stateNode;if(N&&N.__reactInternalMemoizedUnmaskedChildContext===m)return N.__reactInternalMemoizedMaskedChildContext;var L={},K;for(K in C)L[K]=m[K];return N&&(y=y.stateNode,y.__reactInternalMemoizedUnmaskedChildContext=m,y.__reactInternalMemoizedMaskedChildContext=L),L}function di(y){return y=y.childContextTypes,y!=null}function z0(y){Ir(Tr,y),Ir(Br,y)}function ti(y){Ir(Tr,y),Ir(Br,y)}function bu(y,m,C){if(Br.current!==hn)throw Error(t(168));Ft(Br,m,y),Ft(Tr,C,y)}function Ko(y,m,C){var N=y.stateNode;if(y=m.childContextTypes,typeof N.getChildContext!="function")return C;N=N.getChildContext();for(var L in N)if(!(L in y))throw Error(t(108,Fe(m)||"Unknown",L));return c({},C,{},N)}function Dr(y){var m=y.stateNode;return m=m&&m.__reactInternalMemoizedMergedChildContext||hn,xt=Br.current,Ft(Br,m,y),Ft(Tr,Tr.current,y),!0}function ro(y,m,C){var N=y.stateNode;if(!N)throw Error(t(169));C?(m=Ko(y,m,xt),N.__reactInternalMemoizedMergedChildContext=m,Ir(Tr,y),Ir(Br,y),Ft(Br,m,y)):Ir(Tr,y),Ft(Tr,C,y)}var Pu=_.unstable_runWithPriority,xo=_.unstable_scheduleCallback,xl=_.unstable_cancelCallback,Tn=_.unstable_shouldYield,tl=_.unstable_requestPaint,io=_.unstable_now,Ro=_.unstable_getCurrentPriorityLevel,mu=_.unstable_ImmediatePriority,Ao=_.unstable_UserBlockingPriority,it=_.unstable_NormalPriority,Dt=_.unstable_LowPriority,mn=_.unstable_IdlePriority,vr={},ni=tl!==void 0?tl:function(){},mr=null,bi=null,v0=!1,Xr=io(),T0=1e4>Xr?io:function(){return io()-Xr};function Rl(){switch(Ro()){case mu:return 99;case Ao:return 98;case it:return 97;case Dt:return 96;case mn:return 95;default:throw Error(t(332))}}function lt(y){switch(y){case 99:return mu;case 98:return Ao;case 97:return it;case 96:return Dt;case 95:return mn;default:throw Error(t(332))}}function oo(y,m){return y=lt(y),Pu(y,m)}function yu(y,m,C){return y=lt(y),xo(y,m,C)}function la(y){return mr===null?(mr=[y],bi=xo(mu,nl)):mr.push(y),vr}function e0(){if(bi!==null){var y=bi;bi=null,xl(y)}nl()}function nl(){if(!v0&&mr!==null){v0=!0;var y=0;try{var m=mr;oo(99,function(){for(;y=m&&(Fo=!0),y.firstContext=null)}function Bi(y,m){if(Pi!==y&&m!==!1&&m!==0)if((typeof m!="number"||m===1073741823)&&(Pi=y,m=1073741823),m={context:y,observedBits:m,next:null},Ur===null){if(In===null)throw Error(t(308));Ur=m,In.dependencies={expirationTime:0,firstContext:m,responders:null}}else Ur=Ur.next=m;return Wt?y._currentValue:y._currentValue2}var uo=!1;function r0(y){return{baseState:y,firstUpdate:null,lastUpdate:null,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function Ga(y){return{baseState:y.baseState,firstUpdate:y.firstUpdate,lastUpdate:y.lastUpdate,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function m0(y,m){return{expirationTime:y,suspenseConfig:m,tag:0,payload:null,callback:null,next:null,nextEffect:null}}function aa(y,m){y.lastUpdate===null?y.firstUpdate=y.lastUpdate=m:(y.lastUpdate.next=m,y.lastUpdate=m)}function H0(y,m){var C=y.alternate;if(C===null){var N=y.updateQueue,L=null;N===null&&(N=y.updateQueue=r0(y.memoizedState))}else N=y.updateQueue,L=C.updateQueue,N===null?L===null?(N=y.updateQueue=r0(y.memoizedState),L=C.updateQueue=r0(C.memoizedState)):N=y.updateQueue=Ga(L):L===null&&(L=C.updateQueue=Ga(N));L===null||N===L?aa(N,m):N.lastUpdate===null||L.lastUpdate===null?(aa(N,m),aa(L,m)):(aa(N,m),L.lastUpdate=m)}function xs(y,m){var C=y.updateQueue;C=C===null?y.updateQueue=r0(y.memoizedState):Ya(y,C),C.lastCapturedUpdate===null?C.firstCapturedUpdate=C.lastCapturedUpdate=m:(C.lastCapturedUpdate.next=m,C.lastCapturedUpdate=m)}function Ya(y,m){var C=y.alternate;return C!==null&&m===C.updateQueue&&(m=y.updateQueue=Ga(m)),m}function rl(y,m,C,N,L,K){switch(C.tag){case 1:return y=C.payload,typeof y=="function"?y.call(K,N,L):y;case 3:y.effectTag=y.effectTag&-4097|64;case 0:if(y=C.payload,L=typeof y=="function"?y.call(K,N,L):y,L==null)break;return c({},N,L);case 2:uo=!0}return N}function C0(y,m,C,N,L){uo=!1,m=Ya(y,m);for(var K=m.baseState,ie=null,dt=0,ft=m.firstUpdate,mt=K;ft!==null;){var Gn=ft.expirationTime;GnSr?(li=Fn,Fn=null):li=Fn.sibling;var cr=ki(Le,Fn,Ke[Sr],Nt);if(cr===null){Fn===null&&(Fn=li);break}y&&Fn&&cr.alternate===null&&m(Le,Fn),ke=K(cr,ke,Sr),Rr===null?yn=cr:Rr.sibling=cr,Rr=cr,Fn=li}if(Sr===Ke.length)return C(Le,Fn),yn;if(Fn===null){for(;SrSr?(li=Fn,Fn=null):li=Fn.sibling;var ji=ki(Le,Fn,cr.value,Nt);if(ji===null){Fn===null&&(Fn=li);break}y&&Fn&&ji.alternate===null&&m(Le,Fn),ke=K(ji,ke,Sr),Rr===null?yn=ji:Rr.sibling=ji,Rr=ji,Fn=li}if(cr.done)return C(Le,Fn),yn;if(Fn===null){for(;!cr.done;Sr++,cr=Ke.next())cr=f0(Le,cr.value,Nt),cr!==null&&(ke=K(cr,ke,Sr),Rr===null?yn=cr:Rr.sibling=cr,Rr=cr);return yn}for(Fn=N(Le,Fn);!cr.done;Sr++,cr=Ke.next())cr=b0(Fn,Le,Sr,cr.value,Nt),cr!==null&&(y&&cr.alternate!==null&&Fn.delete(cr.key===null?Sr:cr.key),ke=K(cr,ke,Sr),Rr===null?yn=cr:Rr.sibling=cr,Rr=cr);return y&&Fn.forEach(function(Nf){return m(Le,Nf)}),yn}return function(Le,ke,Ke,Nt){var yn=typeof Ke=="object"&&Ke!==null&&Ke.type===P&&Ke.key===null;yn&&(Ke=Ke.props.children);var Rr=typeof Ke=="object"&&Ke!==null;if(Rr)switch(Ke.$$typeof){case A:e:{for(Rr=Ke.key,yn=ke;yn!==null;){if(yn.key===Rr)if(yn.tag===7?Ke.type===P:yn.elementType===Ke.type){C(Le,yn.sibling),ke=L(yn,Ke.type===P?Ke.props.children:Ke.props,Nt),ke.ref=Ol(Le,yn,Ke),ke.return=Le,Le=ke;break e}else{C(Le,yn);break}else m(Le,yn);yn=yn.sibling}Ke.type===P?(ke=Uo(Ke.props.children,Le.mode,Nt,Ke.key),ke.return=Le,Le=ke):(Nt=kf(Ke.type,Ke.key,Ke.props,null,Le.mode,Nt),Nt.ref=Ol(Le,ke,Ke),Nt.return=Le,Le=Nt)}return ie(Le);case T:e:{for(yn=Ke.key;ke!==null;){if(ke.key===yn)if(ke.tag===4&&ke.stateNode.containerInfo===Ke.containerInfo&&ke.stateNode.implementation===Ke.implementation){C(Le,ke.sibling),ke=L(ke,Ke.children||[],Nt),ke.return=Le,Le=ke;break e}else{C(Le,ke);break}else m(Le,ke);ke=ke.sibling}ke=Is(Ke,Le.mode,Nt),ke.return=Le,Le=ke}return ie(Le)}if(typeof Ke=="string"||typeof Ke=="number")return Ke=""+Ke,ke!==null&&ke.tag===6?(C(Le,ke.sibling),ke=L(ke,Ke,Nt),ke.return=Le,Le=ke):(C(Le,ke),ke=Ps(Ke,Le.mode,Nt),ke.return=Le,Le=ke),ie(Le);if(x0(Ke))return wa(Le,ke,Ke,Nt);if(Z(Ke))return D0(Le,ke,Ke,Nt);if(Rr&&Uu(Le,Ke),typeof Ke>"u"&&!yn)switch(Le.tag){case 1:case 0:throw Le=Le.type,Error(t(152,Le.displayName||Le.name||"Component"))}return C(Le,ke)}}var B=b(!0),q=b(!1),Y={},_e={current:Y},se={current:Y},ge={current:Y};function G(y){if(y===Y)throw Error(t(174));return y}function De(y,m){Ft(ge,m,y),Ft(se,y,y),Ft(_e,Y,y),m=kt(m),Ir(_e,y),Ft(_e,m,y)}function je(y){Ir(_e,y),Ir(se,y),Ir(ge,y)}function nt(y){var m=G(ge.current),C=G(_e.current);m=Kt(C,y.type,m),C!==m&&(Ft(se,y,y),Ft(_e,m,y))}function ne(y){se.current===y&&(Ir(_e,y),Ir(se,y))}var Ne={current:0};function Je(y){for(var m=y;m!==null;){if(m.tag===13){var C=m.memoizedState;if(C!==null&&(C=C.dehydrated,C===null||hr(C)||To(C)))return m}else if(m.tag===19&&m.memoizedProps.revealOrder!==void 0){if((m.effectTag&64)!==0)return m}else if(m.child!==null){m.child.return=m,m=m.child;continue}if(m===y)break;for(;m.sibling===null;){if(m.return===null||m.return===y)return null;m=m.return}m.sibling.return=m.return,m=m.sibling}return null}function ut(y,m){return{responder:y,props:m}}var ht=O.ReactCurrentDispatcher,wt=O.ReactCurrentBatchConfig,Vt=0,bt=null,Pt=null,ln=null,jn=null,xn=null,Jn=null,nn=0,$n=null,y0=0,nr=!1,Ge=null,at=0;function ze(){throw Error(t(321))}function yt(y,m){if(m===null)return!1;for(var C=0;Cnn&&(nn=Gn,Za(nn))):(Rf(Gn,ft.suspenseConfig),K=ft.eagerReducer===y?ft.eagerState:y(K,ft.action)),ie=ft,ft=ft.next}while(ft!==null&&ft!==N);mt||(dt=ie,L=K),Se(K,m.memoizedState)||(Fo=!0),m.memoizedState=K,m.baseUpdate=dt,m.baseState=L,C.lastRenderedState=K}return[m.memoizedState,C.dispatch]}function W0(y){var m=An();return typeof y=="function"&&(y=y()),m.memoizedState=m.baseState=y,y=m.queue={last:null,dispatch:null,lastRenderedReducer:gi,lastRenderedState:y},y=y.dispatch=Nl.bind(null,bt,y),[m.memoizedState,y]}function V0(y){return i0(gi,y)}function Gi(y,m,C,N){return y={tag:y,create:m,destroy:C,deps:N,next:null},$n===null?($n={lastEffect:null},$n.lastEffect=y.next=y):(m=$n.lastEffect,m===null?$n.lastEffect=y.next=y:(C=m.next,m.next=y,y.next=C,$n.lastEffect=y)),y}function Yi(y,m,C,N){var L=An();y0|=y,L.memoizedState=Gi(m,C,void 0,N===void 0?null:N)}function gu(y,m,C,N){var L=Vn();N=N===void 0?null:N;var K=void 0;if(Pt!==null){var ie=Pt.memoizedState;if(K=ie.destroy,N!==null&&yt(N,ie.deps)){Gi(0,C,K,N);return}}y0|=y,L.memoizedState=Gi(m,C,K,N)}function Ml(y,m){return Yi(516,192,y,m)}function Cf(y,m){return gu(516,192,y,m)}function ju(y,m){if(typeof m=="function")return y=y(),m(y),function(){m(null)};if(m!=null)return y=y(),m.current=y,function(){m.current=null}}function As(){}function Oo(y,m){return An().memoizedState=[y,m===void 0?null:m],y}function ol(y,m){var C=Vn();m=m===void 0?null:m;var N=C.memoizedState;return N!==null&&m!==null&&yt(m,N[1])?N[0]:(C.memoizedState=[y,m],y)}function Nl(y,m,C){if(!(25>at))throw Error(t(301));var N=y.alternate;if(y===bt||N!==null&&N===bt)if(nr=!0,y={expirationTime:Vt,suspenseConfig:null,action:C,eagerReducer:null,eagerState:null,next:null},Ge===null&&(Ge=new Map),C=Ge.get(m),C===void 0)Ge.set(m,y);else{for(m=C;m.next!==null;)m=m.next;m.next=y}else{var L=E0(),K=il.suspense;L=On(L,y,K),K={expirationTime:L,suspenseConfig:K,action:C,eagerReducer:null,eagerState:null,next:null};var ie=m.last;if(ie===null)K.next=K;else{var dt=ie.next;dt!==null&&(K.next=dt),ie.next=K}if(m.last=K,y.expirationTime===0&&(N===null||N.expirationTime===0)&&(N=m.lastRenderedReducer,N!==null))try{var ft=m.lastRenderedState,mt=N(ft,C);if(K.eagerReducer=N,K.eagerState=mt,Se(mt,ft))return}catch{}finally{}a0(y,L)}}var Mo={readContext:Bi,useCallback:ze,useContext:ze,useEffect:ze,useImperativeHandle:ze,useLayoutEffect:ze,useMemo:ze,useReducer:ze,useRef:ze,useState:ze,useDebugValue:ze,useResponder:ze,useDeferredValue:ze,useTransition:ze},Fl={readContext:Bi,useCallback:Oo,useContext:Bi,useEffect:Ml,useImperativeHandle:function(y,m,C){return C=C!=null?C.concat([y]):null,Yi(4,36,ju.bind(null,m,y),C)},useLayoutEffect:function(y,m){return Yi(4,36,y,m)},useMemo:function(y,m){var C=An();return m=m===void 0?null:m,y=y(),C.memoizedState=[y,m],y},useReducer:function(y,m,C){var N=An();return m=C!==void 0?C(m):m,N.memoizedState=N.baseState=m,y=N.queue={last:null,dispatch:null,lastRenderedReducer:y,lastRenderedState:m},y=y.dispatch=Nl.bind(null,bt,y),[N.memoizedState,y]},useRef:function(y){var m=An();return y={current:y},m.memoizedState=y},useState:W0,useDebugValue:As,useResponder:ut,useDeferredValue:function(y,m){var C=W0(y),N=C[0],L=C[1];return Ml(function(){_.unstable_next(function(){var K=wt.suspense;wt.suspense=m===void 0?null:m;try{L(y)}finally{wt.suspense=K}})},[y,m]),N},useTransition:function(y){var m=W0(!1),C=m[0],N=m[1];return[Oo(function(L){N(!0),_.unstable_next(function(){var K=wt.suspense;wt.suspense=y===void 0?null:y;try{N(!1),L()}finally{wt.suspense=K}})},[y,C]),C]}},ul={readContext:Bi,useCallback:ol,useContext:Bi,useEffect:Cf,useImperativeHandle:function(y,m,C){return C=C!=null?C.concat([y]):null,gu(4,36,ju.bind(null,m,y),C)},useLayoutEffect:function(y,m){return gu(4,36,y,m)},useMemo:function(y,m){var C=Vn();m=m===void 0?null:m;var N=C.memoizedState;return N!==null&&m!==null&&yt(m,N[1])?N[0]:(y=y(),C.memoizedState=[y,m],y)},useReducer:i0,useRef:function(){return Vn().memoizedState},useState:V0,useDebugValue:As,useResponder:ut,useDeferredValue:function(y,m){var C=V0(y),N=C[0],L=C[1];return Cf(function(){_.unstable_next(function(){var K=wt.suspense;wt.suspense=m===void 0?null:m;try{L(y)}finally{wt.suspense=K}})},[y,m]),N},useTransition:function(y){var m=V0(!1),C=m[0],N=m[1];return[ol(function(L){N(!0),_.unstable_next(function(){var K=wt.suspense;wt.suspense=y===void 0?null:y;try{N(!1),L()}finally{wt.suspense=K}})},[y,C]),C]}},o0=null,Ki=null,kr=!1;function zu(y,m){var C=Bo(5,null,null,0);C.elementType="DELETED",C.type="DELETED",C.stateNode=m,C.return=y,C.effectTag=8,y.lastEffect!==null?(y.lastEffect.nextEffect=C,y.lastEffect=C):y.firstEffect=y.lastEffect=C}function Xo(y,m){switch(y.tag){case 5:return m=h0(m,y.type,y.pendingProps),m!==null?(y.stateNode=m,!0):!1;case 6:return m=So(m,y.pendingProps),m!==null?(y.stateNode=m,!0):!1;case 13:return!1;default:return!1}}function No(y){if(kr){var m=Ki;if(m){var C=m;if(!Xo(y,m)){if(m=Co(C),!m||!Xo(y,m)){y.effectTag=y.effectTag&-1025|2,kr=!1,o0=y;return}zu(o0,C)}o0=y,Ki=U0(m)}else y.effectTag=y.effectTag&-1025|2,kr=!1,o0=y}}function fa(y){for(y=y.return;y!==null&&y.tag!==5&&y.tag!==3&&y.tag!==13;)y=y.return;o0=y}function qu(y){if(!w||y!==o0)return!1;if(!kr)return fa(y),kr=!0,!1;var m=y.type;if(y.tag!==5||m!=="head"&&m!=="body"&&!et(m,y.memoizedProps))for(m=Ki;m;)zu(y,m),m=Co(m);if(fa(y),y.tag===13){if(!w)throw Error(t(316));if(y=y.memoizedState,y=y!==null?y.dehydrated:null,!y)throw Error(t(317));Ki=Cl(y)}else Ki=o0?Co(y.stateNode):null;return!0}function Xi(){w&&(Ki=o0=null,kr=!1)}var pi=O.ReactCurrentOwner,Fo=!1;function Qr(y,m,C,N){m.child=y===null?q(m,null,C,N):B(m,y.child,C,N)}function Or(y,m,C,N,L){C=C.render;var K=m.ref;return ko(m,L),N=It(y,m,C,N,K,L),y!==null&&!Fo?(m.updateQueue=y.updateQueue,m.effectTag&=-517,y.expirationTime<=L&&(y.expirationTime=0),Ui(y,m,L)):(m.effectTag|=1,Qr(y,m,N,L),m.child)}function ks(y,m,C,N,L,K){if(y===null){var ie=C.type;return typeof ie=="function"&&!Af(ie)&&ie.defaultProps===void 0&&C.compare===null&&C.defaultProps===void 0?(m.tag=15,m.type=ie,Os(y,m,ie,N,L,K)):(y=kf(C.type,null,N,null,m.mode,K),y.ref=m.ref,y.return=m,m.child=y)}return ie=y.child,Lm)&&ui.set(y,m)))}}function Q0(y,m){y.expirationTimey?m:y)}function s0(y){if(y.lastExpiredTime!==0)y.callbackExpirationTime=1073741823,y.callbackPriority=99,y.callbackNode=la(va.bind(null,y));else{var m=po(y),C=y.callbackNode;if(m===0)C!==null&&(y.callbackNode=null,y.callbackExpirationTime=0,y.callbackPriority=90);else{var N=E0();if(m===1073741823?N=99:m===1||m===2?N=95:(N=10*(1073741821-m)-10*(1073741821-N),N=0>=N?99:250>=N?98:5250>=N?97:95),C!==null){var L=y.callbackPriority;if(y.callbackExpirationTime===m&&L>=N)return;C!==vr&&xl(C)}y.callbackExpirationTime=m,y.callbackPriority=N,m=m===1073741823?la(va.bind(null,y)):yu(N,Po.bind(null,y),{timeout:10*(1073741821-m)-T0()}),y.callbackNode=m}}}function Po(y,m){if(hi=0,m)return m=E0(),es(y,m),s0(y),null;var C=po(y);if(C!==0){if(m=y.callbackNode,(an&(Ei|Di))!==er)throw Error(t(327));if(Bl(),y===te&&C===Te||sl(y,C),J!==null){var N=an;an|=Ei;var L=Pl(y);do try{E1();break}catch(dt){ma(y,dt)}while(1);if(t0(),an=N,L0.current=L,Ee===O0)throw m=Qe,sl(y,C),Da(y,C),s0(y),m;if(J===null)switch(L=y.finishedWork=y.current.alternate,y.finishedExpirationTime=C,N=Ee,te=null,N){case Vr:case O0:throw Error(t(345));case fr:es(y,2=C){y.lastPingedTime=C,sl(y,C);break}}if(K=po(y),K!==0&&K!==C)break;if(N!==0&&N!==C){y.lastPingedTime=N;break}y.timeoutHandle=Xt(Eu.bind(null,y),L);break}Eu(y);break;case _0:if(Da(y,C),N=y.lastSuspendedTime,C===N&&(y.nextKnownPendingLevel=_c(L)),Qt&&(L=y.lastPingedTime,L===0||L>=C)){y.lastPingedTime=C,sl(y,C);break}if(L=po(y),L!==0&&L!==C)break;if(N!==0&&N!==C){y.lastPingedTime=N;break}if(Mt!==1073741823?N=10*(1073741821-Mt)-T0():rt===1073741823?N=0:(N=10*(1073741821-rt)-5e3,L=T0(),C=10*(1073741821-C)-L,N=L-N,0>N&&(N=0),N=(120>N?120:480>N?480:1080>N?1080:1920>N?1920:3e3>N?3e3:4320>N?4320:1960*Ms(N/1960))-N,C=N?N=0:(L=ie.busyDelayMs|0,K=T0()-(10*(1073741821-K)-(ie.timeoutMs|0||5e3)),N=K<=L?0:L+N-K),10 component higher in the tree to provide a loading indicator or placeholder to display.`+or(L))}Ee!==M0&&(Ee=fr),K=_u(K,L),ft=N;do{switch(ft.tag){case 3:ie=K,ft.effectTag|=4096,ft.expirationTime=m;var ke=al(ft,ie,m);xs(ft,ke);break e;case 1:ie=K;var Ke=ft.type,Nt=ft.stateNode;if((ft.effectTag&64)===0&&(typeof Ke.getDerivedStateFromError=="function"||Nt!==null&&typeof Nt.componentDidCatch=="function"&&(zn===null||!zn.has(Nt)))){ft.effectTag|=4096,ft.expirationTime=m;var yn=ha(ft,ie,m);xs(ft,yn);break e}}ft=ft.return}while(ft!==null)}J=Il(J)}catch(Rr){m=Rr;continue}break}while(1)}function Pl(){var y=L0.current;return L0.current=Mo,y===null?Mo:y}function Rf(y,m){yJt&&(Jt=y)}function ld(){for(;J!==null;)J=D1(J)}function E1(){for(;J!==null&&!Tn();)J=D1(J)}function D1(y){var m=$a(y.alternate,y,Te);return y.memoizedProps=y.pendingProps,m===null&&(m=Il(y)),Qa.current=null,m}function Il(y){J=y;do{var m=J.alternate;if(y=J.return,(J.effectTag&2048)===0){e:{var C=m;m=J;var N=Te,L=m.pendingProps;switch(m.tag){case 2:break;case 16:break;case 15:case 0:break;case 1:di(m.type)&&z0(m);break;case 3:je(m),ti(m),L=m.stateNode,L.pendingContext&&(L.context=L.pendingContext,L.pendingContext=null),(C===null||C.child===null)&&qu(m)&&u0(m),wr(m);break;case 5:ne(m);var K=G(ge.current);if(N=m.type,C!==null&&m.stateNode!=null)Qi(C,m,N,L,K),C.ref!==m.ref&&(m.effectTag|=128);else if(L){if(C=G(_e.current),qu(m)){if(L=m,!w)throw Error(t(175));C=xi(L.stateNode,L.type,L.memoizedProps,K,C,L),L.updateQueue=C,C=C!==null,C&&u0(m)}else{var ie=oe(N,L,K,C,m);_i(ie,m,!1,!1),m.stateNode=ie,ee(ie,N,L,K,C)&&u0(m)}m.ref!==null&&(m.effectTag|=128)}else if(m.stateNode===null)throw Error(t(166));break;case 6:if(C&&m.stateNode!=null)dn(C,m,C.memoizedProps,L);else{if(typeof L!="string"&&m.stateNode===null)throw Error(t(166));if(C=G(ge.current),K=G(_e.current),qu(m)){if(C=m,!w)throw Error(t(176));(C=Wr(C.stateNode,C.memoizedProps,C))&&u0(m)}else m.stateNode=Lt(L,C,K,m)}break;case 11:break;case 13:if(Ir(Ne,m),L=m.memoizedState,(m.effectTag&64)!==0){m.expirationTime=N;break e}L=L!==null,K=!1,C===null?m.memoizedProps.fallback!==void 0&&qu(m):(N=C.memoizedState,K=N!==null,L||N===null||(N=C.child.sibling,N!==null&&(ie=m.firstEffect,ie!==null?(m.firstEffect=N,N.nextEffect=ie):(m.firstEffect=m.lastEffect=N,N.nextEffect=null),N.effectTag=8))),L&&!K&&(m.mode&2)!==0&&(C===null&&m.memoizedProps.unstable_avoidThisFallback!==!0||(Ne.current&1)!==0?Ee===Vr&&(Ee=l0):((Ee===Vr||Ee===l0)&&(Ee=_0),Jt!==0&&te!==null&&(Da(te,Te),C1(te,Jt)))),Wn&&L&&(m.effectTag|=4),Ot&&(L||K)&&(m.effectTag|=4);break;case 7:break;case 8:break;case 12:break;case 4:je(m),wr(m);break;case 10:Ii(m);break;case 9:break;case 14:break;case 17:di(m.type)&&z0(m);break;case 19:if(Ir(Ne,m),L=m.memoizedState,L===null)break;if(K=(m.effectTag&64)!==0,ie=L.rendering,ie===null){if(K)g0(L,!1);else if(Ee!==Vr||C!==null&&(C.effectTag&64)!==0)for(C=m.child;C!==null;){if(ie=Je(C),ie!==null){for(m.effectTag|=64,g0(L,!1),C=ie.updateQueue,C!==null&&(m.updateQueue=C,m.effectTag|=4),L.lastEffect===null&&(m.firstEffect=null),m.lastEffect=L.lastEffect,C=N,L=m.child;L!==null;)K=L,N=C,K.effectTag&=2,K.nextEffect=null,K.firstEffect=null,K.lastEffect=null,ie=K.alternate,ie===null?(K.childExpirationTime=0,K.expirationTime=N,K.child=null,K.memoizedProps=null,K.memoizedState=null,K.updateQueue=null,K.dependencies=null):(K.childExpirationTime=ie.childExpirationTime,K.expirationTime=ie.expirationTime,K.child=ie.child,K.memoizedProps=ie.memoizedProps,K.memoizedState=ie.memoizedState,K.updateQueue=ie.updateQueue,N=ie.dependencies,K.dependencies=N===null?null:{expirationTime:N.expirationTime,firstContext:N.firstContext,responders:N.responders}),L=L.sibling;Ft(Ne,Ne.current&1|2,m),m=m.child;break e}C=C.sibling}}else{if(!K)if(C=Je(ie),C!==null){if(m.effectTag|=64,K=!0,C=C.updateQueue,C!==null&&(m.updateQueue=C,m.effectTag|=4),g0(L,!0),L.tail===null&&L.tailMode==="hidden"&&!ie.alternate){m=m.lastEffect=L.lastEffect,m!==null&&(m.nextEffect=null);break}}else T0()>L.tailExpiration&&1L&&(L=N),ie>L&&(L=ie),K=K.sibling;C.childExpirationTime=L}if(m!==null)return m;y!==null&&(y.effectTag&2048)===0&&(y.firstEffect===null&&(y.firstEffect=J.firstEffect),J.lastEffect!==null&&(y.lastEffect!==null&&(y.lastEffect.nextEffect=J.firstEffect),y.lastEffect=J.lastEffect),1y?m:y}function Eu(y){var m=Rl();return oo(99,w1.bind(null,y,m)),null}function w1(y,m){do Bl();while(qr!==null);if((an&(Ei|Di))!==er)throw Error(t(327));var C=y.finishedWork,N=y.finishedExpirationTime;if(C===null)return null;if(y.finishedWork=null,y.finishedExpirationTime=0,C===y.current)throw Error(t(177));y.callbackNode=null,y.callbackExpirationTime=0,y.callbackPriority=90,y.nextKnownPendingLevel=0;var L=_c(C);if(y.firstPendingTime=L,N<=y.lastSuspendedTime?y.firstSuspendedTime=y.lastSuspendedTime=y.nextKnownPendingLevel=0:N<=y.firstSuspendedTime&&(y.firstSuspendedTime=N-1),N<=y.lastPingedTime&&(y.lastPingedTime=0),N<=y.lastExpiredTime&&(y.lastExpiredTime=0),y===te&&(J=te=null,Te=0),1=C?ur(y,m,C):(Ft(Ne,Ne.current&1,m),m=Ui(y,m,C),m!==null?m.sibling:null);Ft(Ne,Ne.current&1,m);break;case 19:if(N=m.childExpirationTime>=C,(y.effectTag&64)!==0){if(N)return zr(y,m,C);m.effectTag|=64}if(L=m.memoizedState,L!==null&&(L.rendering=null,L.tail=null),Ft(Ne,Ne.current,m),!N)return null}return Ui(y,m,C)}Fo=!1}}else Fo=!1;switch(m.expirationTime=0,m.tag){case 2:if(N=m.type,y!==null&&(y.alternate=null,m.alternate=null,m.effectTag|=2),y=m.pendingProps,L=Li(m,Br.current),ko(m,C),L=It(null,m,N,y,L,C),m.effectTag|=1,typeof L=="object"&&L!==null&&typeof L.render=="function"&&L.$$typeof===void 0){if(m.tag=1,Gt(),di(N)){var K=!0;Dr(m)}else K=!1;m.memoizedState=L.state!==null&&L.state!==void 0?L.state:null;var ie=N.getDerivedStateFromProps;typeof ie=="function"&&Bu(m,N,ie,y),L.updater=sa,m.stateNode=L,L._reactInternalFiber=m,kl(m,N,y,C),m=Jo(null,m,N,!0,K,C)}else m.tag=0,Qr(null,m,L,C),m=m.child;return m;case 16:if(L=m.elementType,y!==null&&(y.alternate=null,m.alternate=null,m.effectTag|=2),y=m.pendingProps,Ae(L),L._status!==1)throw L._result;switch(L=L._result,m.type=L,K=m.tag=$o(L),y=Cn(L,y),K){case 0:m=Ll(null,m,L,y,C);break;case 1:m=Qo(null,m,L,y,C);break;case 11:m=Or(null,m,L,y,C);break;case 14:m=ks(null,m,L,Cn(L.type,y),N,C);break;default:throw Error(t(306,L,""))}return m;case 0:return N=m.type,L=m.pendingProps,L=m.elementType===N?L:Cn(N,L),Ll(y,m,N,L,C);case 1:return N=m.type,L=m.pendingProps,L=m.elementType===N?L:Cn(N,L),Qo(y,m,N,L,C);case 3:if(Zo(m),N=m.updateQueue,N===null)throw Error(t(282));if(L=m.memoizedState,L=L!==null?L.element:null,C0(m,N,m.pendingProps,null,C),N=m.memoizedState.element,N===L)Xi(),m=Ui(y,m,C);else{if((L=m.stateNode.hydrate)&&(w?(Ki=U0(m.stateNode.containerInfo),o0=m,L=kr=!0):L=!1),L)for(C=q(m,null,N,C),m.child=C;C;)C.effectTag=C.effectTag&-3|1024,C=C.sibling;else Qr(y,m,N,C),Xi();m=m.child}return m;case 5:return nt(m),y===null&&No(m),N=m.type,L=m.pendingProps,K=y!==null?y.memoizedProps:null,ie=L.children,et(N,L)?ie=null:K!==null&&et(N,K)&&(m.effectTag|=16),G0(y,m),m.mode&4&&C!==1&&ct(N,L)?(m.expirationTime=m.childExpirationTime=1,m=null):(Qr(y,m,ie,C),m=m.child),m;case 6:return y===null&&No(m),null;case 13:return ur(y,m,C);case 4:return De(m,m.stateNode.containerInfo),N=m.pendingProps,y===null?m.child=B(m,null,N,C):Qr(y,m,N,C),m.child;case 11:return N=m.type,L=m.pendingProps,L=m.elementType===N?L:Cn(N,L),Or(y,m,N,L,C);case 7:return Qr(y,m,m.pendingProps,C),m.child;case 8:return Qr(y,m,m.pendingProps.children,C),m.child;case 12:return Qr(y,m,m.pendingProps.children,C),m.child;case 10:e:{if(N=m.type._context,L=m.pendingProps,ie=m.memoizedProps,K=L.value,n0(m,K),ie!==null){var dt=ie.value;if(K=Se(dt,K)?0:(typeof N._calculateChangedBits=="function"?N._calculateChangedBits(dt,K):1073741823)|0,K===0){if(ie.children===L.children&&!Tr.current){m=Ui(y,m,C);break e}}else for(dt=m.child,dt!==null&&(dt.return=m);dt!==null;){var ft=dt.dependencies;if(ft!==null){ie=dt.child;for(var mt=ft.firstContext;mt!==null;){if(mt.context===N&&(mt.observedBits&K)!==0){dt.tag===1&&(mt=m0(C,null),mt.tag=2,H0(dt,mt)),dt.expirationTime"u")return!1;var m=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(m.isDisabled||!m.supportsFiber)return!0;try{var C=m.inject(y);ya=function(N){try{m.onCommitFiberRoot(C,N,void 0,(N.current.effectTag&64)===64)}catch{}},ga=function(N){try{m.onCommitFiberUnmount(C,N)}catch{}}}catch{}return!0}function Ea(y,m,C,N){this.tag=y,this.key=C,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=m,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=N,this.effectTag=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.childExpirationTime=this.expirationTime=0,this.alternate=null}function Bo(y,m,C,N){return new Ea(y,m,C,N)}function Af(y){return y=y.prototype,!(!y||!y.isReactComponent)}function $o(y){if(typeof y=="function")return Af(y)?1:0;if(y!=null){if(y=y.$$typeof,y===ye)return 11;if(y===Me)return 14}return 2}function eu(y,m){var C=y.alternate;return C===null?(C=Bo(y.tag,m,y.key,y.mode),C.elementType=y.elementType,C.type=y.type,C.stateNode=y.stateNode,C.alternate=y,y.alternate=C):(C.pendingProps=m,C.effectTag=0,C.nextEffect=null,C.firstEffect=null,C.lastEffect=null),C.childExpirationTime=y.childExpirationTime,C.expirationTime=y.expirationTime,C.child=y.child,C.memoizedProps=y.memoizedProps,C.memoizedState=y.memoizedState,C.updateQueue=y.updateQueue,m=y.dependencies,C.dependencies=m===null?null:{expirationTime:m.expirationTime,firstContext:m.firstContext,responders:m.responders},C.sibling=y.sibling,C.index=y.index,C.ref=y.ref,C}function kf(y,m,C,N,L,K){var ie=2;if(N=y,typeof y=="function")Af(y)&&(ie=1);else if(typeof y=="string")ie=5;else e:switch(y){case P:return Uo(C.children,L,K,m);case de:ie=8,L|=7;break;case U:ie=8,L|=1;break;case z:return y=Bo(12,C,m,L|8),y.elementType=z,y.type=z,y.expirationTime=K,y;case le:return y=Bo(13,C,m,L),y.type=le,y.elementType=le,y.expirationTime=K,y;case ae:return y=Bo(19,C,m,L),y.elementType=ae,y.expirationTime=K,y;default:if(typeof y=="object"&&y!==null)switch(y.$$typeof){case Q:ie=10;break e;case v:ie=9;break e;case ye:ie=11;break e;case Me:ie=14;break e;case fe:ie=16,N=null;break e}throw Error(t(130,y==null?y:typeof y,""))}return m=Bo(ie,C,m,L),m.elementType=y,m.type=N,m.expirationTime=K,m}function Uo(y,m,C,N){return y=Bo(7,y,N,m),y.expirationTime=C,y}function Ps(y,m,C){return y=Bo(6,y,null,m),y.expirationTime=C,y}function Is(y,m,C){return m=Bo(4,y.children!==null?y.children:[],y.key,m),m.expirationTime=C,m.stateNode={containerInfo:y.containerInfo,pendingChildren:null,implementation:y.implementation},m}function T1(y,m,C){this.tag=m,this.current=null,this.containerInfo=y,this.pingCache=this.pendingChildren=null,this.finishedExpirationTime=0,this.finishedWork=null,this.timeoutHandle=Nn,this.pendingContext=this.context=null,this.hydrate=C,this.callbackNode=null,this.callbackPriority=90,this.lastExpiredTime=this.lastPingedTime=this.nextKnownPendingLevel=this.lastSuspendedTime=this.firstSuspendedTime=this.firstPendingTime=0}function Ec(y,m){var C=y.firstSuspendedTime;return y=y.lastSuspendedTime,C!==0&&C>=m&&y<=m}function Da(y,m){var C=y.firstSuspendedTime,N=y.lastSuspendedTime;Cm||C===0)&&(y.lastSuspendedTime=m),m<=y.lastPingedTime&&(y.lastPingedTime=0),m<=y.lastExpiredTime&&(y.lastExpiredTime=0)}function C1(y,m){m>y.firstPendingTime&&(y.firstPendingTime=m);var C=y.firstSuspendedTime;C!==0&&(m>=C?y.firstSuspendedTime=y.lastSuspendedTime=y.nextKnownPendingLevel=0:m>=y.lastSuspendedTime&&(y.lastSuspendedTime=m+1),m>y.nextKnownPendingLevel&&(y.nextKnownPendingLevel=m))}function es(y,m){var C=y.lastExpiredTime;(C===0||C>m)&&(y.lastExpiredTime=m)}function x1(y){var m=y._reactInternalFiber;if(m===void 0)throw typeof y.render=="function"?Error(t(188)):Error(t(268,Object.keys(y)));return y=qe(m),y===null?null:y.stateNode}function Of(y,m){y=y.memoizedState,y!==null&&y.dehydrated!==null&&y.retryTime{"use strict";Object.defineProperty(Ba,"__esModule",{value:!0});var xX=0;Ba.__interactionsRef=null;Ba.__subscriberRef=null;Ba.unstable_clear=function(u){return u()};Ba.unstable_getCurrent=function(){return null};Ba.unstable_getThreadID=function(){return++xX};Ba.unstable_trace=function(u,l,c){return c()};Ba.unstable_wrap=function(u){return u};Ba.unstable_subscribe=function(){};Ba.unstable_unsubscribe=function(){}});var H9=re(ci=>{"use strict";process.env.NODE_ENV!=="production"&&function(){"use strict";Object.defineProperty(ci,"__esModule",{value:!0});var u=!0,l=0,c=0,p=0;ci.__interactionsRef=null,ci.__subscriberRef=null,u&&(ci.__interactionsRef={current:new Set},ci.__subscriberRef={current:null});function _(ae){if(!u)return ae();var Me=ci.__interactionsRef.current;ci.__interactionsRef.current=new Set;try{return ae()}finally{ci.__interactionsRef.current=Me}}function t(){return u?ci.__interactionsRef.current:null}function O(){return++p}function M(ae,Me,fe){var pe=arguments.length>3&&arguments[3]!==void 0?arguments[3]:l;if(!u)return fe();var Z={__count:1,id:c++,name:ae,timestamp:Me},Ae=ci.__interactionsRef.current,Fe=new Set(Ae);Fe.add(Z),ci.__interactionsRef.current=Fe;var He=ci.__subscriberRef.current,ot;try{He!==null&&He.onInteractionTraced(Z)}finally{try{He!==null&&He.onWorkStarted(Fe,pe)}finally{try{ot=fe()}finally{ci.__interactionsRef.current=Ae;try{He!==null&&He.onWorkStopped(Fe,pe)}finally{Z.__count--,He!==null&&Z.__count===0&&He.onInteractionScheduledWorkCompleted(Z)}}}}return ot}function A(ae){var Me=arguments.length>1&&arguments[1]!==void 0?arguments[1]:l;if(!u)return ae;var fe=ci.__interactionsRef.current,pe=ci.__subscriberRef.current;pe!==null&&pe.onWorkScheduled(fe,Me),fe.forEach(function(Fe){Fe.__count++});var Z=!1;function Ae(){var Fe=ci.__interactionsRef.current;ci.__interactionsRef.current=fe,pe=ci.__subscriberRef.current;try{var He;try{pe!==null&&pe.onWorkStarted(fe,Me)}finally{try{He=ae.apply(void 0,arguments)}finally{ci.__interactionsRef.current=Fe,pe!==null&&pe.onWorkStopped(fe,Me)}}return He}finally{Z||(Z=!0,fe.forEach(function(ot){ot.__count--,pe!==null&&ot.__count===0&&pe.onInteractionScheduledWorkCompleted(ot)}))}}return Ae.cancel=function(){pe=ci.__subscriberRef.current;try{pe!==null&&pe.onWorkCanceled(fe,Me)}finally{fe.forEach(function(He){He.__count--,pe&&He.__count===0&&pe.onInteractionScheduledWorkCompleted(He)})}},Ae}var T=null;u&&(T=new Set);function P(ae){u&&(T.add(ae),T.size===1&&(ci.__subscriberRef.current={onInteractionScheduledWorkCompleted:Q,onInteractionTraced:z,onWorkCanceled:le,onWorkScheduled:v,onWorkStarted:de,onWorkStopped:ye}))}function U(ae){u&&(T.delete(ae),T.size===0&&(ci.__subscriberRef.current=null))}function z(ae){var Me=!1,fe=null;if(T.forEach(function(pe){try{pe.onInteractionTraced(ae)}catch(Z){Me||(Me=!0,fe=Z)}}),Me)throw fe}function Q(ae){var Me=!1,fe=null;if(T.forEach(function(pe){try{pe.onInteractionScheduledWorkCompleted(ae)}catch(Z){Me||(Me=!0,fe=Z)}}),Me)throw fe}function v(ae,Me){var fe=!1,pe=null;if(T.forEach(function(Z){try{Z.onWorkScheduled(ae,Me)}catch(Ae){fe||(fe=!0,pe=Ae)}}),fe)throw pe}function de(ae,Me){var fe=!1,pe=null;if(T.forEach(function(Z){try{Z.onWorkStarted(ae,Me)}catch(Ae){fe||(fe=!0,pe=Ae)}}),fe)throw pe}function ye(ae,Me){var fe=!1,pe=null;if(T.forEach(function(Z){try{Z.onWorkStopped(ae,Me)}catch(Ae){fe||(fe=!0,pe=Ae)}}),fe)throw pe}function le(ae,Me){var fe=!1,pe=null;if(T.forEach(function(Z){try{Z.onWorkCanceled(ae,Me)}catch(Ae){fe||(fe=!0,pe=Ae)}}),fe)throw pe}ci.unstable_clear=_,ci.unstable_getCurrent=t,ci.unstable_getThreadID=O,ci.unstable_trace=M,ci.unstable_wrap=A,ci.unstable_subscribe=P,ci.unstable_unsubscribe=U}()});var W9=re((Ere,p3)=>{"use strict";process.env.NODE_ENV==="production"?p3.exports=q9():p3.exports=H9()});var V9=re((Dre,Mh)=>{"use strict";process.env.NODE_ENV!=="production"&&(Mh.exports=function u(l){"use strict";var c=Eh(),p=fi(),_=GD(),t=dg(),O=W9(),M=0,A=1,T=2,P=3,U=4,z=5,Q=6,v=7,de=8,ye=9,le=10,ae=11,Me=12,fe=13,pe=14,Z=15,Ae=16,Fe=17,He=18,ot=19,st=20,qe=21,Xe=function(){};Xe=function(f,d){for(var g=arguments.length,S=new Array(g>2?g-2:0),x=2;x8)throw new Error("warningWithoutStack() currently supports at most 8 arguments.");if(!f){if(typeof console<"u"){var I=S.map(function($){return""+$});I.unshift("Warning: "+d),Function.prototype.apply.call(console.error,console,I)}try{var j=0,X="Warning: "+d.replace(/%s/g,function(){return S[j++]});throw new Error(X)}catch{}}};var Ie=Xe;function kt(f){return f._reactInternalFiber}function Kt(f,d){f._reactInternalFiber=d}var Ye=p.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;Ye.hasOwnProperty("ReactCurrentDispatcher")||(Ye.ReactCurrentDispatcher={current:null}),Ye.hasOwnProperty("ReactCurrentBatchConfig")||(Ye.ReactCurrentBatchConfig={suspense:null});var V=typeof Symbol=="function"&&Symbol.for,oe=V?Symbol.for("react.element"):60103,ve=V?Symbol.for("react.portal"):60106,ee=V?Symbol.for("react.fragment"):60107,Oe=V?Symbol.for("react.strict_mode"):60108,et=V?Symbol.for("react.profiler"):60114,ct=V?Symbol.for("react.provider"):60109,Lt=V?Symbol.for("react.context"):60110,Xt=V?Symbol.for("react.concurrent_mode"):60111,pn=V?Symbol.for("react.forward_ref"):60112,Nn=V?Symbol.for("react.suspense"):60113,Wt=V?Symbol.for("react.suspense_list"):60120,Ot=V?Symbol.for("react.memo"):60115,Wn=V?Symbol.for("react.lazy"):60116,w=V?Symbol.for("react.fundamental"):60117,Ct=V?Symbol.for("react.responder"):60118,wn=V?Symbol.for("react.scope"):60119,ir=typeof Symbol=="function"&&Symbol.iterator,sr="@@iterator";function Ln(f){if(f===null||typeof f!="object")return null;var d=ir&&f[ir]||f[sr];return typeof d=="function"?d:null}var Er=Ie;Er=function(f,d){if(!f){for(var g=Ye.ReactDebugCurrentFrame,S=g.getStackAddendum(),x=arguments.length,I=new Array(x>2?x-2:0),j=2;j import('./MyComponent'))`,S),f._status=Do,f._result=x}},function(S){f._status===B0&&(f._status=wl,f._result=S)})}}function ua(f,d,g){var S=d.displayName||d.name||"";return f.displayName||(S!==""?g+"("+S+")":g)}function Rt(f){if(f==null)return null;if(typeof f.tag=="number"&&Ie(!1,"Received an unexpected object in getComponentName(). This is likely a bug in React. Please file an issue."),typeof f=="function")return f.displayName||f.name||null;if(typeof f=="string")return f;switch(f){case ee:return"Fragment";case ve:return"Portal";case et:return"Profiler";case Oe:return"StrictMode";case Nn:return"Suspense";case Wt:return"SuspenseList"}if(typeof f=="object")switch(f.$$typeof){case Lt:return"Context.Consumer";case ct:return"Context.Provider";case pn:return ua(f,f.render,"ForwardRef");case Ot:return Rt(f.type);case Wn:{var d=f,g=Sl(d);if(g)return Rt(g);break}}return null}var Kr=0,Ai=1,br=2,Xn=4,Fu=6,wo=8,h0=16,So=32,hr=64,To=128,Co=256,U0=512,xi=1024,Wr=1028,Cl=932,Lu=2047,F0=2048,S0=4096,or=!0,Pr=!0,j0=!0,Ir=!0,Ft=!0,hn=!0,Br=!1,Tr=!1,xt=!1,Li=!1,di=!1,z0=!0,ti=!1,bu=!1,Ko=!1,Dr=!1,ro=!1,Pu=Ye.ReactCurrentOwner;function xo(f){var d=f,g=f;if(f.alternate)for(;d.return;)d=d.return;else{var S=d;do d=S,(d.effectTag&(br|xi))!==Kr&&(g=d.return),S=d.return;while(S)}return d.tag===P?g:null}function xl(f){return xo(f)===f}function Tn(f){{var d=Pu.current;if(d!==null&&d.tag===A){var g=d,S=g.stateNode;S._warnedAboutRefsInRender||Ie(!1,"%s is accessing isMounted inside its render() function. render() should be a pure function of props and state. It should never access something that requires stale data from the previous render, such as refs. Move this logic to componentDidMount and componentDidUpdate instead.",Rt(g.type)||"A component"),S._warnedAboutRefsInRender=!0}}var x=kt(f);return x?xo(x)===x:!1}function tl(f){if(xo(f)!==f)throw Error("Unable to find node on an unmounted component.")}function io(f){var d=f.alternate;if(!d){var g=xo(f);if(g===null)throw Error("Unable to find node on an unmounted component.");return g!==f?null:f}for(var S=f,x=d;;){var I=S.return;if(I===null)break;var j=I.alternate;if(j===null){var X=I.return;if(X!==null){S=x=X;continue}break}if(I.child===j.child){for(var $=I.child;$;){if($===S)return tl(I),f;if($===x)return tl(I),d;$=$.sibling}throw Error("Unable to find node on an unmounted component.")}if(S.return!==x.return)S=I,x=j;else{for(var Re=!1,Pe=I.child;Pe;){if(Pe===S){Re=!0,S=I,x=j;break}if(Pe===x){Re=!0,x=I,S=j;break}Pe=Pe.sibling}if(!Re){for(Pe=j.child;Pe;){if(Pe===S){Re=!0,S=j,x=I;break}if(Pe===x){Re=!0,x=j,S=I;break}Pe=Pe.sibling}if(!Re)throw Error("Child was not found in either parent set. This indicates a bug in React related to the return pointer. Please file an issue.")}}if(S.alternate!==x)throw Error("Return fibers should always be each others' alternates. This error is likely caused by a bug in React. Please file an issue.")}if(S.tag!==P)throw Error("Unable to find node on an unmounted component.");return S.stateNode.current===S?f:d}function Ro(f){var d=io(f);if(!d)return null;for(var g=d;;){if(g.tag===z||g.tag===Q)return g;if(g.child){g.child.return=g,g=g.child;continue}if(g===d)return null;for(;!g.sibling;){if(!g.return||g.return===d)return null;g=g.return}g.sibling.return=g.return,g=g.sibling}return null}function mu(f){var d=io(f);if(!d)return null;for(var g=d;;){if(g.tag===z||g.tag===Q||xt&&g.tag===st)return g;if(g.child&&g.tag!==U){g.child.return=g,g=g.child;continue}if(g===d)return null;for(;!g.sibling;){if(!g.return||g.return===d)return null;g=g.return}g.sibling.return=g.return,g=g.sibling}return null}var Ao=l.getPublicInstance,it=l.getRootHostContext,Dt=l.getChildHostContext,mn=l.prepareForCommit,vr=l.resetAfterCommit,ni=l.createInstance,mr=l.appendInitialChild,bi=l.finalizeInitialChildren,v0=l.prepareUpdate,Xr=l.shouldSetTextContent,T0=l.shouldDeprioritizeSubtree,Rl=l.createTextInstance,lt=l.setTimeout,oo=l.clearTimeout,yu=l.noTimeout,la=l.now,e0=l.isPrimaryRenderer,nl=l.warnsIfNotActing,q0=l.supportsMutation,W=l.supportsPersistence,he=l.supportsHydration,Se=l.mountResponderInstance,we=l.unmountResponderInstance,tt=l.getFundamentalComponentInstance,Cn=l.mountFundamentalComponent,cn=l.shouldUpdateFundamentalComponent,In=l.getInstanceFromNode,Ur=l.appendChild,Pi=l.appendChildToContainer,t0=l.commitTextUpdate,n0=l.commitMount,Ii=l.commitUpdate,jr=l.insertBefore,ko=l.insertInContainerBefore,Bi=l.removeChild,uo=l.removeChildFromContainer,r0=l.resetTextContent,Ga=l.hideInstance,m0=l.hideTextInstance,aa=l.unhideInstance,H0=l.unhideTextInstance,xs=l.updateFundamentalComponent,Ya=l.unmountFundamentalComponent,rl=l.cloneInstance,C0=l.createContainerChildSet,Sn=l.appendChildToContainerChildSet,Tf=l.finalizeContainerChildren,il=l.replaceContainerChildren,Iu=l.cloneHiddenInstance,Bu=l.cloneHiddenTextInstance,sa=l.cloneInstance,Rs=l.canHydrateInstance,Al=l.canHydrateTextInstance,Ka=l.canHydrateSuspenseInstance,kl=l.isSuspenseInstancePending,x0=l.isSuspenseInstanceFallback,Ol=l.registerSuspenseInstanceRetry,Uu=l.getNextHydratableSibling,b=l.getFirstHydratableChild,B=l.hydrateInstance,q=l.hydrateTextInstance,Y=l.hydrateSuspenseInstance,_e=l.getNextHydratableInstanceAfterSuspenseInstance,se=l.commitHydratedContainer,ge=l.commitHydratedSuspenseInstance,G=l.clearSuspenseBoundary,De=l.clearSuspenseBoundaryFromContainer,je=l.didNotMatchHydratedContainerTextInstance,nt=l.didNotMatchHydratedTextInstance,ne=l.didNotHydrateContainerInstance,Ne=l.didNotHydrateInstance,Je=l.didNotFindHydratableContainerInstance,ut=l.didNotFindHydratableContainerTextInstance,ht=l.didNotFindHydratableContainerSuspenseInstance,wt=l.didNotFindHydratableInstance,Vt=l.didNotFindHydratableTextInstance,bt=l.didNotFindHydratableSuspenseInstance,Pt=/^(.*)[\\\/]/,ln=function(f,d,g){var S="";if(d){var x=d.fileName,I=x.replace(Pt,"");if(/^index\./.test(I)){var j=x.match(Pt);if(j){var X=j[1];if(X){var $=X.replace(Pt,"");I=$+"/"+I}}}S=" (at "+I+":"+d.lineNumber+")"}else g&&(S=" (created by "+g+")");return` + in `+(f||"Unknown")+S},jn=Ye.ReactDebugCurrentFrame;function xn(f){switch(f.tag){case P:case U:case Q:case v:case le:case ye:return"";default:var d=f._debugOwner,g=f._debugSource,S=Rt(f.type),x=null;return d&&(x=Rt(d.type)),ln(S,g,x)}}function Jn(f){var d="",g=f;do d+=xn(g),g=g.return;while(g);return d}var nn=null,$n=null;function y0(){{if(nn===null)return null;var f=nn._debugOwner;if(f!==null&&typeof f<"u")return Rt(f.type)}return null}function nr(){return nn===null?"":Jn(nn)}function Ge(){jn.getCurrentStack=null,nn=null,$n=null}function at(f){jn.getCurrentStack=nr,nn=f,$n=null}function ze(f){$n=f}var yt="\u269B",It="\u26D4",Gt=typeof performance<"u"&&typeof performance.mark=="function"&&typeof performance.clearMarks=="function"&&typeof performance.measure=="function"&&typeof performance.clearMeasures=="function",An=null,Vn=null,gi=null,i0=!1,W0=!1,V0=!1,Gi=0,Yi=0,gu=new Set,Ml=function(f){return yt+" "+f},Cf=function(f,d){var g=d?It+" ":yt+" ",S=d?" Warning: "+d:"";return""+g+f+S},ju=function(f){performance.mark(Ml(f))},As=function(f){performance.clearMarks(Ml(f))},Oo=function(f,d,g){var S=Ml(d),x=Cf(f,g);try{performance.measure(x,S)}catch{}performance.clearMarks(S),performance.clearMeasures(x)},ol=function(f,d){return f+" (#"+d+")"},Nl=function(f,d,g){return g===null?f+" ["+(d?"update":"mount")+"]":f+"."+g},Mo=function(f,d){var g=Rt(f.type)||"Unknown",S=f._debugID,x=f.alternate!==null,I=Nl(g,x,d);if(i0&&gu.has(I))return!1;gu.add(I);var j=ol(I,S);return ju(j),!0},Fl=function(f,d){var g=Rt(f.type)||"Unknown",S=f._debugID,x=f.alternate!==null,I=Nl(g,x,d),j=ol(I,S);As(j)},ul=function(f,d,g){var S=Rt(f.type)||"Unknown",x=f._debugID,I=f.alternate!==null,j=Nl(S,I,d),X=ol(j,x);Oo(j,X,g)},o0=function(f){switch(f.tag){case P:case z:case Q:case U:case v:case le:case ye:case de:return!0;default:return!1}},Ki=function(){Vn!==null&&gi!==null&&Fl(gi,Vn),gi=null,Vn=null,V0=!1},kr=function(){for(var f=An;f;)f._debugIsCurrentlyTiming&&ul(f,null,null),f=f.return},zu=function(f){f.return!==null&&zu(f.return),f._debugIsCurrentlyTiming&&Mo(f,null)},Xo=function(){An!==null&&zu(An)};function No(){or&&Yi++}function fa(){or&&(i0&&(W0=!0),Vn!==null&&Vn!=="componentWillMount"&&Vn!=="componentWillReceiveProps"&&(V0=!0))}function qu(f){if(or){if(!Gt||o0(f)||(An=f,!Mo(f,null)))return;f._debugIsCurrentlyTiming=!0}}function Xi(f){if(or){if(!Gt||o0(f))return;f._debugIsCurrentlyTiming=!1,Fl(f,null)}}function pi(f){if(or){if(!Gt||o0(f)||(An=f.return,!f._debugIsCurrentlyTiming))return;f._debugIsCurrentlyTiming=!1,ul(f,null,null)}}function Fo(f){if(or){if(!Gt||o0(f)||(An=f.return,!f._debugIsCurrentlyTiming))return;f._debugIsCurrentlyTiming=!1;var d=f.tag===fe?"Rendering was suspended":"An error was thrown inside this error boundary";ul(f,null,d)}}function Qr(f,d){if(or){if(!Gt||(Ki(),!Mo(f,d)))return;gi=f,Vn=d}}function Or(){if(or){if(!Gt)return;if(Vn!==null&&gi!==null){var f=V0?"Scheduled a cascading update":null;ul(gi,Vn,f)}Vn=null,gi=null}}function ks(f){if(or){if(An=f,!Gt)return;Gi=0,ju("(React Tree Reconciliation)"),Xo()}}function Os(f,d){if(or){if(!Gt)return;var g=null;if(f!==null)if(f.tag===P)g="A top-level update interrupted the previous render";else{var S=Rt(f.type)||"Unknown";g="An update to "+S+" interrupted the previous render"}else Gi>1&&(g="There were cascading updates");Gi=0;var x=d?"(React Tree Reconciliation: Completed Root)":"(React Tree Reconciliation: Yielded)";kr(),Oo(x,"(React Tree Reconciliation)",g)}}function G0(){if(or){if(!Gt)return;i0=!0,W0=!1,gu.clear(),ju("(Committing Changes)")}}function Ll(){if(or){if(!Gt)return;var f=null;W0?f="Lifecycle hook scheduled a cascading update":Gi>0&&(f="Caused by a cascading update in earlier commit"),W0=!1,Gi++,i0=!1,gu.clear(),Oo("(Committing Changes)","(Committing Changes)",f)}}function Qo(){if(or){if(!Gt)return;Yi=0,ju("(Committing Snapshot Effects)")}}function Jo(){if(or){if(!Gt)return;var f=Yi;Yi=0,Oo("(Committing Snapshot Effects: "+f+" Total)","(Committing Snapshot Effects)",null)}}function Zo(){if(or){if(!Gt)return;Yi=0,ju("(Committing Host Effects)")}}function Y0(){if(or){if(!Gt)return;var f=Yi;Yi=0,Oo("(Committing Host Effects: "+f+" Total)","(Committing Host Effects)",null)}}function ur(){if(or){if(!Gt)return;Yi=0,ju("(Calling Lifecycle Methods)")}}function R0(){if(or){if(!Gt)return;var f=Yi;Yi=0,Oo("(Calling Lifecycle Methods: "+f+" Total)","(Calling Lifecycle Methods)",null)}}var lo=[],zr;zr=[];var Ui=-1;function u0(f){return{current:f}}function _i(f,d){if(Ui<0){Ie(!1,"Unexpected pop.");return}d!==zr[Ui]&&Ie(!1,"Unexpected Fiber popped."),f.current=lo[Ui],lo[Ui]=null,zr[Ui]=null,Ui--}function wr(f,d,g){Ui++,lo[Ui]=f.current,zr[Ui]=g,f.current=d}var Qi;Qi={};var dn={};Object.freeze(dn);var ao=u0(dn),g0=u0(!1),Xa=dn;function _u(f,d,g){return Dr?dn:g&&ri(d)?Xa:ao.current}function ca(f,d,g){if(!Dr){var S=f.stateNode;S.__reactInternalMemoizedUnmaskedChildContext=d,S.__reactInternalMemoizedMaskedChildContext=g}}function A0(f,d){if(Dr)return dn;var g=f.type,S=g.contextTypes;if(!S)return dn;var x=f.stateNode;if(x&&x.__reactInternalMemoizedUnmaskedChildContext===d)return x.__reactInternalMemoizedMaskedChildContext;var I={};for(var j in S)I[j]=d[j];{var X=Rt(g)||"Unknown";_(S,I,"context",X,nr)}return x&&ca(f,d,I),I}function da(){return Dr?!1:g0.current}function ri(f){if(Dr)return!1;var d=f.childContextTypes;return d!=null}function bl(f){Dr||(_i(g0,f),_i(ao,f))}function so(f){Dr||(_i(g0,f),_i(ao,f))}function Ji(f,d,g){if(!Dr){if(ao.current!==dn)throw Error("Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue.");wr(ao,d,f),wr(g0,g,f)}}function fo(f,d,g){if(Dr)return g;var S=f.stateNode,x=d.childContextTypes;if(typeof S.getChildContext!="function"){{var I=Rt(d)||"Unknown";Qi[I]||(Qi[I]=!0,Ie(!1,"%s.childContextTypes is specified but there is no getChildContext() method on the instance. You can either define getChildContext() on %s or remove childContextTypes from it.",I,I))}return g}var j;ze("getChildContext"),Qr(f,"getChildContext"),j=S.getChildContext(),Or(),ze(null);for(var X in j)if(!(X in x))throw Error((Rt(d)||"Unknown")+'.getChildContext(): key "'+X+'" is not defined in childContextTypes.');{var $=Rt(d)||"Unknown";_(x,j,"child context",$,nr)}return c({},g,{},j)}function ii(f){if(Dr)return!1;var d=f.stateNode,g=d&&d.__reactInternalMemoizedMergedChildContext||dn;return Xa=ao.current,wr(ao,g,f),wr(g0,g0.current,f),!0}function ll(f,d,g){if(!Dr){var S=f.stateNode;if(!S)throw Error("Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue.");if(g){var x=fo(f,d,Xa);S.__reactInternalMemoizedMergedChildContext=x,_i(g0,f),_i(ao,f),wr(ao,x,f),wr(g0,g,f)}else _i(g0,f),wr(g0,g,f)}}function Hu(f){if(Dr)return dn;if(!(xl(f)&&f.tag===A))throw Error("Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue.");var d=f;do{switch(d.tag){case P:return d.stateNode.context;case A:{var g=d.type;if(ri(g))return d.stateNode.__reactInternalMemoizedMergedChildContext;break}}d=d.return}while(d!==null);throw Error("Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue.")}var K0=1,co=2,Lo=t.unstable_runWithPriority,k0=t.unstable_scheduleCallback,bo=t.unstable_cancelCallback,pa=t.unstable_shouldYield,al=t.unstable_requestPaint,ha=t.unstable_now,Ms=t.unstable_getCurrentPriorityLevel,L0=t.unstable_ImmediatePriority,Qa=t.unstable_UserBlockingPriority,er=t.unstable_NormalPriority,X0=t.unstable_LowPriority,Ei=t.unstable_IdlePriority;if(hn&&!(O.__interactionsRef!=null&&O.__interactionsRef.current!=null))throw Error("It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling");var Di={},Vr=99,O0=98,fr=97,l0=96,_0=95,M0=90,an=pa,te=al!==void 0?al:function(){},J=null,Te=null,Ee=!1,Qe=ha(),rt=Qe<1e4?ha:function(){return ha()-Qe};function Mt(){switch(Ms()){case L0:return Vr;case Qa:return O0;case er:return fr;case X0:return l0;case Ei:return _0;default:throw Error("Unknown priority level.")}}function vn(f){switch(f){case Vr:return L0;case O0:return Qa;case fr:return er;case l0:return X0;case _0:return Ei;default:throw Error("Unknown priority level.")}}function Jt(f,d){var g=vn(f);return Lo(g,d)}function Qt(f,d,g){var S=vn(f);return k0(S,d,g)}function Zt(f){return J===null?(J=[f],Te=k0(L0,oi)):J.push(f),Di}function kn(f){f!==Di&&bo(f)}function Et(){if(Te!==null){var f=Te;Te=null,bo(f)}oi()}function oi(){if(!Ee&&J!==null){Ee=!0;var f=0;try{var d=!0,g=J;Jt(Vr,function(){for(;f1?d-1:0),S=1;S2?g-2:0),x=2;x0&&(Fs.forEach(function(vt){f.add(Rt(vt.type)||"Component"),Ea.add(vt.type)}),Fs=[]);var d=new Set;Ls.length>0&&(Ls.forEach(function(vt){d.add(Rt(vt.type)||"Component"),Ea.add(vt.type)}),Ls=[]);var g=new Set;$a.length>0&&($a.forEach(function(vt){g.add(Rt(vt.type)||"Component"),Ea.add(vt.type)}),$a=[]);var S=new Set;ya.length>0&&(ya.forEach(function(vt){S.add(Rt(vt.type)||"Component"),Ea.add(vt.type)}),ya=[]);var x=new Set;ga.length>0&&(ga.forEach(function(vt){x.add(Rt(vt.type)||"Component"),Ea.add(vt.type)}),ga=[]);var I=new Set;if(bs.length>0&&(bs.forEach(function(vt){I.add(Rt(vt.type)||"Component"),Ea.add(vt.type)}),bs=[]),d.size>0){var j=Io(d);Ie(!1,`Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-unsafe-component-lifecycles for details. + +* Move code with side effects to componentDidMount, and set initial state in the constructor. + +Please update the following components: %s`,j)}if(S.size>0){var X=Io(S);Ie(!1,`Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-unsafe-component-lifecycles for details. + +* Move data fetching code or side effects to componentDidUpdate. +* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state + +Please update the following components: %s`,X)}if(I.size>0){var $=Io(I);Ie(!1,`Using UNSAFE_componentWillUpdate in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-unsafe-component-lifecycles for details. + +* Move data fetching code or side effects to componentDidUpdate. + +Please update the following components: %s`,$)}if(f.size>0){var Re=Io(f);Bl(!1,`componentWillMount has been renamed, and is not recommended for use. See https://fb.me/react-unsafe-component-lifecycles for details. + +* Move code with side effects to componentDidMount, and set initial state in the constructor. +* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder. + +Please update the following components: %s`,Re)}if(g.size>0){var Pe=Io(g);Bl(!1,`componentWillReceiveProps has been renamed, and is not recommended for use. See https://fb.me/react-unsafe-component-lifecycles for details. + +* Move data fetching code or side effects to componentDidUpdate. +* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state +* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder. + +Please update the following components: %s`,Pe)}if(x.size>0){var Ze=Io(x);Bl(!1,`componentWillUpdate has been renamed, and is not recommended for use. See https://fb.me/react-unsafe-component-lifecycles for details. + +* Move data fetching code or side effects to componentDidUpdate. +* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder. + +Please update the following components: %s`,Ze)}};var Bo=new Map,Af=new Set;Du.recordLegacyContextWarning=function(f,d){var g=S1(f);if(g===null){Ie(!1,"Expected to find a StrictMode component in a strict mode tree. This error is likely caused by a bug in React. Please file an issue.");return}if(!Af.has(f.type)){var S=Bo.get(g);(f.type.contextTypes!=null||f.type.childContextTypes!=null||d!==null&&typeof d.getChildContext=="function")&&(S===void 0&&(S=[],Bo.set(g,S)),S.push(f))}},Du.flushLegacyContextWarning=function(){Bo.forEach(function(f,d){var g=new Set;f.forEach(function(I){g.add(Rt(I.type)||"Component"),Af.add(I.type)});var S=Io(g),x=Jn(d);Ie(!1,`Legacy context API has been detected within a strict-mode tree. + +The old API will be supported in all 16.x releases, but applications using it should migrate to the new version. + +Please update the following components: %s + +Learn more about this warning here: https://fb.me/react-legacy-context%s`,S,x)})},Du.discardPendingWarnings=function(){Fs=[],Ls=[],$a=[],ya=[],ga=[],bs=[],Bo=new Map}}var $o=null,eu=null,kf=function(f){$o=f};function Uo(f){{if($o===null)return f;var d=$o(f);return d===void 0?f:d.current}}function Ps(f){return Uo(f)}function Is(f){{if($o===null)return f;var d=$o(f);if(d===void 0){if(f!=null&&typeof f.render=="function"){var g=Uo(f.render);if(f.render!==g){var S={$$typeof:pn,render:g};return f.displayName!==void 0&&(S.displayName=f.displayName),S}}return f}return d.current}}function T1(f,d){{if($o===null)return!1;var g=f.elementType,S=d.type,x=!1,I=typeof S=="object"&&S!==null?S.$$typeof:null;switch(f.tag){case A:{typeof S=="function"&&(x=!0);break}case M:{(typeof S=="function"||I===Wn)&&(x=!0);break}case ae:{(I===pn||I===Wn)&&(x=!0);break}case pe:case Z:{(I===Ot||I===Wn)&&(x=!0);break}default:return!1}if(x){var j=$o(g);if(j!==void 0&&j===$o(S))return!0}return!1}}function Ec(f){{if($o===null||typeof WeakSet!="function")return;eu===null&&(eu=new WeakSet),eu.add(f)}}var Da=function(f,d){{if($o===null)return;var g=d.staleFamilies,S=d.updatedFamilies;fs(),kp(function(){es(f.current,S,g)})}},C1=function(f,d){{if(f.context!==dn)return;fs(),Mm(function(){ry(d,f,null,null)})}};function es(f,d,g){{var S=f.alternate,x=f.child,I=f.sibling,j=f.tag,X=f.type,$=null;switch(j){case M:case Z:case A:$=X;break;case ae:$=X.render;break;default:break}if($o===null)throw new Error("Expected resolveFamily to be set during hot reload.");var Re=!1,Pe=!1;if($!==null){var Ze=$o($);Ze!==void 0&&(g.has(Ze)?Pe=!0:d.has(Ze)&&(j===A?Pe=!0:Re=!0))}eu!==null&&(eu.has(f)||S!==null&&eu.has(S))&&(Pe=!0),Pe&&(f._debugNeedsRemount=!0),(Pe||Re)&&iu(f,On),x!==null&&!Pe&&es(x,d,g),I!==null&&es(I,d,g)}}var x1=function(f,d){{var g=new Set,S=new Set(d.map(function(x){return x.current}));return Of(f.current,S,g),g}};function Of(f,d,g){{var S=f.child,x=f.sibling,I=f.tag,j=f.type,X=null;switch(I){case M:case Z:case A:X=j;break;case ae:X=j.render;break;default:break}var $=!1;X!==null&&d.has(X)&&($=!0),$?Mf(f,g):S!==null&&Of(S,d,g),x!==null&&Of(x,d,g)}}function Mf(f,d){{var g=R1(f,d);if(g)return;for(var S=f;;){switch(S.tag){case z:d.add(S.stateNode);return;case U:d.add(S.stateNode.containerInfo);return;case P:d.add(S.stateNode.containerInfo);return}if(S.return===null)throw new Error("Expected to reach root first.");S=S.return}}}function R1(f,d){for(var g=f,S=!1;;){if(g.tag===z)S=!0,d.add(g.stateNode);else if(g.child!==null){g.child.return=g,g=g.child;continue}if(g===f)return S;for(;g.sibling===null;){if(g.return===null||g.return===f)return S;g=g.return}g.sibling.return=g.return,g=g.sibling}return!1}function wu(f,d){if(f&&f.defaultProps){var g=c({},d),S=f.defaultProps;for(var x in S)g[x]===void 0&&(g[x]=S[x]);return g}return d}function y(f){if(Tl(f),f._status!==Do)throw f._result;return f._result}var m=u0(null),C;C={};var N=null,L=null,K=null,ie=!1;function dt(){N=null,L=null,K=null,ie=!1}function ft(){ie=!0}function mt(){ie=!1}function Gn(f,d){var g=f.type._context;e0?(wr(m,g._currentValue,f),g._currentValue=d,g._currentRenderer===void 0||g._currentRenderer===null||g._currentRenderer===C||Ie(!1,"Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported."),g._currentRenderer=C):(wr(m,g._currentValue2,f),g._currentValue2=d,g._currentRenderer2===void 0||g._currentRenderer2===null||g._currentRenderer2===C||Ie(!1,"Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported."),g._currentRenderer2=C)}function f0(f){var d=m.current;_i(m,f);var g=f.type._context;e0?g._currentValue=d:g._currentValue2=d}function ki(f,d,g){if(Il(g,d))return 0;var S=typeof f._calculateChangedBits=="function"?f._calculateChangedBits(g,d):ui;return(S&ui)!==S&&zt(!1,"calculateChangedBits: Expected the return value to be a 31-bit integer. Instead received: %s",S),S|0}function b0(f,d){for(var g=f;g!==null;){var S=g.alternate;if(g.childExpirationTime=d&&op(),g.firstContext=null)}}function Le(f,d){if(ie&&zt(!1,"Context can only be read while React is rendering. In classes, you can read it in the render method or getDerivedStateFromProps. In function components, you can read it directly in the function body, but not inside Hooks like useReducer() or useMemo()."),K!==f){if(!(d===!1||d===0)){var g;typeof d!="number"||d===ui?(K=f,g=ui):g=d;var S={context:f,observedBits:g,next:null};if(L===null){if(N===null)throw Error("Context can only be read while React is rendering. In classes, you can read it in the render method or getDerivedStateFromProps. In function components, you can read it directly in the function body, but not inside Hooks like useReducer() or useMemo().");L=S,N.dependencies={expirationTime:gt,firstContext:S,responders:null}}else L=L.next=S}}return e0?f._currentValue:f._currentValue2}var ke=0,Ke=1,Nt=2,yn=3,Rr=!1,Fn,Sr;Fn=!1,Sr=null;function li(f){var d={baseState:f,firstUpdate:null,lastUpdate:null,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null};return d}function cr(f){var d={baseState:f.baseState,firstUpdate:f.firstUpdate,lastUpdate:f.lastUpdate,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null};return d}function ji(f,d){var g={expirationTime:f,suspenseConfig:d,tag:ke,payload:null,callback:null,next:null,nextEffect:null};return g.priority=Mt(),g}function Nf(f,d){f.lastUpdate===null?f.firstUpdate=f.lastUpdate=d:(f.lastUpdate.next=d,f.lastUpdate=d)}function ts(f,d){var g=f.alternate,S,x;g===null?(S=f.updateQueue,x=null,S===null&&(S=f.updateQueue=li(f.memoizedState))):(S=f.updateQueue,x=g.updateQueue,S===null?x===null?(S=f.updateQueue=li(f.memoizedState),x=g.updateQueue=li(g.memoizedState)):S=f.updateQueue=cr(x):x===null&&(x=g.updateQueue=cr(S))),x===null||S===x?Nf(S,d):S.lastUpdate===null||x.lastUpdate===null?(Nf(S,d),Nf(x,d)):(Nf(S,d),x.lastUpdate=d),f.tag===A&&(Sr===S||x!==null&&Sr===x)&&!Fn&&(Ie(!1,"An update (setState, replaceState, or forceUpdate) was scheduled from inside an update function. Update functions should be pure, with zero side-effects. Consider using componentDidUpdate or a callback."),Fn=!0)}function gv(f,d){var g=f.updateQueue;g===null?g=f.updateQueue=li(f.memoizedState):g=_v(f,g),g.lastCapturedUpdate===null?g.firstCapturedUpdate=g.lastCapturedUpdate=d:(g.lastCapturedUpdate.next=d,g.lastCapturedUpdate=d)}function _v(f,d){var g=f.alternate;return g!==null&&d===g.updateQueue&&(d=f.updateQueue=cr(d)),d}function Ev(f,d,g,S,x,I){switch(g.tag){case Ke:{var j=g.payload;if(typeof j=="function"){ft(),Pr&&f.mode&zn&&j.call(I,S,x);var X=j.call(I,S,x);return mt(),X}return j}case yn:f.effectTag=f.effectTag&~S0|hr;case ke:{var $=g.payload,Re;return typeof $=="function"?(ft(),Pr&&f.mode&zn&&$.call(I,S,x),Re=$.call(I,S,x),mt()):Re=$,Re==null?S:c({},S,Re)}case Nt:return Rr=!0,S}return S}function Ff(f,d,g,S,x){Rr=!1,d=_v(f,d),Sr=d;for(var I=d.baseState,j=null,X=gt,$=d.firstUpdate,Re=I;$!==null;){var Pe=$.expirationTime;if(Pe from render. Or maybe you meant to call this function rather than return it."))}function Ov(f){function d(We,pt){if(!!f){var Ue=We.lastEffect;Ue!==null?(Ue.nextEffect=pt,We.lastEffect=pt):We.firstEffect=We.lastEffect=pt,pt.nextEffect=null,pt.effectTag=wo}}function g(We,pt){if(!f)return null;for(var Ue=pt;Ue!==null;)d(We,Ue),Ue=Ue.sibling;return null}function S(We,pt){for(var Ue=new Map,_t=pt;_t!==null;)_t.key!==null?Ue.set(_t.key,_t):Ue.set(_t.index,_t),_t=_t.sibling;return Ue}function x(We,pt,Ue){var _t=ps(We,pt,Ue);return _t.index=0,_t.sibling=null,_t}function I(We,pt,Ue){if(We.index=Ue,!f)return pt;var _t=We.alternate;if(_t!==null){var rn=_t.index;return rnrr?(Ti=Mn,Mn=null):Ti=Mn.sibling;var Zi=vt(We,Mn,Ue[rr],_t);if(Zi===null){Mn===null&&(Mn=Ti);break}f&&Mn&&Zi.alternate===null&&d(We,Mn),ai=I(Zi,ai,rr),Mi===null?yr=Zi:Mi.sibling=Zi,Mi=Zi,Mn=Ti}if(rr===Ue.length)return g(We,Mn),yr;if(Mn===null){for(;rrw0?(ku=Ti,Ti=null):ku=Ti.sibling;var mo=vt(We,Ti,Ni.value,_t);if(mo===null){Ti===null&&(Ti=ku);break}f&&Ti&&mo.alternate===null&&d(We,Ti),Zi=I(mo,Zi,w0),rr===null?ai=mo:rr.sibling=mo,rr=mo,Ti=ku}if(Ni.done)return g(We,Ti),ai;if(Ti===null){for(;!Ni.done;w0++,Ni=Mn.next()){var Ql=Ze(We,Ni.value,_t);Ql!==null&&(Zi=I(Ql,Zi,w0),rr===null?ai=Ql:rr.sibling=Ql,rr=Ql)}return ai}for(var J0=S(We,Ti);!Ni.done;w0++,Ni=Mn.next()){var Ou=Tt(J0,We,w0,Ni.value,_t);Ou!==null&&(f&&Ou.alternate!==null&&J0.delete(Ou.key===null?w0:Ou.key),Zi=I(Ou,Zi,w0),rr===null?ai=Ou:rr.sibling=Ou,rr=Ou)}return f&&J0.forEach(function(Qf){return d(We,Qf)}),ai}function pr(We,pt,Ue,_t){if(pt!==null&&pt.tag===Q){g(We,pt.sibling);var rn=x(pt,Ue,_t);return rn.return=We,rn}g(We,pt);var Ut=Gp(Ue,We.mode,_t);return Ut.return=We,Ut}function Ar(We,pt,Ue,_t){for(var rn=Ue.key,Ut=pt;Ut!==null;){if(Ut.key===rn)if(Ut.tag===v?Ue.type===ee:Ut.elementType===Ue.type||T1(Ut,Ue)){g(We,Ut.sibling);var Gr=x(Ut,Ue.type===ee?Ue.props.children:Ue.props,_t);return Gr.ref=Dc(We,Ut,Ue),Gr.return=We,Gr._debugSource=Ue._source,Gr._debugOwner=Ue._owner,Gr}else{g(We,Ut);break}else d(We,Ut);Ut=Ut.sibling}if(Ue.type===ee){var yr=Xl(Ue.props.children,We.mode,_t,Ue.key);return yr.return=We,yr}else{var Mi=Vp(Ue,We.mode,_t);return Mi.ref=Dc(We,pt,Ue),Mi.return=We,Mi}}function d0(We,pt,Ue,_t){for(var rn=Ue.key,Ut=pt;Ut!==null;){if(Ut.key===rn)if(Ut.tag===U&&Ut.stateNode.containerInfo===Ue.containerInfo&&Ut.stateNode.implementation===Ue.implementation){g(We,Ut.sibling);var Gr=x(Ut,Ue.children||[],_t);return Gr.return=We,Gr}else{g(We,Ut);break}else d(We,Ut);Ut=Ut.sibling}var yr=Yp(Ue,We.mode,_t);return yr.return=We,yr}function Jr(We,pt,Ue,_t){var rn=typeof Ue=="object"&&Ue!==null&&Ue.type===ee&&Ue.key===null;rn&&(Ue=Ue.props.children);var Ut=typeof Ue=="object"&&Ue!==null;if(Ut)switch(Ue.$$typeof){case oe:return j(Ar(We,pt,Ue,_t));case ve:return j(d0(We,pt,Ue,_t))}if(typeof Ue=="string"||typeof Ue=="number")return j(pr(We,pt,""+Ue,_t));if(L1(Ue))return Ht(We,pt,Ue,_t);if(Ln(Ue))return Yn(We,pt,Ue,_t);if(Ut&&b1(We,Ue),typeof Ue=="function"&&P1(),typeof Ue>"u"&&!rn)switch(We.tag){case A:{var Gr=We.stateNode;if(Gr.render._isMockFunction)break}case M:{var yr=We.type;throw Error((yr.displayName||yr.name||"Component")+"(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.")}}return g(We,pt)}return Jr}var Bs=Ov(!0),I1=Ov(!1);function $g(f,d){if(!(f===null||d.child===f.child))throw Error("Resuming work not yet implemented.");if(d.child!==null){var g=d.child,S=ps(g,g.pendingProps,g.expirationTime);for(d.child=S,S.return=d;g.sibling!==null;)g=g.sibling,S=S.sibling=ps(g,g.pendingProps,g.expirationTime),S.return=d;S.sibling=null}}function e4(f,d){for(var g=f.child;g!==null;)Z_(g,d),g=g.sibling}var Sa={},ns=u0(Sa),nu=u0(Sa),Ul=u0(Sa);function c0(f){if(f===Sa)throw Error("Expected host context to exist. This error is likely caused by a bug in React. Please file an issue.");return f}function Wu(){var f=c0(Ul.current);return f}function wc(f,d){wr(Ul,d,f),wr(nu,f,f),wr(ns,Sa,f);var g=it(d);_i(ns,f),wr(ns,g,f)}function Vu(f){_i(ns,f),_i(nu,f),_i(Ul,f)}function Su(){var f=c0(ns.current);return f}function Sc(f){var d=c0(Ul.current),g=c0(ns.current),S=Dt(g,f.type,d);g!==S&&(wr(nu,f,f),wr(ns,S,f))}function wd(f){nu.current===f&&(_i(ns,f),_i(nu,f))}var t4=0,Mv=1,Sd=1,Tc=2,Gu=u0(t4);function B1(f,d){return(f&d)!==0}function Lf(f){return f&Mv}function Td(f,d){return f&Mv|d}function n4(f,d){return f|d}function ar(f,d){wr(Gu,d,f)}function bf(f){_i(Gu,f)}function Cd(f,d){var g=f.memoizedState;if(g!==null)return g.dehydrated!==null;var S=f.memoizedProps;return S.fallback===void 0?!1:S.unstable_avoidThisFallback!==!0?!0:!d}function U1(f){for(var d=f;d!==null;){if(d.tag===fe){var g=d.memoizedState;if(g!==null){var S=g.dehydrated;if(S===null||kl(S)||x0(S))return d}}else if(d.tag===ot&&d.memoizedProps.revealOrder!==void 0){var x=(d.effectTag&hr)!==Kr;if(x)return d}else if(d.child!==null){d.child.return=d,d=d.child;continue}if(d===f)return null;for(;d.sibling===null;){if(d.return===null||d.return===f)return null;d=d.return}d.sibling.return=d.return,d=d.sibling}return null}var r4={},Nr=Array.isArray;function i4(f,d,g,S){return{fiber:S,props:d,responder:f,rootEventTypes:null,state:g}}function o4(f,d,g,S,x){var I=r4,j=f.getInitialState;j!==null&&(I=j(d));var X=i4(f,d,I,g);if(!x)for(var $=g;$!==null;){var Re=$.tag;if(Re===z){x=$.stateNode;break}else if(Re===P){x=$.stateNode.containerInfo;break}$=$.return}Se(f,X,d,I,x),S.set(f,X)}function xd(f,d,g,S,x){var I,j;if(f&&(I=f.responder,j=f.props),!(I&&I.$$typeof===Ct))throw Error("An invalid value was used as an event listener. Expect one or many event listeners created via React.unstable_useResponder().");var X=j;if(g.has(I)){zt(!1,'Duplicate event responder "%s" found in event listeners. Event listeners passed to elements cannot use the same event responder more than once.',I.displayName);return}g.add(I);var $=S.get(I);$===void 0?o4(I,X,d,S,x):($.props=X,$.fiber=d)}function en(f,d,g){var S=new Set,x=d.dependencies;if(f!=null){x===null&&(x=d.dependencies={expirationTime:gt,firstContext:null,responders:new Map});var I=x.responders;if(I===null&&(I=new Map),Nr(f))for(var j=0,X=f.length;j0){var I=x.dispatch;if(dl!==null){var j=dl.get(x);if(j!==void 0){dl.delete(x);var X=S.memoizedState,$=j;do{var Re=$.action;X=f(X,Re),$=$.next}while($!==null);return Il(X,S.memoizedState)||op(),S.memoizedState=X,S.baseUpdate===x.last&&(S.baseState=X),x.lastRenderedState=X,[X,I]}}return[S.memoizedState,I]}var Pe=x.last,Ze=S.baseUpdate,vt=S.baseState,Tt;if(Ze!==null?(Pe!==null&&(Pe.next=null),Tt=Ze.next):Tt=Pe!==null?Pe.next:null,Tt!==null){var St=vt,Ht=null,Yn=null,pr=Ze,Ar=Tt,d0=!1;do{var Jr=Ar.expirationTime;if(Jrrs&&(rs=Jr,v2(rs));else if(Pm(Jr,Ar.suspenseConfig),Ar.eagerReducer===f)St=Ar.eagerState;else{var We=Ar.action;St=f(St,We)}pr=Ar,Ar=Ar.next}while(Ar!==null&&Ar!==Tt);d0||(Yn=pr,Ht=St),Il(St,S.memoizedState)||op(),S.memoizedState=St,S.baseUpdate=Yn,S.baseState=Ht,x.lastRenderedState=St}var pt=x.dispatch;return[S.memoizedState,pt]}function Mc(f){var d=qf();typeof f=="function"&&(f=f()),d.memoizedState=d.baseState=f;var g=d.queue={last:null,dispatch:null,lastRenderedReducer:Lv,lastRenderedState:f},S=g.dispatch=V1.bind(null,cl,g);return[d.memoizedState,S]}function z1(f){return Oc(Lv,f)}function q1(f,d,g,S){var x={tag:f,create:d,destroy:g,deps:S,next:null};if(Ku===null)Ku=os(),Ku.lastEffect=x.next=x;else{var I=Ku.lastEffect;if(I===null)Ku.lastEffect=x.next=x;else{var j=I.next;I.next=x,x.next=j,Ku.lastEffect=x}}return x}function Nd(f){var d=qf(),g={current:f};return Object.seal(g),d.memoizedState=g,g}function bv(f){var d=kc();return d.memoizedState}function Fd(f,d,g,S){var x=qf(),I=S===void 0?null:S;js|=f,x.memoizedState=q1(d,g,void 0,I)}function Ld(f,d,g,S){var x=kc(),I=S===void 0?null:S,j=void 0;if(gn!==null){var X=gn.memoizedState;if(j=X.destroy,I!==null){var $=X.deps;if(kd(I,$)){q1(If,g,j,I);return}}}js|=f,x.memoizedState=q1(d,g,j,I)}function H1(f,d){return typeof jest<"u"&&Km(cl),Fd(Xn|U0,Bn|Rd,f,d)}function W1(f,d){return typeof jest<"u"&&Km(cl),Ld(Xn|U0,Bn|Rd,f,d)}function bd(f,d){return Fd(Xn,Bf|Uf,f,d)}function Pv(f,d){return Ld(Xn,Bf|Uf,f,d)}function Iv(f,d){if(typeof d=="function"){var g=d,S=f();return g(S),function(){g(null)}}else if(d!=null){var x=d;x.hasOwnProperty("current")||zt(!1,"Expected useImperativeHandle() first argument to either be a ref callback or React.createRef() object. Instead received: %s.","an object with keys {"+Object.keys(x).join(", ")+"}");var I=f();return x.current=I,function(){x.current=null}}}function Pd(f,d,g){typeof d!="function"&&zt(!1,"Expected useImperativeHandle() second argument to be a function that creates a handle. Instead received: %s.",d!==null?typeof d:"null");var S=g!=null?g.concat([f]):null;return Fd(Xn,Bf|Uf,Iv.bind(null,d,f),S)}function Bv(f,d,g){typeof d!="function"&&zt(!1,"Expected useImperativeHandle() second argument to be a function that creates a handle. Instead received: %s.",d!==null?typeof d:"null");var S=g!=null?g.concat([f]):null;return Ld(Xn,Bf|Uf,Iv.bind(null,d,f),S)}function s4(f,d){}var Uv=s4;function Cu(f,d){var g=qf(),S=d===void 0?null:d;return g.memoizedState=[f,S],f}function Qu(f,d){var g=kc(),S=d===void 0?null:d,x=g.memoizedState;if(x!==null&&S!==null){var I=x[1];if(kd(S,I))return x[0]}return g.memoizedState=[f,S],f}function pl(f,d){var g=qf(),S=d===void 0?null:d,x=f();return g.memoizedState=[x,S],x}function zl(f,d){var g=kc(),S=d===void 0?null:d,x=g.memoizedState;if(x!==null&&S!==null){var I=x[1];if(kd(S,I))return x[0]}var j=f();return g.memoizedState=[j,S],j}function Id(f,d){var g=Mc(f),S=g[0],x=g[1];return H1(function(){t.unstable_next(function(){var I=Yu.suspense;Yu.suspense=d===void 0?null:d;try{x(f)}finally{Yu.suspense=I}})},[f,d]),S}function jv(f,d){var g=z1(f),S=g[0],x=g[1];return W1(function(){t.unstable_next(function(){var I=Yu.suspense;Yu.suspense=d===void 0?null:d;try{x(f)}finally{Yu.suspense=I}})},[f,d]),S}function Bd(f){var d=Mc(!1),g=d[0],S=d[1],x=Cu(function(I){S(!0),t.unstable_next(function(){var j=Yu.suspense;Yu.suspense=f===void 0?null:f;try{S(!1),I()}finally{Yu.suspense=j}})},[f,g]);return[x,g]}function zv(f){var d=z1(!1),g=d[0],S=d[1],x=Qu(function(I){S(!0),t.unstable_next(function(){var j=Yu.suspense;Yu.suspense=f===void 0?null:f;try{S(!1),I()}finally{Yu.suspense=j}})},[f,g]);return[x,g]}function V1(f,d,g){if(!(Rc=0){var g=Nc()-Fc;f.actualDuration+=g,d&&(f.selfBaseDuration=g),Fc=-1}}var xu=null,ls=null,Ta=!1;function qd(){Ta&&zt(!1,"We should not be hydrating here. This is a bug in React. Please file a bug.")}function f4(f){if(!he)return!1;var d=f.stateNode.containerInfo;return ls=b(d),xu=f,Ta=!0,!0}function c4(f,d){return he?(ls=Uu(d),Vd(f),Ta=!0,!0):!1}function Hd(f,d){switch(f.tag){case P:ne(f.stateNode.containerInfo,d);break;case z:Ne(f.type,f.memoizedProps,f.stateNode,d);break}var g=iE();g.stateNode=d,g.return=f,g.effectTag=wo,f.lastEffect!==null?(f.lastEffect.nextEffect=g,f.lastEffect=g):f.firstEffect=f.lastEffect=g}function Kv(f,d){switch(d.effectTag=d.effectTag&~xi|br,f.tag){case P:{var g=f.stateNode.containerInfo;switch(d.tag){case z:var S=d.type,x=d.pendingProps;Je(g,S,x);break;case Q:var I=d.pendingProps;ut(g,I);break;case fe:ht(g);break}break}case z:{var j=f.type,X=f.memoizedProps,$=f.stateNode;switch(d.tag){case z:var Re=d.type,Pe=d.pendingProps;wt(j,X,$,Re,Pe);break;case Q:var Ze=d.pendingProps;Vt(j,X,$,Ze);break;case fe:bt(j,X,$);break}break}default:return}}function Xv(f,d){switch(f.tag){case z:{var g=f.type,S=f.pendingProps,x=Rs(d,g,S);return x!==null?(f.stateNode=x,!0):!1}case Q:{var I=f.pendingProps,j=Al(d,I);return j!==null?(f.stateNode=j,!0):!1}case fe:{if(Br){var X=Ka(d);if(X!==null){var $={dehydrated:X,retryTime:xr};f.memoizedState=$;var Re=oE(X);return Re.return=f,f.child=Re,!0}}return!1}default:return!1}}function Wd(f){if(!!Ta){var d=ls;if(!d){Kv(xu,f),Ta=!1,xu=f;return}var g=d;if(!Xv(f,d)){if(d=Uu(g),!d||!Xv(f,d)){Kv(xu,f),Ta=!1,xu=f;return}Hd(xu,g)}xu=f,ls=b(d)}}function d4(f,d,g){if(!he)throw Error("Expected prepareToHydrateHostInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.");var S=f.stateNode,x=B(S,f.type,f.memoizedProps,d,g,f);return f.updateQueue=x,x!==null}function p4(f){if(!he)throw Error("Expected prepareToHydrateHostTextInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.");var d=f.stateNode,g=f.memoizedProps,S=q(d,g,f);if(S){var x=xu;if(x!==null)switch(x.tag){case P:{var I=x.stateNode.containerInfo;je(I,d,g);break}case z:{var j=x.type,X=x.memoizedProps,$=x.stateNode;nt(j,X,$,d,g);break}}}return S}function Qv(f){if(!he)throw Error("Expected prepareToHydrateHostSuspenseInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.");var d=f.memoizedState,g=d!==null?d.dehydrated:null;if(!g)throw Error("Expected to have a hydrated suspense instance. This error is likely caused by a bug in React. Please file an issue.");Y(g,f)}function h4(f){if(!he)throw Error("Expected skipPastDehydratedSuspenseInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.");var d=f.memoizedState,g=d!==null?d.dehydrated:null;if(!g)throw Error("Expected to have a hydrated suspense instance. This error is likely caused by a bug in React. Please file an issue.");return _e(g)}function Vd(f){for(var d=f.return;d!==null&&d.tag!==z&&d.tag!==P&&d.tag!==fe;)d=d.return;xu=d}function Lc(f){if(!he||f!==xu)return!1;if(!Ta)return Vd(f),Ta=!0,!1;var d=f.type;if(f.tag!==z||d!=="head"&&d!=="body"&&!Xr(d,f.memoizedProps))for(var g=ls;g;)Hd(f,g),g=Uu(g);return Vd(f),f.tag===fe?ls=h4(f):ls=xu?Uu(f.stateNode):null,!0}function bc(){!he||(xu=null,ls=null,Ta=!1)}var Pc=Ye.ReactCurrentOwner,Ca=!1,Gd,Hl,Wl,Vl,Yd,xa,Kd,Xd,Hf,Qd;Gd={},Hl={},Wl={},Vl={},Yd={},xa=!1,Kd=!1,Xd={},Hf={},Qd={};function vo(f,d,g,S){f===null?d.child=I1(d,null,g,S):d.child=Bs(d,f.child,g,S)}function Jv(f,d,g,S){d.child=Bs(d,f.child,null,S),d.child=Bs(d,null,g,S)}function Zv(f,d,g,S,x){if(d.type!==d.elementType){var I=g.propTypes;I&&_(I,S,"prop",Rt(g),nr)}var j=g.render,X=d.ref,$;return D0(d,x),Pc.current=d,ze("render"),$=zf(f,d,j,S,X,x),Pr&&d.mode&zn&&d.memoizedState!==null&&($=zf(f,d,j,S,X,x)),ze(null),f!==null&&!Ca?(Od(f,d,x),Ra(f,d,x)):(d.effectTag|=Ai,vo(f,d,$,x),d.child)}function $v(f,d,g,S,x,I){if(f===null){var j=g.type;if(Q_(j)&&g.compare===null&&g.defaultProps===void 0){var X=j;return X=Uo(j),d.tag=Z,d.type=X,$d(d,j),em(f,d,X,S,x,I)}{var $=j.propTypes;$&&_($,S,"prop",Rt(j),nr)}var Re=Wp(g.type,null,S,null,d.mode,I);return Re.ref=d.ref,Re.return=d,d.child=Re,Re}{var Pe=g.type,Ze=Pe.propTypes;Ze&&_(Ze,S,"prop",Rt(Pe),nr)}var vt=f.child;if(x component appears to have a render method, but doesn't extend React.Component. This is likely to cause errors. Change %s to extend React.Component instead.",$,$),Gd[$]=!0)}d.mode&zn&&Du.recordLegacyContextWarning(d,null),Pc.current=d,X=zf(null,d,g,x,I,S)}if(d.effectTag|=Ai,typeof X=="object"&&X!==null&&typeof X.render=="function"&&X.$$typeof===void 0){{var Re=Rt(g)||"Unknown";Hl[Re]||(Ie(!1,"The <%s /> component appears to be a function component that returns a class instance. Change %s to a class that extends React.Component instead. If you can't use a class try assigning the prototype on the function as a workaround. `%s.prototype = React.Component.prototype`. Don't use an arrow function since it cannot be called with `new` by React.",Re,Re,Re),Hl[Re]=!0)}d.tag=A,j1();var Pe=!1;ri(g)?(Pe=!0,ii(d)):Pe=!1,d.memoizedState=X.state!==null&&X.state!==void 0?X.state:null;var Ze=g.getDerivedStateFromProps;return typeof Ze=="function"&&F1(d,g,Ze,x),xv(d,X),md(d,g,x,S),Zd(null,d,g,!0,Pe,S)}else return d.tag=M,Dr&&g.contextTypes&&Ie(!1,"%s uses the legacy contextTypes API which is no longer supported. Use React.createContext() with React.useContext() instead.",Rt(g)||"Unknown"),Pr&&d.mode&zn&&d.memoizedState!==null&&(X=zf(null,d,g,x,I,S)),vo(null,d,X,S),$d(d,g),d.child}function $d(f,d){if(d&&d.childContextTypes&&Ie(!1,"%s(...): childContextTypes cannot be defined on a function component.",d.displayName||d.name||"Component"),f.ref!==null){var g="",S=y0();S&&(g+=` + +Check the render method of \``+S+"`.");var x=S||f._debugID||"",I=f._debugSource;I&&(x=I.fileName+":"+I.lineNumber),Yd[x]||(Yd[x]=!0,zt(!1,"Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?%s",g))}if(bu&&d.defaultProps!==void 0){var j=Rt(d)||"Unknown";Qd[j]||(Ie(!1,"%s: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.",j),Qd[j]=!0)}if(typeof d.getDerivedStateFromProps=="function"){var X=Rt(d)||"Unknown";Vl[X]||(Ie(!1,"%s: Function components do not support getDerivedStateFromProps.",X),Vl[X]=!0)}if(typeof d.contextType=="object"&&d.contextType!==null){var $=Rt(d)||"Unknown";Wl[$]||(Ie(!1,"%s: Function components do not support contextType.",$),Wl[$]=!0)}}var X1={dehydrated:null,retryTime:gt};function ep(f,d,g){return B1(f,Tc)&&(d===null||d.memoizedState!==null)}function om(f,d,g){var S=d.mode,x=d.pendingProps;oy(d)&&(d.effectTag|=hr);var I=Gu.current,j=!1,X=(d.effectTag&hr)!==Kr;if(X||ep(I,f,d)?(j=!0,d.effectTag&=~hr):(f===null||f.memoizedState!==null)&&x.fallback!==void 0&&x.unstable_avoidThisFallback!==!0&&(I=n4(I,Sd)),I=Lf(I),ar(d,I),"maxDuration"in x&&(Kd||(Kd=!0,zt(!1,"maxDuration has been removed from React. Remove the maxDuration prop."))),f===null){if(x.fallback!==void 0&&(Wd(d),Br)){var $=d.memoizedState;if($!==null){var Re=$.dehydrated;if(Re!==null)return um(d,Re,g)}}if(j){var Pe=x.fallback,Ze=Xl(null,S,gt,null);if(Ze.return=d,(d.mode&Mr)===lr){var vt=d.memoizedState,Tt=vt!==null?d.child.child:d.child;Ze.child=Tt;for(var St=Tt;St!==null;)St.return=Ze,St=St.sibling}var Ht=Xl(Pe,S,g,null);return Ht.return=d,Ze.sibling=Ht,d.memoizedState=X1,d.child=Ze,Ht}else{var Yn=x.children;return d.memoizedState=null,d.child=I1(d,null,Yn,g)}}else{var pr=f.memoizedState;if(pr!==null){if(Br){var Ar=pr.dehydrated;if(Ar!==null)if(X){if(d.memoizedState!==null)return d.child=f.child,d.effectTag|=hr,null;var d0=x.fallback,Jr=Xl(null,S,gt,null);if(Jr.return=d,Jr.child=null,(d.mode&Mr)===lr)for(var We=Jr.child=d.child;We!==null;)We.return=Jr,We=We.sibling;else Bs(d,f.child,null,g);if(Ft&&d.mode&Cr){for(var pt=0,Ue=Jr.child;Ue!==null;)pt+=Ue.treeBaseDuration,Ue=Ue.sibling;Jr.treeBaseDuration=pt}var _t=Xl(d0,S,g,null);return _t.return=d,Jr.sibling=_t,_t.effectTag|=br,Jr.childExpirationTime=gt,d.memoizedState=X1,d.child=Jr,_t}else return E4(f,d,Ar,pr,g)}var rn=f.child,Ut=rn.sibling;if(j){var Gr=x.fallback,yr=ps(rn,rn.pendingProps,gt);if(yr.return=d,(d.mode&Mr)===lr){var Mi=d.memoizedState,Mn=Mi!==null?d.child.child:d.child;if(Mn!==rn.child){yr.child=Mn;for(var ai=Mn;ai!==null;)ai.return=yr,ai=ai.sibling}}if(Ft&&d.mode&Cr){for(var rr=0,Ti=yr.child;Ti!==null;)rr+=Ti.treeBaseDuration,Ti=Ti.sibling;yr.treeBaseDuration=rr}var Zi=ps(Ut,Gr,Ut.expirationTime);return Zi.return=d,yr.sibling=Zi,yr.childExpirationTime=gt,d.memoizedState=X1,d.child=yr,Zi}else{var w0=x.children,ku=rn.child,Ni=Bs(d,ku,w0,g);return d.memoizedState=null,d.child=Ni}}else{var mo=f.child;if(j){var Ql=x.fallback,J0=Xl(null,S,gt,null);if(J0.return=d,J0.child=mo,mo!==null&&(mo.return=J0),(d.mode&Mr)===lr){var Ou=d.memoizedState,Qf=Ou!==null?d.child.child:d.child;J0.child=Qf;for(var ka=Qf;ka!==null;)ka.return=J0,ka=ka.sibling}if(Ft&&d.mode&Cr){for(var hs=0,qo=J0.child;qo!==null;)hs+=qo.treeBaseDuration,qo=qo.sibling;J0.treeBaseDuration=hs}var Z0=Xl(Ql,S,g,null);return Z0.return=d,J0.sibling=Z0,Z0.effectTag|=br,J0.childExpirationTime=gt,d.memoizedState=X1,d.child=J0,Z0}else{d.memoizedState=null;var $s=x.children;return d.child=Bs(d,mo,$s,g)}}}}function tp(f,d,g){d.memoizedState=null;var S=d.pendingProps,x=S.children;return vo(f,d,x,g),d.child}function um(f,d,g){if((f.mode&Mr)===lr)zt(!1,"Cannot hydrate Suspense in legacy mode. Switch from ReactDOM.hydrate(element, container) to ReactDOM.createBlockingRoot(container, { hydrate: true }).render(element) or remove the Suspense components from the server rendered components."),f.expirationTime=On;else if(x0(d)){var S=Au(),x=sl(S);hn&&cs(x),f.expirationTime=x}else f.expirationTime=xr,hn&&cs(xr);return null}function E4(f,d,g,S,x){if(qd(),(d.mode&Mr)===lr||x0(g))return tp(f,d,x);var I=f.childExpirationTime>=x;if(Ca||I){if(x. Use lowercase "%s" instead.',f,f.toLowerCase());break}case"forward":case"backward":{zt(!1,'"%s" is not a valid value for revealOrder on . React uses the -s suffix in the spelling. Use "%ss" instead.',f,f.toLowerCase());break}default:zt(!1,'"%s" is not a supported revealOrder on . Did you mean "together", "forwards" or "backwards"?',f);break}else zt(!1,'%s is not a supported value for revealOrder on . Did you mean "together", "forwards" or "backwards"?',f)}function am(f,d){f!==void 0&&!Hf[f]&&(f!=="collapsed"&&f!=="hidden"?(Hf[f]=!0,zt(!1,'"%s" is not a supported value for tail on . Did you mean "collapsed" or "hidden"?',f)):d!=="forwards"&&d!=="backwards"&&(Hf[f]=!0,zt(!1,' is only valid if revealOrder is "forwards" or "backwards". Did you mean to specify revealOrder="forwards"?',f)))}function sm(f,d){{var g=Array.isArray(f),S=!g&&typeof Ln(f)=="function";if(g||S){var x=g?"array":"iterable";return zt(!1,"A nested %s was passed to row #%s in . Wrap it in an additional SuspenseList to configure its revealOrder: ... {%s} ... ",x,d,x),!1}}return!0}function T4(f,d){if((d==="forwards"||d==="backwards")&&f!==void 0&&f!==null&&f!==!1)if(Array.isArray(f)){for(var g=0;g. This is not useful since it needs multiple rows. Did you mean to pass multiple children or an array?',d)}}function np(f,d,g,S,x,I){var j=f.memoizedState;j===null?f.memoizedState={isBackwards:d,rendering:null,last:S,tail:g,tailExpiration:0,tailMode:x,lastEffect:I}:(j.isBackwards=d,j.rendering=null,j.last=S,j.tail=g,j.tailExpiration=0,j.tailMode=x,j.lastEffect=I)}function rp(f,d,g){var S=d.pendingProps,x=S.revealOrder,I=S.tail,j=S.children;S4(x),am(I,x),T4(j,x),vo(f,d,j,g);var X=Gu.current,$=B1(X,Tc);if($)X=Td(X,Tc),d.effectTag|=hr;else{var Re=f!==null&&(f.effectTag&hr)!==Kr;Re&&D4(d,d.child,g),X=Lf(X)}if(ar(d,X),(d.mode&Mr)===lr)d.memoizedState=null;else switch(x){case"forwards":{var Pe=w4(d.child),Ze;Pe===null?(Ze=d.child,d.child=null):(Ze=Pe.sibling,Pe.sibling=null),np(d,!1,Ze,Pe,I,d.lastEffect);break}case"backwards":{var vt=null,Tt=d.child;for(d.child=null;Tt!==null;){var St=Tt.alternate;if(St!==null&&U1(St)===null){d.child=Tt;break}var Ht=Tt.sibling;Tt.sibling=vt,vt=Tt,Tt=Ht}np(d,!0,vt,null,I,d.lastEffect);break}case"together":{np(d,!1,null,null,void 0,d.lastEffect);break}default:d.memoizedState=null}return d.child}function C4(f,d,g){wc(d,d.stateNode.containerInfo);var S=d.pendingProps;return f===null?d.child=Bs(d,null,S,g):vo(f,d,S,g),d.child}function x4(f,d,g){var S=d.type,x=S._context,I=d.pendingProps,j=d.memoizedProps,X=I.value;{var $=d.type.propTypes;$&&_($,I,"prop","Context.Provider",nr)}if(Gn(d,X),j!==null){var Re=j.value,Pe=ki(x,X,Re);if(Pe===0){if(j.children===I.children&&!da())return Ra(f,d,g)}else wa(d,x,Pe,g)}var Ze=I.children;return vo(f,d,Ze,g),d.child}var fm=!1;function R4(f,d,g){var S=d.type;S._context===void 0?S!==S.Consumer&&(fm||(fm=!0,zt(!1,"Rendering directly is not supported and will be removed in a future major release. Did you mean to render instead?"))):S=S._context;var x=d.pendingProps,I=x.children;typeof I!="function"&&Ie(!1,"A context consumer was rendered with multiple children, or a child that isn't a function. A context consumer expects a single child that is a function. If you did pass a function, make sure there is no trailing or leading whitespace around it."),D0(d,g);var j=Le(S,x.unstable_observedBits),X;return Pc.current=d,ze("render"),X=I(j),ze(null),d.effectTag|=Ai,vo(f,d,X,g),d.child}function A4(f,d,g){var S=d.type.impl;if(S.reconcileChildren===!1)return null;var x=d.pendingProps,I=x.children;return vo(f,d,I,g),d.child}function ip(f,d,g){var S=d.pendingProps,x=S.children;return vo(f,d,x,g),d.child}function op(){Ca=!0}function Ra(f,d,g){Xi(d),f!==null&&(d.dependencies=f.dependencies),Ft&&Yv(d);var S=d.expirationTime;S!==gt&&v2(S);var x=d.childExpirationTime;return x=g;$&&(d.effectTag|=Xn)}break;case fe:{var Re=d.memoizedState;if(Re!==null){if(Br&&Re.dehydrated!==null){ar(d,Lf(Gu.current)),d.effectTag|=hr;break}var Pe=d.child,Ze=Pe.childExpirationTime;if(Ze!==gt&&Ze>=g)return om(f,d,g);ar(d,Lf(Gu.current));var vt=Ra(f,d,g);return vt!==null?vt.sibling:null}else ar(d,Lf(Gu.current));break}case ot:{var Tt=(f.effectTag&hr)!==Kr,St=d.childExpirationTime>=g;if(Tt){if(St)return rp(f,d,g);d.effectTag|=hr}var Ht=d.memoizedState;if(Ht!==null&&(Ht.rendering=null,Ht.tail=null),ar(d,Gu.current),St)break;return null}}return Ra(f,d,g)}else Ca=!1}else Ca=!1;switch(d.expirationTime=gt,d.tag){case T:return _4(f,d,d.type,g);case Ae:{var Yn=d.elementType;return qs(f,d,Yn,S,g)}case M:{var pr=d.type,Ar=d.pendingProps,d0=d.elementType===pr?Ar:wu(pr,Ar);return Jd(f,d,pr,d0,g)}case A:{var Jr=d.type,We=d.pendingProps,pt=d.elementType===Jr?We:wu(Jr,We);return rm(f,d,Jr,pt,g)}case P:return y4(f,d,g);case z:return g4(f,d,g);case Q:return zs(f,d);case fe:return om(f,d,g);case U:return C4(f,d,g);case ae:{var Ue=d.type,_t=d.pendingProps,rn=d.elementType===Ue?_t:wu(Ue,_t);return Zv(f,d,Ue,rn,g)}case v:return v4(f,d,g);case de:return m4(f,d,g);case Me:return tm(f,d,g);case le:return x4(f,d,g);case ye:return R4(f,d,g);case pe:{var Ut=d.type,Gr=d.pendingProps,yr=wu(Ut,Gr);if(d.type!==d.elementType){var Mi=Ut.propTypes;Mi&&_(Mi,yr,"prop",Rt(Ut),nr)}return yr=wu(Ut.type,yr),$v(f,d,Ut,yr,S,g)}case Z:return em(f,d,d.type,d.pendingProps,S,g);case Fe:{var Mn=d.type,ai=d.pendingProps,rr=d.elementType===Mn?ai:wu(Mn,ai);return K1(f,d,Mn,rr,g)}case ot:return rp(f,d,g);case st:{if(xt)return A4(f,d,g);break}case qe:{if(Li)return ip(f,d,g);break}}throw Error("Unknown unit of work tag ("+d.tag+"). This error is likely caused by a bug in React. Please file an issue.")}function k4(f,d,g,S){return{currentFiber:f,impl:g,instance:null,prevProps:null,props:d,state:S}}function lp(f){return f.tag===fe&&f.memoizedState!==null}function ap(f){return f.child.sibling.child}var O4={};function dm(f,d,g){if(Li){if(f.tag===z){var S=f.type,x=f.memoizedProps,I=f.stateNode,j=Ao(I);j!==null&&d(S,x||O4,j)===!0&&g.push(j)}var X=f.child;lp(f)&&(X=ap(f)),X!==null&&pm(X,d,g)}}function M4(f,d){if(Li){if(f.tag===z){var g=f.type,S=f.memoizedProps,x=f.stateNode,I=Ao(x);if(I!==null&&d(g,S,I)===!0)return I}var j=f.child;if(lp(f)&&(j=ap(f)),j!==null)return hm(j,d)}return null}function pm(f,d,g){for(var S=f;S!==null;)dm(S,d,g),S=S.sibling}function hm(f,d){for(var g=f;g!==null;){var S=M4(g,d);if(S!==null)return S;g=g.sibling}return null}function vm(f,d,g){if(N4(f,d))g.push(f.stateNode.methods);else{var S=f.child;lp(f)&&(S=ap(f)),S!==null&&sp(S,d,g)}}function sp(f,d,g){for(var S=f;S!==null;)vm(S,d,g),S=S.sibling}function N4(f,d){return f.tag===qe&&f.type===d&&f.stateNode!==null}function F4(f,d){return{getChildren:function(){var g=d.fiber,S=g.child,x=[];return S!==null&&sp(S,f,x),x.length===0?null:x},getChildrenFromRoot:function(){for(var g=d.fiber,S=g;S!==null;){var x=S.return;if(x===null||(S=x,S.tag===qe&&S.type===f))break}var I=[];return sp(S.child,f,I),I.length===0?null:I},getParent:function(){for(var g=d.fiber.return;g!==null;){if(g.tag===qe&&g.type===f)return g.stateNode.methods;g=g.return}return null},getProps:function(){var g=d.fiber;return g.memoizedProps},queryAllNodes:function(g){var S=d.fiber,x=S.child,I=[];return x!==null&&pm(x,g,I),I.length===0?null:I},queryFirstNode:function(g){var S=d.fiber,x=S.child;return x!==null?hm(x,g):null},containsNode:function(g){for(var S=In(g);S!==null;){if(S.tag===qe&&S.type===f&&S.stateNode===d)return!0;S=S.return}return!1}}}function P0(f){f.effectTag|=Xn}function Q1(f){f.effectTag|=To}var Hs,Ws,J1,Z1;if(q0)Hs=function(f,d,g,S){for(var x=d.child;x!==null;){if(x.tag===z||x.tag===Q)mr(f,x.stateNode);else if(xt&&x.tag===st)mr(f,x.stateNode.instance);else if(x.tag!==U){if(x.child!==null){x.child.return=x,x=x.child;continue}}if(x===d)return;for(;x.sibling===null;){if(x.return===null||x.return===d)return;x=x.return}x.sibling.return=x.return,x=x.sibling}},Ws=function(f){},J1=function(f,d,g,S,x){var I=f.memoizedProps;if(I!==S){var j=d.stateNode,X=Su(),$=v0(j,g,I,S,x,X);d.updateQueue=$,$&&P0(d)}},Z1=function(f,d,g,S){g!==S&&P0(d)};else if(W){Hs=function(f,d,g,S){for(var x=d.child;x!==null;){e:if(x.tag===z){var I=x.stateNode;if(g&&S){var j=x.memoizedProps,X=x.type;I=Iu(I,X,j,x)}mr(f,I)}else if(x.tag===Q){var $=x.stateNode;if(g&&S){var Re=x.memoizedProps;$=Bu($,Re,x)}mr(f,$)}else if(xt&&x.tag===st){var Pe=x.stateNode.instance;if(g&&S){var Ze=x.memoizedProps,vt=x.type;Pe=Iu(Pe,vt,Ze,x)}mr(f,Pe)}else if(x.tag!==U){if(x.tag===fe){if((x.effectTag&Xn)!==Kr){var Tt=x.memoizedState!==null;if(Tt){var St=x.child;if(St!==null){St.child!==null&&(St.child.return=St,Hs(f,St,!0,Tt));var Ht=St.sibling;if(Ht!==null){Ht.return=x,x=Ht;continue}}}}if(x.child!==null){x.child.return=x,x=x.child;continue}}else if(x.child!==null){x.child.return=x,x=x.child;continue}}if(x=x,x===d)return;for(;x.sibling===null;){if(x.return===null||x.return===d)return;x=x.return}x.sibling.return=x.return,x=x.sibling}};var fp=function(f,d,g,S){for(var x=d.child;x!==null;){e:if(x.tag===z){var I=x.stateNode;if(g&&S){var j=x.memoizedProps,X=x.type;I=Iu(I,X,j,x)}Sn(f,I)}else if(x.tag===Q){var $=x.stateNode;if(g&&S){var Re=x.memoizedProps;$=Bu($,Re,x)}Sn(f,$)}else if(xt&&x.tag===st){var Pe=x.stateNode.instance;if(g&&S){var Ze=x.memoizedProps,vt=x.type;Pe=Iu(Pe,vt,Ze,x)}Sn(f,Pe)}else if(x.tag!==U){if(x.tag===fe){if((x.effectTag&Xn)!==Kr){var Tt=x.memoizedState!==null;if(Tt){var St=x.child;if(St!==null){St.child!==null&&(St.child.return=St,fp(f,St,!0,Tt));var Ht=St.sibling;if(Ht!==null){Ht.return=x,x=Ht;continue}}}}if(x.child!==null){x.child.return=x,x=x.child;continue}}else if(x.child!==null){x.child.return=x,x=x.child;continue}}if(x=x,x===d)return;for(;x.sibling===null;){if(x.return===null||x.return===d)return;x=x.return}x.sibling.return=x.return,x=x.sibling}};Ws=function(f){var d=f.stateNode,g=f.firstEffect===null;if(!g){var S=d.containerInfo,x=C0(S);fp(x,f,!1,!1),d.pendingChildren=x,P0(f),Tf(S,x)}},J1=function(f,d,g,S,x){var I=f.stateNode,j=f.memoizedProps,X=d.firstEffect===null;if(X&&j===S){d.stateNode=I;return}var $=d.stateNode,Re=Su(),Pe=null;if(j!==S&&(Pe=v0($,g,j,S,x,Re)),X&&Pe===null){d.stateNode=I;return}var Ze=rl(I,Pe,g,j,S,d,X,$);bi(Ze,g,S,x,Re)&&P0(d),d.stateNode=Ze,X?P0(d):Hs(Ze,d,!1,!1)},Z1=function(f,d,g,S){if(g!==S){var x=Wu(),I=Su();d.stateNode=Rl(S,x,I,d),P0(d)}}}else Ws=function(f){},J1=function(f,d,g,S,x){},Z1=function(f,d,g,S){};function $1(f,d){switch(f.tailMode){case"hidden":{for(var g=f.tail,S=null;g!==null;)g.alternate!==null&&(S=g),g=g.sibling;S===null?f.tail=null:S.sibling=null;break}case"collapsed":{for(var x=f.tail,I=null;x!==null;)x.alternate!==null&&(I=x),x=x.sibling;I===null?!d&&f.tail!==null?f.tail.sibling=null:f.tail=null:I.sibling=null;break}}}function mm(f,d,g){var S=d.pendingProps;switch(d.tag){case T:break;case Ae:break;case Z:case M:break;case A:{var x=d.type;ri(x)&&bl(d);break}case P:{Vu(d),so(d);var I=d.stateNode;if(I.pendingContext&&(I.context=I.pendingContext,I.pendingContext=null),f===null||f.child===null){var j=Lc(d);j&&P0(d)}Ws(d);break}case z:{wd(d);var X=Wu(),$=d.type;if(f!==null&&d.stateNode!=null){if(J1(f,d,$,S,X),Tr){var Re=f.memoizedProps.listeners,Pe=S.listeners;Re!==Pe&&P0(d)}f.ref!==d.ref&&Q1(d)}else{if(!S){if(d.stateNode===null)throw Error("We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue.");break}var Ze=Su(),vt=Lc(d);if(vt){if(d4(d,X,Ze)&&P0(d),Tr){var Tt=S.listeners;Tt!=null&&en(Tt,d,X)}}else{var St=ni($,S,X,Ze,d);if(Hs(St,d,!1,!1),d.stateNode=St,Tr){var Ht=S.listeners;Ht!=null&&en(Ht,d,X)}bi(St,$,S,X,Ze)&&P0(d)}d.ref!==null&&Q1(d)}break}case Q:{var Yn=S;if(f&&d.stateNode!=null){var pr=f.memoizedProps;Z1(f,d,pr,Yn)}else{if(typeof Yn!="string"&&d.stateNode===null)throw Error("We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue.");var Ar=Wu(),d0=Su(),Jr=Lc(d);Jr?p4(d)&&P0(d):d.stateNode=Rl(Yn,Ar,d0,d)}break}case ae:break;case fe:{bf(d);var We=d.memoizedState;if(Br&&We!==null&&We.dehydrated!==null)if(f===null){var pt=Lc(d);if(!pt)throw Error("A dehydrated suspense component was completed without a hydrated node. This is probably a bug in React.");return Qv(d),hn&&cs(xr),null}else return bc(),(d.effectTag&hr)===Kr&&(d.memoizedState=null),d.effectTag|=Xn,null;if((d.effectTag&hr)!==Kr)return d.expirationTime=g,d;var Ue=We!==null,_t=!1;if(f===null)d.memoizedProps.fallback!==void 0&&Lc(d);else{var rn=f.memoizedState;if(_t=rn!==null,!Ue&&rn!==null){var Ut=f.child.sibling;if(Ut!==null){var Gr=d.firstEffect;Gr!==null?(d.firstEffect=Ut,Ut.nextEffect=Gr):(d.firstEffect=d.lastEffect=Ut,Ut.nextEffect=null),Ut.effectTag=wo}}}if(Ue&&!_t&&(d.mode&Mr)!==lr){var yr=f===null&&d.memoizedProps.unstable_avoidThisFallback!==!0;yr||B1(Gu.current,Sd)?Im():Bm()}W&&Ue&&(d.effectTag|=Xn),q0&&(Ue||_t)&&(d.effectTag|=Xn),ti&&d.updateQueue!==null&&d.memoizedProps.suspenseCallback!=null&&(d.effectTag|=Xn);break}case v:break;case de:break;case Me:break;case U:Vu(d),Ws(d);break;case le:f0(d);break;case ye:break;case pe:break;case Fe:{var Mi=d.type;ri(Mi)&&bl(d);break}case ot:{bf(d);var Mn=d.memoizedState;if(Mn===null)break;var ai=(d.effectTag&hr)!==Kr,rr=Mn.rendering;if(rr===null)if(ai)$1(Mn,!1);else{var Ti=g_()&&(f===null||(f.effectTag&hr)===Kr);if(!Ti)for(var Zi=d.child;Zi!==null;){var w0=U1(Zi);if(w0!==null){ai=!0,d.effectTag|=hr,$1(Mn,!1);var ku=w0.updateQueue;return ku!==null&&(d.updateQueue=ku,d.effectTag|=Xn),Mn.lastEffect===null&&(d.firstEffect=null),d.lastEffect=Mn.lastEffect,e4(d,g),ar(d,Td(Gu.current,Tc)),d.child}Zi=Zi.sibling}}else{if(!ai){var Ni=U1(rr);if(Ni!==null){d.effectTag|=hr,ai=!0;var mo=Ni.updateQueue;if(mo!==null&&(d.updateQueue=mo,d.effectTag|=Xn),$1(Mn,!0),Mn.tail===null&&Mn.tailMode==="hidden"&&!rr.alternate){var Ql=d.lastEffect=Mn.lastEffect;return Ql!==null&&(Ql.nextEffect=null),null}}else if(rt()>Mn.tailExpiration&&g>xr){d.effectTag|=hr,ai=!0,$1(Mn,!1);var J0=g-1;d.expirationTime=d.childExpirationTime=J0,hn&&cs(J0)}}if(Mn.isBackwards)rr.sibling=d.child,d.child=rr;else{var Ou=Mn.last;Ou!==null?Ou.sibling=rr:d.child=rr,Mn.last=rr}}if(Mn.tail!==null){if(Mn.tailExpiration===0){var Qf=500;Mn.tailExpiration=rt()+Qf}var ka=Mn.tail;Mn.rendering=ka,Mn.tail=ka.sibling,Mn.lastEffect=d.lastEffect,ka.sibling=null;var hs=Gu.current;return ai?hs=Td(hs,Tc):hs=Lf(hs),ar(d,hs),ka}break}case st:{if(xt){var qo=d.type.impl,Z0=d.stateNode;if(Z0===null){var $s=qo.getInitialState,dy;$s!==void 0&&(dy=$s(S)),Z0=d.stateNode=k4(d,S,qo,dy||{});var py=tt(Z0);if(Z0.instance=py,qo.reconcileChildren===!1)return null;Hs(py,d,!1,!1),Cn(Z0)}else{var DE=Z0.props;if(Z0.prevProps=DE,Z0.props=S,Z0.currentFiber=d,W){var hy=sa(Z0);Z0.instance=hy,Hs(hy,d,!1,!1)}var wE=cn(Z0);wE&&P0(d)}}break}case qe:{if(Li)if(f===null){var SE=d.type,eh={fiber:d,methods:null};if(d.stateNode=eh,eh.methods=F4(SE,eh),Tr){var vy=S.listeners;if(vy!=null){var TE=Wu();en(vy,d,TE)}}d.ref!==null&&(Q1(d),P0(d))}else{if(Tr){var CE=f.memoizedProps.listeners,xE=S.listeners;(CE!==xE||d.ref!==null)&&P0(d)}else d.ref!==null&&P0(d);f.ref!==d.ref&&Q1(d)}break}default:throw Error("Unknown unit of work tag ("+d.tag+"). This error is likely caused by a bug in React. Please file an issue.")}return null}function L4(f,d){switch(f.tag){case A:{var g=f.type;ri(g)&&bl(f);var S=f.effectTag;return S&S0?(f.effectTag=S&~S0|hr,f):null}case P:{Vu(f),so(f);var x=f.effectTag;if((x&hr)!==Kr)throw Error("The root failed to unmount after an error. This is likely a bug in React. Please file an issue.");return f.effectTag=x&~S0|hr,f}case z:return wd(f),null;case fe:{if(bf(f),Br){var I=f.memoizedState;if(I!==null&&I.dehydrated!==null){if(f.alternate===null)throw Error("Threw in newly mounted dehydrated component. This is likely a bug in React. Please file an issue.");bc()}}var j=f.effectTag;return j&S0?(f.effectTag=j&~S0|hr,f):null}case ot:return bf(f),null;case U:return Vu(f),null;case le:return f0(f),null;default:return null}}function ym(f){switch(f.tag){case A:{var d=f.type.childContextTypes;d!=null&&bl(f);break}case P:{Vu(f),so(f);break}case z:{wd(f);break}case U:Vu(f);break;case fe:bf(f);break;case ot:bf(f);break;case le:f0(f);break;default:break}}function cp(f,d){return{value:f,source:d,stack:Jn(d)}}var dp=function(f,d,g,S,x,I,j,X,$){var Re=Array.prototype.slice.call(arguments,3);try{d.apply(g,Re)}catch(Pe){this.onError(Pe)}};if(typeof window<"u"&&typeof window.dispatchEvent=="function"&&typeof document<"u"&&typeof document.createEvent=="function"){var pp=document.createElement("react"),b4=function(f,d,g,S,x,I,j,X,$){if(!(typeof document<"u"))throw Error("The `document` global was defined when React was initialized, but is not defined anymore. This can happen in a test environment if a component schedules an update from an asynchronous callback, but the test has already finished running. To solve this, you can either unmount the component at the end of your test (and ensure that any asynchronous operations get canceled in `componentWillUnmount`), or you can change the test itself to be asynchronous.");var Re=document.createEvent("Event"),Pe=!0,Ze=window.event,vt=Object.getOwnPropertyDescriptor(window,"event"),Tt=Array.prototype.slice.call(arguments,3);function St(){pp.removeEventListener(d0,St,!1),typeof window.event<"u"&&window.hasOwnProperty("event")&&(window.event=Ze),d.apply(g,Tt),Pe=!1}var Ht,Yn=!1,pr=!1;function Ar(Jr){if(Ht=Jr.error,Yn=!0,Ht===null&&Jr.colno===0&&Jr.lineno===0&&(pr=!0),Jr.defaultPrevented&&Ht!=null&&typeof Ht=="object")try{Ht._suppressLogging=!0}catch{}}var d0="react-"+(f||"invokeguardedcallback");window.addEventListener("error",Ar),pp.addEventListener(d0,St,!1),Re.initEvent(d0,!1,!1),pp.dispatchEvent(Re),vt&&Object.defineProperty(window,"event",vt),Pe&&(Yn?pr&&(Ht=new Error("A cross-origin error was thrown. React doesn't have access to the actual error object in development. See https://fb.me/react-crossorigin-error for more information.")):Ht=new Error(`An error was thrown inside one of your components, but React doesn't know what it was. This is likely due to browser flakiness. React does its best to preserve the "Pause on exceptions" behavior of the DevTools, which requires some DEV-mode only tricks. It's possible that these don't work in your browser. Try triggering the error in production mode, or switching to a modern browser. If you suspect that this is actually an issue with React, please file an issue.`),this.onError(Ht)),window.removeEventListener("error",Ar)};dp=b4}var P4=dp,Wf=!1,e2=null,I4={onError:function(f){Wf=!0,e2=f}};function as(f,d,g,S,x,I,j,X,$){Wf=!1,e2=null,P4.apply(I4,arguments)}function Gl(){return Wf}function Yl(){if(Wf){var f=e2;return Wf=!1,e2=null,f}else throw Error("clearCaughtError was called but no error was captured. This error is likely caused by a bug in React. Please file an issue.")}function B4(f){return!0}function U4(f){var d=B4(f);if(d!==!1){var g=f.error;{var S=f.componentName,x=f.componentStack,I=f.errorBoundaryName,j=f.errorBoundaryFound,X=f.willRetry;if(g!=null&&g._suppressLogging){if(j&&X)return;console.error(g)}var $=S?"The above error occurred in the <"+S+"> component:":"The above error occurred in one of your React components:",Re;j&&I?X?Re="React will try to recreate this component tree from scratch "+("using the error boundary you provided, "+I+"."):Re="This error was initially handled by the error boundary "+I+`. +Recreating the tree from scratch failed so React will unmount the tree.`:Re=`Consider adding an error boundary to your tree to customize error handling behavior. +Visit https://fb.me/react-error-boundaries to learn more about error boundaries.`;var Pe=""+$+x+` + +`+(""+Re);console.error(Pe)}}}var gm=null;gm=new Set;var hp=typeof WeakSet=="function"?WeakSet:Set;function vp(f,d){var g=d.source,S=d.stack;S===null&&g!==null&&(S=Jn(g));var x={componentName:g!==null?Rt(g.type):null,componentStack:S!==null?S:"",error:d.value,errorBoundary:null,errorBoundaryName:null,errorBoundaryFound:!1,willRetry:!1};f!==null&&f.tag===A&&(x.errorBoundary=f.stateNode,x.errorBoundaryName=Rt(f.type),x.errorBoundaryFound=!0,x.willRetry=!0);try{U4(x)}catch(I){setTimeout(function(){throw I})}}var j4=function(f,d){Qr(f,"componentWillUnmount"),d.props=f.memoizedProps,d.state=f.memoizedState,d.componentWillUnmount(),Or()};function _m(f,d){if(as(null,j4,null,f,d),Gl()){var g=Yl();Js(f,g)}}function mp(f){var d=f.ref;if(d!==null)if(typeof d=="function"){if(as(null,d,null,null),Gl()){var g=Yl();Js(f,g)}}else d.current=null}function z4(f,d){if(as(null,d,null),Gl()){var g=Yl();Js(f,g)}}function q4(f,d){switch(d.tag){case M:case ae:case Z:{Vf(u4,If,d);return}case A:{if(d.effectTag&Co&&f!==null){var g=f.memoizedProps,S=f.memoizedState;Qr(d,"getSnapshotBeforeUpdate");var x=d.stateNode;d.type===d.elementType&&!xa&&(x.props!==d.memoizedProps&&zt(!1,"Expected %s props to match memoized props before getSnapshotBeforeUpdate. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",Rt(d.type)||"instance"),x.state!==d.memoizedState&&zt(!1,"Expected %s state to match memoized state before getSnapshotBeforeUpdate. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",Rt(d.type)||"instance"));var I=x.getSnapshotBeforeUpdate(d.elementType===d.type?g:wu(d.type,g),S);{var j=gm;I===void 0&&!j.has(d.type)&&(j.add(d.type),Ie(!1,"%s.getSnapshotBeforeUpdate(): A snapshot value (or null) must be returned. You have returned undefined.",Rt(d.type)))}x.__reactInternalSnapshotBeforeUpdate=I,Or()}return}case P:case z:case Q:case U:case Fe:return;default:throw Error("This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue.")}}function Vf(f,d,g){var S=g.updateQueue,x=S!==null?S.lastEffect:null;if(x!==null){var I=x.next,j=I;do{if((j.tag&f)!==If){var X=j.destroy;j.destroy=void 0,X!==void 0&&X()}if((j.tag&d)!==If){var $=j.create;j.destroy=$();{var Re=j.destroy;if(Re!==void 0&&typeof Re!="function"){var Pe=void 0;Re===null?Pe=" You returned null. If your effect does not require clean up, return undefined (or nothing).":typeof Re.then=="function"?Pe=` + +It looks like you wrote useEffect(async () => ...) or returned a Promise. Instead, write the async function inside your effect and call it immediately: + +useEffect(() => { + async function fetchData() { + // You can await here + const response = await MyAPI.getData(someId); + // ... + } + fetchData(); +}, [someId]); // Or [] if effect doesn't need props or state + +Learn more about data fetching with Hooks: https://fb.me/react-hooks-data-fetching`:Pe=" You returned: "+Re,Ie(!1,"An effect function must not return anything besides a function, which is used for clean-up.%s%s",Pe,Jn(g))}}}j=j.next}while(j!==I)}}function H4(f){if((f.effectTag&U0)!==Kr)switch(f.tag){case M:case ae:case Z:{Vf(Bn,If,f),Vf(If,Rd,f);break}default:break}}function Em(f,d,g,S){switch(g.tag){case M:case ae:case Z:{Vf(l4,Uf,g);break}case A:{var x=g.stateNode;if(g.effectTag&Xn)if(d===null)Qr(g,"componentDidMount"),g.type===g.elementType&&!xa&&(x.props!==g.memoizedProps&&zt(!1,"Expected %s props to match memoized props before componentDidMount. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",Rt(g.type)||"instance"),x.state!==g.memoizedState&&zt(!1,"Expected %s state to match memoized state before componentDidMount. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",Rt(g.type)||"instance")),x.componentDidMount(),Or();else{var I=g.elementType===g.type?d.memoizedProps:wu(g.type,d.memoizedProps),j=d.memoizedState;Qr(g,"componentDidUpdate"),g.type===g.elementType&&!xa&&(x.props!==g.memoizedProps&&zt(!1,"Expected %s props to match memoized props before componentDidUpdate. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",Rt(g.type)||"instance"),x.state!==g.memoizedState&&zt(!1,"Expected %s state to match memoized state before componentDidUpdate. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",Rt(g.type)||"instance")),x.componentDidUpdate(I,j,x.__reactInternalSnapshotBeforeUpdate),Or()}var X=g.updateQueue;X!==null&&(g.type===g.elementType&&!xa&&(x.props!==g.memoizedProps&&zt(!1,"Expected %s props to match memoized props before processing the update queue. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",Rt(g.type)||"instance"),x.state!==g.memoizedState&&zt(!1,"Expected %s state to match memoized state before processing the update queue. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",Rt(g.type)||"instance")),jo(g,X,x,S));return}case P:{var $=g.updateQueue;if($!==null){var Re=null;if(g.child!==null)switch(g.child.tag){case z:Re=Ao(g.child.stateNode);break;case A:Re=g.child.stateNode;break}jo(g,$,Re,S)}return}case z:{var Pe=g.stateNode;if(d===null&&g.effectTag&Xn){var Ze=g.type,vt=g.memoizedProps;n0(Pe,Ze,vt,g)}return}case Q:return;case U:return;case Me:{if(Ft){var Tt=g.memoizedProps.onRender;typeof Tt=="function"&&(hn?Tt(g.memoizedProps.id,d===null?"mount":"update",g.actualDuration,g.treeBaseDuration,g.actualStartTime,Vv(),f.memoizedInteractions):Tt(g.memoizedProps.id,d===null?"mount":"update",g.actualDuration,g.treeBaseDuration,g.actualStartTime,Vv()))}return}case fe:{Z4(f,g);return}case ot:case Fe:case st:case qe:return;default:throw Error("This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue.")}}function W4(f,d){if(q0)for(var g=f;;){if(g.tag===z){var S=g.stateNode;d?Ga(S):aa(g.stateNode,g.memoizedProps)}else if(g.tag===Q){var x=g.stateNode;d?m0(x):H0(x,g.memoizedProps)}else if(g.tag===fe&&g.memoizedState!==null&&g.memoizedState.dehydrated===null){var I=g.child.sibling;I.return=g,g=I;continue}else if(g.child!==null){g.child.return=g,g=g.child;continue}if(g===f)return;for(;g.sibling===null;){if(g.return===null||g.return===f)return;g=g.return}g.sibling.return=g.return,g=g.sibling}}function V4(f){var d=f.ref;if(d!==null){var g=f.stateNode,S;switch(f.tag){case z:S=Ao(g);break;default:S=g}Li&&f.tag===qe&&(S=g.methods),typeof d=="function"?d(S):(d.hasOwnProperty("current")||Ie(!1,"Unexpected ref object provided for %s. Use either a ref-setter function or React.createRef().%s",Rt(f.type),Jn(f)),d.current=S)}}function G4(f){var d=f.ref;d!==null&&(typeof d=="function"?d(null):d.current=null)}function Dm(f,d,g){switch(V_(d),d.tag){case M:case ae:case pe:case Z:{var S=d.updateQueue;if(S!==null){var x=S.lastEffect;if(x!==null){var I=x.next,j=g>fr?fr:g;Jt(j,function(){var pr=I;do{var Ar=pr.destroy;Ar!==void 0&&z4(d,Ar),pr=pr.next}while(pr!==I)})}}break}case A:{mp(d);var X=d.stateNode;typeof X.componentWillUnmount=="function"&&_m(d,X);return}case z:{if(Tr){var $=d.dependencies;if($!==null){var Re=$.responders;if(Re!==null){for(var Pe=Array.from(Re.values()),Ze=0,vt=Pe.length;Ze component higher in the tree to provide a loading indicator or placeholder to display.`+Jn(g))}y_(),S=cp(S,g);var vt=d;do{switch(vt.tag){case P:{var Tt=S;vt.effectTag|=S0,vt.expirationTime=x;var St=xm(vt,Tt,x);gv(vt,St);return}case A:var Ht=S,Yn=vt.type,pr=vt.stateNode;if((vt.effectTag&hr)===Kr&&(typeof Yn.getDerivedStateFromError=="function"||pr!==null&&typeof pr.componentDidCatch=="function"&&!Fp(pr))){vt.effectTag|=S0,vt.expirationTime=x;var Ar=Rm(vt,Ht,x);gv(vt,Ar);return}break;default:break}vt=vt.return}while(vt!==null)}var n_=Math.ceil,Ep=Ye.ReactCurrentDispatcher,Am=Ye.ReactCurrentOwner,Dp=Ye.IsSomeRendererActing,Oi=0,Ic=1,r_=2,wp=4,Sp=8,Ru=16,hl=32,Vs=0,r2=1,Tp=2,Bc=3,Uc=4,Cp=5,Rn=Oi,ru=null,_n=null,I0=gt,N0=Vs,i2=null,vl=On,jc=On,o2=null,Gf=gt,u2=!1,xp=0,km=500,sn=null,l2=!1,a2=null,Yf=null,zc=!1,Kf=null,qc=M0,Rp=gt,Gs=null,i_=50,Xf=0,s2=null,o_=50,f2=0,Ys=null,Ks=null,Hc=gt;function Au(){return(Rn&(Ru|hl))!==Oi?s0(rt()):(Hc!==gt||(Hc=s0(rt())),Hc)}function u_(){return s0(rt())}function Xs(f,d,g){var S=d.mode;if((S&Mr)===lr)return On;var x=Mt();if((S&qr)===lr)return x===Vr?On:a0;if((Rn&Ru)!==Oi)return I0;var I;if(g!==null)I=ma(f,g.timeoutMs|0||Ns);else switch(x){case Vr:I=On;break;case O0:I=Za(f);break;case fr:case l0:I=sl(f);break;case _0:I=hi;break;default:throw Error("Expected a valid priority level")}return ru!==null&&I===I0&&(I-=1),I}function l_(f,d){L_(),B_(f);var g=c2(f,d);if(g===null){P_(f);return}bp(f,d),fa();var S=Mt();if(d===On?(Rn&Sp)!==Oi&&(Rn&(Ru|hl))===Oi?(ds(g,d),Wc(g)):(ou(g),ds(g,d),Rn===Oi&&Et()):(ou(g),ds(g,d)),(Rn&wp)!==Oi&&(S===O0||S===Vr))if(Gs===null)Gs=new Map([[g,d]]);else{var x=Gs.get(g);(x===void 0||x>d)&&Gs.set(g,d)}}var iu=l_;function c2(f,d){f.expirationTimex?S:x}function ou(f){var d=f.lastExpiredTime;if(d!==gt){f.callbackExpirationTime=On,f.callbackPriority=Vr,f.callbackNode=Zt(Wc.bind(null,f));return}var g=d2(f),S=f.callbackNode;if(g===gt){S!==null&&(f.callbackNode=null,f.callbackExpirationTime=gt,f.callbackPriority=M0);return}var x=Au(),I=E1(x,g);if(S!==null){var j=f.callbackPriority,X=f.callbackExpirationTime;if(X===g&&j>=I)return;kn(S)}f.callbackExpirationTime=g,f.callbackPriority=I;var $;g===On?$=Zt(Wc.bind(null,f)):ro?$=Qt(I,Ap.bind(null,f)):$=Qt(I,Ap.bind(null,f),{timeout:Po(g)-rt()}),f.callbackNode=$}function Ap(f,d){if(Hc=gt,d){var g=Au();return Yc(f,g),ou(f),null}var S=d2(f);if(S!==gt){var x=f.callbackNode;if((Rn&(Ru|hl))!==Oi)throw Error("Should not already be working.");if(fs(),(f!==ru||S!==I0)&&(Qs(f,S),jp(f,S)),_n!==null){var I=Rn;Rn|=Ru;var j=Lm(f),X=p2(f);ks(_n);do try{D_();break}catch(Pe){Fm(f,Pe)}while(!0);if(dt(),Rn=I,bm(j),hn&&h2(X),N0===r2){var $=i2;throw Lp(),Qs(f,S),Aa(f,S),ou(f),$}if(_n!==null)Lp();else{Vm();var Re=f.finishedWork=f.current.alternate;f.finishedExpirationTime=S,a_(f,Re,N0,S)}if(ou(f),f.callbackNode===x)return Ap.bind(null,f)}}return null}function a_(f,d,g,S){switch(ru=null,g){case Vs:case r2:throw Error("Root did not complete. This is a bug in React.");case Tp:{Yc(f,S>hi?hi:S);break}case Bc:{Aa(f,S);var x=f.lastSuspendedTime;S===x&&(f.nextKnownPendingLevel=Mp(d)),Bp();var I=vl===On;if(I&&!(z0&&Zs.current)){var j=xp+km-rt();if(j>10){if(u2){var X=f.lastPingedTime;if(X===gt||X>=S){f.lastPingedTime=S,Qs(f,S);break}}var $=d2(f);if($!==gt&&$!==S)break;if(x!==gt&&x!==S){f.lastPingedTime=x;break}f.timeoutHandle=lt(ss.bind(null,f),j);break}}ss(f);break}case Uc:{Aa(f,S);var Re=f.lastSuspendedTime;if(S===Re&&(f.nextKnownPendingLevel=Mp(d)),Bp(),!(z0&&Zs.current)){if(u2){var Pe=f.lastPingedTime;if(Pe===gt||Pe>=S){f.lastPingedTime=S,Qs(f,S);break}}var Ze=d2(f);if(Ze!==gt&&Ze!==S)break;if(Re!==gt&&Re!==S){f.lastPingedTime=Re;break}var vt;if(jc!==On)vt=Po(jc)-rt();else if(vl===On)vt=0;else{var Tt=__(vl),St=rt(),Ht=Po(S)-St,Yn=St-Tt;Yn<0&&(Yn=0),vt=N_(Yn)-Yn,Ht10){f.timeoutHandle=lt(ss.bind(null,f),vt);break}}ss(f);break}case Cp:{if(!(z0&&Zs.current)&&vl!==On&&o2!==null){var pr=F_(vl,S,o2);if(pr>10){Aa(f,S),f.timeoutHandle=lt(ss.bind(null,f),pr);break}}ss(f);break}default:throw Error("Unknown root exit status.")}}function Wc(f){var d=f.lastExpiredTime,g=d!==gt?d:On;if(f.finishedExpirationTime===g)ss(f);else{if((Rn&(Ru|hl))!==Oi)throw Error("Should not already be working.");if(fs(),(f!==ru||g!==I0)&&(Qs(f,g),jp(f,g)),_n!==null){var S=Rn;Rn|=Ru;var x=Lm(f),I=p2(f);ks(_n);do try{Um();break}catch(X){Fm(f,X)}while(!0);if(dt(),Rn=S,bm(x),hn&&h2(I),N0===r2){var j=i2;throw Lp(),Qs(f,g),Aa(f,g),ou(f),j}if(_n!==null)throw Error("Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue.");Vm(),f.finishedWork=f.current.alternate,f.finishedExpirationTime=g,s_(f,N0,g),ou(f)}}return null}function s_(f,d,g){ru=null,(d===Bc||d===Uc)&&Bp(),ss(f)}function f_(f,d){Yc(f,d),ou(f),(Rn&(Ru|hl))===Oi&&Et()}function Om(){if((Rn&(Ic|Ru|hl))!==Oi){(Rn&Ru)!==Oi&&zt(!1,"unstable_flushDiscreteUpdates: Cannot flush updates when React is already rendering.");return}d_(),fs()}function c_(f){return Jt(fr,f)}function Mm(f,d,g,S){return Jt(Vr,f.bind(null,d,g,S))}function d_(){if(Gs!==null){var f=Gs;Gs=null,f.forEach(function(d,g){Yc(g,d),ou(g)}),Et()}}function p_(f,d){var g=Rn;Rn|=Ic;try{return f(d)}finally{Rn=g,Rn===Oi&&Et()}}function h_(f,d){var g=Rn;Rn|=r_;try{return f(d)}finally{Rn=g,Rn===Oi&&Et()}}function Nm(f,d,g,S){var x=Rn;Rn|=wp;try{return Jt(O0,f.bind(null,d,g,S))}finally{Rn=x,Rn===Oi&&Et()}}function v_(f,d){var g=Rn;Rn&=~Ic,Rn|=Sp;try{return f(d)}finally{Rn=g,Rn===Oi&&Et()}}function kp(f,d){if((Rn&(Ru|hl))!==Oi)throw Error("flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering.");var g=Rn;Rn|=Ic;try{return Jt(Vr,f.bind(null,d))}finally{Rn=g,Et()}}function m_(f){var d=Rn;Rn|=Ic;try{Jt(Vr,f)}finally{Rn=d,Rn===Oi&&Et()}}function Qs(f,d){f.finishedWork=null,f.finishedExpirationTime=gt;var g=f.timeoutHandle;if(g!==yu&&(f.timeoutHandle=yu,oo(g)),_n!==null)for(var S=_n.return;S!==null;)ym(S),S=S.return;ru=f,_n=ps(f.current,null,d),I0=d,N0=Vs,i2=null,vl=On,jc=On,o2=null,Gf=gt,u2=!1,hn&&(Ks=null),Du.discardPendingWarnings(),Kl=null}function Fm(f,d){do{try{if(dt(),j1(),Ge(),_n===null||_n.return===null)return N0=r2,i2=d,null;Ft&&_n.mode&Cr&&Y1(_n,!0),t_(f,_n.return,_n,d,I0),_n=zm(_n)}catch(g){d=g;continue}return}while(!0)}function Lm(f){var d=Ep.current;return Ep.current=G1,d===null?G1:d}function bm(f){Ep.current=f}function p2(f){if(hn){var d=O.__interactionsRef.current;return O.__interactionsRef.current=f.memoizedInteractions,d}return null}function h2(f){hn&&(O.__interactionsRef.current=f)}function Op(){xp=rt()}function Pm(f,d){fhi&&(vl=f),d!==null&&fhi&&(jc=f,o2=d)}function v2(f){f>Gf&&(Gf=f)}function Im(){N0===Vs&&(N0=Bc)}function Bm(){(N0===Vs||N0===Bc)&&(N0=Uc),Gf!==gt&&ru!==null&&(Aa(ru,I0),ny(ru,Gf))}function y_(){N0!==Cp&&(N0=Tp)}function g_(){return N0===Vs}function __(f){var d=Po(f);return d-Ns}function E_(f,d){var g=Po(f);return g-(d.timeoutMs|0||Ns)}function Um(){for(;_n!==null;)_n=jm(_n)}function D_(){for(;_n!==null&&!an();)_n=jm(_n)}function jm(f){var d=f.alternate;qu(f),at(f);var g;return Ft&&(f.mode&Cr)!==lr?(zd(f),g=Vc(d,f,I0),Y1(f,!0)):g=Vc(d,f,I0),Ge(),f.memoizedProps=f.pendingProps,g===null&&(g=zm(f)),Am.current=null,g}function zm(f){_n=f;do{var d=_n.alternate,g=_n.return;if((_n.effectTag&F0)===Kr){at(_n);var S=void 0;if(!Ft||(_n.mode&Cr)===lr?S=mm(d,_n,I0):(zd(_n),S=mm(d,_n,I0),Y1(_n,!1)),pi(_n),Ge(),w_(_n),S!==null)return S;if(g!==null&&(g.effectTag&F0)===Kr){g.firstEffect===null&&(g.firstEffect=_n.firstEffect),_n.lastEffect!==null&&(g.lastEffect!==null&&(g.lastEffect.nextEffect=_n.firstEffect),g.lastEffect=_n.lastEffect);var x=_n.effectTag;x>Ai&&(g.lastEffect!==null?g.lastEffect.nextEffect=_n:g.firstEffect=_n,g.lastEffect=_n)}}else{var I=L4(_n,I0);if(Ft&&(_n.mode&Cr)!==lr){Y1(_n,!1);for(var j=_n.actualDuration,X=_n.child;X!==null;)j+=X.actualDuration,X=X.sibling;_n.actualDuration=j}if(I!==null)return Fo(_n),I.effectTag&=Lu,I;pi(_n),g!==null&&(g.firstEffect=g.lastEffect=null,g.effectTag|=F0)}var $=_n.sibling;if($!==null)return $;_n=g}while(_n!==null);return N0===Vs&&(N0=Cp),null}function Mp(f){var d=f.expirationTime,g=f.childExpirationTime;return d>g?d:g}function w_(f){if(!(I0!==xr&&f.childExpirationTime===xr)){var d=gt;if(Ft&&(f.mode&Cr)!==lr){for(var g=f.actualDuration,S=f.selfBaseDuration,x=f.alternate===null||f.child!==f.alternate.child,I=f.child;I!==null;){var j=I.expirationTime,X=I.childExpirationTime;j>d&&(d=j),X>d&&(d=X),x&&(g+=I.actualDuration),S+=I.treeBaseDuration,I=I.sibling}f.actualDuration=g,f.treeBaseDuration=S}else for(var $=f.child;$!==null;){var Re=$.expirationTime,Pe=$.childExpirationTime;Re>d&&(d=Re),Pe>d&&(d=Pe),$=$.sibling}f.childExpirationTime=d}}function ss(f){var d=Mt();return Jt(Vr,S_.bind(null,f,d)),null}function S_(f,d){do fs();while(Kf!==null);if(b_(),(Rn&(Ru|hl))!==Oi)throw Error("Should not already be working.");var g=f.finishedWork,S=f.finishedExpirationTime;if(g===null)return null;if(f.finishedWork=null,f.finishedExpirationTime=gt,g===f.current)throw Error("Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue.");f.callbackNode=null,f.callbackExpirationTime=gt,f.callbackPriority=M0,f.nextKnownPendingLevel=gt,G0();var x=Mp(g);aE(f,S,x),f===ru&&(ru=null,_n=null,I0=gt);var I;if(g.effectTag>Ai?g.lastEffect!==null?(g.lastEffect.nextEffect=g,I=g.firstEffect):I=g:I=g.firstEffect,I!==null){var j=Rn;Rn|=hl;var X=p2(f);Am.current=null,Qo(),mn(f.containerInfo),sn=I;do if(as(null,T_,null),Gl()){if(sn===null)throw Error("Should be working on an effect.");var $=Yl();Js(sn,$),sn=sn.nextEffect}while(sn!==null);Jo(),Ft&&Gv(),Zo(),sn=I;do if(as(null,C_,null,f,d),Gl()){if(sn===null)throw Error("Should be working on an effect.");var Re=Yl();Js(sn,Re),sn=sn.nextEffect}while(sn!==null);Y0(),vr(f.containerInfo),f.current=g,ur(),sn=I;do if(as(null,Np,null,f,S),Gl()){if(sn===null)throw Error("Should be working on an effect.");var Pe=Yl();Js(sn,Pe),sn=sn.nextEffect}while(sn!==null);R0(),sn=null,te(),hn&&h2(X),Rn=j}else f.current=g,Qo(),Jo(),Ft&&Gv(),Zo(),Y0(),ur(),R0();Ll();var Ze=zc;if(zc)zc=!1,Kf=f,Rp=S,qc=d;else for(sn=I;sn!==null;){var vt=sn.nextEffect;sn.nextEffect=null,sn=vt}var Tt=f.firstPendingTime;if(Tt!==gt){if(hn){if(Ks!==null){var St=Ks;Ks=null;for(var Ht=0;Htfr?fr:qc;return qc=M0,Jt(f,x_)}}function x_(){if(Kf===null)return!1;var f=Kf,d=Rp;if(Kf=null,Rp=gt,(Rn&(Ru|hl))!==Oi)throw Error("Cannot flush passive effects while already rendering.");var g=Rn;Rn|=hl;for(var S=p2(f),x=f.current.firstEffect;x!==null;){{if(at(x),as(null,H4,null,x),Gl()){if(x===null)throw Error("Should be working on an effect.");var I=Yl();Js(x,I)}Ge()}var j=x.nextEffect;x.nextEffect=null,x=j}return hn&&(h2(S),Qm(f,d)),Rn=g,Et(),f2=Kf===null?0:f2+1,!0}function Fp(f){return Yf!==null&&Yf.has(f)}function R_(f){Yf===null?Yf=new Set([f]):Yf.add(f)}function A_(f){l2||(l2=!0,a2=f)}var k_=A_;function qm(f,d,g){var S=cp(g,d),x=xm(f,S,On);ts(f,x);var I=c2(f,On);I!==null&&(ou(I),ds(I,On))}function Js(f,d){if(f.tag===P){qm(f,f,d);return}for(var g=f.return;g!==null;){if(g.tag===P){qm(g,f,d);return}else if(g.tag===A){var S=g.type,x=g.stateNode;if(typeof S.getDerivedStateFromError=="function"||typeof x.componentDidCatch=="function"&&!Fp(x)){var I=cp(d,f),j=Rm(g,I,On);ts(g,j);var X=c2(g,On);X!==null&&(ou(X),ds(X,On));return}}g=g.return}}function Hm(f,d,g){var S=f.pingCache;if(S!==null&&S.delete(d),ru===f&&I0===g){N0===Uc||N0===Bc&&vl===On&&rt()-xpi_)throw Xf=0,s2=null,Error("Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.");f2>o_&&(f2=0,zt(!1,"Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render."))}function b_(){Du.flushLegacyContextWarning(),Ir&&Du.flushPendingUnsafeLifecycleWarnings()}function Vm(){var f=!0;Os(Ys,f),Ys=null}function Lp(){var f=!1;Os(Ys,f),Ys=null}function bp(f,d){or&&ru!==null&&d>I0&&(Ys=f)}var m2=null;function P_(f){{var d=f.tag;if(d!==P&&d!==A&&d!==M&&d!==ae&&d!==pe&&d!==Z)return;var g=Rt(f.type)||"ReactComponent";if(m2!==null){if(m2.has(g))return;m2.add(g)}else m2=new Set([g]);Ie(!1,"Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in %s.%s",d===A?"the componentWillUnmount method":"a useEffect cleanup function",Jn(f))}}var Vc;if(j0){var I_=null;Vc=function(f,d,g){var S=ey(I_,d);try{return up(f,d,g)}catch(I){if(I!==null&&typeof I=="object"&&typeof I.then=="function")throw I;if(dt(),j1(),ym(d),ey(d,S),Ft&&d.mode&Cr&&zd(d),as(null,up,null,f,d,g),Gl()){var x=Yl();throw x}else throw I}}}else Vc=up;var Gm=!1,Ym=!1;function B_(f){if(f.tag===A)switch($n){case"getChildContext":if(Ym)return;Ie(!1,"setState(...): Cannot call setState() inside getChildContext()"),Ym=!0;break;case"render":if(Gm)return;Ie(!1,"Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state."),Gm=!0;break}}var Zs={current:!1};function Pp(f){nl===!0&&Dp.current===!0&&Zs.current!==!0&&Ie(!1,`It looks like you're using the wrong act() around your test interactions. +Be sure to use the matching version of act() corresponding to your renderer: + +// for react-dom: +import {act} from 'react-dom/test-utils'; +// ... +act(() => ...); + +// for react-test-renderer: +import TestRenderer from 'react-test-renderer'; +const {act} = TestRenderer; +// ... +act(() => ...);%s`,Jn(f))}function Km(f){nl===!0&&(f.mode&zn)!==lr&&Dp.current===!1&&Zs.current===!1&&Ie(!1,`An update to %s ran an effect, but was not wrapped in act(...). + +When testing, code that causes React state updates should be wrapped into act(...): + +act(() => { + /* fire events that update state */ +}); +/* assert on the output */ + +This ensures that you're testing the behavior the user would see in the browser. Learn more at https://fb.me/react-wrap-tests-with-act%s`,Rt(f.type),Jn(f))}function U_(f){nl===!0&&Rn===Oi&&Dp.current===!1&&Zs.current===!1&&Ie(!1,`An update to %s inside a test was not wrapped in act(...). + +When testing, code that causes React state updates should be wrapped into act(...): + +act(() => { + /* fire events that update state */ +}); +/* assert on the output */ + +This ensures that you're testing the behavior the user would see in the browser. Learn more at https://fb.me/react-wrap-tests-with-act%s`,Rt(f.type),Jn(f))}var j_=U_,Ip=!1;function z_(f){Ip===!1&&t.unstable_flushAllWithoutAsserting===void 0&&(f.mode&Mr||f.mode&qr?(Ip=!0,Ie(!1,`In Concurrent or Sync modes, the "scheduler" module needs to be mocked to guarantee consistent behaviour across tests and browsers. For example, with jest: +jest.mock('scheduler', () => require('scheduler/unstable_mock')); + +For more info, visit https://fb.me/react-mock-scheduler`)):di===!0&&(Ip=!0,Ie(!1,`Starting from React v17, the "scheduler" module will need to be mocked to guarantee consistent behaviour across tests and browsers. For example, with jest: +jest.mock('scheduler', () => require('scheduler/unstable_mock')); + +For more info, visit https://fb.me/react-mock-scheduler`)))}var Kl=null;function q_(f){{var d=Mt();if((f.mode&qr)!==Kr&&(d===O0||d===Vr))for(var g=f;g!==null;){var S=g.alternate;if(S!==null)switch(g.tag){case A:var x=S.updateQueue;if(x!==null)for(var I=x.firstUpdate;I!==null;){var j=I.priority;if(j===O0||j===Vr){Kl===null?Kl=new Set([Rt(g.type)]):Kl.add(Rt(g.type));break}I=I.next}break;case M:case ae:case Z:if(g.memoizedState!==null&&g.memoizedState.baseUpdate!==null)for(var X=g.memoizedState.baseUpdate;X!==null;){var $=X.priority;if($===O0||$===Vr){Kl===null?Kl=new Set([Rt(g.type)]):Kl.add(Rt(g.type));break}if(X.next===g.memoizedState.baseUpdate)break;X=X.next}break;default:break}g=g.return}}}function Bp(){if(Kl!==null){var f=[];Kl.forEach(function(d){return f.push(d)}),Kl=null,f.length>0&&Ie(!1,`%s triggered a user-blocking update that suspended. + +The fix is to split the update into multiple parts: a user-blocking update to provide immediate feedback, and another update that triggers the bulk of the changes. + +Refer to the documentation for useTransition to learn how to implement this pattern.`,f.sort().join(", "))}}function Up(f,d){return d*1e3+f.interactionThreadID}function cs(f){!hn||(Ks===null?Ks=[f]:Ks.push(f))}function Xm(f,d,g){if(!!hn&&g.size>0){var S=f.pendingInteractionMap,x=S.get(d);x!=null?g.forEach(function(X){x.has(X)||X.__count++,x.add(X)}):(S.set(d,new Set(g)),g.forEach(function(X){X.__count++}));var I=O.__subscriberRef.current;if(I!==null){var j=Up(f,d);I.onWorkScheduled(g,j)}}}function ds(f,d){!hn||Xm(f,d,O.__interactionsRef.current)}function jp(f,d){if(!!hn){var g=new Set;if(f.pendingInteractionMap.forEach(function(I,j){j>=d&&I.forEach(function(X){return g.add(X)})}),f.memoizedInteractions=g,g.size>0){var S=O.__subscriberRef.current;if(S!==null){var x=Up(f,d);try{S.onWorkStarted(g,x)}catch(I){Qt(Vr,function(){throw I})}}}}}function Qm(f,d){if(!!hn){var g=f.firstPendingTime,S;try{if(S=O.__subscriberRef.current,S!==null&&f.memoizedInteractions.size>0){var x=Up(f,d);S.onWorkStopped(f.memoizedInteractions,x)}}catch(j){Qt(Vr,function(){throw j})}finally{var I=f.pendingInteractionMap;I.forEach(function(j,X){X>g&&(I.delete(X),j.forEach(function($){if($.__count--,S!==null&&$.__count===0)try{S.onInteractionScheduledWorkCompleted($)}catch(Re){Qt(Vr,function(){throw Re})}}))})}}}var zp=null,qp=null,y2=!1,H_=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u";function Jm(f){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u")return!1;var d=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(d.isDisabled)return!0;if(!d.supportsFiber)return Ie(!1,"The installed version of React DevTools is too old and will not work with the current version of React. Please update React DevTools. https://fb.me/react-devtools"),!0;try{var g=d.inject(f);zp=function(S,x){try{var I=(S.current.effectTag&hr)===hr;if(Ft){var j=u_(),X=E1(j,x);d.onCommitFiberRoot(g,S,X,I)}else d.onCommitFiberRoot(g,S,void 0,I)}catch($){y2||(y2=!0,Ie(!1,"React DevTools encountered an error: %s",$))}},qp=function(S){try{d.onCommitFiberUnmount(g,S)}catch(x){y2||(y2=!0,Ie(!1,"React DevTools encountered an error: %s",x))}}}catch(S){Ie(!1,"React DevTools encountered an error: %s.",S)}return!0}function W_(f,d){typeof zp=="function"&&zp(f,d)}function V_(f){typeof qp=="function"&&qp(f)}var Hp;{Hp=!1;try{var Zm=Object.preventExtensions({}),G_=new Map([[Zm,null]]),Y_=new Set([Zm]);G_.set(0,0),Y_.add(0)}catch{Hp=!0}}var K_=1;function X_(f,d,g,S){this.tag=f,this.key=g,this.elementType=null,this.type=null,this.stateNode=null,this.return=null,this.child=null,this.sibling=null,this.index=0,this.ref=null,this.pendingProps=d,this.memoizedProps=null,this.updateQueue=null,this.memoizedState=null,this.dependencies=null,this.mode=S,this.effectTag=Kr,this.nextEffect=null,this.firstEffect=null,this.lastEffect=null,this.expirationTime=gt,this.childExpirationTime=gt,this.alternate=null,Ft&&(this.actualDuration=Number.NaN,this.actualStartTime=Number.NaN,this.selfBaseDuration=Number.NaN,this.treeBaseDuration=Number.NaN,this.actualDuration=0,this.actualStartTime=-1,this.selfBaseDuration=0,this.treeBaseDuration=0),or&&(this._debugID=K_++,this._debugIsCurrentlyTiming=!1),this._debugSource=null,this._debugOwner=null,this._debugNeedsRemount=!1,this._debugHookTypes=null,!Hp&&typeof Object.preventExtensions=="function"&&Object.preventExtensions(this)}var uu=function(f,d,g,S){return new X_(f,d,g,S)};function Gc(f){var d=f.prototype;return!!(d&&d.isReactComponent)}function Q_(f){return typeof f=="function"&&!Gc(f)&&f.defaultProps===void 0}function J_(f){if(typeof f=="function")return Gc(f)?A:M;if(f!=null){var d=f.$$typeof;if(d===pn)return ae;if(d===Ot)return pe}return T}function ps(f,d,g){var S=f.alternate;S===null?(S=uu(f.tag,d,f.key,f.mode),S.elementType=f.elementType,S.type=f.type,S.stateNode=f.stateNode,S._debugID=f._debugID,S._debugSource=f._debugSource,S._debugOwner=f._debugOwner,S._debugHookTypes=f._debugHookTypes,S.alternate=f,f.alternate=S):(S.pendingProps=d,S.effectTag=Kr,S.nextEffect=null,S.firstEffect=null,S.lastEffect=null,Ft&&(S.actualDuration=0,S.actualStartTime=-1)),S.childExpirationTime=f.childExpirationTime,S.expirationTime=f.expirationTime,S.child=f.child,S.memoizedProps=f.memoizedProps,S.memoizedState=f.memoizedState,S.updateQueue=f.updateQueue;var x=f.dependencies;switch(S.dependencies=x===null?null:{expirationTime:x.expirationTime,firstContext:x.firstContext,responders:x.responders},S.sibling=f.sibling,S.index=f.index,S.ref=f.ref,Ft&&(S.selfBaseDuration=f.selfBaseDuration,S.treeBaseDuration=f.treeBaseDuration),S._debugNeedsRemount=f._debugNeedsRemount,S.tag){case T:case M:case Z:S.type=Uo(f.type);break;case A:S.type=Ps(f.type);break;case ae:S.type=Is(f.type);break;default:break}return S}function Z_(f,d){f.effectTag&=br,f.nextEffect=null,f.firstEffect=null,f.lastEffect=null;var g=f.alternate;if(g===null)f.childExpirationTime=gt,f.expirationTime=d,f.child=null,f.memoizedProps=null,f.memoizedState=null,f.updateQueue=null,f.dependencies=null,Ft&&(f.selfBaseDuration=0,f.treeBaseDuration=0);else{f.childExpirationTime=g.childExpirationTime,f.expirationTime=g.expirationTime,f.child=g.child,f.memoizedProps=g.memoizedProps,f.memoizedState=g.memoizedState,f.updateQueue=g.updateQueue;var S=g.dependencies;f.dependencies=S===null?null:{expirationTime:S.expirationTime,firstContext:S.firstContext,responders:S.responders},Ft&&(f.selfBaseDuration=g.selfBaseDuration,f.treeBaseDuration=g.treeBaseDuration)}return f}function $_(f){var d;return f===co?d=qr|Mr|zn:f===K0?d=Mr|zn:d=lr,Ft&&H_&&(d|=Cr),uu(P,null,null,d)}function Wp(f,d,g,S,x,I){var j,X=T,$=f;if(typeof f=="function")Gc(f)?(X=A,$=Ps($)):$=Uo($);else if(typeof f=="string")X=z;else{e:switch(f){case ee:return Xl(g.children,x,I,d);case Xt:X=de,x|=qr|Mr|zn;break;case Oe:X=de,x|=zn;break;case et:return tE(g,x,I,d);case Nn:return nE(g,x,I,d);case Wt:return rE(g,x,I,d);default:{if(typeof f=="object"&&f!==null)switch(f.$$typeof){case ct:X=le;break e;case Lt:X=ye;break e;case pn:X=ae,$=Is($);break e;case Ot:X=pe;break e;case Wn:X=Ae,$=null;break e;case w:if(xt)return $m(f,g,x,I,d);break;case wn:if(Li)return eE(f,g,x,I,d)}var Re="";{(f===void 0||typeof f=="object"&&f!==null&&Object.keys(f).length===0)&&(Re+=" You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.");var Pe=S?Rt(S.type):null;Pe&&(Re+=` + +Check the render method of \``+Pe+"`.")}throw Error("Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: "+(f==null?f:typeof f)+"."+Re)}}}return j=uu(X,g,d,x),j.elementType=f,j.type=$,j.expirationTime=I,j}function Vp(f,d,g){var S=null;S=f._owner;var x=f.type,I=f.key,j=f.props,X=Wp(x,I,j,S,d,g);return X._debugSource=f._source,X._debugOwner=f._owner,X}function Xl(f,d,g,S){var x=uu(v,f,S,d);return x.expirationTime=g,x}function $m(f,d,g,S,x){var I=uu(st,d,x,g);return I.elementType=f,I.type=f,I.expirationTime=S,I}function eE(f,d,g,S,x){var I=uu(qe,d,x,g);return I.type=f,I.elementType=f,I.expirationTime=S,I}function tE(f,d,g,S){(typeof f.id!="string"||typeof f.onRender!="function")&&Ie(!1,'Profiler must specify an "id" string and "onRender" function as props');var x=uu(Me,f,S,d|Cr);return x.elementType=et,x.type=et,x.expirationTime=g,x}function nE(f,d,g,S){var x=uu(fe,f,S,d);return x.type=Nn,x.elementType=Nn,x.expirationTime=g,x}function rE(f,d,g,S){var x=uu(ot,f,S,d);return x.type=Wt,x.elementType=Wt,x.expirationTime=g,x}function Gp(f,d,g){var S=uu(Q,f,null,d);return S.expirationTime=g,S}function iE(){var f=uu(z,null,null,lr);return f.elementType="DELETED",f.type="DELETED",f}function oE(f){var d=uu(He,null,null,lr);return d.stateNode=f,d}function Yp(f,d,g){var S=f.children!==null?f.children:[],x=uu(U,S,f.key,d);return x.expirationTime=g,x.stateNode={containerInfo:f.containerInfo,pendingChildren:null,implementation:f.implementation},x}function ey(f,d){return f===null&&(f=uu(T,null,null,lr)),f.tag=d.tag,f.key=d.key,f.elementType=d.elementType,f.type=d.type,f.stateNode=d.stateNode,f.return=d.return,f.child=d.child,f.sibling=d.sibling,f.index=d.index,f.ref=d.ref,f.pendingProps=d.pendingProps,f.memoizedProps=d.memoizedProps,f.updateQueue=d.updateQueue,f.memoizedState=d.memoizedState,f.dependencies=d.dependencies,f.mode=d.mode,f.effectTag=d.effectTag,f.nextEffect=d.nextEffect,f.firstEffect=d.firstEffect,f.lastEffect=d.lastEffect,f.expirationTime=d.expirationTime,f.childExpirationTime=d.childExpirationTime,f.alternate=d.alternate,Ft&&(f.actualDuration=d.actualDuration,f.actualStartTime=d.actualStartTime,f.selfBaseDuration=d.selfBaseDuration,f.treeBaseDuration=d.treeBaseDuration),f._debugID=d._debugID,f._debugSource=d._debugSource,f._debugOwner=d._debugOwner,f._debugIsCurrentlyTiming=d._debugIsCurrentlyTiming,f._debugNeedsRemount=d._debugNeedsRemount,f._debugHookTypes=d._debugHookTypes,f}function uE(f,d,g){this.tag=d,this.current=null,this.containerInfo=f,this.pendingChildren=null,this.pingCache=null,this.finishedExpirationTime=gt,this.finishedWork=null,this.timeoutHandle=yu,this.context=null,this.pendingContext=null,this.hydrate=g,this.callbackNode=null,this.callbackPriority=M0,this.firstPendingTime=gt,this.firstSuspendedTime=gt,this.lastSuspendedTime=gt,this.nextKnownPendingLevel=gt,this.lastPingedTime=gt,this.lastExpiredTime=gt,hn&&(this.interactionThreadID=O.unstable_getThreadID(),this.memoizedInteractions=new Set,this.pendingInteractionMap=new Map),ti&&(this.hydrationCallbacks=null)}function lE(f,d,g,S){var x=new uE(f,d,g);ti&&(x.hydrationCallbacks=S);var I=$_(d);return x.current=I,I.stateNode=x,x}function ty(f,d){var g=f.firstSuspendedTime,S=f.lastSuspendedTime;return g!==gt&&g>=d&&S<=d}function Aa(f,d){var g=f.firstSuspendedTime,S=f.lastSuspendedTime;gd||g===gt)&&(f.lastSuspendedTime=d),d<=f.lastPingedTime&&(f.lastPingedTime=gt),d<=f.lastExpiredTime&&(f.lastExpiredTime=gt)}function ny(f,d){var g=f.firstPendingTime;d>g&&(f.firstPendingTime=d);var S=f.firstSuspendedTime;S!==gt&&(d>=S?f.firstSuspendedTime=f.lastSuspendedTime=f.nextKnownPendingLevel=gt:d>=f.lastSuspendedTime&&(f.lastSuspendedTime=d+1),d>f.nextKnownPendingLevel&&(f.nextKnownPendingLevel=d))}function aE(f,d,g){f.firstPendingTime=g,d<=f.lastSuspendedTime?f.firstSuspendedTime=f.lastSuspendedTime=f.nextKnownPendingLevel=gt:d<=f.firstSuspendedTime&&(f.firstSuspendedTime=d-1),d<=f.lastPingedTime&&(f.lastPingedTime=gt),d<=f.lastExpiredTime&&(f.lastExpiredTime=gt)}function Yc(f,d){var g=f.lastExpiredTime;(g===gt||g>d)&&(f.lastExpiredTime=d)}var sE={debugTool:null},g2=sE,Kp,Xp;Kp=!1,Xp={};function fE(f){if(!f)return dn;var d=kt(f),g=Hu(d);if(d.tag===A){var S=d.type;if(ri(S))return fo(d,S,g)}return g}function Qp(f){var d=kt(f);if(d===void 0)throw typeof f.render=="function"?Error("Unable to find node on an unmounted component."):Error("Argument appears to not be a ReactComponent. Keys: "+Object.keys(f));var g=Ro(d);return g===null?null:g.stateNode}function cE(f,d){{var g=kt(f);if(g===void 0)throw typeof f.render=="function"?Error("Unable to find node on an unmounted component."):Error("Argument appears to not be a ReactComponent. Keys: "+Object.keys(f));var S=Ro(g);if(S===null)return null;if(S.mode&zn){var x=Rt(g.type)||"Component";Xp[x]||(Xp[x]=!0,g.mode&zn?Ie(!1,"%s is deprecated in StrictMode. %s was passed an instance of %s which is inside StrictMode. Instead, add a ref directly to the element you want to reference. Learn more about using refs safely here: https://fb.me/react-strict-mode-find-node%s",d,d,x,Jn(S)):Ie(!1,"%s is deprecated in StrictMode. %s was passed an instance of %s which renders StrictMode children. Instead, add a ref directly to the element you want to reference. Learn more about using refs safely here: https://fb.me/react-strict-mode-find-node%s",d,d,x,Jn(S)))}return S.stateNode}return Qp(f)}function dE(f,d,g,S){return lE(f,d,g,S)}function ry(f,d,g,S){var x=d.current,I=Au();typeof jest<"u"&&(z_(x),Pp(x));var j=ho(),X=Xs(I,x,j);g2.debugTool&&(x.alternate===null?g2.debugTool.onMountContainer(d):f===null?g2.debugTool.onUnmountContainer(d):g2.debugTool.onUpdateContainer(d));var $=fE(g);d.context===null?d.context=$:d.pendingContext=$,$n==="render"&&nn!==null&&!Kp&&(Kp=!0,Ie(!1,`Render methods should be a pure function of props and state; triggering nested component updates from render is not allowed. If necessary, trigger nested updates in componentDidUpdate. + +Check the render method of %s.`,Rt(nn.type)||"Unknown"));var Re=ji(X,j);return Re.payload={element:f},S=S===void 0?null:S,S!==null&&(typeof S!="function"&&Ie(!1,"render(...): Expected the last optional `callback` argument to be a function. Instead received: %s.",S),Re.callback=S),ts(x,Re),iu(x,X),X}function pE(f){var d=f.current;if(!d.child)return null;switch(d.child.tag){case z:return Ao(d.child.stateNode);default:return d.child.stateNode}}function hE(f){switch(f.tag){case P:var d=f.stateNode;d.hydrate&&f_(d,d.firstPendingTime);break;case fe:kp(function(){return iu(f,On)});var g=Za(Au());_2(f,g);break}}function iy(f,d){var g=f.memoizedState;g!==null&&g.dehydrated!==null&&g.retryTime=d.length)return S;var x=d[g],I=Array.isArray(f)?f.slice():c({},f);return I[x]=$p(f[x],d,g+1,S),I},fy=function(f,d,g){return $p(f,d,0,g)};uy=function(f,d,g,S){for(var x=f.memoizedState;x!==null&&d>0;)x=x.next,d--;if(x!==null){var I=fy(x.memoizedState,g,S);x.memoizedState=I,x.baseState=I,f.memoizedProps=c({},f.memoizedProps),iu(f,On)}},ly=function(f,d,g){f.pendingProps=fy(f.memoizedProps,d,g),f.alternate&&(f.alternate.pendingProps=f.pendingProps),iu(f,On)},ay=function(f){iu(f,On)},sy=function(f){Zp=f}}function gE(f){var d=f.findFiberByHostInstance,g=Ye.ReactCurrentDispatcher;return Jm(c({},f,{overrideHookState:uy,overrideProps:ly,setSuspenseHandler:sy,scheduleUpdate:ay,currentDispatcherRef:g,findHostInstanceByFiber:function(S){var x=Ro(S);return x===null?null:x.stateNode},findFiberByHostInstance:function(S){return d?d(S):null},findHostInstancesForRefresh:x1,scheduleRefresh:Da,scheduleRoot:C1,setRefreshHandler:kf,getCurrentFiber:function(){return nn}}))}var cy=Object.freeze({createContainer:dE,updateContainer:ry,batchedEventUpdates:h_,batchedUpdates:p_,unbatchedUpdates:v_,deferredUpdates:c_,syncUpdates:Mm,discreteUpdates:Nm,flushDiscreteUpdates:Om,flushControlled:m_,flushSync:kp,flushPassiveEffects:fs,IsThisRendererActing:Zs,getPublicRootInstance:pE,attemptSynchronousHydration:hE,attemptUserBlockingHydration:vE,attemptContinuousHydration:Jp,attemptHydrationAtCurrentPriority:mE,findHostInstance:Qp,findHostInstanceWithWarning:cE,findHostInstanceWithNoPortals:yE,shouldSuspend:oy,injectIntoDevTools:gE}),_E=cy.default||cy;Mh.exports=_E;var EE=Mh.exports;return Mh.exports=u,EE})});var G9=re((wre,h3)=>{"use strict";process.env.NODE_ENV==="production"?h3.exports=z9():h3.exports=V9()});var K9=re((Sre,Y9)=>{"use strict";var RX={ALIGN_COUNT:8,ALIGN_AUTO:0,ALIGN_FLEX_START:1,ALIGN_CENTER:2,ALIGN_FLEX_END:3,ALIGN_STRETCH:4,ALIGN_BASELINE:5,ALIGN_SPACE_BETWEEN:6,ALIGN_SPACE_AROUND:7,DIMENSION_COUNT:2,DIMENSION_WIDTH:0,DIMENSION_HEIGHT:1,DIRECTION_COUNT:3,DIRECTION_INHERIT:0,DIRECTION_LTR:1,DIRECTION_RTL:2,DISPLAY_COUNT:2,DISPLAY_FLEX:0,DISPLAY_NONE:1,EDGE_COUNT:9,EDGE_LEFT:0,EDGE_TOP:1,EDGE_RIGHT:2,EDGE_BOTTOM:3,EDGE_START:4,EDGE_END:5,EDGE_HORIZONTAL:6,EDGE_VERTICAL:7,EDGE_ALL:8,EXPERIMENTAL_FEATURE_COUNT:1,EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS:0,FLEX_DIRECTION_COUNT:4,FLEX_DIRECTION_COLUMN:0,FLEX_DIRECTION_COLUMN_REVERSE:1,FLEX_DIRECTION_ROW:2,FLEX_DIRECTION_ROW_REVERSE:3,JUSTIFY_COUNT:6,JUSTIFY_FLEX_START:0,JUSTIFY_CENTER:1,JUSTIFY_FLEX_END:2,JUSTIFY_SPACE_BETWEEN:3,JUSTIFY_SPACE_AROUND:4,JUSTIFY_SPACE_EVENLY:5,LOG_LEVEL_COUNT:6,LOG_LEVEL_ERROR:0,LOG_LEVEL_WARN:1,LOG_LEVEL_INFO:2,LOG_LEVEL_DEBUG:3,LOG_LEVEL_VERBOSE:4,LOG_LEVEL_FATAL:5,MEASURE_MODE_COUNT:3,MEASURE_MODE_UNDEFINED:0,MEASURE_MODE_EXACTLY:1,MEASURE_MODE_AT_MOST:2,NODE_TYPE_COUNT:2,NODE_TYPE_DEFAULT:0,NODE_TYPE_TEXT:1,OVERFLOW_COUNT:3,OVERFLOW_VISIBLE:0,OVERFLOW_HIDDEN:1,OVERFLOW_SCROLL:2,POSITION_TYPE_COUNT:2,POSITION_TYPE_RELATIVE:0,POSITION_TYPE_ABSOLUTE:1,PRINT_OPTIONS_COUNT:3,PRINT_OPTIONS_LAYOUT:1,PRINT_OPTIONS_STYLE:2,PRINT_OPTIONS_CHILDREN:4,UNIT_COUNT:4,UNIT_UNDEFINED:0,UNIT_POINT:1,UNIT_PERCENT:2,UNIT_AUTO:3,WRAP_COUNT:3,WRAP_NO_WRAP:0,WRAP_WRAP:1,WRAP_WRAP_REVERSE:2};Y9.exports=RX});var Z9=re((Tre,J9)=>{"use strict";var AX=Object.assign||function(u){for(var l=1;l"}}]),u}(),X9=function(){pg(u,null,[{key:"fromJS",value:function(c){var p=c.width,_=c.height;return new u(p,_)}}]);function u(l,c){m3(this,u),this.width=l,this.height=c}return pg(u,[{key:"fromJS",value:function(c){c(this.width,this.height)}},{key:"toString",value:function(){return""}}]),u}(),Q9=function(){function u(l,c){m3(this,u),this.unit=l,this.value=c}return pg(u,[{key:"fromJS",value:function(c){c(this.unit,this.value)}},{key:"toString",value:function(){switch(this.unit){case Ua.UNIT_POINT:return String(this.value);case Ua.UNIT_PERCENT:return this.value+"%";case Ua.UNIT_AUTO:return"auto";default:return this.value+"?"}}},{key:"valueOf",value:function(){return this.value}}]),u}();J9.exports=function(u,l){function c(O,M,A){var T=O[M];O[M]=function(){for(var P=arguments.length,U=Array(P),z=0;z1?U-1:0),Q=1;Q1&&arguments[1]!==void 0?arguments[1]:NaN,A=arguments.length>2&&arguments[2]!==void 0?arguments[2]:NaN,T=arguments.length>3&&arguments[3]!==void 0?arguments[3]:Ua.DIRECTION_LTR;return O.call(this,M,A,T)}),AX({Config:l.Config,Node:l.Node,Layout:u("Layout",kX),Size:u("Size",X9),Value:u("Value",Q9),getInstanceCount:function(){return l.getInstanceCount.apply(l,arguments)}},Ua)}});var $9=re((exports,module)=>{(function(u,l){typeof define=="function"&&define.amd?define([],function(){return l}):typeof module=="object"&&module.exports?module.exports=l:(u.nbind=u.nbind||{}).init=l})(exports,function(Module,cb){typeof Module=="function"&&(cb=Module,Module={}),Module.onRuntimeInitialized=function(u,l){return function(){u&&u.apply(this,arguments);try{Module.ccall("nbind_init")}catch(c){l(c);return}l(null,{bind:Module._nbind_value,reflect:Module.NBind.reflect,queryType:Module.NBind.queryType,toggleLightGC:Module.toggleLightGC,lib:Module})}}(Module.onRuntimeInitialized,cb);var Module;Module||(Module=(typeof Module<"u"?Module:null)||{});var moduleOverrides={};for(var key in Module)Module.hasOwnProperty(key)&&(moduleOverrides[key]=Module[key]);var ENVIRONMENT_IS_WEB=!1,ENVIRONMENT_IS_WORKER=!1,ENVIRONMENT_IS_NODE=!1,ENVIRONMENT_IS_SHELL=!1;if(Module.ENVIRONMENT)if(Module.ENVIRONMENT==="WEB")ENVIRONMENT_IS_WEB=!0;else if(Module.ENVIRONMENT==="WORKER")ENVIRONMENT_IS_WORKER=!0;else if(Module.ENVIRONMENT==="NODE")ENVIRONMENT_IS_NODE=!0;else if(Module.ENVIRONMENT==="SHELL")ENVIRONMENT_IS_SHELL=!0;else throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.");else ENVIRONMENT_IS_WEB=typeof window=="object",ENVIRONMENT_IS_WORKER=typeof importScripts=="function",ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof Kn=="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER,ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){Module.print||(Module.print=console.log),Module.printErr||(Module.printErr=console.warn);var nodeFS,nodePath;Module.read=function(l,c){nodeFS||(nodeFS={}("")),nodePath||(nodePath={}("")),l=nodePath.normalize(l);var p=nodeFS.readFileSync(l);return c?p:p.toString()},Module.readBinary=function(l){var c=Module.read(l,!0);return c.buffer||(c=new Uint8Array(c)),assert(c.buffer),c},Module.load=function(l){globalEval(read(l))},Module.thisProgram||(process.argv.length>1?Module.thisProgram=process.argv[1].replace(/\\/g,"/"):Module.thisProgram="unknown-program"),Module.arguments=process.argv.slice(2),typeof module<"u"&&(module.exports=Module),Module.inspect=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL)Module.print||(Module.print=print),typeof printErr<"u"&&(Module.printErr=printErr),typeof read<"u"?Module.read=read:Module.read=function(){throw"no read() available"},Module.readBinary=function(l){if(typeof readbuffer=="function")return new Uint8Array(readbuffer(l));var c=read(l,"binary");return assert(typeof c=="object"),c},typeof scriptArgs<"u"?Module.arguments=scriptArgs:typeof arguments<"u"&&(Module.arguments=arguments),typeof quit=="function"&&(Module.quit=function(u,l){quit(u)});else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(Module.read=function(l){var c=new XMLHttpRequest;return c.open("GET",l,!1),c.send(null),c.responseText},ENVIRONMENT_IS_WORKER&&(Module.readBinary=function(l){var c=new XMLHttpRequest;return c.open("GET",l,!1),c.responseType="arraybuffer",c.send(null),new Uint8Array(c.response)}),Module.readAsync=function(l,c,p){var _=new XMLHttpRequest;_.open("GET",l,!0),_.responseType="arraybuffer",_.onload=function(){_.status==200||_.status==0&&_.response?c(_.response):p()},_.onerror=p,_.send(null)},typeof arguments<"u"&&(Module.arguments=arguments),typeof console<"u")Module.print||(Module.print=function(l){console.log(l)}),Module.printErr||(Module.printErr=function(l){console.warn(l)});else{var TRY_USE_DUMP=!1;Module.print||(Module.print=TRY_USE_DUMP&&typeof dump<"u"?function(u){dump(u)}:function(u){})}ENVIRONMENT_IS_WORKER&&(Module.load=importScripts),typeof Module.setWindowTitle>"u"&&(Module.setWindowTitle=function(u){document.title=u})}else throw"Unknown runtime environment. Where are we?";function globalEval(u){eval.call(null,u)}!Module.load&&Module.read&&(Module.load=function(l){globalEval(Module.read(l))}),Module.print||(Module.print=function(){}),Module.printErr||(Module.printErr=Module.print),Module.arguments||(Module.arguments=[]),Module.thisProgram||(Module.thisProgram="./this.program"),Module.quit||(Module.quit=function(u,l){throw l}),Module.print=Module.print,Module.printErr=Module.printErr,Module.preRun=[],Module.postRun=[];for(var key in moduleOverrides)moduleOverrides.hasOwnProperty(key)&&(Module[key]=moduleOverrides[key]);moduleOverrides=void 0;var Runtime={setTempRet0:function(u){return tempRet0=u,u},getTempRet0:function(){return tempRet0},stackSave:function(){return STACKTOP},stackRestore:function(u){STACKTOP=u},getNativeTypeSize:function(u){switch(u){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(u[u.length-1]==="*")return Runtime.QUANTUM_SIZE;if(u[0]==="i"){var l=parseInt(u.substr(1));return assert(l%8===0),l/8}else return 0}}},getNativeFieldSize:function(u){return Math.max(Runtime.getNativeTypeSize(u),Runtime.QUANTUM_SIZE)},STACK_ALIGN:16,prepVararg:function(u,l){return l==="double"||l==="i64"?u&7&&(assert((u&7)===4),u+=4):assert((u&3)===0),u},getAlignSize:function(u,l,c){return!c&&(u=="i64"||u=="double")?8:u?Math.min(l||(u?Runtime.getNativeFieldSize(u):0),Runtime.QUANTUM_SIZE):Math.min(l,8)},dynCall:function(u,l,c){return c&&c.length?Module["dynCall_"+u].apply(null,[l].concat(c)):Module["dynCall_"+u].call(null,l)},functionPointers:[],addFunction:function(u){for(var l=0;l>2],c=(l+u+15|0)&-16;if(HEAP32[DYNAMICTOP_PTR>>2]=c,c>=TOTAL_MEMORY){var p=enlargeMemory();if(!p)return HEAP32[DYNAMICTOP_PTR>>2]=l,0}return l},alignMemory:function(u,l){var c=u=Math.ceil(u/(l||16))*(l||16);return c},makeBigInt:function(u,l,c){var p=c?+(u>>>0)+ +(l>>>0)*4294967296:+(u>>>0)+ +(l|0)*4294967296;return p},GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module.Runtime=Runtime;var ABORT=0,EXITSTATUS=0;function assert(u,l){u||abort("Assertion failed: "+l)}function getCFunc(ident){var func=Module["_"+ident];if(!func)try{func=eval("_"+ident)}catch(u){}return assert(func,"Cannot call unknown function "+ident+" (perhaps LLVM optimizations or closure removed it?)"),func}var cwrap,ccall;(function(){var JSfuncs={stackSave:function(){Runtime.stackSave()},stackRestore:function(){Runtime.stackRestore()},arrayToC:function(u){var l=Runtime.stackAlloc(u.length);return writeArrayToMemory(u,l),l},stringToC:function(u){var l=0;if(u!=null&&u!==0){var c=(u.length<<2)+1;l=Runtime.stackAlloc(c),stringToUTF8(u,l,c)}return l}},toC={string:JSfuncs.stringToC,array:JSfuncs.arrayToC};ccall=function(l,c,p,_,t){var O=getCFunc(l),M=[],A=0;if(_)for(var T=0;T<_.length;T++){var P=toC[p[T]];P?(A===0&&(A=Runtime.stackSave()),M[T]=P(_[T])):M[T]=_[T]}var U=O.apply(null,M);if(c==="string"&&(U=Pointer_stringify(U)),A!==0){if(t&&t.async){EmterpreterAsync.asyncFinalizers.push(function(){Runtime.stackRestore(A)});return}Runtime.stackRestore(A)}return U};var sourceRegex=/^function\s*[a-zA-Z$_0-9]*\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;function parseJSFunc(u){var l=u.toString().match(sourceRegex).slice(1);return{arguments:l[0],body:l[1],returnValue:l[2]}}var JSsource=null;function ensureJSsource(){if(!JSsource){JSsource={};for(var u in JSfuncs)JSfuncs.hasOwnProperty(u)&&(JSsource[u]=parseJSFunc(JSfuncs[u]))}}cwrap=function cwrap(ident,returnType,argTypes){argTypes=argTypes||[];var cfunc=getCFunc(ident),numericArgs=argTypes.every(function(u){return u==="number"}),numericRet=returnType!=="string";if(numericRet&&numericArgs)return cfunc;var argNames=argTypes.map(function(u,l){return"$"+l}),funcstr="(function("+argNames.join(",")+") {",nargs=argTypes.length;if(!numericArgs){ensureJSsource(),funcstr+="var stack = "+JSsource.stackSave.body+";";for(var i=0;i>0]=l;break;case"i8":HEAP8[u>>0]=l;break;case"i16":HEAP16[u>>1]=l;break;case"i32":HEAP32[u>>2]=l;break;case"i64":tempI64=[l>>>0,(tempDouble=l,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[u>>2]=tempI64[0],HEAP32[u+4>>2]=tempI64[1];break;case"float":HEAPF32[u>>2]=l;break;case"double":HEAPF64[u>>3]=l;break;default:abort("invalid type for setValue: "+c)}}Module.setValue=setValue;function getValue(u,l,c){switch(l=l||"i8",l.charAt(l.length-1)==="*"&&(l="i32"),l){case"i1":return HEAP8[u>>0];case"i8":return HEAP8[u>>0];case"i16":return HEAP16[u>>1];case"i32":return HEAP32[u>>2];case"i64":return HEAP32[u>>2];case"float":return HEAPF32[u>>2];case"double":return HEAPF64[u>>3];default:abort("invalid type for setValue: "+l)}return null}Module.getValue=getValue;var ALLOC_NORMAL=0,ALLOC_STACK=1,ALLOC_STATIC=2,ALLOC_DYNAMIC=3,ALLOC_NONE=4;Module.ALLOC_NORMAL=ALLOC_NORMAL,Module.ALLOC_STACK=ALLOC_STACK,Module.ALLOC_STATIC=ALLOC_STATIC,Module.ALLOC_DYNAMIC=ALLOC_DYNAMIC,Module.ALLOC_NONE=ALLOC_NONE;function allocate(u,l,c,p){var _,t;typeof u=="number"?(_=!0,t=u):(_=!1,t=u.length);var O=typeof l=="string"?l:null,M;if(c==ALLOC_NONE?M=p:M=[typeof _malloc=="function"?_malloc:Runtime.staticAlloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][c===void 0?ALLOC_STATIC:c](Math.max(t,O?1:l.length)),_){var p=M,A;for(assert((M&3)==0),A=M+(t&-4);p>2]=0;for(A=M+t;p>0]=0;return M}if(O==="i8")return u.subarray||u.slice?HEAPU8.set(u,M):HEAPU8.set(new Uint8Array(u),M),M;for(var T=0,P,U,z;T>0],c|=p,!(p==0&&!l||(_++,l&&_==l)););l||(l=_);var t="";if(c<128){for(var O=1024,M;l>0;)M=String.fromCharCode.apply(String,HEAPU8.subarray(u,u+Math.min(l,O))),t=t?t+M:M,u+=O,l-=O;return t}return Module.UTF8ToString(u)}Module.Pointer_stringify=Pointer_stringify;function AsciiToString(u){for(var l="";;){var c=HEAP8[u++>>0];if(!c)return l;l+=String.fromCharCode(c)}}Module.AsciiToString=AsciiToString;function stringToAscii(u,l){return writeAsciiToMemory(u,l,!1)}Module.stringToAscii=stringToAscii;var UTF8Decoder=typeof TextDecoder<"u"?new TextDecoder("utf8"):void 0;function UTF8ArrayToString(u,l){for(var c=l;u[c];)++c;if(c-l>16&&u.subarray&&UTF8Decoder)return UTF8Decoder.decode(u.subarray(l,c));for(var p,_,t,O,M,A,T="";;){if(p=u[l++],!p)return T;if(!(p&128)){T+=String.fromCharCode(p);continue}if(_=u[l++]&63,(p&224)==192){T+=String.fromCharCode((p&31)<<6|_);continue}if(t=u[l++]&63,(p&240)==224?p=(p&15)<<12|_<<6|t:(O=u[l++]&63,(p&248)==240?p=(p&7)<<18|_<<12|t<<6|O:(M=u[l++]&63,(p&252)==248?p=(p&3)<<24|_<<18|t<<12|O<<6|M:(A=u[l++]&63,p=(p&1)<<30|_<<24|t<<18|O<<12|M<<6|A))),p<65536)T+=String.fromCharCode(p);else{var P=p-65536;T+=String.fromCharCode(55296|P>>10,56320|P&1023)}}}Module.UTF8ArrayToString=UTF8ArrayToString;function UTF8ToString(u){return UTF8ArrayToString(HEAPU8,u)}Module.UTF8ToString=UTF8ToString;function stringToUTF8Array(u,l,c,p){if(!(p>0))return 0;for(var _=c,t=c+p-1,O=0;O=55296&&M<=57343&&(M=65536+((M&1023)<<10)|u.charCodeAt(++O)&1023),M<=127){if(c>=t)break;l[c++]=M}else if(M<=2047){if(c+1>=t)break;l[c++]=192|M>>6,l[c++]=128|M&63}else if(M<=65535){if(c+2>=t)break;l[c++]=224|M>>12,l[c++]=128|M>>6&63,l[c++]=128|M&63}else if(M<=2097151){if(c+3>=t)break;l[c++]=240|M>>18,l[c++]=128|M>>12&63,l[c++]=128|M>>6&63,l[c++]=128|M&63}else if(M<=67108863){if(c+4>=t)break;l[c++]=248|M>>24,l[c++]=128|M>>18&63,l[c++]=128|M>>12&63,l[c++]=128|M>>6&63,l[c++]=128|M&63}else{if(c+5>=t)break;l[c++]=252|M>>30,l[c++]=128|M>>24&63,l[c++]=128|M>>18&63,l[c++]=128|M>>12&63,l[c++]=128|M>>6&63,l[c++]=128|M&63}}return l[c]=0,c-_}Module.stringToUTF8Array=stringToUTF8Array;function stringToUTF8(u,l,c){return stringToUTF8Array(u,HEAPU8,l,c)}Module.stringToUTF8=stringToUTF8;function lengthBytesUTF8(u){for(var l=0,c=0;c=55296&&p<=57343&&(p=65536+((p&1023)<<10)|u.charCodeAt(++c)&1023),p<=127?++l:p<=2047?l+=2:p<=65535?l+=3:p<=2097151?l+=4:p<=67108863?l+=5:l+=6}return l}Module.lengthBytesUTF8=lengthBytesUTF8;var UTF16Decoder=typeof TextDecoder<"u"?new TextDecoder("utf-16le"):void 0;function demangle(u){var l=Module.___cxa_demangle||Module.__cxa_demangle;if(l){try{var c=u.substr(1),p=lengthBytesUTF8(c)+1,_=_malloc(p);stringToUTF8(c,_,p);var t=_malloc(4),O=l(_,0,0,t);if(getValue(t,"i32")===0&&O)return Pointer_stringify(O)}catch{}finally{_&&_free(_),t&&_free(t),O&&_free(O)}return u}return Runtime.warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling"),u}function demangleAll(u){var l=/__Z[\w\d_]+/g;return u.replace(l,function(c){var p=demangle(c);return c===p?c:c+" ["+p+"]"})}function jsStackTrace(){var u=new Error;if(!u.stack){try{throw new Error(0)}catch(l){u=l}if(!u.stack)return"(no stack trace available)"}return u.stack.toString()}function stackTrace(){var u=jsStackTrace();return Module.extraStackTrace&&(u+=` +`+Module.extraStackTrace()),demangleAll(u)}Module.stackTrace=stackTrace;var HEAP,buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferViews(){Module.HEAP8=HEAP8=new Int8Array(buffer),Module.HEAP16=HEAP16=new Int16Array(buffer),Module.HEAP32=HEAP32=new Int32Array(buffer),Module.HEAPU8=HEAPU8=new Uint8Array(buffer),Module.HEAPU16=HEAPU16=new Uint16Array(buffer),Module.HEAPU32=HEAPU32=new Uint32Array(buffer),Module.HEAPF32=HEAPF32=new Float32Array(buffer),Module.HEAPF64=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed,STACK_BASE,STACKTOP,STACK_MAX,DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0,staticSealed=!1;function abortOnCannotGrowMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")}function enlargeMemory(){abortOnCannotGrowMemory()}var TOTAL_STACK=Module.TOTAL_STACK||5242880,TOTAL_MEMORY=Module.TOTAL_MEMORY||134217728;TOTAL_MEMORY0;){var l=u.shift();if(typeof l=="function"){l();continue}var c=l.func;typeof c=="number"?l.arg===void 0?Module.dynCall_v(c):Module.dynCall_vi(c,l.arg):c(l.arg===void 0?null:l.arg)}}var __ATPRERUN__=[],__ATINIT__=[],__ATMAIN__=[],__ATEXIT__=[],__ATPOSTRUN__=[],runtimeInitialized=!1,runtimeExited=!1;function preRun(){if(Module.preRun)for(typeof Module.preRun=="function"&&(Module.preRun=[Module.preRun]);Module.preRun.length;)addOnPreRun(Module.preRun.shift());callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){runtimeInitialized||(runtimeInitialized=!0,callRuntimeCallbacks(__ATINIT__))}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__),runtimeExited=!0}function postRun(){if(Module.postRun)for(typeof Module.postRun=="function"&&(Module.postRun=[Module.postRun]);Module.postRun.length;)addOnPostRun(Module.postRun.shift());callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(u){__ATPRERUN__.unshift(u)}Module.addOnPreRun=addOnPreRun;function addOnInit(u){__ATINIT__.unshift(u)}Module.addOnInit=addOnInit;function addOnPreMain(u){__ATMAIN__.unshift(u)}Module.addOnPreMain=addOnPreMain;function addOnExit(u){__ATEXIT__.unshift(u)}Module.addOnExit=addOnExit;function addOnPostRun(u){__ATPOSTRUN__.unshift(u)}Module.addOnPostRun=addOnPostRun;function intArrayFromString(u,l,c){var p=c>0?c:lengthBytesUTF8(u)+1,_=new Array(p),t=stringToUTF8Array(u,_,0,_.length);return l&&(_.length=t),_}Module.intArrayFromString=intArrayFromString;function intArrayToString(u){for(var l=[],c=0;c255&&(p&=255),l.push(String.fromCharCode(p))}return l.join("")}Module.intArrayToString=intArrayToString;function writeStringToMemory(u,l,c){Runtime.warnOnce("writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!");var p,_;c&&(_=l+lengthBytesUTF8(u),p=HEAP8[_]),stringToUTF8(u,l,1/0),c&&(HEAP8[_]=p)}Module.writeStringToMemory=writeStringToMemory;function writeArrayToMemory(u,l){HEAP8.set(u,l)}Module.writeArrayToMemory=writeArrayToMemory;function writeAsciiToMemory(u,l,c){for(var p=0;p>0]=u.charCodeAt(p);c||(HEAP8[l>>0]=0)}if(Module.writeAsciiToMemory=writeAsciiToMemory,(!Math.imul||Math.imul(4294967295,5)!==-5)&&(Math.imul=function u(l,c){var p=l>>>16,_=l&65535,t=c>>>16,O=c&65535;return _*O+(p*O+_*t<<16)|0}),Math.imul=Math.imul,!Math.fround){var froundBuffer=new Float32Array(1);Math.fround=function(u){return froundBuffer[0]=u,froundBuffer[0]}}Math.fround=Math.fround,Math.clz32||(Math.clz32=function(u){u=u>>>0;for(var l=0;l<32;l++)if(u&1<<31-l)return l;return 32}),Math.clz32=Math.clz32,Math.trunc||(Math.trunc=function(u){return u<0?Math.ceil(u):Math.floor(u)}),Math.trunc=Math.trunc;var Math_abs=Math.abs,Math_cos=Math.cos,Math_sin=Math.sin,Math_tan=Math.tan,Math_acos=Math.acos,Math_asin=Math.asin,Math_atan=Math.atan,Math_atan2=Math.atan2,Math_exp=Math.exp,Math_log=Math.log,Math_sqrt=Math.sqrt,Math_ceil=Math.ceil,Math_floor=Math.floor,Math_pow=Math.pow,Math_imul=Math.imul,Math_fround=Math.fround,Math_round=Math.round,Math_min=Math.min,Math_clz32=Math.clz32,Math_trunc=Math.trunc,runDependencies=0,runDependencyWatcher=null,dependenciesFulfilled=null;function getUniqueRunDependency(u){return u}function addRunDependency(u){runDependencies++,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies)}Module.addRunDependency=addRunDependency;function removeRunDependency(u){if(runDependencies--,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies),runDependencies==0&&(runDependencyWatcher!==null&&(clearInterval(runDependencyWatcher),runDependencyWatcher=null),dependenciesFulfilled)){var l=dependenciesFulfilled;dependenciesFulfilled=null,l()}}Module.removeRunDependency=removeRunDependency,Module.preloadedImages={},Module.preloadedAudios={};var ASM_CONSTS=[function(u,l,c,p,_,t,O,M){return _nbind.callbackSignatureList[u].apply(this,arguments)}];function _emscripten_asm_const_iiiiiiii(u,l,c,p,_,t,O,M){return ASM_CONSTS[u](l,c,p,_,t,O,M)}function _emscripten_asm_const_iiiii(u,l,c,p,_){return ASM_CONSTS[u](l,c,p,_)}function _emscripten_asm_const_iiidddddd(u,l,c,p,_,t,O,M,A){return ASM_CONSTS[u](l,c,p,_,t,O,M,A)}function _emscripten_asm_const_iiididi(u,l,c,p,_,t,O){return ASM_CONSTS[u](l,c,p,_,t,O)}function _emscripten_asm_const_iiii(u,l,c,p){return ASM_CONSTS[u](l,c,p)}function _emscripten_asm_const_iiiid(u,l,c,p,_){return ASM_CONSTS[u](l,c,p,_)}function _emscripten_asm_const_iiiiii(u,l,c,p,_,t){return ASM_CONSTS[u](l,c,p,_,t)}STATIC_BASE=Runtime.GLOBAL_BASE,STATICTOP=STATIC_BASE+12800,__ATINIT__.push({func:function(){__GLOBAL__sub_I_Yoga_cpp()}},{func:function(){__GLOBAL__sub_I_nbind_cc()}},{func:function(){__GLOBAL__sub_I_common_cc()}},{func:function(){__GLOBAL__sub_I_Binding_cc()}}),allocate([0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,192,127,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,0,0,128,191,0,0,128,191,0,0,192,127,0,0,0,0,0,0,0,0,0,0,128,63,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,2,0,0,0,0,0,0,0,190,12,0,0,200,12,0,0,208,12,0,0,216,12,0,0,230,12,0,0,242,12,0,0,1,0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,0,192,127,3,0,0,0,180,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,182,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,4,0,0,0,183,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,184,45,0,0,185,45,0,0,181,45,0,0,181,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,148,4,0,0,3,0,0,0,187,45,0,0,164,4,0,0,188,45,0,0,2,0,0,0,189,45,0,0,164,4,0,0,188,45,0,0,185,45,0,0,164,4,0,0,185,45,0,0,164,4,0,0,188,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0,6,0,0,0,1,0,0,0,7,0,0,0,183,45,0,0,182,45,0,0,181,45,0,0,190,45,0,0,190,45,0,0,182,45,0,0,182,45,0,0,185,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,185,45,0,0,48,5,0,0,3,0,0,0,56,5,0,0,1,0,0,0,189,45,0,0,185,45,0,0,164,4,0,0,76,5,0,0,2,0,0,0,191,45,0,0,186,45,0,0,182,45,0,0,185,45,0,0,192,45,0,0,185,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,76,5,0,0,76,5,0,0,136,5,0,0,182,45,0,0,181,45,0,0,2,0,0,0,190,45,0,0,136,5,0,0,56,19,0,0,156,5,0,0,2,0,0,0,184,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,0,0,0,9,0,0,0,1,0,0,0,10,0,0,0,204,5,0,0,181,45,0,0,181,45,0,0,2,0,0,0,180,45,0,0,204,5,0,0,2,0,0,0,195,45,0,0,236,5,0,0,97,19,0,0,198,45,0,0,211,45,0,0,212,45,0,0,213,45,0,0,214,45,0,0,215,45,0,0,188,45,0,0,182,45,0,0,216,45,0,0,217,45,0,0,218,45,0,0,219,45,0,0,192,45,0,0,181,45,0,0,0,0,0,0,185,45,0,0,110,19,0,0,186,45,0,0,115,19,0,0,221,45,0,0,120,19,0,0,148,4,0,0,132,19,0,0,96,6,0,0,145,19,0,0,222,45,0,0,164,19,0,0,223,45,0,0,173,19,0,0,0,0,0,0,3,0,0,0,104,6,0,0,1,0,0,0,187,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,12,0,0,0,1,0,0,0,13,0,0,0,185,45,0,0,224,45,0,0,164,6,0,0,188,45,0,0,172,6,0,0,180,6,0,0,2,0,0,0,188,6,0,0,7,0,0,0,224,45,0,0,7,0,0,0,164,6,0,0,1,0,0,0,213,45,0,0,185,45,0,0,224,45,0,0,172,6,0,0,185,45,0,0,224,45,0,0,164,6,0,0,185,45,0,0,224,45,0,0,211,45,0,0,211,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,172,6,0,0,222,45,0,0,211,45,0,0,224,45,0,0,188,45,0,0,222,45,0,0,211,45,0,0,40,7,0,0,188,45,0,0,2,0,0,0,224,45,0,0,185,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,222,45,0,0,224,45,0,0,148,4,0,0,185,45,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,185,45,0,0,164,6,0,0,148,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,14,0,0,0,15,0,0,0,1,0,0,0,16,0,0,0,148,7,0,0,2,0,0,0,225,45,0,0,183,45,0,0,188,45,0,0,168,7,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,234,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,148,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,9,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,242,45,0,0,0,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,110,111,100,101,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,119,104,105,99,104,32,115,116,105,108,108,32,104,97,115,32,99,104,105,108,100,114,101,110,32,97,116,116,97,99,104,101,100,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,115,116,105,108,108,32,97,116,116,97,99,104,101,100,32,116,111,32,97,32,112,97,114,101,110,116,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,99,111,110,102,105,103,0,67,97,110,110,111,116,32,115,101,116,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,67,104,105,108,100,32,97,108,114,101,97,100,121,32,104,97,115,32,97,32,112,97,114,101,110,116,44,32,105,116,32,109,117,115,116,32,98,101,32,114,101,109,111,118,101,100,32,102,105,114,115,116,46,0,67,97,110,110,111,116,32,97,100,100,32,99,104,105,108,100,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,79,110,108,121,32,108,101,97,102,32,110,111,100,101,115,32,119,105,116,104,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,115,104,111,117,108,100,32,109,97,110,117,97,108,108,121,32,109,97,114,107,32,116,104,101,109,115,101,108,118,101,115,32,97,115,32,100,105,114,116,121,0,67,97,110,110,111,116,32,103,101,116,32,108,97,121,111,117,116,32,112,114,111,112,101,114,116,105,101,115,32,111,102,32,109,117,108,116,105,45,101,100,103,101,32,115,104,111,114,116,104,97,110,100,115,0,37,115,37,100,46,123,91,115,107,105,112,112,101,100,93,32,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,61,62,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,37,115,37,100,46,123,37,115,0,42,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,37,115,10,0,37,115,37,100,46,125,37,115,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,79,117,116,32,111,102,32,99,97,99,104,101,32,101,110,116,114,105,101,115,33,10,0,83,99,97,108,101,32,102,97,99,116,111,114,32,115,104,111,117,108,100,32,110,111,116,32,98,101,32,108,101,115,115,32,116,104,97,110,32,122,101,114,111,0,105,110,105,116,105,97,108,0,37,115,10,0,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,0,85,78,68,69,70,73,78,69,68,0,69,88,65,67,84,76,89,0,65,84,95,77,79,83,84,0,76,65,89,95,85,78,68,69,70,73,78,69,68,0,76,65,89,95,69,88,65,67,84,76,89,0,76,65,89,95,65,84,95,77,79,83,84,0,97,118,97,105,108,97,98,108,101,87,105,100,116,104,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,119,105,100,116,104,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,97,118,97,105,108,97,98,108,101,72,101,105,103,104,116,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,104,101,105,103,104,116,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,102,108,101,120,0,115,116,114,101,116,99,104,0,109,117,108,116,105,108,105,110,101,45,115,116,114,101,116,99,104,0,69,120,112,101,99,116,101,100,32,110,111,100,101,32,116,111,32,104,97,118,101,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,0,109,101,97,115,117,114,101,0,69,120,112,101,99,116,32,99,117,115,116,111,109,32,98,97,115,101,108,105,110,101,32,102,117,110,99,116,105,111,110,32,116,111,32,110,111,116,32,114,101,116,117,114,110,32,78,97,78,0,97,98,115,45,109,101,97,115,117,114,101,0,97,98,115,45,108,97,121,111,117,116,0,78,111,100,101,0,99,114,101,97,116,101,68,101,102,97,117,108,116,0,99,114,101,97,116,101,87,105,116,104,67,111,110,102,105,103,0,100,101,115,116,114,111,121,0,114,101,115,101,116,0,99,111,112,121,83,116,121,108,101,0,115,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,115,101,116,80,111,115,105,116,105,111,110,0,115,101,116,80,111,115,105,116,105,111,110,80,101,114,99,101,110,116,0,115,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,115,101,116,65,108,105,103,110,73,116,101,109,115,0,115,101,116,65,108,105,103,110,83,101,108,102,0,115,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,115,101,116,70,108,101,120,87,114,97,112,0,115,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,115,101,116,77,97,114,103,105,110,0,115,101,116,77,97,114,103,105,110,80,101,114,99,101,110,116,0,115,101,116,77,97,114,103,105,110,65,117,116,111,0,115,101,116,79,118,101,114,102,108,111,119,0,115,101,116,68,105,115,112,108,97,121,0,115,101,116,70,108,101,120,0,115,101,116,70,108,101,120,66,97,115,105,115,0,115,101,116,70,108,101,120,66,97,115,105,115,80,101,114,99,101,110,116,0,115,101,116,70,108,101,120,71,114,111,119,0,115,101,116,70,108,101,120,83,104,114,105,110,107,0,115,101,116,87,105,100,116,104,0,115,101,116,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,87,105,100,116,104,65,117,116,111,0,115,101,116,72,101,105,103,104,116,0,115,101,116,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,72,101,105,103,104,116,65,117,116,111,0,115,101,116,77,105,110,87,105,100,116,104,0,115,101,116,77,105,110,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,105,110,72,101,105,103,104,116,0,115,101,116,77,105,110,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,77,97,120,87,105,100,116,104,0,115,101,116,77,97,120,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,97,120,72,101,105,103,104,116,0,115,101,116,77,97,120,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,65,115,112,101,99,116,82,97,116,105,111,0,115,101,116,66,111,114,100,101,114,0,115,101,116,80,97,100,100,105,110,103,0,115,101,116,80,97,100,100,105,110,103,80,101,114,99,101,110,116,0,103,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,103,101,116,80,111,115,105,116,105,111,110,0,103,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,103,101,116,65,108,105,103,110,73,116,101,109,115,0,103,101,116,65,108,105,103,110,83,101,108,102,0,103,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,103,101,116,70,108,101,120,87,114,97,112,0,103,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,103,101,116,77,97,114,103,105,110,0,103,101,116,70,108,101,120,66,97,115,105,115,0,103,101,116,70,108,101,120,71,114,111,119,0,103,101,116,70,108,101,120,83,104,114,105,110,107,0,103,101,116,87,105,100,116,104,0,103,101,116,72,101,105,103,104,116,0,103,101,116,77,105,110,87,105,100,116,104,0,103,101,116,77,105,110,72,101,105,103,104,116,0,103,101,116,77,97,120,87,105,100,116,104,0,103,101,116,77,97,120,72,101,105,103,104,116,0,103,101,116,65,115,112,101,99,116,82,97,116,105,111,0,103,101,116,66,111,114,100,101,114,0,103,101,116,79,118,101,114,102,108,111,119,0,103,101,116,68,105,115,112,108,97,121,0,103,101,116,80,97,100,100,105,110,103,0,105,110,115,101,114,116,67,104,105,108,100,0,114,101,109,111,118,101,67,104,105,108,100,0,103,101,116,67,104,105,108,100,67,111,117,110,116,0,103,101,116,80,97,114,101,110,116,0,103,101,116,67,104,105,108,100,0,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,117,110,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,109,97,114,107,68,105,114,116,121,0,105,115,68,105,114,116,121,0,99,97,108,99,117,108,97,116,101,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,76,101,102,116,0,103,101,116,67,111,109,112,117,116,101,100,82,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,84,111,112,0,103,101,116,67,111,109,112,117,116,101,100,66,111,116,116,111,109,0,103,101,116,67,111,109,112,117,116,101,100,87,105,100,116,104,0,103,101,116,67,111,109,112,117,116,101,100,72,101,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,77,97,114,103,105,110,0,103,101,116,67,111,109,112,117,116,101,100,66,111,114,100,101,114,0,103,101,116,67,111,109,112,117,116,101,100,80,97,100,100,105,110,103,0,67,111,110,102,105,103,0,99,114,101,97,116,101,0,115,101,116,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,115,101,116,80,111,105,110,116,83,99,97,108,101,70,97,99,116,111,114,0,105,115,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,86,97,108,117,101,0,76,97,121,111,117,116,0,83,105,122,101,0,103,101,116,73,110,115,116,97,110,99,101,67,111,117,110,116,0,73,110,116,54,52,0,1,1,1,2,2,4,4,4,4,8,8,4,8,118,111,105,100,0,98,111,111,108,0,115,116,100,58,58,115,116,114,105,110,103,0,99,98,70,117,110,99,116,105,111,110,32,38,0,99,111,110,115,116,32,99,98,70,117,110,99,116,105,111,110,32,38,0,69,120,116,101,114,110,97,108,0,66,117,102,102,101,114,0,78,66,105,110,100,73,68,0,78,66,105,110,100,0,98,105,110,100,95,118,97,108,117,101,0,114,101,102,108,101,99,116,0,113,117,101,114,121,84,121,112,101,0,108,97,108,108,111,99,0,108,114,101,115,101,116,0,123,114,101,116,117,114,110,40,95,110,98,105,110,100,46,99,97,108,108,98,97,99,107,83,105,103,110,97,116,117,114,101,76,105,115,116,91,36,48,93,46,97,112,112,108,121,40,116,104,105,115,44,97,114,103,117,109,101,110,116,115,41,41,59,125,0,95,110,98,105,110,100,95,110,101,119,0,17,0,10,0,17,17,17,0,0,0,0,5,0,0,0,0,0,0,9,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,15,10,17,17,17,3,10,7,0,1,19,9,11,11,0,0,9,6,11,0,0,11,0,6,17,0,0,0,17,17,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,10,10,17,17,17,0,10,0,0,2,0,9,11,0,0,0,9,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,4,13,0,0,0,0,9,14,0,0,0,0,0,14,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,15,0,0,0,0,9,16,0,0,0,0,0,16,0,0,16,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,10,0,0,0,0,9,11,0,0,0,0,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,45,43,32,32,32,48,88,48,120,0,40,110,117,108,108,41,0,45,48,88,43,48,88,32,48,88,45,48,120,43,48,120,32,48,120,0,105,110,102,0,73,78,70,0,110,97,110,0,78,65,78,0,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,46,0,84,33,34,25,13,1,2,3,17,75,28,12,16,4,11,29,18,30,39,104,110,111,112,113,98,32,5,6,15,19,20,21,26,8,22,7,40,36,23,24,9,10,14,27,31,37,35,131,130,125,38,42,43,60,61,62,63,67,71,74,77,88,89,90,91,92,93,94,95,96,97,99,100,101,102,103,105,106,107,108,114,115,116,121,122,123,124,0,73,108,108,101,103,97,108,32,98,121,116,101,32,115,101,113,117,101,110,99,101,0,68,111,109,97,105,110,32,101,114,114,111,114,0,82,101,115,117,108,116,32,110,111,116,32,114,101,112,114,101,115,101,110,116,97,98,108,101,0,78,111,116,32,97,32,116,116,121,0,80,101,114,109,105,115,115,105,111,110,32,100,101,110,105,101,100,0,79,112,101,114,97,116,105,111,110,32,110,111,116,32,112,101,114,109,105,116,116,101,100,0,78,111,32,115,117,99,104,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,0,78,111,32,115,117,99,104,32,112,114,111,99,101,115,115,0,70,105,108,101,32,101,120,105,115,116,115,0,86,97,108,117,101,32,116,111,111,32,108,97,114,103,101,32,102,111,114,32,100,97,116,97,32,116,121,112,101,0,78,111,32,115,112,97,99,101,32,108,101,102,116,32,111,110,32,100,101,118,105,99,101,0,79,117,116,32,111,102,32,109,101,109,111,114,121,0,82,101,115,111,117,114,99,101,32,98,117,115,121,0,73,110,116,101,114,114,117,112,116,101,100,32,115,121,115,116,101,109,32,99,97,108,108,0,82,101,115,111,117,114,99,101,32,116,101,109,112,111,114,97,114,105,108,121,32,117,110,97,118,97,105,108,97,98,108,101,0,73,110,118,97,108,105,100,32,115,101,101,107,0,67,114,111,115,115,45,100,101,118,105,99,101,32,108,105,110,107,0,82,101,97,100,45,111,110,108,121,32,102,105,108,101,32,115,121,115,116,101,109,0,68,105,114,101,99,116,111,114,121,32,110,111,116,32,101,109,112,116,121,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,112,101,101,114,0,79,112,101,114,97,116,105,111,110,32,116,105,109,101,100,32,111,117,116,0,67,111,110,110,101,99,116,105,111,110,32,114,101,102,117,115,101,100,0,72,111,115,116,32,105,115,32,100,111,119,110,0,72,111,115,116,32,105,115,32,117,110,114,101,97,99,104,97,98,108,101,0,65,100,100,114,101,115,115,32,105,110,32,117,115,101,0,66,114,111,107,101,110,32,112,105,112,101,0,73,47,79,32,101,114,114,111,114,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,32,111,114,32,97,100,100,114,101,115,115,0,66,108,111,99,107,32,100,101,118,105,99,101,32,114,101,113,117,105,114,101,100,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,0,78,111,116,32,97,32,100,105,114,101,99,116,111,114,121,0,73,115,32,97,32,100,105,114,101,99,116,111,114,121,0,84,101,120,116,32,102,105,108,101,32,98,117,115,121,0,69,120,101,99,32,102,111,114,109,97,116,32,101,114,114,111,114,0,73,110,118,97,108,105,100,32,97,114,103,117,109,101,110,116,0,65,114,103,117,109,101,110,116,32,108,105,115,116,32,116,111,111,32,108,111,110,103,0,83,121,109,98,111,108,105,99,32,108,105,110,107,32,108,111,111,112,0,70,105,108,101,110,97,109,101,32,116,111,111,32,108,111,110,103,0,84,111,111,32,109,97,110,121,32,111,112,101,110,32,102,105,108,101,115,32,105,110,32,115,121,115,116,101,109,0,78,111,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,97,118,97,105,108,97,98,108,101,0,66,97,100,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,0,78,111,32,99,104,105,108,100,32,112,114,111,99,101,115,115,0,66,97,100,32,97,100,100,114,101,115,115,0,70,105,108,101,32,116,111,111,32,108,97,114,103,101,0,84,111,111,32,109,97,110,121,32,108,105,110,107,115,0,78,111,32,108,111,99,107,115,32,97,118,97,105,108,97,98,108,101,0,82,101,115,111,117,114,99,101,32,100,101,97,100,108,111,99,107,32,119,111,117,108,100,32,111,99,99,117,114,0,83,116,97,116,101,32,110,111,116,32,114,101,99,111,118,101,114,97,98,108,101,0,80,114,101,118,105,111,117,115,32,111,119,110,101,114,32,100,105,101,100,0,79,112,101,114,97,116,105,111,110,32,99,97,110,99,101,108,101,100,0,70,117,110,99,116,105,111,110,32,110,111,116,32,105,109,112,108,101,109,101,110,116,101,100,0,78,111,32,109,101,115,115,97,103,101,32,111,102,32,100,101,115,105,114,101,100,32,116,121,112,101,0,73,100,101,110,116,105,102,105,101,114,32,114,101,109,111,118,101,100,0,68,101,118,105,99,101,32,110,111,116,32,97,32,115,116,114,101,97,109,0,78,111,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,0,68,101,118,105,99,101,32,116,105,109,101,111,117,116,0,79,117,116,32,111,102,32,115,116,114,101,97,109,115,32,114,101,115,111,117,114,99,101,115,0,76,105,110,107,32,104,97,115,32,98,101,101,110,32,115,101,118,101,114,101,100,0,80,114,111,116,111,99,111,108,32,101,114,114,111,114,0,66,97,100,32,109,101,115,115,97,103,101,0,70,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32,105,110,32,98,97,100,32,115,116,97,116,101,0,78,111,116,32,97,32,115,111,99,107,101,116,0,68,101,115,116,105,110,97,116,105,111,110,32,97,100,100,114,101,115,115,32,114,101,113,117,105,114,101,100,0,77,101,115,115,97,103,101,32,116,111,111,32,108,97,114,103,101,0,80,114,111,116,111,99,111,108,32,119,114,111,110,103,32,116,121,112,101,32,102,111,114,32,115,111,99,107,101,116,0,80,114,111,116,111,99,111,108,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,80,114,111,116,111,99,111,108,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,83,111,99,107,101,116,32,116,121,112,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,78,111,116,32,115,117,112,112,111,114,116,101,100,0,80,114,111,116,111,99,111,108,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,65,100,100,114,101,115,115,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,112,114,111,116,111,99,111,108,0,65,100,100,114,101,115,115,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,78,101,116,119,111,114,107,32,105,115,32,100,111,119,110,0,78,101,116,119,111,114,107,32,117,110,114,101,97,99,104,97,98,108,101,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,110,101,116,119,111,114,107,0,67,111,110,110,101,99,116,105,111,110,32,97,98,111,114,116,101,100,0,78,111,32,98,117,102,102,101,114,32,115,112,97,99,101,32,97,118,97,105,108,97,98,108,101,0,83,111,99,107,101,116,32,105,115,32,99,111,110,110,101,99,116,101,100,0,83,111,99,107,101,116,32,110,111,116,32,99,111,110,110,101,99,116,101,100,0,67,97,110,110,111,116,32,115,101,110,100,32,97,102,116,101,114,32,115,111,99,107,101,116,32,115,104,117,116,100,111,119,110,0,79,112,101,114,97,116,105,111,110,32,97,108,114,101,97,100,121,32,105,110,32,112,114,111,103,114,101,115,115,0,79,112,101,114,97,116,105,111,110,32,105,110,32,112,114,111,103,114,101,115,115,0,83,116,97,108,101,32,102,105,108,101,32,104,97,110,100,108,101,0,82,101,109,111,116,101,32,73,47,79,32,101,114,114,111,114,0,81,117,111,116,97,32,101,120,99,101,101,100,101,100,0,78,111,32,109,101,100,105,117,109,32,102,111,117,110,100,0,87,114,111,110,103,32,109,101,100,105,117,109,32,116,121,112,101,0,78,111,32,101,114,114,111,114,32,105,110,102,111,114,109,97,116,105,111,110,0,0],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE);var tempDoublePtr=STATICTOP;STATICTOP+=16;function _atexit(u,l){__ATEXIT__.unshift({func:u,arg:l})}function ___cxa_atexit(){return _atexit.apply(null,arguments)}function _abort(){Module.abort()}function __ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj(){Module.printErr("missing function: _ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj"),abort(-1)}function __decorate(u,l,c,p){var _=arguments.length,t=_<3?l:p===null?p=Object.getOwnPropertyDescriptor(l,c):p,O;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")t=Reflect.decorate(u,l,c,p);else for(var M=u.length-1;M>=0;M--)(O=u[M])&&(t=(_<3?O(t):_>3?O(l,c,t):O(l,c))||t);return _>3&&t&&Object.defineProperty(l,c,t),t}function _defineHidden(u){return function(l,c){Object.defineProperty(l,c,{configurable:!1,enumerable:!1,value:u,writable:!0})}}var _nbind={};function __nbind_free_external(u){_nbind.externalList[u].dereference(u)}function __nbind_reference_external(u){_nbind.externalList[u].reference()}function _llvm_stackrestore(u){var l=_llvm_stacksave,c=l.LLVM_SAVEDSTACKS[u];l.LLVM_SAVEDSTACKS.splice(u,1),Runtime.stackRestore(c)}function __nbind_register_pool(u,l,c,p){_nbind.Pool.pageSize=u,_nbind.Pool.usedPtr=l/4,_nbind.Pool.rootPtr=c,_nbind.Pool.pagePtr=p/4,HEAP32[l/4]=16909060,HEAP8[l]==1&&(_nbind.bigEndian=!0),HEAP32[l/4]=0,_nbind.makeTypeKindTbl=(t={},t[1024]=_nbind.PrimitiveType,t[64]=_nbind.Int64Type,t[2048]=_nbind.BindClass,t[3072]=_nbind.BindClassPtr,t[4096]=_nbind.SharedClassPtr,t[5120]=_nbind.ArrayType,t[6144]=_nbind.ArrayType,t[7168]=_nbind.CStringType,t[9216]=_nbind.CallbackType,t[10240]=_nbind.BindType,t),_nbind.makeTypeNameTbl={Buffer:_nbind.BufferType,External:_nbind.ExternalType,Int64:_nbind.Int64Type,_nbind_new:_nbind.CreateValueType,bool:_nbind.BooleanType,"cbFunction &":_nbind.CallbackType,"const cbFunction &":_nbind.CallbackType,"const std::string &":_nbind.StringType,"std::string":_nbind.StringType},Module.toggleLightGC=_nbind.toggleLightGC,_nbind.callUpcast=Module.dynCall_ii;var _=_nbind.makeType(_nbind.constructType,{flags:2048,id:0,name:""});_.proto=Module,_nbind.BindClass.list.push(_);var t}function _emscripten_set_main_loop_timing(u,l){if(Browser.mainLoop.timingMode=u,Browser.mainLoop.timingValue=l,!Browser.mainLoop.func)return 1;if(u==0)Browser.mainLoop.scheduler=function(){var O=Math.max(0,Browser.mainLoop.tickStartTime+l-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,O)},Browser.mainLoop.method="timeout";else if(u==1)Browser.mainLoop.scheduler=function(){Browser.requestAnimationFrame(Browser.mainLoop.runner)},Browser.mainLoop.method="rAF";else if(u==2){if(!window.setImmediate){let t=function(O){O.source===window&&O.data===p&&(O.stopPropagation(),c.shift()())};var _=t,c=[],p="setimmediate";window.addEventListener("message",t,!0),window.setImmediate=function(M){c.push(M),ENVIRONMENT_IS_WORKER?(Module.setImmediates===void 0&&(Module.setImmediates=[]),Module.setImmediates.push(M),window.postMessage({target:p})):window.postMessage(p,"*")}}Browser.mainLoop.scheduler=function(){window.setImmediate(Browser.mainLoop.runner)},Browser.mainLoop.method="immediate"}return 0}function _emscripten_get_now(){abort()}function _emscripten_set_main_loop(u,l,c,p,_){Module.noExitRuntime=!0,assert(!Browser.mainLoop.func,"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters."),Browser.mainLoop.func=u,Browser.mainLoop.arg=p;var t;typeof p<"u"?t=function(){Module.dynCall_vi(u,p)}:t=function(){Module.dynCall_v(u)};var O=Browser.mainLoop.currentlyRunningMainloop;if(Browser.mainLoop.runner=function(){if(!ABORT){if(Browser.mainLoop.queue.length>0){var A=Date.now(),T=Browser.mainLoop.queue.shift();if(T.func(T.arg),Browser.mainLoop.remainingBlockers){var P=Browser.mainLoop.remainingBlockers,U=P%1==0?P-1:Math.floor(P);T.counted?Browser.mainLoop.remainingBlockers=U:(U=U+.5,Browser.mainLoop.remainingBlockers=(8*P+U)/9)}if(console.log('main loop blocker "'+T.name+'" took '+(Date.now()-A)+" ms"),Browser.mainLoop.updateStatus(),O1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else Browser.mainLoop.timingMode==0&&(Browser.mainLoop.tickStartTime=_emscripten_get_now());Browser.mainLoop.method==="timeout"&&Module.ctx&&(Module.printErr("Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!"),Browser.mainLoop.method=""),Browser.mainLoop.runIter(t),!(O0?_emscripten_set_main_loop_timing(0,1e3/l):_emscripten_set_main_loop_timing(1,1),Browser.mainLoop.scheduler()),c)throw"SimulateInfiniteLoop"}var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null,Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var u=Browser.mainLoop.timingMode,l=Browser.mainLoop.timingValue,c=Browser.mainLoop.func;Browser.mainLoop.func=null,_emscripten_set_main_loop(c,0,!1,Browser.mainLoop.arg,!0),_emscripten_set_main_loop_timing(u,l),Browser.mainLoop.scheduler()},updateStatus:function(){if(Module.setStatus){var u=Module.statusMessage||"Please wait...",l=Browser.mainLoop.remainingBlockers,c=Browser.mainLoop.expectedBlockers;l?l"u"&&(console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."),Module.noImageDecoding=!0);var u={};u.canHandle=function(t){return!Module.noImageDecoding&&/\.(jpg|jpeg|png|bmp)$/i.test(t)},u.handle=function(t,O,M,A){var T=null;if(Browser.hasBlobConstructor)try{T=new Blob([t],{type:Browser.getMimetype(O)}),T.size!==t.length&&(T=new Blob([new Uint8Array(t).buffer],{type:Browser.getMimetype(O)}))}catch(Q){Runtime.warnOnce("Blob constructor present but fails: "+Q+"; falling back to blob builder")}if(!T){var P=new Browser.BlobBuilder;P.append(new Uint8Array(t).buffer),T=P.getBlob()}var U=Browser.URLObject.createObjectURL(T),z=new Image;z.onload=function(){assert(z.complete,"Image "+O+" could not be decoded");var v=document.createElement("canvas");v.width=z.width,v.height=z.height;var de=v.getContext("2d");de.drawImage(z,0,0),Module.preloadedImages[O]=v,Browser.URLObject.revokeObjectURL(U),M&&M(t)},z.onerror=function(v){console.log("Image "+U+" could not be decoded"),A&&A()},z.src=U},Module.preloadPlugins.push(u);var l={};l.canHandle=function(t){return!Module.noAudioDecoding&&t.substr(-4)in{".ogg":1,".wav":1,".mp3":1}},l.handle=function(t,O,M,A){var T=!1;function P(de){T||(T=!0,Module.preloadedAudios[O]=de,M&&M(t))}function U(){T||(T=!0,Module.preloadedAudios[O]=new Audio,A&&A())}if(Browser.hasBlobConstructor){try{var z=new Blob([t],{type:Browser.getMimetype(O)})}catch{return U()}var Q=Browser.URLObject.createObjectURL(z),v=new Audio;v.addEventListener("canplaythrough",function(){P(v)},!1),v.onerror=function(ye){if(T)return;console.log("warning: browser could not fully decode audio "+O+", trying slower base64 approach");function le(ae){for(var Me="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fe="=",pe="",Z=0,Ae=0,Fe=0;Fe=6;){var He=Z>>Ae-6&63;Ae-=6,pe+=Me[He]}return Ae==2?(pe+=Me[(Z&3)<<4],pe+=fe+fe):Ae==4&&(pe+=Me[(Z&15)<<2],pe+=fe),pe}v.src="data:audio/x-"+O.substr(-3)+";base64,"+le(t),P(v)},v.src=Q,Browser.safeSetTimeout(function(){P(v)},1e4)}else return U()},Module.preloadPlugins.push(l);function c(){Browser.pointerLock=document.pointerLockElement===Module.canvas||document.mozPointerLockElement===Module.canvas||document.webkitPointerLockElement===Module.canvas||document.msPointerLockElement===Module.canvas}var p=Module.canvas;p&&(p.requestPointerLock=p.requestPointerLock||p.mozRequestPointerLock||p.webkitRequestPointerLock||p.msRequestPointerLock||function(){},p.exitPointerLock=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock||document.msExitPointerLock||function(){},p.exitPointerLock=p.exitPointerLock.bind(document),document.addEventListener("pointerlockchange",c,!1),document.addEventListener("mozpointerlockchange",c,!1),document.addEventListener("webkitpointerlockchange",c,!1),document.addEventListener("mspointerlockchange",c,!1),Module.elementPointerLock&&p.addEventListener("click",function(_){!Browser.pointerLock&&Module.canvas.requestPointerLock&&(Module.canvas.requestPointerLock(),_.preventDefault())},!1))},createContext:function(u,l,c,p){if(l&&Module.ctx&&u==Module.canvas)return Module.ctx;var _,t;if(l){var O={antialias:!1,alpha:!1};if(p)for(var M in p)O[M]=p[M];t=GL.createContext(u,O),t&&(_=GL.getContext(t).GLctx)}else _=u.getContext("2d");return _?(c&&(l||assert(typeof GLctx>"u","cannot set in module if GLctx is used, but we are a non-GL context that would replace it"),Module.ctx=_,l&&GL.makeContextCurrent(t),Module.useWebGL=l,Browser.moduleContextCreatedCallbacks.forEach(function(A){A()}),Browser.init()),_):null},destroyContext:function(u,l,c){},fullscreenHandlersInstalled:!1,lockPointer:void 0,resizeCanvas:void 0,requestFullscreen:function(u,l,c){Browser.lockPointer=u,Browser.resizeCanvas=l,Browser.vrDevice=c,typeof Browser.lockPointer>"u"&&(Browser.lockPointer=!0),typeof Browser.resizeCanvas>"u"&&(Browser.resizeCanvas=!1),typeof Browser.vrDevice>"u"&&(Browser.vrDevice=null);var p=Module.canvas;function _(){Browser.isFullscreen=!1;var O=p.parentNode;(document.fullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.webkitFullscreenElement||document.webkitCurrentFullScreenElement)===O?(p.exitFullscreen=document.exitFullscreen||document.cancelFullScreen||document.mozCancelFullScreen||document.msExitFullscreen||document.webkitCancelFullScreen||function(){},p.exitFullscreen=p.exitFullscreen.bind(document),Browser.lockPointer&&p.requestPointerLock(),Browser.isFullscreen=!0,Browser.resizeCanvas&&Browser.setFullscreenCanvasSize()):(O.parentNode.insertBefore(p,O),O.parentNode.removeChild(O),Browser.resizeCanvas&&Browser.setWindowedCanvasSize()),Module.onFullScreen&&Module.onFullScreen(Browser.isFullscreen),Module.onFullscreen&&Module.onFullscreen(Browser.isFullscreen),Browser.updateCanvasDimensions(p)}Browser.fullscreenHandlersInstalled||(Browser.fullscreenHandlersInstalled=!0,document.addEventListener("fullscreenchange",_,!1),document.addEventListener("mozfullscreenchange",_,!1),document.addEventListener("webkitfullscreenchange",_,!1),document.addEventListener("MSFullscreenChange",_,!1));var t=document.createElement("div");p.parentNode.insertBefore(t,p),t.appendChild(p),t.requestFullscreen=t.requestFullscreen||t.mozRequestFullScreen||t.msRequestFullscreen||(t.webkitRequestFullscreen?function(){t.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}:null)||(t.webkitRequestFullScreen?function(){t.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}:null),c?t.requestFullscreen({vrDisplay:c}):t.requestFullscreen()},requestFullScreen:function(u,l,c){return Module.printErr("Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead."),Browser.requestFullScreen=function(p,_,t){return Browser.requestFullscreen(p,_,t)},Browser.requestFullscreen(u,l,c)},nextRAF:0,fakeRequestAnimationFrame:function(u){var l=Date.now();if(Browser.nextRAF===0)Browser.nextRAF=l+1e3/60;else for(;l+2>=Browser.nextRAF;)Browser.nextRAF+=1e3/60;var c=Math.max(Browser.nextRAF-l,0);setTimeout(u,c)},requestAnimationFrame:function u(l){typeof window>"u"?Browser.fakeRequestAnimationFrame(l):(window.requestAnimationFrame||(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||Browser.fakeRequestAnimationFrame),window.requestAnimationFrame(l))},safeCallback:function(u){return function(){if(!ABORT)return u.apply(null,arguments)}},allowAsyncCallbacks:!0,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function(){Browser.allowAsyncCallbacks=!1},resumeAsyncCallbacks:function(){if(Browser.allowAsyncCallbacks=!0,Browser.queuedAsyncCallbacks.length>0){var u=Browser.queuedAsyncCallbacks;Browser.queuedAsyncCallbacks=[],u.forEach(function(l){l()})}},safeRequestAnimationFrame:function(u){return Browser.requestAnimationFrame(function(){ABORT||(Browser.allowAsyncCallbacks?u():Browser.queuedAsyncCallbacks.push(u))})},safeSetTimeout:function(u,l){return Module.noExitRuntime=!0,setTimeout(function(){ABORT||(Browser.allowAsyncCallbacks?u():Browser.queuedAsyncCallbacks.push(u))},l)},safeSetInterval:function(u,l){return Module.noExitRuntime=!0,setInterval(function(){ABORT||Browser.allowAsyncCallbacks&&u()},l)},getMimetype:function(u){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",bmp:"image/bmp",ogg:"audio/ogg",wav:"audio/wav",mp3:"audio/mpeg"}[u.substr(u.lastIndexOf(".")+1)]},getUserMedia:function(u){window.getUserMedia||(window.getUserMedia=navigator.getUserMedia||navigator.mozGetUserMedia),window.getUserMedia(u)},getMovementX:function(u){return u.movementX||u.mozMovementX||u.webkitMovementX||0},getMovementY:function(u){return u.movementY||u.mozMovementY||u.webkitMovementY||0},getMouseWheelDelta:function(u){var l=0;switch(u.type){case"DOMMouseScroll":l=u.detail;break;case"mousewheel":l=u.wheelDelta;break;case"wheel":l=u.deltaY;break;default:throw"unrecognized mouse wheel event: "+u.type}return l},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(u){if(Browser.pointerLock)u.type!="mousemove"&&"mozMovementX"in u?Browser.mouseMovementX=Browser.mouseMovementY=0:(Browser.mouseMovementX=Browser.getMovementX(u),Browser.mouseMovementY=Browser.getMovementY(u)),typeof SDL<"u"?(Browser.mouseX=SDL.mouseX+Browser.mouseMovementX,Browser.mouseY=SDL.mouseY+Browser.mouseMovementY):(Browser.mouseX+=Browser.mouseMovementX,Browser.mouseY+=Browser.mouseMovementY);else{var l=Module.canvas.getBoundingClientRect(),c=Module.canvas.width,p=Module.canvas.height,_=typeof window.scrollX<"u"?window.scrollX:window.pageXOffset,t=typeof window.scrollY<"u"?window.scrollY:window.pageYOffset;if(u.type==="touchstart"||u.type==="touchend"||u.type==="touchmove"){var O=u.touch;if(O===void 0)return;var M=O.pageX-(_+l.left),A=O.pageY-(t+l.top);M=M*(c/l.width),A=A*(p/l.height);var T={x:M,y:A};if(u.type==="touchstart")Browser.lastTouches[O.identifier]=T,Browser.touches[O.identifier]=T;else if(u.type==="touchend"||u.type==="touchmove"){var P=Browser.touches[O.identifier];P||(P=T),Browser.lastTouches[O.identifier]=P,Browser.touches[O.identifier]=T}return}var U=u.pageX-(_+l.left),z=u.pageY-(t+l.top);U=U*(c/l.width),z=z*(p/l.height),Browser.mouseMovementX=U-Browser.mouseX,Browser.mouseMovementY=z-Browser.mouseY,Browser.mouseX=U,Browser.mouseY=z}},asyncLoad:function(u,l,c,p){var _=p?"":"al "+u;Module.readAsync(u,function(t){assert(t,'Loading data file "'+u+'" failed (no arrayBuffer).'),l(new Uint8Array(t)),_&&removeRunDependency(_)},function(t){if(c)c();else throw'Loading data file "'+u+'" failed.'}),_&&addRunDependency(_)},resizeListeners:[],updateResizeListeners:function(){var u=Module.canvas;Browser.resizeListeners.forEach(function(l){l(u.width,u.height)})},setCanvasSize:function(u,l,c){var p=Module.canvas;Browser.updateCanvasDimensions(p,u,l),c||Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL<"u"){var u=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];u=u|8388608,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=u}Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL<"u"){var u=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];u=u&-8388609,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=u}Browser.updateResizeListeners()},updateCanvasDimensions:function(u,l,c){l&&c?(u.widthNative=l,u.heightNative=c):(l=u.widthNative,c=u.heightNative);var p=l,_=c;if(Module.forcedAspectRatio&&Module.forcedAspectRatio>0&&(p/_>2];return l},getStr:function(){var u=Pointer_stringify(SYSCALLS.get());return u},get64:function(){var u=SYSCALLS.get(),l=SYSCALLS.get();return u>=0?assert(l===0):assert(l===-1),u},getZero:function(){assert(SYSCALLS.get()===0)}};function ___syscall6(u,l){SYSCALLS.varargs=l;try{var c=SYSCALLS.getStreamFromFD();return FS.close(c),0}catch(p){return(typeof FS>"u"||!(p instanceof FS.ErrnoError))&&abort(p),-p.errno}}function ___syscall54(u,l){SYSCALLS.varargs=l;try{return 0}catch(c){return(typeof FS>"u"||!(c instanceof FS.ErrnoError))&&abort(c),-c.errno}}function _typeModule(u){var l=[[0,1,"X"],[1,1,"const X"],[128,1,"X *"],[256,1,"X &"],[384,1,"X &&"],[512,1,"std::shared_ptr"],[640,1,"std::unique_ptr"],[5120,1,"std::vector"],[6144,2,"std::array"],[9216,-1,"std::function"]];function c(A,T,P,U,z,Q){if(T==1){var v=U&896;(v==128||v==256||v==384)&&(A="X const")}var de;return Q?de=P.replace("X",A).replace("Y",z):de=A.replace("X",P).replace("Y",z),de.replace(/([*&]) (?=[*&])/g,"$1")}function p(A,T,P,U,z){throw new Error(A+" type "+P.replace("X",T+"?")+(U?" with flag "+U:"")+" in "+z)}function _(A,T,P,U,z,Q,v,de){Q===void 0&&(Q="X"),de===void 0&&(de=1);var ye=P(A);if(ye)return ye;var le=U(A),ae=le.placeholderFlag,Me=l[ae];v&&Me&&(Q=c(v[2],v[0],Q,Me[0],"?",!0));var fe;ae==0&&(fe="Unbound"),ae>=10&&(fe="Corrupt"),de>20&&(fe="Deeply nested"),fe&&p(fe,A,Q,ae,z||"?");var pe=le.paramList[0],Z=_(pe,T,P,U,z,Q,Me,de+1),Ae,Fe={flags:Me[0],id:A,name:"",paramList:[Z]},He=[],ot="?";switch(le.placeholderFlag){case 1:Ae=Z.spec;break;case 2:if((Z.flags&15360)==1024&&Z.spec.ptrSize==1){Fe.flags=7168;break}case 3:case 6:case 5:Ae=Z.spec,Z.flags&15360;break;case 8:ot=""+le.paramList[1],Fe.paramList.push(le.paramList[1]);break;case 9:for(var st=0,qe=le.paramList[1];st>2]=u),u}function _llvm_stacksave(){var u=_llvm_stacksave;return u.LLVM_SAVEDSTACKS||(u.LLVM_SAVEDSTACKS=[]),u.LLVM_SAVEDSTACKS.push(Runtime.stackSave()),u.LLVM_SAVEDSTACKS.length-1}function ___syscall140(u,l){SYSCALLS.varargs=l;try{var c=SYSCALLS.getStreamFromFD(),p=SYSCALLS.get(),_=SYSCALLS.get(),t=SYSCALLS.get(),O=SYSCALLS.get(),M=_;return FS.llseek(c,M,O),HEAP32[t>>2]=c.position,c.getdents&&M===0&&O===0&&(c.getdents=null),0}catch(A){return(typeof FS>"u"||!(A instanceof FS.ErrnoError))&&abort(A),-A.errno}}function ___syscall146(u,l){SYSCALLS.varargs=l;try{var c=SYSCALLS.get(),p=SYSCALLS.get(),_=SYSCALLS.get(),t=0;___syscall146.buffer||(___syscall146.buffers=[null,[],[]],___syscall146.printChar=function(P,U){var z=___syscall146.buffers[P];assert(z),U===0||U===10?((P===1?Module.print:Module.printErr)(UTF8ArrayToString(z,0)),z.length=0):z.push(U)});for(var O=0;O<_;O++){for(var M=HEAP32[p+O*8>>2],A=HEAP32[p+(O*8+4)>>2],T=0;T"u"||!(P instanceof FS.ErrnoError))&&abort(P),-P.errno}}function __nbind_finish(){for(var u=0,l=_nbind.BindClass.list;uu.pageSize/2||l>u.pageSize-c){var p=_nbind.typeNameTbl.NBind.proto;return p.lalloc(l)}else return HEAPU32[u.usedPtr]=c+l,u.rootPtr+c},u.lreset=function(l,c){var p=HEAPU32[u.pagePtr];if(p){var _=_nbind.typeNameTbl.NBind.proto;_.lreset(l,c)}else HEAPU32[u.usedPtr]=l},u}();_nbind.Pool=Pool;function constructType(u,l){var c=u==10240?_nbind.makeTypeNameTbl[l.name]||_nbind.BindType:_nbind.makeTypeKindTbl[u],p=new c(l);return typeIdTbl[l.id]=p,_nbind.typeNameTbl[l.name]=p,p}_nbind.constructType=constructType;function getType(u){return typeIdTbl[u]}_nbind.getType=getType;function queryType(u){var l=HEAPU8[u],c=_nbind.structureList[l][1];u/=4,c<0&&(++u,c=HEAPU32[u]+1);var p=Array.prototype.slice.call(HEAPU32.subarray(u+1,u+1+c));return l==9&&(p=[p[0],p.slice(1)]),{paramList:p,placeholderFlag:l}}_nbind.queryType=queryType;function getTypes(u,l){return u.map(function(c){return typeof c=="number"?_nbind.getComplexType(c,constructType,getType,queryType,l):_nbind.typeNameTbl[c]})}_nbind.getTypes=getTypes;function readTypeIdList(u,l){return Array.prototype.slice.call(HEAPU32,u/4,u/4+l)}_nbind.readTypeIdList=readTypeIdList;function readAsciiString(u){for(var l=u;HEAPU8[l++];);return String.fromCharCode.apply("",HEAPU8.subarray(u,l-1))}_nbind.readAsciiString=readAsciiString;function readPolicyList(u){var l={};if(u)for(;;){var c=HEAPU32[u/4];if(!c)break;l[readAsciiString(c)]=!0,u+=4}return l}_nbind.readPolicyList=readPolicyList;function getDynCall(u,l){var c={float32_t:"d",float64_t:"d",int64_t:"d",uint64_t:"d",void:"v"},p=u.map(function(t){return c[t.name]||"i"}).join(""),_=Module["dynCall_"+p];if(!_)throw new Error("dynCall_"+p+" not found for "+l+"("+u.map(function(t){return t.name}).join(", ")+")");return _}_nbind.getDynCall=getDynCall;function addMethod(u,l,c,p){var _=u[l];u.hasOwnProperty(l)&&_?((_.arity||_.arity===0)&&(_=_nbind.makeOverloader(_,_.arity),u[l]=_),_.addMethod(c,p)):(c.arity=p,u[l]=c)}_nbind.addMethod=addMethod;function throwError(u){throw new Error(u)}_nbind.throwError=throwError,_nbind.bigEndian=!1,_a=_typeModule(_typeModule),_nbind.Type=_a.Type,_nbind.makeType=_a.makeType,_nbind.getComplexType=_a.getComplexType,_nbind.structureList=_a.structureList;var BindType=function(u){__extends(l,u);function l(){var c=u!==null&&u.apply(this,arguments)||this;return c.heap=HEAPU32,c.ptrSize=4,c}return l.prototype.needsWireRead=function(c){return!!this.wireRead||!!this.makeWireRead},l.prototype.needsWireWrite=function(c){return!!this.wireWrite||!!this.makeWireWrite},l}(_nbind.Type);_nbind.BindType=BindType;var PrimitiveType=function(u){__extends(l,u);function l(c){var p=u.call(this,c)||this,_=c.flags&32?{32:HEAPF32,64:HEAPF64}:c.flags&8?{8:HEAPU8,16:HEAPU16,32:HEAPU32}:{8:HEAP8,16:HEAP16,32:HEAP32};return p.heap=_[c.ptrSize*8],p.ptrSize=c.ptrSize,p}return l.prototype.needsWireWrite=function(c){return!!c&&!!c.Strict},l.prototype.makeWireWrite=function(c,p){return p&&p.Strict&&function(_){if(typeof _=="number")return _;throw new Error("Type mismatch")}},l}(BindType);_nbind.PrimitiveType=PrimitiveType;function pushCString(u,l){if(u==null){if(l&&l.Nullable)return 0;throw new Error("Type mismatch")}if(l&&l.Strict){if(typeof u!="string")throw new Error("Type mismatch")}else u=u.toString();var c=Module.lengthBytesUTF8(u)+1,p=_nbind.Pool.lalloc(c);return Module.stringToUTF8Array(u,HEAPU8,p,c),p}_nbind.pushCString=pushCString;function popCString(u){return u===0?null:Module.Pointer_stringify(u)}_nbind.popCString=popCString;var CStringType=function(u){__extends(l,u);function l(){var c=u!==null&&u.apply(this,arguments)||this;return c.wireRead=popCString,c.wireWrite=pushCString,c.readResources=[_nbind.resources.pool],c.writeResources=[_nbind.resources.pool],c}return l.prototype.makeWireWrite=function(c,p){return function(_){return pushCString(_,p)}},l}(BindType);_nbind.CStringType=CStringType;var BooleanType=function(u){__extends(l,u);function l(){var c=u!==null&&u.apply(this,arguments)||this;return c.wireRead=function(p){return!!p},c}return l.prototype.needsWireWrite=function(c){return!!c&&!!c.Strict},l.prototype.makeWireRead=function(c){return"!!("+c+")"},l.prototype.makeWireWrite=function(c,p){return p&&p.Strict&&function(_){if(typeof _=="boolean")return _;throw new Error("Type mismatch")}||c},l}(BindType);_nbind.BooleanType=BooleanType;var Wrapper=function(){function u(){}return u.prototype.persist=function(){this.__nbindState|=1},u}();_nbind.Wrapper=Wrapper;function makeBound(u,l){var c=function(p){__extends(_,p);function _(t,O,M,A){var T=p.call(this)||this;if(!(T instanceof _))return new(Function.prototype.bind.apply(_,Array.prototype.concat.apply([null],arguments)));var P=O,U=M,z=A;if(t!==_nbind.ptrMarker){var Q=T.__nbindConstructor.apply(T,arguments);P=4608,z=HEAPU32[Q/4],U=HEAPU32[Q/4+1]}var v={configurable:!0,enumerable:!1,value:null,writable:!1},de={__nbindFlags:P,__nbindPtr:U};z&&(de.__nbindShared=z,_nbind.mark(T));for(var ye=0,le=Object.keys(de);ye>=1;var c=_nbind.valueList[u];return _nbind.valueList[u]=firstFreeValue,firstFreeValue=u,c}else{if(l)return _nbind.popShared(u,l);throw new Error("Invalid value slot "+u)}}_nbind.popValue=popValue;var valueBase=18446744073709552e3;function push64(u){return typeof u=="number"?u:pushValue(u)*4096+valueBase}function pop64(u){return u=3?O=Buffer.from(t):O=new Buffer(t),O.copy(p)}else getBuffer(p).set(t)}}_nbind.commitBuffer=commitBuffer;var dirtyList=[],gcTimer=0;function sweep(){for(var u=0,l=dirtyList;u>2]=DYNAMIC_BASE,staticSealed=!0;function invoke_viiiii(u,l,c,p,_,t){try{Module.dynCall_viiiii(u,l,c,p,_,t)}catch(O){if(typeof O!="number"&&O!=="longjmp")throw O;Module.setThrew(1,0)}}function invoke_vif(u,l,c){try{Module.dynCall_vif(u,l,c)}catch(p){if(typeof p!="number"&&p!=="longjmp")throw p;Module.setThrew(1,0)}}function invoke_vid(u,l,c){try{Module.dynCall_vid(u,l,c)}catch(p){if(typeof p!="number"&&p!=="longjmp")throw p;Module.setThrew(1,0)}}function invoke_fiff(u,l,c,p){try{return Module.dynCall_fiff(u,l,c,p)}catch(_){if(typeof _!="number"&&_!=="longjmp")throw _;Module.setThrew(1,0)}}function invoke_vi(u,l){try{Module.dynCall_vi(u,l)}catch(c){if(typeof c!="number"&&c!=="longjmp")throw c;Module.setThrew(1,0)}}function invoke_vii(u,l,c){try{Module.dynCall_vii(u,l,c)}catch(p){if(typeof p!="number"&&p!=="longjmp")throw p;Module.setThrew(1,0)}}function invoke_ii(u,l){try{return Module.dynCall_ii(u,l)}catch(c){if(typeof c!="number"&&c!=="longjmp")throw c;Module.setThrew(1,0)}}function invoke_viddi(u,l,c,p,_){try{Module.dynCall_viddi(u,l,c,p,_)}catch(t){if(typeof t!="number"&&t!=="longjmp")throw t;Module.setThrew(1,0)}}function invoke_vidd(u,l,c,p){try{Module.dynCall_vidd(u,l,c,p)}catch(_){if(typeof _!="number"&&_!=="longjmp")throw _;Module.setThrew(1,0)}}function invoke_iiii(u,l,c,p){try{return Module.dynCall_iiii(u,l,c,p)}catch(_){if(typeof _!="number"&&_!=="longjmp")throw _;Module.setThrew(1,0)}}function invoke_diii(u,l,c,p){try{return Module.dynCall_diii(u,l,c,p)}catch(_){if(typeof _!="number"&&_!=="longjmp")throw _;Module.setThrew(1,0)}}function invoke_di(u,l){try{return Module.dynCall_di(u,l)}catch(c){if(typeof c!="number"&&c!=="longjmp")throw c;Module.setThrew(1,0)}}function invoke_iid(u,l,c){try{return Module.dynCall_iid(u,l,c)}catch(p){if(typeof p!="number"&&p!=="longjmp")throw p;Module.setThrew(1,0)}}function invoke_iii(u,l,c){try{return Module.dynCall_iii(u,l,c)}catch(p){if(typeof p!="number"&&p!=="longjmp")throw p;Module.setThrew(1,0)}}function invoke_viiddi(u,l,c,p,_,t){try{Module.dynCall_viiddi(u,l,c,p,_,t)}catch(O){if(typeof O!="number"&&O!=="longjmp")throw O;Module.setThrew(1,0)}}function invoke_viiiiii(u,l,c,p,_,t,O){try{Module.dynCall_viiiiii(u,l,c,p,_,t,O)}catch(M){if(typeof M!="number"&&M!=="longjmp")throw M;Module.setThrew(1,0)}}function invoke_dii(u,l,c){try{return Module.dynCall_dii(u,l,c)}catch(p){if(typeof p!="number"&&p!=="longjmp")throw p;Module.setThrew(1,0)}}function invoke_i(u){try{return Module.dynCall_i(u)}catch(l){if(typeof l!="number"&&l!=="longjmp")throw l;Module.setThrew(1,0)}}function invoke_iiiiii(u,l,c,p,_,t){try{return Module.dynCall_iiiiii(u,l,c,p,_,t)}catch(O){if(typeof O!="number"&&O!=="longjmp")throw O;Module.setThrew(1,0)}}function invoke_viiid(u,l,c,p,_){try{Module.dynCall_viiid(u,l,c,p,_)}catch(t){if(typeof t!="number"&&t!=="longjmp")throw t;Module.setThrew(1,0)}}function invoke_viififi(u,l,c,p,_,t,O){try{Module.dynCall_viififi(u,l,c,p,_,t,O)}catch(M){if(typeof M!="number"&&M!=="longjmp")throw M;Module.setThrew(1,0)}}function invoke_viii(u,l,c,p){try{Module.dynCall_viii(u,l,c,p)}catch(_){if(typeof _!="number"&&_!=="longjmp")throw _;Module.setThrew(1,0)}}function invoke_v(u){try{Module.dynCall_v(u)}catch(l){if(typeof l!="number"&&l!=="longjmp")throw l;Module.setThrew(1,0)}}function invoke_viid(u,l,c,p){try{Module.dynCall_viid(u,l,c,p)}catch(_){if(typeof _!="number"&&_!=="longjmp")throw _;Module.setThrew(1,0)}}function invoke_idd(u,l,c){try{return Module.dynCall_idd(u,l,c)}catch(p){if(typeof p!="number"&&p!=="longjmp")throw p;Module.setThrew(1,0)}}function invoke_viiii(u,l,c,p,_){try{Module.dynCall_viiii(u,l,c,p,_)}catch(t){if(typeof t!="number"&&t!=="longjmp")throw t;Module.setThrew(1,0)}}Module.asmGlobalArg={Math,Int8Array,Int16Array,Int32Array,Uint8Array,Uint16Array,Uint32Array,Float32Array,Float64Array,NaN:NaN,Infinity:1/0},Module.asmLibraryArg={abort,assert,enlargeMemory,getTotalMemory,abortOnCannotGrowMemory,invoke_viiiii,invoke_vif,invoke_vid,invoke_fiff,invoke_vi,invoke_vii,invoke_ii,invoke_viddi,invoke_vidd,invoke_iiii,invoke_diii,invoke_di,invoke_iid,invoke_iii,invoke_viiddi,invoke_viiiiii,invoke_dii,invoke_i,invoke_iiiiii,invoke_viiid,invoke_viififi,invoke_viii,invoke_v,invoke_viid,invoke_idd,invoke_viiii,_emscripten_asm_const_iiiii,_emscripten_asm_const_iiidddddd,_emscripten_asm_const_iiiid,__nbind_reference_external,_emscripten_asm_const_iiiiiiii,_removeAccessorPrefix,_typeModule,__nbind_register_pool,__decorate,_llvm_stackrestore,___cxa_atexit,__extends,__nbind_get_value_object,__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,_emscripten_set_main_loop_timing,__nbind_register_primitive,__nbind_register_type,_emscripten_memcpy_big,__nbind_register_function,___setErrNo,__nbind_register_class,__nbind_finish,_abort,_nbind_value,_llvm_stacksave,___syscall54,_defineHidden,_emscripten_set_main_loop,_emscripten_get_now,__nbind_register_callback_signature,_emscripten_asm_const_iiiiii,__nbind_free_external,_emscripten_asm_const_iiii,_emscripten_asm_const_iiididi,___syscall6,_atexit,___syscall140,___syscall146,DYNAMICTOP_PTR,tempDoublePtr,ABORT,STACKTOP,STACK_MAX,cttz_i8,___dso_handle};var asm=function(u,l,c){var p=new u.Int8Array(c),_=new u.Int16Array(c),t=new u.Int32Array(c),O=new u.Uint8Array(c),M=new u.Uint16Array(c),A=new u.Uint32Array(c),T=new u.Float32Array(c),P=new u.Float64Array(c),U=l.DYNAMICTOP_PTR|0,z=l.tempDoublePtr|0,Q=l.ABORT|0,v=l.STACKTOP|0,de=l.STACK_MAX|0,ye=l.cttz_i8|0,le=l.___dso_handle|0,ae=0,Me=0,fe=0,pe=0,Z=u.NaN,Ae=u.Infinity,Fe=0,He=0,ot=0,st=0,qe=0,Xe=0,Ie=u.Math.floor,kt=u.Math.abs,Kt=u.Math.sqrt,Ye=u.Math.pow,V=u.Math.cos,oe=u.Math.sin,ve=u.Math.tan,ee=u.Math.acos,Oe=u.Math.asin,et=u.Math.atan,ct=u.Math.atan2,Lt=u.Math.exp,Xt=u.Math.log,pn=u.Math.ceil,Nn=u.Math.imul,Wt=u.Math.min,Ot=u.Math.max,Wn=u.Math.clz32,w=u.Math.fround,Ct=l.abort,wn=l.assert,ir=l.enlargeMemory,sr=l.getTotalMemory,Ln=l.abortOnCannotGrowMemory,Er=l.invoke_viiiii,zt=l.invoke_vif,p0=l.invoke_vid,B0=l.invoke_fiff,Do=l.invoke_vi,wl=l.invoke_vii,Sl=l.invoke_ii,Tl=l.invoke_viddi,ua=l.invoke_vidd,Rt=l.invoke_iiii,Kr=l.invoke_diii,Ai=l.invoke_di,br=l.invoke_iid,Xn=l.invoke_iii,Fu=l.invoke_viiddi,wo=l.invoke_viiiiii,h0=l.invoke_dii,So=l.invoke_i,hr=l.invoke_iiiiii,To=l.invoke_viiid,Co=l.invoke_viififi,U0=l.invoke_viii,xi=l.invoke_v,Wr=l.invoke_viid,Cl=l.invoke_idd,Lu=l.invoke_viiii,F0=l._emscripten_asm_const_iiiii,S0=l._emscripten_asm_const_iiidddddd,or=l._emscripten_asm_const_iiiid,Pr=l.__nbind_reference_external,j0=l._emscripten_asm_const_iiiiiiii,Ir=l._removeAccessorPrefix,Ft=l._typeModule,hn=l.__nbind_register_pool,Br=l.__decorate,Tr=l._llvm_stackrestore,xt=l.___cxa_atexit,Li=l.__extends,di=l.__nbind_get_value_object,z0=l.__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,ti=l._emscripten_set_main_loop_timing,bu=l.__nbind_register_primitive,Ko=l.__nbind_register_type,Dr=l._emscripten_memcpy_big,ro=l.__nbind_register_function,Pu=l.___setErrNo,xo=l.__nbind_register_class,xl=l.__nbind_finish,Tn=l._abort,tl=l._nbind_value,io=l._llvm_stacksave,Ro=l.___syscall54,mu=l._defineHidden,Ao=l._emscripten_set_main_loop,it=l._emscripten_get_now,Dt=l.__nbind_register_callback_signature,mn=l._emscripten_asm_const_iiiiii,vr=l.__nbind_free_external,ni=l._emscripten_asm_const_iiii,mr=l._emscripten_asm_const_iiididi,bi=l.___syscall6,v0=l._atexit,Xr=l.___syscall140,T0=l.___syscall146,Rl=w(0);let lt=w(0);function oo(e){e=e|0;var n=0;return n=v,v=v+e|0,v=v+15&-16,n|0}function yu(){return v|0}function la(e){e=e|0,v=e}function e0(e,n){e=e|0,n=n|0,v=e,de=n}function nl(e,n){e=e|0,n=n|0,ae||(ae=e,Me=n)}function q0(e){e=e|0,Xe=e}function W(){return Xe|0}function he(){var e=0,n=0;bn(8104,8,400)|0,bn(8504,408,540)|0,e=9044,n=e+44|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));p[9088]=0,p[9089]=1,t[2273]=0,t[2274]=948,t[2275]=948,xt(17,8104,le|0)|0}function Se(e){e=e|0,Tf(e+948|0)}function we(e){return e=w(e),((zn(e)|0)&2147483647)>>>0>2139095040|0}function tt(e,n,r){e=e|0,n=n|0,r=r|0;e:do if(t[e+(n<<3)+4>>2]|0)e=e+(n<<3)|0;else{if((n|2|0)==3&&t[e+60>>2]|0){e=e+56|0;break}switch(n|0){case 0:case 2:case 4:case 5:{if(t[e+52>>2]|0){e=e+48|0;break e}break}default:}if(t[e+68>>2]|0){e=e+64|0;break}else{e=(n|1|0)==5?948:r;break}}while(0);return e|0}function Cn(e){e=e|0;var n=0;return n=Dy(1e3)|0,cn(e,(n|0)!=0,2456),t[2276]=(t[2276]|0)+1,bn(n|0,8104,1e3)|0,p[e+2>>0]|0&&(t[n+4>>2]=2,t[n+12>>2]=4),t[n+976>>2]=e,n|0}function cn(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0;a=v,v=v+16|0,o=a,n||(t[o>>2]=r,_u(e,5,3197,o)),v=a}function In(){return Cn(956)|0}function Ur(e){e=e|0;var n=0;return n=Bt(1e3)|0,Pi(n,e),cn(t[e+976>>2]|0,1,2456),t[2276]=(t[2276]|0)+1,t[n+944>>2]=0,n|0}function Pi(e,n){e=e|0,n=n|0;var r=0;bn(e|0,n|0,948)|0,da(e+948|0,n+948|0),r=e+960|0,e=n+960|0,n=r+40|0;do t[r>>2]=t[e>>2],r=r+4|0,e=e+4|0;while((r|0)<(n|0))}function t0(e){e=e|0;var n=0,r=0,o=0,a=0;if(n=e+944|0,r=t[n>>2]|0,r|0&&(n0(r+948|0,e)|0,t[n>>2]=0),r=Ii(e)|0,r|0){n=0;do t[(jr(e,n)|0)+944>>2]=0,n=n+1|0;while((n|0)!=(r|0))}r=e+948|0,o=t[r>>2]|0,a=e+952|0,n=t[a>>2]|0,(n|0)!=(o|0)&&(t[a>>2]=n+(~((n+-4-o|0)>>>2)<<2)),ko(r),wy(e),t[2276]=(t[2276]|0)+-1}function n0(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0;o=t[e>>2]|0,E=e+4|0,r=t[E>>2]|0,s=r;e:do if((o|0)==(r|0))a=o,h=4;else for(e=o;;){if((t[e>>2]|0)==(n|0)){a=e,h=4;break e}if(e=e+4|0,(e|0)==(r|0)){e=0;break}}while(0);return(h|0)==4&&((a|0)!=(r|0)?(o=a+4|0,e=s-o|0,n=e>>2,n&&(ih(a|0,o|0,e|0)|0,r=t[E>>2]|0),e=a+(n<<2)|0,(r|0)==(e|0)||(t[E>>2]=r+(~((r+-4-e|0)>>>2)<<2)),e=1):e=0),e|0}function Ii(e){return e=e|0,(t[e+952>>2]|0)-(t[e+948>>2]|0)>>2|0}function jr(e,n){e=e|0,n=n|0;var r=0;return r=t[e+948>>2]|0,(t[e+952>>2]|0)-r>>2>>>0>n>>>0?e=t[r+(n<<2)>>2]|0:e=0,e|0}function ko(e){e=e|0;var n=0,r=0,o=0,a=0;o=v,v=v+32|0,n=o,a=t[e>>2]|0,r=(t[e+4>>2]|0)-a|0,((t[e+8>>2]|0)-a|0)>>>0>r>>>0&&(a=r>>2,Mr(n,a,a,e+8|0),qr(e,n),Cr(n)),v=o}function Bi(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0;k=Ii(e)|0;do if(k|0){if((t[(jr(e,0)|0)+944>>2]|0)==(e|0)){if(!(n0(e+948|0,n)|0))break;bn(n+400|0,8504,540)|0,t[n+944>>2]=0,Sn(e);break}h=t[(t[e+976>>2]|0)+12>>2]|0,E=e+948|0,D=(h|0)==0,r=0,s=0;do o=t[(t[E>>2]|0)+(s<<2)>>2]|0,(o|0)==(n|0)?Sn(e):(a=Ur(o)|0,t[(t[E>>2]|0)+(r<<2)>>2]=a,t[a+944>>2]=e,D||rD[h&15](o,a,e,r),r=r+1|0),s=s+1|0;while((s|0)!=(k|0));if(r>>>0>>0){D=e+948|0,E=e+952|0,h=r,r=t[E>>2]|0;do s=(t[D>>2]|0)+(h<<2)|0,o=s+4|0,a=r-o|0,n=a>>2,n&&(ih(s|0,o|0,a|0)|0,r=t[E>>2]|0),a=r,o=s+(n<<2)|0,(a|0)!=(o|0)&&(r=a+(~((a+-4-o|0)>>>2)<<2)|0,t[E>>2]=r),h=h+1|0;while((h|0)!=(k|0))}}while(0)}function uo(e){e=e|0;var n=0,r=0,o=0,a=0;r0(e,(Ii(e)|0)==0,2491),r0(e,(t[e+944>>2]|0)==0,2545),n=e+948|0,r=t[n>>2]|0,o=e+952|0,a=t[o>>2]|0,(a|0)!=(r|0)&&(t[o>>2]=a+(~((a+-4-r|0)>>>2)<<2)),ko(n),n=e+976|0,r=t[n>>2]|0,bn(e|0,8104,1e3)|0,p[r+2>>0]|0&&(t[e+4>>2]=2,t[e+12>>2]=4),t[n>>2]=r}function r0(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0;a=v,v=v+16|0,o=a,n||(t[o>>2]=r,R0(e,5,3197,o)),v=a}function Ga(){return t[2276]|0}function m0(){var e=0;return e=Dy(20)|0,aa((e|0)!=0,2592),t[2277]=(t[2277]|0)+1,t[e>>2]=t[239],t[e+4>>2]=t[240],t[e+8>>2]=t[241],t[e+12>>2]=t[242],t[e+16>>2]=t[243],e|0}function aa(e,n){e=e|0,n=n|0;var r=0,o=0;o=v,v=v+16|0,r=o,e||(t[r>>2]=n,R0(0,5,3197,r)),v=o}function H0(e){e=e|0,wy(e),t[2277]=(t[2277]|0)+-1}function xs(e,n){e=e|0,n=n|0;var r=0;n?(r0(e,(Ii(e)|0)==0,2629),r=1):(r=0,n=0),t[e+964>>2]=n,t[e+988>>2]=r}function Ya(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;o=v,v=v+16|0,s=o+8|0,a=o+4|0,h=o,t[a>>2]=n,r0(e,(t[n+944>>2]|0)==0,2709),r0(e,(t[e+964>>2]|0)==0,2763),rl(e),n=e+948|0,t[h>>2]=(t[n>>2]|0)+(r<<2),t[s>>2]=t[h>>2],C0(n,s,a)|0,t[(t[a>>2]|0)+944>>2]=e,Sn(e),v=o}function rl(e){e=e|0;var n=0,r=0,o=0,a=0,s=0,h=0,E=0;if(r=Ii(e)|0,r|0&&(t[(jr(e,0)|0)+944>>2]|0)!=(e|0)){o=t[(t[e+976>>2]|0)+12>>2]|0,a=e+948|0,s=(o|0)==0,n=0;do h=t[(t[a>>2]|0)+(n<<2)>>2]|0,E=Ur(h)|0,t[(t[a>>2]|0)+(n<<2)>>2]=E,t[E+944>>2]=e,s||rD[o&15](h,E,e,n),n=n+1|0;while((n|0)!=(r|0))}}function C0(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0,xe=0,ce=0,ue=0,Be=0,be=0;Be=v,v=v+64|0,F=Be+52|0,E=Be+48|0,H=Be+28|0,xe=Be+24|0,ce=Be+20|0,ue=Be,o=t[e>>2]|0,s=o,n=o+((t[n>>2]|0)-s>>2<<2)|0,o=e+4|0,a=t[o>>2]|0,h=e+8|0;do if(a>>>0<(t[h>>2]|0)>>>0){if((n|0)==(a|0)){t[n>>2]=t[r>>2],t[o>>2]=(t[o>>2]|0)+4;break}ui(e,n,a,n+4|0),n>>>0<=r>>>0&&(r=(t[o>>2]|0)>>>0>r>>>0?r+4|0:r),t[n>>2]=t[r>>2]}else{o=(a-s>>2)+1|0,a=so(e)|0,a>>>0>>0&&gr(e),R=t[e>>2]|0,k=(t[h>>2]|0)-R|0,s=k>>1,Mr(ue,k>>2>>>0>>1>>>0?s>>>0>>0?o:s:a,n-R>>2,e+8|0),R=ue+8|0,o=t[R>>2]|0,s=ue+12|0,k=t[s>>2]|0,h=k,D=o;do if((o|0)==(k|0)){if(k=ue+4|0,o=t[k>>2]|0,be=t[ue>>2]|0,a=be,o>>>0<=be>>>0){o=h-a>>1,o=(o|0)==0?1:o,Mr(H,o,o>>>2,t[ue+16>>2]|0),t[xe>>2]=t[k>>2],t[ce>>2]=t[R>>2],t[E>>2]=t[xe>>2],t[F>>2]=t[ce>>2],xr(H,E,F),o=t[ue>>2]|0,t[ue>>2]=t[H>>2],t[H>>2]=o,o=H+4|0,be=t[k>>2]|0,t[k>>2]=t[o>>2],t[o>>2]=be,o=H+8|0,be=t[R>>2]|0,t[R>>2]=t[o>>2],t[o>>2]=be,o=H+12|0,be=t[s>>2]|0,t[s>>2]=t[o>>2],t[o>>2]=be,Cr(H),o=t[R>>2]|0;break}s=o,h=((s-a>>2)+1|0)/-2|0,E=o+(h<<2)|0,a=D-s|0,s=a>>2,s&&(ih(E|0,o|0,a|0)|0,o=t[k>>2]|0),be=E+(s<<2)|0,t[R>>2]=be,t[k>>2]=o+(h<<2),o=be}while(0);t[o>>2]=t[r>>2],t[R>>2]=(t[R>>2]|0)+4,n=gt(e,ue,n)|0,Cr(ue)}while(0);return v=Be,n|0}function Sn(e){e=e|0;var n=0;do{if(n=e+984|0,p[n>>0]|0)break;p[n>>0]=1,T[e+504>>2]=w(Z),e=t[e+944>>2]|0}while((e|0)!=0)}function Tf(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-4-o|0)>>>2)<<2)),$e(r))}function il(e){return e=e|0,t[e+944>>2]|0}function Iu(e){e=e|0,r0(e,(t[e+964>>2]|0)!=0,2832),Sn(e)}function Bu(e){return e=e|0,(p[e+984>>0]|0)!=0|0}function sa(e,n){e=e|0,n=n|0,HI(e,n,400)|0&&(bn(e|0,n|0,400)|0,Sn(e))}function Rs(e){e=e|0;var n=lt;return n=w(T[e+44>>2]),e=we(n)|0,w(e?w(0):n)}function Al(e){e=e|0;var n=lt;return n=w(T[e+48>>2]),we(n)|0&&(n=p[(t[e+976>>2]|0)+2>>0]|0?w(1):w(0)),w(n)}function Ka(e,n){e=e|0,n=n|0,t[e+980>>2]=n}function kl(e){return e=e|0,t[e+980>>2]|0}function x0(e,n){e=e|0,n=n|0;var r=0;r=e+4|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Sn(e))}function Ol(e){return e=e|0,t[e+4>>2]|0}function Uu(e,n){e=e|0,n=n|0;var r=0;r=e+8|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Sn(e))}function b(e){return e=e|0,t[e+8>>2]|0}function B(e,n){e=e|0,n=n|0;var r=0;r=e+12|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Sn(e))}function q(e){return e=e|0,t[e+12>>2]|0}function Y(e,n){e=e|0,n=n|0;var r=0;r=e+16|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Sn(e))}function _e(e){return e=e|0,t[e+16>>2]|0}function se(e,n){e=e|0,n=n|0;var r=0;r=e+20|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Sn(e))}function ge(e){return e=e|0,t[e+20>>2]|0}function G(e,n){e=e|0,n=n|0;var r=0;r=e+24|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Sn(e))}function De(e){return e=e|0,t[e+24>>2]|0}function je(e,n){e=e|0,n=n|0;var r=0;r=e+28|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Sn(e))}function nt(e){return e=e|0,t[e+28>>2]|0}function ne(e,n){e=e|0,n=n|0;var r=0;r=e+32|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Sn(e))}function Ne(e){return e=e|0,t[e+32>>2]|0}function Je(e,n){e=e|0,n=n|0;var r=0;r=e+36|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Sn(e))}function ut(e){return e=e|0,t[e+36>>2]|0}function ht(e,n){e=e|0,n=w(n);var r=0;r=e+40|0,w(T[r>>2])!=n&&(T[r>>2]=n,Sn(e))}function wt(e,n){e=e|0,n=w(n);var r=0;r=e+44|0,w(T[r>>2])!=n&&(T[r>>2]=n,Sn(e))}function Vt(e,n){e=e|0,n=w(n);var r=0;r=e+48|0,w(T[r>>2])!=n&&(T[r>>2]=n,Sn(e))}function bt(e,n){e=e|0,n=w(n);var r=0,o=0,a=0,s=0;s=we(n)|0,r=(s^1)&1,o=e+52|0,a=e+56|0,s|w(T[o>>2])==n&&(t[a>>2]|0)==(r|0)||(T[o>>2]=n,t[a>>2]=r,Sn(e))}function Pt(e,n){e=e|0,n=w(n);var r=0,o=0;o=e+52|0,r=e+56|0,w(T[o>>2])==n&&(t[r>>2]|0)==2||(T[o>>2]=n,o=we(n)|0,t[r>>2]=o?3:2,Sn(e))}function ln(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+52|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function jn(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,a=0,s=0;s=we(r)|0,o=(s^1)&1,a=e+132+(n<<3)|0,n=e+132+(n<<3)+4|0,s|w(T[a>>2])==r&&(t[n>>2]|0)==(o|0)||(T[a>>2]=r,t[n>>2]=o,Sn(e))}function xn(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,a=0,s=0;s=we(r)|0,o=s?0:2,a=e+132+(n<<3)|0,n=e+132+(n<<3)+4|0,s|w(T[a>>2])==r&&(t[n>>2]|0)==(o|0)||(T[a>>2]=r,t[n>>2]=o,Sn(e))}function Jn(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=n+132+(r<<3)|0,n=t[o+4>>2]|0,r=e,t[r>>2]=t[o>>2],t[r+4>>2]=n}function nn(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,a=0,s=0;s=we(r)|0,o=(s^1)&1,a=e+60+(n<<3)|0,n=e+60+(n<<3)+4|0,s|w(T[a>>2])==r&&(t[n>>2]|0)==(o|0)||(T[a>>2]=r,t[n>>2]=o,Sn(e))}function $n(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,a=0,s=0;s=we(r)|0,o=s?0:2,a=e+60+(n<<3)|0,n=e+60+(n<<3)+4|0,s|w(T[a>>2])==r&&(t[n>>2]|0)==(o|0)||(T[a>>2]=r,t[n>>2]=o,Sn(e))}function y0(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=n+60+(r<<3)|0,n=t[o+4>>2]|0,r=e,t[r>>2]=t[o>>2],t[r+4>>2]=n}function nr(e,n){e=e|0,n=n|0;var r=0;r=e+60+(n<<3)+4|0,(t[r>>2]|0)!=3&&(T[e+60+(n<<3)>>2]=w(Z),t[r>>2]=3,Sn(e))}function Ge(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,a=0,s=0;s=we(r)|0,o=(s^1)&1,a=e+204+(n<<3)|0,n=e+204+(n<<3)+4|0,s|w(T[a>>2])==r&&(t[n>>2]|0)==(o|0)||(T[a>>2]=r,t[n>>2]=o,Sn(e))}function at(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,a=0,s=0;s=we(r)|0,o=s?0:2,a=e+204+(n<<3)|0,n=e+204+(n<<3)+4|0,s|w(T[a>>2])==r&&(t[n>>2]|0)==(o|0)||(T[a>>2]=r,t[n>>2]=o,Sn(e))}function ze(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=n+204+(r<<3)|0,n=t[o+4>>2]|0,r=e,t[r>>2]=t[o>>2],t[r+4>>2]=n}function yt(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,a=0,s=0;s=we(r)|0,o=(s^1)&1,a=e+276+(n<<3)|0,n=e+276+(n<<3)+4|0,s|w(T[a>>2])==r&&(t[n>>2]|0)==(o|0)||(T[a>>2]=r,t[n>>2]=o,Sn(e))}function It(e,n){return e=e|0,n=n|0,w(T[e+276+(n<<3)>>2])}function Gt(e,n){e=e|0,n=w(n);var r=0,o=0,a=0,s=0;s=we(n)|0,r=(s^1)&1,o=e+348|0,a=e+352|0,s|w(T[o>>2])==n&&(t[a>>2]|0)==(r|0)||(T[o>>2]=n,t[a>>2]=r,Sn(e))}function An(e,n){e=e|0,n=w(n);var r=0,o=0;o=e+348|0,r=e+352|0,w(T[o>>2])==n&&(t[r>>2]|0)==2||(T[o>>2]=n,o=we(n)|0,t[r>>2]=o?3:2,Sn(e))}function Vn(e){e=e|0;var n=0;n=e+352|0,(t[n>>2]|0)!=3&&(T[e+348>>2]=w(Z),t[n>>2]=3,Sn(e))}function gi(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+348|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function i0(e,n){e=e|0,n=w(n);var r=0,o=0,a=0,s=0;s=we(n)|0,r=(s^1)&1,o=e+356|0,a=e+360|0,s|w(T[o>>2])==n&&(t[a>>2]|0)==(r|0)||(T[o>>2]=n,t[a>>2]=r,Sn(e))}function W0(e,n){e=e|0,n=w(n);var r=0,o=0;o=e+356|0,r=e+360|0,w(T[o>>2])==n&&(t[r>>2]|0)==2||(T[o>>2]=n,o=we(n)|0,t[r>>2]=o?3:2,Sn(e))}function V0(e){e=e|0;var n=0;n=e+360|0,(t[n>>2]|0)!=3&&(T[e+356>>2]=w(Z),t[n>>2]=3,Sn(e))}function Gi(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+356|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function Yi(e,n){e=e|0,n=w(n);var r=0,o=0,a=0,s=0;s=we(n)|0,r=(s^1)&1,o=e+364|0,a=e+368|0,s|w(T[o>>2])==n&&(t[a>>2]|0)==(r|0)||(T[o>>2]=n,t[a>>2]=r,Sn(e))}function gu(e,n){e=e|0,n=w(n);var r=0,o=0,a=0,s=0;s=we(n)|0,r=s?0:2,o=e+364|0,a=e+368|0,s|w(T[o>>2])==n&&(t[a>>2]|0)==(r|0)||(T[o>>2]=n,t[a>>2]=r,Sn(e))}function Ml(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+364|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function Cf(e,n){e=e|0,n=w(n);var r=0,o=0,a=0,s=0;s=we(n)|0,r=(s^1)&1,o=e+372|0,a=e+376|0,s|w(T[o>>2])==n&&(t[a>>2]|0)==(r|0)||(T[o>>2]=n,t[a>>2]=r,Sn(e))}function ju(e,n){e=e|0,n=w(n);var r=0,o=0,a=0,s=0;s=we(n)|0,r=s?0:2,o=e+372|0,a=e+376|0,s|w(T[o>>2])==n&&(t[a>>2]|0)==(r|0)||(T[o>>2]=n,t[a>>2]=r,Sn(e))}function As(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+372|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function Oo(e,n){e=e|0,n=w(n);var r=0,o=0,a=0,s=0;s=we(n)|0,r=(s^1)&1,o=e+380|0,a=e+384|0,s|w(T[o>>2])==n&&(t[a>>2]|0)==(r|0)||(T[o>>2]=n,t[a>>2]=r,Sn(e))}function ol(e,n){e=e|0,n=w(n);var r=0,o=0,a=0,s=0;s=we(n)|0,r=s?0:2,o=e+380|0,a=e+384|0,s|w(T[o>>2])==n&&(t[a>>2]|0)==(r|0)||(T[o>>2]=n,t[a>>2]=r,Sn(e))}function Nl(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+380|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function Mo(e,n){e=e|0,n=w(n);var r=0,o=0,a=0,s=0;s=we(n)|0,r=(s^1)&1,o=e+388|0,a=e+392|0,s|w(T[o>>2])==n&&(t[a>>2]|0)==(r|0)||(T[o>>2]=n,t[a>>2]=r,Sn(e))}function Fl(e,n){e=e|0,n=w(n);var r=0,o=0,a=0,s=0;s=we(n)|0,r=s?0:2,o=e+388|0,a=e+392|0,s|w(T[o>>2])==n&&(t[a>>2]|0)==(r|0)||(T[o>>2]=n,t[a>>2]=r,Sn(e))}function ul(e,n){e=e|0,n=n|0;var r=0,o=0;o=n+388|0,r=t[o+4>>2]|0,n=e,t[n>>2]=t[o>>2],t[n+4>>2]=r}function o0(e,n){e=e|0,n=w(n);var r=0;r=e+396|0,w(T[r>>2])!=n&&(T[r>>2]=n,Sn(e))}function Ki(e){return e=e|0,w(T[e+396>>2])}function kr(e){return e=e|0,w(T[e+400>>2])}function zu(e){return e=e|0,w(T[e+404>>2])}function Xo(e){return e=e|0,w(T[e+408>>2])}function No(e){return e=e|0,w(T[e+412>>2])}function fa(e){return e=e|0,w(T[e+416>>2])}function qu(e){return e=e|0,w(T[e+420>>2])}function Xi(e,n){switch(e=e|0,n=n|0,r0(e,(n|0)<6,2918),n|0){case 0:{n=(t[e+496>>2]|0)==2?5:4;break}case 2:{n=(t[e+496>>2]|0)==2?4:5;break}default:}return w(T[e+424+(n<<2)>>2])}function pi(e,n){switch(e=e|0,n=n|0,r0(e,(n|0)<6,2918),n|0){case 0:{n=(t[e+496>>2]|0)==2?5:4;break}case 2:{n=(t[e+496>>2]|0)==2?4:5;break}default:}return w(T[e+448+(n<<2)>>2])}function Fo(e,n){switch(e=e|0,n=n|0,r0(e,(n|0)<6,2918),n|0){case 0:{n=(t[e+496>>2]|0)==2?5:4;break}case 2:{n=(t[e+496>>2]|0)==2?4:5;break}default:}return w(T[e+472+(n<<2)>>2])}function Qr(e,n){e=e|0,n=n|0;var r=0,o=lt;return r=t[e+4>>2]|0,(r|0)==(t[n+4>>2]|0)?r?(o=w(T[e>>2]),e=w(kt(w(o-w(T[n>>2]))))>2]=0,t[o+4>>2]=0,t[o+8>>2]=0,z0(o|0,e|0,n|0,0),R0(e,3,(p[o+11>>0]|0)<0?t[o>>2]|0:o,r),dB(o),v=r}function G0(e,n,r,o){e=w(e),n=w(n),r=r|0,o=o|0;var a=lt;e=w(e*n),a=w(JE(e,w(1)));do if(Or(a,w(0))|0)e=w(e-a);else{if(e=w(e-a),Or(a,w(1))|0){e=w(e+w(1));break}if(r){e=w(e+w(1));break}o||(a>w(.5)?a=w(1):(o=Or(a,w(.5))|0,a=w(o?1:0)),e=w(e+a))}while(0);return w(e/n)}function Ll(e,n,r,o,a,s,h,E,D,k,R,F,H){e=e|0,n=w(n),r=r|0,o=w(o),a=a|0,s=w(s),h=h|0,E=w(E),D=w(D),k=w(k),R=w(R),F=w(F),H=H|0;var xe=0,ce=lt,ue=lt,Be=lt,be=lt,Ve=lt,me=lt;return D>2]),ce!=w(0))?(Be=w(G0(n,ce,0,0)),be=w(G0(o,ce,0,0)),ue=w(G0(s,ce,0,0)),ce=w(G0(E,ce,0,0))):(ue=s,Be=n,ce=E,be=o),(a|0)==(e|0)?xe=Or(ue,Be)|0:xe=0,(h|0)==(r|0)?H=Or(ce,be)|0:H=0,!xe&&(Ve=w(n-R),!(Qo(e,Ve,D)|0))&&!(Jo(e,Ve,a,D)|0)?xe=Zo(e,Ve,a,s,D)|0:xe=1,!H&&(me=w(o-F),!(Qo(r,me,k)|0))&&!(Jo(r,me,h,k)|0)?H=Zo(r,me,h,E,k)|0:H=1,H=xe&H),H|0}function Qo(e,n,r){return e=e|0,n=w(n),r=w(r),(e|0)==1?e=Or(n,r)|0:e=0,e|0}function Jo(e,n,r,o){return e=e|0,n=w(n),r=r|0,o=w(o),(e|0)==2&(r|0)==0?n>=o?e=1:e=Or(n,o)|0:e=0,e|0}function Zo(e,n,r,o,a){return e=e|0,n=w(n),r=r|0,o=w(o),a=w(a),(e|0)==2&(r|0)==2&o>n?a<=n?e=1:e=Or(n,a)|0:e=0,e|0}function Y0(e,n,r,o,a,s,h,E,D,k,R){e=e|0,n=w(n),r=w(r),o=o|0,a=a|0,s=s|0,h=w(h),E=w(E),D=D|0,k=k|0,R=R|0;var F=0,H=0,xe=0,ce=0,ue=lt,Be=lt,be=0,Ve=0,me=0,Ce=0,At=0,Zn=0,on=0,Yt=0,Pn=0,Qn=0,tn=0,$r=lt,lu=lt,au=lt,su=0,Zu=0;tn=v,v=v+160|0,Yt=tn+152|0,on=tn+120|0,Zn=tn+104|0,me=tn+72|0,ce=tn+56|0,At=tn+8|0,Ve=tn,Ce=(t[2279]|0)+1|0,t[2279]=Ce,Pn=e+984|0,(p[Pn>>0]|0)!=0&&(t[e+512>>2]|0)!=(t[2278]|0)?be=4:(t[e+516>>2]|0)==(o|0)?Qn=0:be=4,(be|0)==4&&(t[e+520>>2]=0,t[e+924>>2]=-1,t[e+928>>2]=-1,T[e+932>>2]=w(-1),T[e+936>>2]=w(-1),Qn=1);e:do if(t[e+964>>2]|0)if(ue=w(ur(e,2,h)),Be=w(ur(e,0,h)),F=e+916|0,au=w(T[F>>2]),lu=w(T[e+920>>2]),$r=w(T[e+932>>2]),Ll(a,n,s,r,t[e+924>>2]|0,au,t[e+928>>2]|0,lu,$r,w(T[e+936>>2]),ue,Be,R)|0)be=22;else if(xe=t[e+520>>2]|0,!xe)be=21;else for(H=0;;){if(F=e+524+(H*24|0)|0,$r=w(T[F>>2]),lu=w(T[e+524+(H*24|0)+4>>2]),au=w(T[e+524+(H*24|0)+16>>2]),Ll(a,n,s,r,t[e+524+(H*24|0)+8>>2]|0,$r,t[e+524+(H*24|0)+12>>2]|0,lu,au,w(T[e+524+(H*24|0)+20>>2]),ue,Be,R)|0){be=22;break e}if(H=H+1|0,H>>>0>=xe>>>0){be=21;break}}else{if(D){if(F=e+916|0,!(Or(w(T[F>>2]),n)|0)){be=21;break}if(!(Or(w(T[e+920>>2]),r)|0)){be=21;break}if((t[e+924>>2]|0)!=(a|0)){be=21;break}F=(t[e+928>>2]|0)==(s|0)?F:0,be=22;break}if(xe=t[e+520>>2]|0,!xe)be=21;else for(H=0;;){if(F=e+524+(H*24|0)|0,Or(w(T[F>>2]),n)|0&&Or(w(T[e+524+(H*24|0)+4>>2]),r)|0&&(t[e+524+(H*24|0)+8>>2]|0)==(a|0)&&(t[e+524+(H*24|0)+12>>2]|0)==(s|0)){be=22;break e}if(H=H+1|0,H>>>0>=xe>>>0){be=21;break}}}while(0);do if((be|0)==21)p[11697]|0?(F=0,be=28):(F=0,be=31);else if((be|0)==22){if(H=(p[11697]|0)!=0,!((F|0)!=0&(Qn^1)))if(H){be=28;break}else{be=31;break}ce=F+16|0,t[e+908>>2]=t[ce>>2],xe=F+20|0,t[e+912>>2]=t[xe>>2],(p[11698]|0)==0|H^1||(t[Ve>>2]=lo(Ce)|0,t[Ve+4>>2]=Ce,R0(e,4,2972,Ve),H=t[e+972>>2]|0,H|0&&tf[H&127](e),a=zr(a,D)|0,s=zr(s,D)|0,Zu=+w(T[ce>>2]),su=+w(T[xe>>2]),t[At>>2]=a,t[At+4>>2]=s,P[At+8>>3]=+n,P[At+16>>3]=+r,P[At+24>>3]=Zu,P[At+32>>3]=su,t[At+40>>2]=k,R0(e,4,2989,At))}while(0);return(be|0)==28&&(H=lo(Ce)|0,t[ce>>2]=H,t[ce+4>>2]=Ce,t[ce+8>>2]=Qn?3047:11699,R0(e,4,3038,ce),H=t[e+972>>2]|0,H|0&&tf[H&127](e),At=zr(a,D)|0,be=zr(s,D)|0,t[me>>2]=At,t[me+4>>2]=be,P[me+8>>3]=+n,P[me+16>>3]=+r,t[me+24>>2]=k,R0(e,4,3049,me),be=31),(be|0)==31&&(Ui(e,n,r,o,a,s,h,E,D,R),p[11697]|0&&(H=t[2279]|0,At=lo(H)|0,t[Zn>>2]=At,t[Zn+4>>2]=H,t[Zn+8>>2]=Qn?3047:11699,R0(e,4,3083,Zn),H=t[e+972>>2]|0,H|0&&tf[H&127](e),At=zr(a,D)|0,Zn=zr(s,D)|0,su=+w(T[e+908>>2]),Zu=+w(T[e+912>>2]),t[on>>2]=At,t[on+4>>2]=Zn,P[on+8>>3]=su,P[on+16>>3]=Zu,t[on+24>>2]=k,R0(e,4,3092,on)),t[e+516>>2]=o,F||(H=e+520|0,F=t[H>>2]|0,(F|0)==16&&(p[11697]|0&&R0(e,4,3124,Yt),t[H>>2]=0,F=0),D?F=e+916|0:(t[H>>2]=F+1,F=e+524+(F*24|0)|0),T[F>>2]=n,T[F+4>>2]=r,t[F+8>>2]=a,t[F+12>>2]=s,t[F+16>>2]=t[e+908>>2],t[F+20>>2]=t[e+912>>2],F=0)),D&&(t[e+416>>2]=t[e+908>>2],t[e+420>>2]=t[e+912>>2],p[e+985>>0]=1,p[Pn>>0]=0),t[2279]=(t[2279]|0)+-1,t[e+512>>2]=t[2278],v=tn,Qn|(F|0)==0|0}function ur(e,n,r){e=e|0,n=n|0,r=w(r);var o=lt;return o=w(Ji(e,n,r)),w(o+w(fo(e,n,r)))}function R0(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0;s=v,v=v+16|0,a=s,t[a>>2]=o,e?o=t[e+976>>2]|0:o=0,ca(o,e,n,r,a),v=s}function lo(e){return e=e|0,(e>>>0>60?3201:3201+(60-e)|0)|0}function zr(e,n){e=e|0,n=n|0;var r=0,o=0,a=0;return a=v,v=v+32|0,r=a+12|0,o=a,t[r>>2]=t[254],t[r+4>>2]=t[255],t[r+8>>2]=t[256],t[o>>2]=t[257],t[o+4>>2]=t[258],t[o+8>>2]=t[259],(e|0)>2?e=11699:e=t[(n?o:r)+(e<<2)>>2]|0,v=a,e|0}function Ui(e,n,r,o,a,s,h,E,D,k){e=e|0,n=w(n),r=w(r),o=o|0,a=a|0,s=s|0,h=w(h),E=w(E),D=D|0,k=k|0;var R=0,F=0,H=0,xe=0,ce=lt,ue=lt,Be=lt,be=lt,Ve=lt,me=lt,Ce=lt,At=0,Zn=0,on=0,Yt=lt,Pn=lt,Qn=0,tn=lt,$r=0,lu=0,au=0,su=0,Zu=0,ec=0,tc=0,Jl=0,nc=0,vs=0,ms=0,rc=0,ic=0,oc=0,_r=0,Zl=0,uc=0,Ma=0,lc=lt,ac=lt,ys=lt,gs=lt,Na=lt,Ho=0,El=0,Mu=0,$l=0,rf=0,of=lt,_s=lt,uf=lt,lf=lt,Wo=lt,go=lt,ea=0,si=lt,af=lt,fu=lt,Fa=lt,cu=lt,La=lt,sf=0,ff=0,ba=lt,Vo=lt,ta=0,cf=0,df=0,pf=0,Un=lt,Ri=0,_o=0,du=0,Go=0,Hn=0,un=0,na=0,jt=lt,hf=0,zi=0;na=v,v=v+16|0,Ho=na+12|0,El=na+8|0,Mu=na+4|0,$l=na,r0(e,(a|0)==0|(we(n)|0)^1,3326),r0(e,(s|0)==0|(we(r)|0)^1,3406),_o=Hu(e,o)|0,t[e+496>>2]=_o,Hn=K0(2,_o)|0,un=K0(0,_o)|0,T[e+440>>2]=w(Ji(e,Hn,h)),T[e+444>>2]=w(fo(e,Hn,h)),T[e+428>>2]=w(Ji(e,un,h)),T[e+436>>2]=w(fo(e,un,h)),T[e+464>>2]=w(co(e,Hn)),T[e+468>>2]=w(Lo(e,Hn)),T[e+452>>2]=w(co(e,un)),T[e+460>>2]=w(Lo(e,un)),T[e+488>>2]=w(k0(e,Hn,h)),T[e+492>>2]=w(bo(e,Hn,h)),T[e+476>>2]=w(k0(e,un,h)),T[e+484>>2]=w(bo(e,un,h));do if(t[e+964>>2]|0)pa(e,n,r,a,s,h,E);else{if(du=e+948|0,Go=(t[e+952>>2]|0)-(t[du>>2]|0)>>2,!Go){al(e,n,r,a,s,h,E);break}if(!D&&ha(e,n,r,a,s,h,E)|0)break;rl(e),Zl=e+508|0,p[Zl>>0]=0,Hn=K0(t[e+4>>2]|0,_o)|0,un=Ms(Hn,_o)|0,Ri=ii(Hn)|0,uc=t[e+8>>2]|0,cf=e+28|0,Ma=(t[cf>>2]|0)!=0,cu=Ri?h:E,ba=Ri?E:h,lc=w(L0(e,Hn,h)),ac=w(Qa(e,Hn,h)),ce=w(L0(e,un,h)),La=w(er(e,Hn,h)),Vo=w(er(e,un,h)),on=Ri?a:s,ta=Ri?s:a,Un=Ri?La:Vo,Ve=Ri?Vo:La,Fa=w(ur(e,2,h)),be=w(ur(e,0,h)),ue=w(w(dn(e+364|0,h))-Un),Be=w(w(dn(e+380|0,h))-Un),me=w(w(dn(e+372|0,E))-Ve),Ce=w(w(dn(e+388|0,E))-Ve),ys=Ri?ue:me,gs=Ri?Be:Ce,Fa=w(n-Fa),n=w(Fa-Un),we(n)|0?Un=n:Un=w(Ci(w(Zc(n,Be)),ue)),af=w(r-be),n=w(af-Ve),we(n)|0?fu=n:fu=w(Ci(w(Zc(n,Ce)),me)),ue=Ri?Un:fu,si=Ri?fu:Un;e:do if((on|0)==1)for(o=0,F=0;;){if(R=jr(e,F)|0,!o)w(Ei(R))>w(0)&&w(Di(R))>w(0)?o=R:o=0;else if(X0(R)|0){xe=0;break e}if(F=F+1|0,F>>>0>=Go>>>0){xe=o;break}}else xe=0;while(0);At=xe+500|0,Zn=xe+504|0,o=0,R=0,n=w(0),H=0;do{if(F=t[(t[du>>2]|0)+(H<<2)>>2]|0,(t[F+36>>2]|0)==1)Vr(F),p[F+985>>0]=1,p[F+984>>0]=0;else{wr(F),D&&ao(F,Hu(F,_o)|0,ue,si,Un);do if((t[F+24>>2]|0)!=1)if((F|0)==(xe|0)){t[At>>2]=t[2278],T[Zn>>2]=w(0);break}else{O0(e,F,Un,a,fu,Un,fu,s,_o,k);break}else R|0&&(t[R+960>>2]=F),t[F+960>>2]=0,R=F,o=(o|0)==0?F:o;while(0);go=w(T[F+504>>2]),n=w(n+w(go+w(ur(F,Hn,Un))))}H=H+1|0}while((H|0)!=(Go|0));for(au=n>ue,ea=Ma&((on|0)==2&au)?1:on,$r=(ta|0)==1,Zu=$r&(D^1),ec=(ea|0)==1,tc=(ea|0)==2,Jl=976+(Hn<<2)|0,nc=(ta|2|0)==2,oc=$r&(Ma^1),vs=1040+(un<<2)|0,ms=1040+(Hn<<2)|0,rc=976+(un<<2)|0,ic=(ta|0)!=1,au=Ma&((on|0)!=0&au),lu=e+976|0,$r=$r^1,n=ue,Qn=0,su=0,go=w(0),Na=w(0);;){e:do if(Qn>>>0>>0)for(Zn=t[du>>2]|0,H=0,Ce=w(0),me=w(0),Be=w(0),ue=w(0),F=0,R=0,xe=Qn;;){if(At=t[Zn+(xe<<2)>>2]|0,(t[At+36>>2]|0)!=1&&(t[At+940>>2]=su,(t[At+24>>2]|0)!=1)){if(be=w(ur(At,Hn,Un)),_r=t[Jl>>2]|0,r=w(dn(At+380+(_r<<3)|0,cu)),Ve=w(T[At+504>>2]),r=w(Zc(r,Ve)),r=w(Ci(w(dn(At+364+(_r<<3)|0,cu)),r)),Ma&(H|0)!=0&w(be+w(me+r))>n){s=H,be=Ce,on=xe;break e}be=w(be+r),r=w(me+be),be=w(Ce+be),X0(At)|0&&(Be=w(Be+w(Ei(At))),ue=w(ue-w(Ve*w(Di(At))))),R|0&&(t[R+960>>2]=At),t[At+960>>2]=0,H=H+1|0,R=At,F=(F|0)==0?At:F}else be=Ce,r=me;if(xe=xe+1|0,xe>>>0>>0)Ce=be,me=r;else{s=H,on=xe;break}}else s=0,be=w(0),Be=w(0),ue=w(0),F=0,on=Qn;while(0);_r=Be>w(0)&Bew(0)&uegs&((we(gs)|0)^1))n=gs,_r=51;else if(p[(t[lu>>2]|0)+3>>0]|0)_r=51;else{if(Yt!=w(0)&&w(Ei(e))!=w(0)){_r=53;break}n=be,_r=53}while(0);if((_r|0)==51&&(_r=0,we(n)|0?_r=53:(Pn=w(n-be),tn=n)),(_r|0)==53&&(_r=0,be>2]|0,xe=Pnw(0),me=w(Pn/Yt),Be=w(0),be=w(0),n=w(0),R=F;do r=w(dn(R+380+(H<<3)|0,cu)),ue=w(dn(R+364+(H<<3)|0,cu)),ue=w(Zc(r,w(Ci(ue,w(T[R+504>>2]))))),xe?(r=w(ue*w(Di(R))),r!=w(-0)&&(jt=w(ue-w(Ve*r)),of=w(fr(R,Hn,jt,tn,Un)),jt!=of)&&(Be=w(Be-w(of-ue)),n=w(n+r))):At&&(_s=w(Ei(R)),_s!=w(0))&&(jt=w(ue+w(me*_s)),uf=w(fr(R,Hn,jt,tn,Un)),jt!=uf)&&(Be=w(Be-w(uf-ue)),be=w(be-_s)),R=t[R+960>>2]|0;while((R|0)!=0);if(n=w(Ce+n),ue=w(Pn+Be),rf)n=w(0);else{Ve=w(Yt+be),xe=t[Jl>>2]|0,At=uew(0),Ve=w(ue/Ve),n=w(0);do{jt=w(dn(F+380+(xe<<3)|0,cu)),Be=w(dn(F+364+(xe<<3)|0,cu)),Be=w(Zc(jt,w(Ci(Be,w(T[F+504>>2]))))),At?(jt=w(Be*w(Di(F))),ue=w(-jt),jt!=w(-0)?(jt=w(me*ue),ue=w(fr(F,Hn,w(Be+(Zn?ue:jt)),tn,Un))):ue=Be):H&&(lf=w(Ei(F)),lf!=w(0))?ue=w(fr(F,Hn,w(Be+w(Ve*lf)),tn,Un)):ue=Be,n=w(n-w(ue-Be)),be=w(ur(F,Hn,Un)),r=w(ur(F,un,Un)),ue=w(ue+be),T[El>>2]=ue,t[$l>>2]=1,Be=w(T[F+396>>2]);e:do if(we(Be)|0){R=we(si)|0;do if(!R){if(au|(Qi(F,un,si)|0|$r)||(l0(e,F)|0)!=4||(t[(_0(F,un)|0)+4>>2]|0)==3||(t[(M0(F,un)|0)+4>>2]|0)==3)break;T[Ho>>2]=si,t[Mu>>2]=1;break e}while(0);if(Qi(F,un,si)|0){R=t[F+992+(t[rc>>2]<<2)>>2]|0,jt=w(r+w(dn(R,si))),T[Ho>>2]=jt,R=ic&(t[R+4>>2]|0)==2,t[Mu>>2]=((we(jt)|0|R)^1)&1;break}else{T[Ho>>2]=si,t[Mu>>2]=R?0:2;break}}else jt=w(ue-be),Yt=w(jt/Be),jt=w(Be*jt),t[Mu>>2]=1,T[Ho>>2]=w(r+(Ri?Yt:jt));while(0);an(F,Hn,tn,Un,$l,El),an(F,un,si,Un,Mu,Ho);do if(!(Qi(F,un,si)|0)&&(l0(e,F)|0)==4){if((t[(_0(F,un)|0)+4>>2]|0)==3){R=0;break}R=(t[(M0(F,un)|0)+4>>2]|0)!=3}else R=0;while(0);jt=w(T[El>>2]),Yt=w(T[Ho>>2]),hf=t[$l>>2]|0,zi=t[Mu>>2]|0,Y0(F,Ri?jt:Yt,Ri?Yt:jt,_o,Ri?hf:zi,Ri?zi:hf,Un,fu,D&(R^1),3488,k)|0,p[Zl>>0]=p[Zl>>0]|p[F+508>>0],F=t[F+960>>2]|0}while((F|0)!=0)}}else n=w(0);if(n=w(Pn+n),zi=n>0]=zi|O[Zl>>0],tc&n>w(0)?(R=t[Jl>>2]|0,(t[e+364+(R<<3)+4>>2]|0)!=0&&(Wo=w(dn(e+364+(R<<3)|0,cu)),Wo>=w(0))?ue=w(Ci(w(0),w(Wo-w(tn-n)))):ue=w(0)):ue=n,At=Qn>>>0>>0,At){xe=t[du>>2]|0,H=Qn,R=0;do F=t[xe+(H<<2)>>2]|0,t[F+24>>2]|0||(R=((t[(_0(F,Hn)|0)+4>>2]|0)==3&1)+R|0,R=R+((t[(M0(F,Hn)|0)+4>>2]|0)==3&1)|0),H=H+1|0;while((H|0)!=(on|0));R?(be=w(0),r=w(0)):_r=101}else _r=101;e:do if((_r|0)==101)switch(_r=0,uc|0){case 1:{R=0,be=w(ue*w(.5)),r=w(0);break e}case 2:{R=0,be=ue,r=w(0);break e}case 3:{if(s>>>0<=1){R=0,be=w(0),r=w(0);break e}r=w((s+-1|0)>>>0),R=0,be=w(0),r=w(w(Ci(ue,w(0)))/r);break e}case 5:{r=w(ue/w((s+1|0)>>>0)),R=0,be=r;break e}case 4:{r=w(ue/w(s>>>0)),R=0,be=w(r*w(.5));break e}default:{R=0,be=w(0),r=w(0);break e}}while(0);if(n=w(lc+be),At){Be=w(ue/w(R|0)),H=t[du>>2]|0,F=Qn,ue=w(0);do{R=t[H+(F<<2)>>2]|0;e:do if((t[R+36>>2]|0)!=1){switch(t[R+24>>2]|0){case 1:{if(te(R,Hn)|0){if(!D)break e;jt=w(J(R,Hn,tn)),jt=w(jt+w(co(e,Hn))),jt=w(jt+w(Ji(R,Hn,Un))),T[R+400+(t[ms>>2]<<2)>>2]=jt;break e}break}case 0:if(zi=(t[(_0(R,Hn)|0)+4>>2]|0)==3,jt=w(Be+n),n=zi?jt:n,D&&(zi=R+400+(t[ms>>2]<<2)|0,T[zi>>2]=w(n+w(T[zi>>2]))),zi=(t[(M0(R,Hn)|0)+4>>2]|0)==3,jt=w(Be+n),n=zi?jt:n,Zu){jt=w(r+w(ur(R,Hn,Un))),ue=si,n=w(n+w(jt+w(T[R+504>>2])));break e}else{n=w(n+w(r+w(Te(R,Hn,Un)))),ue=w(Ci(ue,w(Te(R,un,Un))));break e}default:}D&&(jt=w(be+w(co(e,Hn))),zi=R+400+(t[ms>>2]<<2)|0,T[zi>>2]=w(jt+w(T[zi>>2])))}while(0);F=F+1|0}while((F|0)!=(on|0))}else ue=w(0);if(r=w(ac+n),nc?be=w(w(fr(e,un,w(Vo+ue),ba,h))-Vo):be=si,Be=w(w(fr(e,un,w(Vo+(oc?si:ue)),ba,h))-Vo),At&D){F=Qn;do{H=t[(t[du>>2]|0)+(F<<2)>>2]|0;do if((t[H+36>>2]|0)!=1){if((t[H+24>>2]|0)==1){if(te(H,un)|0){if(jt=w(J(H,un,si)),jt=w(jt+w(co(e,un))),jt=w(jt+w(Ji(H,un,Un))),R=t[vs>>2]|0,T[H+400+(R<<2)>>2]=jt,!(we(jt)|0))break}else R=t[vs>>2]|0;jt=w(co(e,un)),T[H+400+(R<<2)>>2]=w(jt+w(Ji(H,un,Un)));break}R=l0(e,H)|0;do if((R|0)==4){if((t[(_0(H,un)|0)+4>>2]|0)==3){_r=139;break}if((t[(M0(H,un)|0)+4>>2]|0)==3){_r=139;break}if(Qi(H,un,si)|0){n=ce;break}hf=t[H+908+(t[Jl>>2]<<2)>>2]|0,t[Ho>>2]=hf,n=w(T[H+396>>2]),zi=we(n)|0,ue=(t[z>>2]=hf,w(T[z>>2])),zi?n=Be:(Pn=w(ur(H,un,Un)),jt=w(ue/n),n=w(n*ue),n=w(Pn+(Ri?jt:n))),T[El>>2]=n,T[Ho>>2]=w(w(ur(H,Hn,Un))+ue),t[Mu>>2]=1,t[$l>>2]=1,an(H,Hn,tn,Un,Mu,Ho),an(H,un,si,Un,$l,El),n=w(T[Ho>>2]),Pn=w(T[El>>2]),jt=Ri?n:Pn,n=Ri?Pn:n,zi=((we(jt)|0)^1)&1,Y0(H,jt,n,_o,zi,((we(n)|0)^1)&1,Un,fu,1,3493,k)|0,n=ce}else _r=139;while(0);e:do if((_r|0)==139){_r=0,n=w(be-w(Te(H,un,Un)));do if((t[(_0(H,un)|0)+4>>2]|0)==3){if((t[(M0(H,un)|0)+4>>2]|0)!=3)break;n=w(ce+w(Ci(w(0),w(n*w(.5)))));break e}while(0);if((t[(M0(H,un)|0)+4>>2]|0)==3){n=ce;break}if((t[(_0(H,un)|0)+4>>2]|0)==3){n=w(ce+w(Ci(w(0),n)));break}switch(R|0){case 1:{n=ce;break e}case 2:{n=w(ce+w(n*w(.5)));break e}default:{n=w(ce+n);break e}}}while(0);jt=w(go+n),zi=H+400+(t[vs>>2]<<2)|0,T[zi>>2]=w(jt+w(T[zi>>2]))}while(0);F=F+1|0}while((F|0)!=(on|0))}if(go=w(go+Be),Na=w(Ci(Na,r)),s=su+1|0,on>>>0>=Go>>>0)break;n=tn,Qn=on,su=s}do if(D){if(R=s>>>0>1,!R&&!(Ee(e)|0))break;if(!(we(si)|0)){n=w(si-go);e:do switch(t[e+12>>2]|0){case 3:{ce=w(ce+n),me=w(0);break}case 2:{ce=w(ce+w(n*w(.5))),me=w(0);break}case 4:{si>go?me=w(n/w(s>>>0)):me=w(0);break}case 7:if(si>go){ce=w(ce+w(n/w(s<<1>>>0))),me=w(n/w(s>>>0)),me=R?me:w(0);break e}else{ce=w(ce+w(n*w(.5))),me=w(0);break e}case 6:{me=w(n/w(su>>>0)),me=si>go&R?me:w(0);break}default:me=w(0)}while(0);if(s|0)for(At=1040+(un<<2)|0,Zn=976+(un<<2)|0,xe=0,F=0;;){e:do if(F>>>0>>0)for(ue=w(0),Be=w(0),n=w(0),H=F;;){R=t[(t[du>>2]|0)+(H<<2)>>2]|0;do if((t[R+36>>2]|0)!=1&&(t[R+24>>2]|0)==0){if((t[R+940>>2]|0)!=(xe|0))break e;if(Qe(R,un)|0&&(jt=w(T[R+908+(t[Zn>>2]<<2)>>2]),n=w(Ci(n,w(jt+w(ur(R,un,Un)))))),(l0(e,R)|0)!=5)break;Wo=w(rt(R)),Wo=w(Wo+w(Ji(R,0,Un))),jt=w(T[R+912>>2]),jt=w(w(jt+w(ur(R,0,Un)))-Wo),Wo=w(Ci(Be,Wo)),jt=w(Ci(ue,jt)),ue=jt,Be=Wo,n=w(Ci(n,w(Wo+jt)))}while(0);if(R=H+1|0,R>>>0>>0)H=R;else{H=R;break}}else Be=w(0),n=w(0),H=F;while(0);if(Ve=w(me+n),r=ce,ce=w(ce+Ve),F>>>0>>0){be=w(r+Be),R=F;do{F=t[(t[du>>2]|0)+(R<<2)>>2]|0;e:do if((t[F+36>>2]|0)!=1&&(t[F+24>>2]|0)==0)switch(l0(e,F)|0){case 1:{jt=w(r+w(Ji(F,un,Un))),T[F+400+(t[At>>2]<<2)>>2]=jt;break e}case 3:{jt=w(w(ce-w(fo(F,un,Un)))-w(T[F+908+(t[Zn>>2]<<2)>>2])),T[F+400+(t[At>>2]<<2)>>2]=jt;break e}case 2:{jt=w(r+w(w(Ve-w(T[F+908+(t[Zn>>2]<<2)>>2]))*w(.5))),T[F+400+(t[At>>2]<<2)>>2]=jt;break e}case 4:{if(jt=w(r+w(Ji(F,un,Un))),T[F+400+(t[At>>2]<<2)>>2]=jt,Qi(F,un,si)|0||(Ri?(ue=w(T[F+908>>2]),n=w(ue+w(ur(F,Hn,Un))),Be=Ve):(Be=w(T[F+912>>2]),Be=w(Be+w(ur(F,un,Un))),n=Ve,ue=w(T[F+908>>2])),Or(n,ue)|0&&Or(Be,w(T[F+912>>2]))|0))break e;Y0(F,n,Be,_o,1,1,Un,fu,1,3501,k)|0;break e}case 5:{T[F+404>>2]=w(w(be-w(rt(F)))+w(J(F,0,si)));break e}default:break e}while(0);R=R+1|0}while((R|0)!=(H|0))}if(xe=xe+1|0,(xe|0)==(s|0))break;F=H}}}while(0);if(T[e+908>>2]=w(fr(e,2,Fa,h,h)),T[e+912>>2]=w(fr(e,0,af,E,h)),(ea|0)!=0&&(sf=t[e+32>>2]|0,ff=(ea|0)==2,!(ff&(sf|0)!=2))?ff&(sf|0)==2&&(n=w(La+tn),n=w(Ci(w(Zc(n,w(Mt(e,Hn,Na,cu)))),La)),_r=198):(n=w(fr(e,Hn,Na,cu,h)),_r=198),(_r|0)==198&&(T[e+908+(t[976+(Hn<<2)>>2]<<2)>>2]=n),(ta|0)!=0&&(df=t[e+32>>2]|0,pf=(ta|0)==2,!(pf&(df|0)!=2))?pf&(df|0)==2&&(n=w(Vo+si),n=w(Ci(w(Zc(n,w(Mt(e,un,w(Vo+go),ba)))),Vo)),_r=204):(n=w(fr(e,un,w(Vo+go),ba,h)),_r=204),(_r|0)==204&&(T[e+908+(t[976+(un<<2)>>2]<<2)>>2]=n),D){if((t[cf>>2]|0)==2){F=976+(un<<2)|0,H=1040+(un<<2)|0,R=0;do xe=jr(e,R)|0,t[xe+24>>2]|0||(hf=t[F>>2]|0,jt=w(T[e+908+(hf<<2)>>2]),zi=xe+400+(t[H>>2]<<2)|0,jt=w(jt-w(T[zi>>2])),T[zi>>2]=w(jt-w(T[xe+908+(hf<<2)>>2]))),R=R+1|0;while((R|0)!=(Go|0))}if(o|0){R=Ri?ea:a;do vn(e,o,Un,R,fu,_o,k),o=t[o+960>>2]|0;while((o|0)!=0)}if(R=(Hn|2|0)==3,F=(un|2|0)==3,R|F){o=0;do H=t[(t[du>>2]|0)+(o<<2)>>2]|0,(t[H+36>>2]|0)!=1&&(R&&Jt(e,H,Hn),F&&Jt(e,H,un)),o=o+1|0;while((o|0)!=(Go|0))}}}while(0);v=na}function u0(e,n){e=e|0,n=w(n);var r=0;cn(e,n>=w(0),3147),r=n==w(0),T[e+4>>2]=r?w(0):n}function _i(e,n,r,o){e=e|0,n=w(n),r=w(r),o=o|0;var a=lt,s=lt,h=0,E=0,D=0;t[2278]=(t[2278]|0)+1,wr(e),Qi(e,2,n)|0?(a=w(dn(t[e+992>>2]|0,n)),D=1,a=w(a+w(ur(e,2,n)))):(a=w(dn(e+380|0,n)),a>=w(0)?D=2:(D=((we(n)|0)^1)&1,a=n)),Qi(e,0,r)|0?(s=w(dn(t[e+996>>2]|0,r)),E=1,s=w(s+w(ur(e,0,n)))):(s=w(dn(e+388|0,r)),s>=w(0)?E=2:(E=((we(r)|0)^1)&1,s=r)),h=e+976|0,Y0(e,a,s,o,D,E,n,r,1,3189,t[h>>2]|0)|0&&(ao(e,t[e+496>>2]|0,n,r,n),g0(e,w(T[(t[h>>2]|0)+4>>2]),w(0),w(0)),p[11696]|0)&&ks(e,7)}function wr(e){e=e|0;var n=0,r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0;E=v,v=v+32|0,h=E+24|0,s=E+16|0,o=E+8|0,a=E,r=0;do n=e+380+(r<<3)|0,(t[e+380+(r<<3)+4>>2]|0)!=0&&(D=n,k=t[D+4>>2]|0,R=o,t[R>>2]=t[D>>2],t[R+4>>2]=k,R=e+364+(r<<3)|0,k=t[R+4>>2]|0,D=a,t[D>>2]=t[R>>2],t[D+4>>2]=k,t[s>>2]=t[o>>2],t[s+4>>2]=t[o+4>>2],t[h>>2]=t[a>>2],t[h+4>>2]=t[a+4>>2],Qr(s,h)|0)||(n=e+348+(r<<3)|0),t[e+992+(r<<2)>>2]=n,r=r+1|0;while((r|0)!=2);v=E}function Qi(e,n,r){e=e|0,n=n|0,r=w(r);var o=0;switch(e=t[e+992+(t[976+(n<<2)>>2]<<2)>>2]|0,t[e+4>>2]|0){case 0:case 3:{e=0;break}case 1:{w(T[e>>2])>2])>2]|0){case 2:{n=w(w(w(T[e>>2])*n)/w(100));break}case 1:{n=w(T[e>>2]);break}default:n=w(Z)}return w(n)}function ao(e,n,r,o,a){e=e|0,n=n|0,r=w(r),o=w(o),a=w(a);var s=0,h=lt;n=t[e+944>>2]|0?n:1,s=K0(t[e+4>>2]|0,n)|0,n=Ms(s,n)|0,r=w(lr(e,s,r)),o=w(lr(e,n,o)),h=w(r+w(Ji(e,s,a))),T[e+400+(t[1040+(s<<2)>>2]<<2)>>2]=h,r=w(r+w(fo(e,s,a))),T[e+400+(t[1e3+(s<<2)>>2]<<2)>>2]=r,r=w(o+w(Ji(e,n,a))),T[e+400+(t[1040+(n<<2)>>2]<<2)>>2]=r,a=w(o+w(fo(e,n,a))),T[e+400+(t[1e3+(n<<2)>>2]<<2)>>2]=a}function g0(e,n,r,o){e=e|0,n=w(n),r=w(r),o=w(o);var a=0,s=0,h=lt,E=lt,D=0,k=0,R=lt,F=0,H=lt,xe=lt,ce=lt,ue=lt;if(n!=w(0)&&(a=e+400|0,ue=w(T[a>>2]),s=e+404|0,ce=w(T[s>>2]),F=e+416|0,xe=w(T[F>>2]),k=e+420|0,h=w(T[k>>2]),H=w(ue+r),R=w(ce+o),o=w(H+xe),E=w(R+h),D=(t[e+988>>2]|0)==1,T[a>>2]=w(G0(ue,n,0,D)),T[s>>2]=w(G0(ce,n,0,D)),r=w(JE(w(xe*n),w(1))),Or(r,w(0))|0?s=0:s=(Or(r,w(1))|0)^1,r=w(JE(w(h*n),w(1))),Or(r,w(0))|0?a=0:a=(Or(r,w(1))|0)^1,ue=w(G0(o,n,D&s,D&(s^1))),T[F>>2]=w(ue-w(G0(H,n,0,D))),ue=w(G0(E,n,D&a,D&(a^1))),T[k>>2]=w(ue-w(G0(R,n,0,D))),s=(t[e+952>>2]|0)-(t[e+948>>2]|0)>>2,s|0)){a=0;do g0(jr(e,a)|0,n,H,R),a=a+1|0;while((a|0)!=(s|0))}}function Xa(e,n,r,o,a){switch(e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,r|0){case 5:case 0:{e=Yw(t[489]|0,o,a)|0;break}default:e=aB(o,a)|0}return e|0}function _u(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0;a=v,v=v+16|0,s=a,t[s>>2]=o,ca(e,0,n,r,s),v=a}function ca(e,n,r,o,a){if(e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,e=e|0?e:956,hS[t[e+8>>2]&1](e,n,r,o,a)|0,(r|0)==5)Tn();else return}function A0(e,n,r){e=e|0,n=n|0,r=r|0,p[e+n>>0]=r&1}function da(e,n){e=e|0,n=n|0;var r=0,o=0;t[e>>2]=0,t[e+4>>2]=0,t[e+8>>2]=0,r=n+4|0,o=(t[r>>2]|0)-(t[n>>2]|0)>>2,o|0&&(ri(e,o),bl(e,t[n>>2]|0,t[r>>2]|0,o))}function ri(e,n){e=e|0,n=n|0;var r=0;if((so(e)|0)>>>0>>0&&gr(e),n>>>0>1073741823)Tn();else{r=Bt(n<<2)|0,t[e+4>>2]=r,t[e>>2]=r,t[e+8>>2]=r+(n<<2);return}}function bl(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,o=e+4|0,e=r-n|0,(e|0)>0&&(bn(t[o>>2]|0,n|0,e|0)|0,t[o>>2]=(t[o>>2]|0)+(e>>>2<<2))}function so(e){return e=e|0,1073741823}function Ji(e,n,r){return e=e|0,n=n|0,r=w(r),ii(n)|0&&(t[e+96>>2]|0)!=0?e=e+92|0:e=tt(e+60|0,t[1040+(n<<2)>>2]|0,992)|0,w(ll(e,r))}function fo(e,n,r){return e=e|0,n=n|0,r=w(r),ii(n)|0&&(t[e+104>>2]|0)!=0?e=e+100|0:e=tt(e+60|0,t[1e3+(n<<2)>>2]|0,992)|0,w(ll(e,r))}function ii(e){return e=e|0,(e|1|0)==3|0}function ll(e,n){return e=e|0,n=w(n),(t[e+4>>2]|0)==3?n=w(0):n=w(dn(e,n)),w(n)}function Hu(e,n){return e=e|0,n=n|0,e=t[e>>2]|0,((e|0)==0?(n|0)>1?n:1:e)|0}function K0(e,n){e=e|0,n=n|0;var r=0;e:do if((n|0)==2){switch(e|0){case 2:{e=3;break e}case 3:break;default:{r=4;break e}}e=2}else r=4;while(0);return e|0}function co(e,n){e=e|0,n=n|0;var r=lt;return ii(n)|0&&(t[e+312>>2]|0)!=0&&(r=w(T[e+308>>2]),r>=w(0))||(r=w(Ci(w(T[(tt(e+276|0,t[1040+(n<<2)>>2]|0,992)|0)>>2]),w(0)))),w(r)}function Lo(e,n){e=e|0,n=n|0;var r=lt;return ii(n)|0&&(t[e+320>>2]|0)!=0&&(r=w(T[e+316>>2]),r>=w(0))||(r=w(Ci(w(T[(tt(e+276|0,t[1e3+(n<<2)>>2]|0,992)|0)>>2]),w(0)))),w(r)}function k0(e,n,r){e=e|0,n=n|0,r=w(r);var o=lt;return ii(n)|0&&(t[e+240>>2]|0)!=0&&(o=w(dn(e+236|0,r)),o>=w(0))||(o=w(Ci(w(dn(tt(e+204|0,t[1040+(n<<2)>>2]|0,992)|0,r)),w(0)))),w(o)}function bo(e,n,r){e=e|0,n=n|0,r=w(r);var o=lt;return ii(n)|0&&(t[e+248>>2]|0)!=0&&(o=w(dn(e+244|0,r)),o>=w(0))||(o=w(Ci(w(dn(tt(e+204|0,t[1e3+(n<<2)>>2]|0,992)|0,r)),w(0)))),w(o)}function pa(e,n,r,o,a,s,h){e=e|0,n=w(n),r=w(r),o=o|0,a=a|0,s=w(s),h=w(h);var E=lt,D=lt,k=lt,R=lt,F=lt,H=lt,xe=0,ce=0,ue=0;ue=v,v=v+16|0,xe=ue,ce=e+964|0,r0(e,(t[ce>>2]|0)!=0,3519),E=w(er(e,2,n)),D=w(er(e,0,n)),k=w(ur(e,2,n)),R=w(ur(e,0,n)),we(n)|0?F=n:F=w(Ci(w(0),w(w(n-k)-E))),we(r)|0?H=r:H=w(Ci(w(0),w(w(r-R)-D))),(o|0)==1&(a|0)==1?(T[e+908>>2]=w(fr(e,2,w(n-k),s,s)),n=w(fr(e,0,w(r-R),h,s))):(vS[t[ce>>2]&1](xe,e,F,o,H,a),F=w(E+w(T[xe>>2])),H=w(n-k),T[e+908>>2]=w(fr(e,2,(o|2|0)==2?F:H,s,s)),H=w(D+w(T[xe+4>>2])),n=w(r-R),n=w(fr(e,0,(a|2|0)==2?H:n,h,s))),T[e+912>>2]=n,v=ue}function al(e,n,r,o,a,s,h){e=e|0,n=w(n),r=w(r),o=o|0,a=a|0,s=w(s),h=w(h);var E=lt,D=lt,k=lt,R=lt;k=w(er(e,2,s)),E=w(er(e,0,s)),R=w(ur(e,2,s)),D=w(ur(e,0,s)),n=w(n-R),T[e+908>>2]=w(fr(e,2,(o|2|0)==2?k:n,s,s)),r=w(r-D),T[e+912>>2]=w(fr(e,0,(a|2|0)==2?E:r,h,s))}function ha(e,n,r,o,a,s,h){e=e|0,n=w(n),r=w(r),o=o|0,a=a|0,s=w(s),h=w(h);var E=0,D=lt,k=lt;return E=(o|0)==2,!(n<=w(0)&E)&&!(r<=w(0)&(a|0)==2)&&!((o|0)==1&(a|0)==1)?e=0:(D=w(ur(e,0,s)),k=w(ur(e,2,s)),E=n>2]=w(fr(e,2,E?w(0):n,s,s)),n=w(r-D),E=r>2]=w(fr(e,0,E?w(0):n,h,s)),e=1),e|0}function Ms(e,n){return e=e|0,n=n|0,Qt(e)|0?e=K0(2,n)|0:e=0,e|0}function L0(e,n,r){return e=e|0,n=n|0,r=w(r),r=w(k0(e,n,r)),w(r+w(co(e,n)))}function Qa(e,n,r){return e=e|0,n=n|0,r=w(r),r=w(bo(e,n,r)),w(r+w(Lo(e,n)))}function er(e,n,r){e=e|0,n=n|0,r=w(r);var o=lt;return o=w(L0(e,n,r)),w(o+w(Qa(e,n,r)))}function X0(e){return e=e|0,t[e+24>>2]|0?e=0:w(Ei(e))!=w(0)?e=1:e=w(Di(e))!=w(0),e|0}function Ei(e){e=e|0;var n=lt;if(t[e+944>>2]|0){if(n=w(T[e+44>>2]),we(n)|0)return n=w(T[e+40>>2]),e=n>w(0)&((we(n)|0)^1),w(e?n:w(0))}else n=w(0);return w(n)}function Di(e){e=e|0;var n=lt,r=0,o=lt;do if(t[e+944>>2]|0){if(n=w(T[e+48>>2]),we(n)|0){if(r=p[(t[e+976>>2]|0)+2>>0]|0,r<<24>>24==0&&(o=w(T[e+40>>2]),o>24?w(1):w(0)}}else n=w(0);while(0);return w(n)}function Vr(e){e=e|0;var n=0,r=0;if(x2(e+400|0,0,540)|0,p[e+985>>0]=1,rl(e),r=Ii(e)|0,r|0){n=e+948|0,e=0;do Vr(t[(t[n>>2]|0)+(e<<2)>>2]|0),e=e+1|0;while((e|0)!=(r|0))}}function O0(e,n,r,o,a,s,h,E,D,k){e=e|0,n=n|0,r=w(r),o=o|0,a=w(a),s=w(s),h=w(h),E=E|0,D=D|0,k=k|0;var R=0,F=lt,H=0,xe=0,ce=lt,ue=lt,Be=0,be=lt,Ve=0,me=lt,Ce=0,At=0,Zn=0,on=0,Yt=0,Pn=0,Qn=0,tn=0,$r=0,lu=0;$r=v,v=v+16|0,Zn=$r+12|0,on=$r+8|0,Yt=$r+4|0,Pn=$r,tn=K0(t[e+4>>2]|0,D)|0,Ce=ii(tn)|0,F=w(dn(Zt(n)|0,Ce?s:h)),At=Qi(n,2,s)|0,Qn=Qi(n,0,h)|0;do if(!(we(F)|0)&&!(we(Ce?r:a)|0)){if(R=n+504|0,!(we(w(T[R>>2]))|0)&&(!(kn(t[n+976>>2]|0,0)|0)||(t[n+500>>2]|0)==(t[2278]|0)))break;T[R>>2]=w(Ci(F,w(er(n,tn,s))))}else H=7;while(0);do if((H|0)==7){if(Ve=Ce^1,!(Ve|At^1)){h=w(dn(t[n+992>>2]|0,s)),T[n+504>>2]=w(Ci(h,w(er(n,2,s))));break}if(!(Ce|Qn^1)){h=w(dn(t[n+996>>2]|0,h)),T[n+504>>2]=w(Ci(h,w(er(n,0,s))));break}T[Zn>>2]=w(Z),T[on>>2]=w(Z),t[Yt>>2]=0,t[Pn>>2]=0,be=w(ur(n,2,s)),me=w(ur(n,0,s)),At?(ce=w(be+w(dn(t[n+992>>2]|0,s))),T[Zn>>2]=ce,t[Yt>>2]=1,xe=1):(xe=0,ce=w(Z)),Qn?(F=w(me+w(dn(t[n+996>>2]|0,h))),T[on>>2]=F,t[Pn>>2]=1,R=1):(R=0,F=w(Z)),H=t[e+32>>2]|0,Ce&(H|0)==2?H=2:we(ce)|0&&!(we(r)|0)&&(T[Zn>>2]=r,t[Yt>>2]=2,xe=2,ce=r),!((H|0)==2&Ve)&&we(F)|0&&!(we(a)|0)&&(T[on>>2]=a,t[Pn>>2]=2,R=2,F=a),ue=w(T[n+396>>2]),Be=we(ue)|0;do if(Be)H=xe;else{if((xe|0)==1&Ve){T[on>>2]=w(w(ce-be)/ue),t[Pn>>2]=1,R=1,H=1;break}Ce&(R|0)==1?(T[Zn>>2]=w(ue*w(F-me)),t[Yt>>2]=1,R=1,H=1):H=xe}while(0);lu=we(r)|0,xe=(l0(e,n)|0)!=4,!(Ce|At|((o|0)!=1|lu)|(xe|(H|0)==1))&&(T[Zn>>2]=r,t[Yt>>2]=1,!Be)&&(T[on>>2]=w(w(r-be)/ue),t[Pn>>2]=1,R=1),!(Qn|Ve|((E|0)!=1|(we(a)|0))|(xe|(R|0)==1))&&(T[on>>2]=a,t[Pn>>2]=1,!Be)&&(T[Zn>>2]=w(ue*w(a-me)),t[Yt>>2]=1),an(n,2,s,s,Yt,Zn),an(n,0,h,s,Pn,on),r=w(T[Zn>>2]),a=w(T[on>>2]),Y0(n,r,a,D,t[Yt>>2]|0,t[Pn>>2]|0,s,h,0,3565,k)|0,h=w(T[n+908+(t[976+(tn<<2)>>2]<<2)>>2]),T[n+504>>2]=w(Ci(h,w(er(n,tn,s))))}while(0);t[n+500>>2]=t[2278],v=$r}function fr(e,n,r,o,a){return e=e|0,n=n|0,r=w(r),o=w(o),a=w(a),o=w(Mt(e,n,r,o)),w(Ci(o,w(er(e,n,a))))}function l0(e,n){return e=e|0,n=n|0,n=n+20|0,n=t[((t[n>>2]|0)==0?e+16|0:n)>>2]|0,(n|0)==5&&Qt(t[e+4>>2]|0)|0&&(n=1),n|0}function _0(e,n){return e=e|0,n=n|0,ii(n)|0&&(t[e+96>>2]|0)!=0?n=4:n=t[1040+(n<<2)>>2]|0,e+60+(n<<3)|0}function M0(e,n){return e=e|0,n=n|0,ii(n)|0&&(t[e+104>>2]|0)!=0?n=5:n=t[1e3+(n<<2)>>2]|0,e+60+(n<<3)|0}function an(e,n,r,o,a,s){switch(e=e|0,n=n|0,r=w(r),o=w(o),a=a|0,s=s|0,r=w(dn(e+380+(t[976+(n<<2)>>2]<<3)|0,r)),r=w(r+w(ur(e,n,o))),t[a>>2]|0){case 2:case 1:{a=we(r)|0,o=w(T[s>>2]),T[s>>2]=a|o>2]=2,T[s>>2]=r);break}default:}}function te(e,n){return e=e|0,n=n|0,e=e+132|0,ii(n)|0&&(t[(tt(e,4,948)|0)+4>>2]|0)!=0?e=1:e=(t[(tt(e,t[1040+(n<<2)>>2]|0,948)|0)+4>>2]|0)!=0,e|0}function J(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,a=0;return e=e+132|0,ii(n)|0&&(o=tt(e,4,948)|0,(t[o+4>>2]|0)!=0)?a=4:(o=tt(e,t[1040+(n<<2)>>2]|0,948)|0,t[o+4>>2]|0?a=4:r=w(0)),(a|0)==4&&(r=w(dn(o,r))),w(r)}function Te(e,n,r){e=e|0,n=n|0,r=w(r);var o=lt;return o=w(T[e+908+(t[976+(n<<2)>>2]<<2)>>2]),o=w(o+w(Ji(e,n,r))),w(o+w(fo(e,n,r)))}function Ee(e){e=e|0;var n=0,r=0,o=0;e:do if(Qt(t[e+4>>2]|0)|0)n=0;else if((t[e+16>>2]|0)!=5)if(r=Ii(e)|0,!r)n=0;else for(n=0;;){if(o=jr(e,n)|0,(t[o+24>>2]|0)==0&&(t[o+20>>2]|0)==5){n=1;break e}if(n=n+1|0,n>>>0>=r>>>0){n=0;break}}else n=1;while(0);return n|0}function Qe(e,n){e=e|0,n=n|0;var r=lt;return r=w(T[e+908+(t[976+(n<<2)>>2]<<2)>>2]),r>=w(0)&((we(r)|0)^1)|0}function rt(e){e=e|0;var n=lt,r=0,o=0,a=0,s=0,h=0,E=0,D=lt;if(r=t[e+968>>2]|0,r)D=w(T[e+908>>2]),n=w(T[e+912>>2]),n=w(fS[r&0](e,D,n)),r0(e,(we(n)|0)^1,3573);else{s=Ii(e)|0;do if(s|0){for(r=0,a=0;;){if(o=jr(e,a)|0,t[o+940>>2]|0){h=8;break}if((t[o+24>>2]|0)!=1)if(E=(l0(e,o)|0)==5,E){r=o;break}else r=(r|0)==0?o:r;if(a=a+1|0,a>>>0>=s>>>0){h=8;break}}if((h|0)==8&&!r)break;return n=w(rt(r)),w(n+w(T[r+404>>2]))}while(0);n=w(T[e+912>>2])}return w(n)}function Mt(e,n,r,o){e=e|0,n=n|0,r=w(r),o=w(o);var a=lt,s=0;return Qt(n)|0?(n=1,s=3):ii(n)|0?(n=0,s=3):(o=w(Z),a=w(Z)),(s|0)==3&&(a=w(dn(e+364+(n<<3)|0,o)),o=w(dn(e+380+(n<<3)|0,o))),s=o=w(0)&((we(o)|0)^1)),r=s?o:r,s=a>=w(0)&((we(a)|0)^1)&r>2]|0,s)|0,ce=Ms(Be,s)|0,ue=ii(Be)|0,F=w(ur(n,2,r)),H=w(ur(n,0,r)),Qi(n,2,r)|0?E=w(F+w(dn(t[n+992>>2]|0,r))):te(n,2)|0&&Et(n,2)|0?(E=w(T[e+908>>2]),D=w(co(e,2)),D=w(E-w(D+w(Lo(e,2)))),E=w(J(n,2,r)),E=w(fr(n,2,w(D-w(E+w(oi(n,2,r)))),r,r))):E=w(Z),Qi(n,0,a)|0?D=w(H+w(dn(t[n+996>>2]|0,a))):te(n,0)|0&&Et(n,0)|0?(D=w(T[e+912>>2]),Ve=w(co(e,0)),Ve=w(D-w(Ve+w(Lo(e,0)))),D=w(J(n,0,a)),D=w(fr(n,0,w(Ve-w(D+w(oi(n,0,a)))),a,r))):D=w(Z),k=we(E)|0,R=we(D)|0;do if(k^R&&(xe=w(T[n+396>>2]),!(we(xe)|0)))if(k){E=w(F+w(w(D-H)*xe));break}else{Ve=w(H+w(w(E-F)/xe)),D=R?Ve:D;break}while(0);R=we(E)|0,k=we(D)|0,R|k&&(me=(R^1)&1,o=r>w(0)&((o|0)!=0&R),E=ue?E:o?r:E,Y0(n,E,D,s,ue?me:o?2:me,R&(k^1)&1,E,D,0,3623,h)|0,E=w(T[n+908>>2]),E=w(E+w(ur(n,2,r))),D=w(T[n+912>>2]),D=w(D+w(ur(n,0,r)))),Y0(n,E,D,s,1,1,E,D,1,3635,h)|0,Et(n,Be)|0&&!(te(n,Be)|0)?(me=t[976+(Be<<2)>>2]|0,Ve=w(T[e+908+(me<<2)>>2]),Ve=w(Ve-w(T[n+908+(me<<2)>>2])),Ve=w(Ve-w(Lo(e,Be))),Ve=w(Ve-w(fo(n,Be,r))),Ve=w(Ve-w(oi(n,Be,ue?r:a))),T[n+400+(t[1040+(Be<<2)>>2]<<2)>>2]=Ve):be=21;do if((be|0)==21){if(!(te(n,Be)|0)&&(t[e+8>>2]|0)==1){me=t[976+(Be<<2)>>2]|0,Ve=w(T[e+908+(me<<2)>>2]),Ve=w(w(Ve-w(T[n+908+(me<<2)>>2]))*w(.5)),T[n+400+(t[1040+(Be<<2)>>2]<<2)>>2]=Ve;break}!(te(n,Be)|0)&&(t[e+8>>2]|0)==2&&(me=t[976+(Be<<2)>>2]|0,Ve=w(T[e+908+(me<<2)>>2]),Ve=w(Ve-w(T[n+908+(me<<2)>>2])),T[n+400+(t[1040+(Be<<2)>>2]<<2)>>2]=Ve)}while(0);Et(n,ce)|0&&!(te(n,ce)|0)?(me=t[976+(ce<<2)>>2]|0,Ve=w(T[e+908+(me<<2)>>2]),Ve=w(Ve-w(T[n+908+(me<<2)>>2])),Ve=w(Ve-w(Lo(e,ce))),Ve=w(Ve-w(fo(n,ce,r))),Ve=w(Ve-w(oi(n,ce,ue?a:r))),T[n+400+(t[1040+(ce<<2)>>2]<<2)>>2]=Ve):be=30;do if((be|0)==30&&!(te(n,ce)|0)){if((l0(e,n)|0)==2){me=t[976+(ce<<2)>>2]|0,Ve=w(T[e+908+(me<<2)>>2]),Ve=w(w(Ve-w(T[n+908+(me<<2)>>2]))*w(.5)),T[n+400+(t[1040+(ce<<2)>>2]<<2)>>2]=Ve;break}me=(l0(e,n)|0)==3,me^(t[e+28>>2]|0)==2&&(me=t[976+(ce<<2)>>2]|0,Ve=w(T[e+908+(me<<2)>>2]),Ve=w(Ve-w(T[n+908+(me<<2)>>2])),T[n+400+(t[1040+(ce<<2)>>2]<<2)>>2]=Ve)}while(0)}function Jt(e,n,r){e=e|0,n=n|0,r=r|0;var o=lt,a=0;a=t[976+(r<<2)>>2]|0,o=w(T[n+908+(a<<2)>>2]),o=w(w(T[e+908+(a<<2)>>2])-o),o=w(o-w(T[n+400+(t[1040+(r<<2)>>2]<<2)>>2])),T[n+400+(t[1e3+(r<<2)>>2]<<2)>>2]=o}function Qt(e){return e=e|0,(e|1|0)==1|0}function Zt(e){e=e|0;var n=lt;switch(t[e+56>>2]|0){case 0:case 3:{n=w(T[e+40>>2]),n>w(0)&((we(n)|0)^1)?e=p[(t[e+976>>2]|0)+2>>0]|0?1056:992:e=1056;break}default:e=e+52|0}return e|0}function kn(e,n){return e=e|0,n=n|0,(p[e+n>>0]|0)!=0|0}function Et(e,n){return e=e|0,n=n|0,e=e+132|0,ii(n)|0&&(t[(tt(e,5,948)|0)+4>>2]|0)!=0?e=1:e=(t[(tt(e,t[1e3+(n<<2)>>2]|0,948)|0)+4>>2]|0)!=0,e|0}function oi(e,n,r){e=e|0,n=n|0,r=w(r);var o=0,a=0;return e=e+132|0,ii(n)|0&&(o=tt(e,5,948)|0,(t[o+4>>2]|0)!=0)?a=4:(o=tt(e,t[1e3+(n<<2)>>2]|0,948)|0,t[o+4>>2]|0?a=4:r=w(0)),(a|0)==4&&(r=w(dn(o,r))),w(r)}function lr(e,n,r){return e=e|0,n=n|0,r=w(r),te(e,n)|0?r=w(J(e,n,r)):r=w(-w(oi(e,n,r))),w(r)}function zn(e){return e=w(e),T[z>>2]=e,t[z>>2]|0|0}function Mr(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>1073741823)Tn();else{a=Bt(n<<2)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<2)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<2)}function qr(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>2)<<2)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function Cr(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-4-n|0)>>>2)<<2)),e=t[e>>2]|0,e|0&&$e(e)}function ui(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0;if(h=e+4|0,E=t[h>>2]|0,a=E-o|0,s=a>>2,e=n+(s<<2)|0,e>>>0>>0){o=E;do t[o>>2]=t[e>>2],e=e+4|0,o=(t[h>>2]|0)+4|0,t[h>>2]=o;while(e>>>0>>0)}s|0&&ih(E+(0-s<<2)|0,n|0,a|0)|0}function gt(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0;return E=n+4|0,D=t[E>>2]|0,a=t[e>>2]|0,h=r,s=h-a|0,o=D+(0-(s>>2)<<2)|0,t[E>>2]=o,(s|0)>0&&bn(o|0,a|0,s|0)|0,a=e+4|0,s=n+8|0,o=(t[a>>2]|0)-h|0,(o|0)>0&&(bn(t[s>>2]|0,r|0,o|0)|0,t[s>>2]=(t[s>>2]|0)+(o>>>2<<2)),h=t[e>>2]|0,t[e>>2]=t[E>>2],t[E>>2]=h,h=t[a>>2]|0,t[a>>2]=t[s>>2],t[s>>2]=h,h=e+8|0,r=n+12|0,e=t[h>>2]|0,t[h>>2]=t[r>>2],t[r>>2]=e,t[n>>2]=t[E>>2],D|0}function xr(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;if(h=t[n>>2]|0,s=t[r>>2]|0,(h|0)!=(s|0)){a=e+8|0,r=((s+-4-h|0)>>>2)+1|0,e=h,o=t[a>>2]|0;do t[o>>2]=t[e>>2],o=(t[a>>2]|0)+4|0,t[a>>2]=o,e=e+4|0;while((e|0)!=(s|0));t[n>>2]=h+(r<<2)}}function hi(){he()}function E0(){var e=0;return e=Bt(4)|0,On(e),e|0}function On(e){e=e|0,t[e>>2]=m0()|0}function a0(e){e=e|0,e|0&&(Q0(e),$e(e))}function Q0(e){e=e|0,H0(t[e>>2]|0)}function po(e,n,r){e=e|0,n=n|0,r=r|0,A0(t[e>>2]|0,n,r)}function s0(e,n){e=e|0,n=w(n),u0(t[e>>2]|0,n)}function Po(e,n){return e=e|0,n=n|0,kn(t[e>>2]|0,n)|0}function va(){var e=0;return e=Bt(8)|0,Ja(e,0),e|0}function Ja(e,n){e=e|0,n=n|0,n?n=Cn(t[n>>2]|0)|0:n=In()|0,t[e>>2]=n,t[e+4>>2]=0,Ka(n,e)}function Ns(e){e=e|0;var n=0;return n=Bt(8)|0,Ja(n,e),n|0}function xf(e){e=e|0,e|0&&(sl(e),$e(e))}function sl(e){e=e|0;var n=0;t0(t[e>>2]|0),n=e+4|0,e=t[n>>2]|0,t[n>>2]=0,e|0&&(ma(e),$e(e))}function ma(e){e=e|0,Pl(e)}function Pl(e){e=e|0,e=t[e>>2]|0,e|0&&vr(e|0)}function Rf(e){return e=e|0,kl(e)|0}function Za(e){e=e|0;var n=0,r=0;r=e+4|0,n=t[r>>2]|0,t[r>>2]=0,n|0&&(ma(n),$e(n)),uo(t[e>>2]|0)}function ld(e,n){e=e|0,n=n|0,sa(t[e>>2]|0,t[n>>2]|0)}function E1(e,n){e=e|0,n=n|0,G(t[e>>2]|0,n)}function D1(e,n,r){e=e|0,n=n|0,r=+r,jn(t[e>>2]|0,n,w(r))}function Il(e,n,r){e=e|0,n=n|0,r=+r,xn(t[e>>2]|0,n,w(r))}function _c(e,n){e=e|0,n=n|0,B(t[e>>2]|0,n)}function Eu(e,n){e=e|0,n=n|0,Y(t[e>>2]|0,n)}function w1(e,n){e=e|0,n=n|0,se(t[e>>2]|0,n)}function ad(e,n){e=e|0,n=n|0,x0(t[e>>2]|0,n)}function Bl(e,n){e=e|0,n=n|0,je(t[e>>2]|0,n)}function Du(e,n){e=e|0,n=n|0,Uu(t[e>>2]|0,n)}function S1(e,n,r){e=e|0,n=n|0,r=+r,nn(t[e>>2]|0,n,w(r))}function Io(e,n,r){e=e|0,n=n|0,r=+r,$n(t[e>>2]|0,n,w(r))}function Fs(e,n){e=e|0,n=n|0,nr(t[e>>2]|0,n)}function Ls(e,n){e=e|0,n=n|0,ne(t[e>>2]|0,n)}function $a(e,n){e=e|0,n=n|0,Je(t[e>>2]|0,n)}function ya(e,n){e=e|0,n=+n,ht(t[e>>2]|0,w(n))}function ga(e,n){e=e|0,n=+n,bt(t[e>>2]|0,w(n))}function bs(e,n){e=e|0,n=+n,Pt(t[e>>2]|0,w(n))}function Ea(e,n){e=e|0,n=+n,wt(t[e>>2]|0,w(n))}function Bo(e,n){e=e|0,n=+n,Vt(t[e>>2]|0,w(n))}function Af(e,n){e=e|0,n=+n,Gt(t[e>>2]|0,w(n))}function $o(e,n){e=e|0,n=+n,An(t[e>>2]|0,w(n))}function eu(e){e=e|0,Vn(t[e>>2]|0)}function kf(e,n){e=e|0,n=+n,i0(t[e>>2]|0,w(n))}function Uo(e,n){e=e|0,n=+n,W0(t[e>>2]|0,w(n))}function Ps(e){e=e|0,V0(t[e>>2]|0)}function Is(e,n){e=e|0,n=+n,Yi(t[e>>2]|0,w(n))}function T1(e,n){e=e|0,n=+n,gu(t[e>>2]|0,w(n))}function Ec(e,n){e=e|0,n=+n,Cf(t[e>>2]|0,w(n))}function Da(e,n){e=e|0,n=+n,ju(t[e>>2]|0,w(n))}function C1(e,n){e=e|0,n=+n,Oo(t[e>>2]|0,w(n))}function es(e,n){e=e|0,n=+n,ol(t[e>>2]|0,w(n))}function x1(e,n){e=e|0,n=+n,Mo(t[e>>2]|0,w(n))}function Of(e,n){e=e|0,n=+n,Fl(t[e>>2]|0,w(n))}function Mf(e,n){e=e|0,n=+n,o0(t[e>>2]|0,w(n))}function R1(e,n,r){e=e|0,n=n|0,r=+r,yt(t[e>>2]|0,n,w(r))}function wu(e,n,r){e=e|0,n=n|0,r=+r,Ge(t[e>>2]|0,n,w(r))}function y(e,n,r){e=e|0,n=n|0,r=+r,at(t[e>>2]|0,n,w(r))}function m(e){return e=e|0,De(t[e>>2]|0)|0}function C(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0;o=v,v=v+16|0,a=o,Jn(a,t[n>>2]|0,r),N(e,a),v=o}function N(e,n){e=e|0,n=n|0,L(e,t[n+4>>2]|0,+w(T[n>>2]))}function L(e,n,r){e=e|0,n=n|0,r=+r,t[e>>2]=n,P[e+8>>3]=r}function K(e){return e=e|0,q(t[e>>2]|0)|0}function ie(e){return e=e|0,_e(t[e>>2]|0)|0}function dt(e){return e=e|0,ge(t[e>>2]|0)|0}function ft(e){return e=e|0,Ol(t[e>>2]|0)|0}function mt(e){return e=e|0,nt(t[e>>2]|0)|0}function Gn(e){return e=e|0,b(t[e>>2]|0)|0}function f0(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0;o=v,v=v+16|0,a=o,y0(a,t[n>>2]|0,r),N(e,a),v=o}function ki(e){return e=e|0,Ne(t[e>>2]|0)|0}function b0(e){return e=e|0,ut(t[e>>2]|0)|0}function wa(e,n){e=e|0,n=n|0;var r=0,o=0;r=v,v=v+16|0,o=r,ln(o,t[n>>2]|0),N(e,o),v=r}function D0(e){return e=e|0,+ +w(Rs(t[e>>2]|0))}function Le(e){return e=e|0,+ +w(Al(t[e>>2]|0))}function ke(e,n){e=e|0,n=n|0;var r=0,o=0;r=v,v=v+16|0,o=r,gi(o,t[n>>2]|0),N(e,o),v=r}function Ke(e,n){e=e|0,n=n|0;var r=0,o=0;r=v,v=v+16|0,o=r,Gi(o,t[n>>2]|0),N(e,o),v=r}function Nt(e,n){e=e|0,n=n|0;var r=0,o=0;r=v,v=v+16|0,o=r,Ml(o,t[n>>2]|0),N(e,o),v=r}function yn(e,n){e=e|0,n=n|0;var r=0,o=0;r=v,v=v+16|0,o=r,As(o,t[n>>2]|0),N(e,o),v=r}function Rr(e,n){e=e|0,n=n|0;var r=0,o=0;r=v,v=v+16|0,o=r,Nl(o,t[n>>2]|0),N(e,o),v=r}function Fn(e,n){e=e|0,n=n|0;var r=0,o=0;r=v,v=v+16|0,o=r,ul(o,t[n>>2]|0),N(e,o),v=r}function Sr(e){return e=e|0,+ +w(Ki(t[e>>2]|0))}function li(e,n){return e=e|0,n=n|0,+ +w(It(t[e>>2]|0,n))}function cr(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0;o=v,v=v+16|0,a=o,ze(a,t[n>>2]|0,r),N(e,a),v=o}function ji(e,n,r){e=e|0,n=n|0,r=r|0,Ya(t[e>>2]|0,t[n>>2]|0,r)}function Nf(e,n){e=e|0,n=n|0,Bi(t[e>>2]|0,t[n>>2]|0)}function ts(e){return e=e|0,Ii(t[e>>2]|0)|0}function gv(e){return e=e|0,e=il(t[e>>2]|0)|0,e?e=Rf(e)|0:e=0,e|0}function _v(e,n){return e=e|0,n=n|0,e=jr(t[e>>2]|0,n)|0,e?e=Rf(e)|0:e=0,e|0}function Ev(e,n){e=e|0,n=n|0;var r=0,o=0;o=Bt(4)|0,Ff(o,n),r=e+4|0,n=t[r>>2]|0,t[r>>2]=o,n|0&&(ma(n),$e(n)),xs(t[e>>2]|0,1)}function Ff(e,n){e=e|0,n=n|0,hd(e,n)}function Yg(e,n,r,o,a,s){e=e|0,n=n|0,r=w(r),o=o|0,a=w(a),s=s|0;var h=0,E=0;h=v,v=v+16|0,E=h,Dv(E,kl(n)|0,+r,o,+a,s),T[e>>2]=w(+P[E>>3]),T[e+4>>2]=w(+P[E+8>>3]),v=h}function Dv(e,n,r,o,a,s){e=e|0,n=n|0,r=+r,o=o|0,a=+a,s=s|0;var h=0,E=0,D=0,k=0,R=0;h=v,v=v+32|0,R=h+8|0,k=h+20|0,D=h,E=h+16|0,P[R>>3]=r,t[k>>2]=o,P[D>>3]=a,t[E>>2]=s,A1(e,t[n+4>>2]|0,R,k,D,E),v=h}function A1(e,n,r,o,a,s){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0;var h=0,E=0;h=v,v=v+16|0,E=h,yl(E),n=jo(n)|0,wv(e,n,+P[r>>3],t[o>>2]|0,+P[a>>3],t[s>>2]|0),gl(E),v=h}function jo(e){return e=e|0,t[e>>2]|0}function wv(e,n,r,o,a,s){e=e|0,n=n|0,r=+r,o=o|0,a=+a,s=s|0;var h=0;h=ho(Kg()|0)|0,r=+fl(r),o=sd(o)|0,a=+fl(a),Sv(e,mr(0,h|0,n|0,+r,o|0,+a,sd(s)|0)|0)}function Kg(){var e=0;return p[7608]|0||(N1(9120),e=7608,t[e>>2]=1,t[e+4>>2]=0),9120}function ho(e){return e=e|0,t[e+8>>2]|0}function fl(e){return e=+e,+ +M1(e)}function sd(e){return e=e|0,O1(e)|0}function Sv(e,n){e=e|0,n=n|0;var r=0,o=0,a=0;a=v,v=v+32|0,r=a,o=n,o&1?(fd(r,0),di(o|0,r|0)|0,cd(e,r),dd(r)):(t[e>>2]=t[n>>2],t[e+4>>2]=t[n+4>>2],t[e+8>>2]=t[n+8>>2],t[e+12>>2]=t[n+12>>2]),v=a}function fd(e,n){e=e|0,n=n|0,k1(e,n),t[e+8>>2]=0,p[e+24>>0]=0}function cd(e,n){e=e|0,n=n|0,n=n+8|0,t[e>>2]=t[n>>2],t[e+4>>2]=t[n+4>>2],t[e+8>>2]=t[n+8>>2],t[e+12>>2]=t[n+12>>2]}function dd(e){e=e|0,p[e+24>>0]=0}function k1(e,n){e=e|0,n=n|0,t[e>>2]=n}function O1(e){return e=e|0,e|0}function M1(e){return e=+e,+e}function N1(e){e=e|0,tu(e,pd()|0,4)}function pd(){return 1064}function tu(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r,t[e+8>>2]=Dt(n|0,r+1|0)|0}function hd(e,n){e=e|0,n=n|0,n=t[n>>2]|0,t[e>>2]=n,Pr(n|0)}function Tv(e){e=e|0;var n=0,r=0;r=e+4|0,n=t[r>>2]|0,t[r>>2]=0,n|0&&(ma(n),$e(n)),xs(t[e>>2]|0,0)}function F1(e){e=e|0,Iu(t[e>>2]|0)}function vd(e){return e=e|0,Bu(t[e>>2]|0)|0}function Cv(e,n,r,o){e=e|0,n=+n,r=+r,o=o|0,_i(t[e>>2]|0,w(n),w(r),o)}function Xg(e){return e=e|0,+ +w(kr(t[e>>2]|0))}function xv(e){return e=e|0,+ +w(Xo(t[e>>2]|0))}function Rv(e){return e=e|0,+ +w(zu(t[e>>2]|0))}function Qg(e){return e=e|0,+ +w(No(t[e>>2]|0))}function Av(e){return e=e|0,+ +w(fa(t[e>>2]|0))}function md(e){return e=e|0,+ +w(qu(t[e>>2]|0))}function Jg(e,n){e=e|0,n=n|0,P[e>>3]=+w(kr(t[n>>2]|0)),P[e+8>>3]=+w(Xo(t[n>>2]|0)),P[e+16>>3]=+w(zu(t[n>>2]|0)),P[e+24>>3]=+w(No(t[n>>2]|0)),P[e+32>>3]=+w(fa(t[n>>2]|0)),P[e+40>>3]=+w(qu(t[n>>2]|0))}function Zg(e,n){return e=e|0,n=n|0,+ +w(Xi(t[e>>2]|0,n))}function yd(e,n){return e=e|0,n=n|0,+ +w(pi(t[e>>2]|0,n))}function gd(e,n){return e=e|0,n=n|0,+ +w(Fo(t[e>>2]|0,n))}function _d(){return Ga()|0}function Ed(){Dd(),kv(),L1(),Dc(),b1(),P1()}function Dd(){GN(11713,4938,1)}function kv(){cN(10448)}function L1(){GM(10408)}function Dc(){vM(10324)}function b1(){DE(10096)}function P1(){Ov(9132)}function Ov(e){e=e|0;var n=0,r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0,xe=0,ce=0,ue=0,Be=0,be=0,Ve=0,me=0,Ce=0,At=0,Zn=0,on=0,Yt=0,Pn=0,Qn=0,tn=0,$r=0,lu=0,au=0,su=0,Zu=0,ec=0,tc=0,Jl=0,nc=0,vs=0,ms=0,rc=0,ic=0,oc=0,_r=0,Zl=0,uc=0,Ma=0,lc=0,ac=0,ys=0,gs=0,Na=0,Ho=0,El=0,Mu=0,$l=0,rf=0,of=0,_s=0,uf=0,lf=0,Wo=0,go=0,ea=0,si=0,af=0,fu=0,Fa=0,cu=0,La=0,sf=0,ff=0,ba=0,Vo=0,ta=0,cf=0,df=0,pf=0,Un=0,Ri=0,_o=0,du=0,Go=0,Hn=0,un=0,na=0;n=v,v=v+672|0,r=n+656|0,na=n+648|0,un=n+640|0,Hn=n+632|0,Go=n+624|0,du=n+616|0,_o=n+608|0,Ri=n+600|0,Un=n+592|0,pf=n+584|0,df=n+576|0,cf=n+568|0,ta=n+560|0,Vo=n+552|0,ba=n+544|0,ff=n+536|0,sf=n+528|0,La=n+520|0,cu=n+512|0,Fa=n+504|0,fu=n+496|0,af=n+488|0,si=n+480|0,ea=n+472|0,go=n+464|0,Wo=n+456|0,lf=n+448|0,uf=n+440|0,_s=n+432|0,of=n+424|0,rf=n+416|0,$l=n+408|0,Mu=n+400|0,El=n+392|0,Ho=n+384|0,Na=n+376|0,gs=n+368|0,ys=n+360|0,ac=n+352|0,lc=n+344|0,Ma=n+336|0,uc=n+328|0,Zl=n+320|0,_r=n+312|0,oc=n+304|0,ic=n+296|0,rc=n+288|0,ms=n+280|0,vs=n+272|0,nc=n+264|0,Jl=n+256|0,tc=n+248|0,ec=n+240|0,Zu=n+232|0,su=n+224|0,au=n+216|0,lu=n+208|0,$r=n+200|0,tn=n+192|0,Qn=n+184|0,Pn=n+176|0,Yt=n+168|0,on=n+160|0,Zn=n+152|0,At=n+144|0,Ce=n+136|0,me=n+128|0,Ve=n+120|0,be=n+112|0,Be=n+104|0,ue=n+96|0,ce=n+88|0,xe=n+80|0,H=n+72|0,F=n+64|0,R=n+56|0,k=n+48|0,D=n+40|0,E=n+32|0,h=n+24|0,s=n+16|0,a=n+8|0,o=n,Bs(e,3646),I1(e,3651,2)|0,$g(e,3665,2)|0,e4(e,3682,18)|0,t[na>>2]=19,t[na+4>>2]=0,t[r>>2]=t[na>>2],t[r+4>>2]=t[na+4>>2],Sa(e,3690,r)|0,t[un>>2]=1,t[un+4>>2]=0,t[r>>2]=t[un>>2],t[r+4>>2]=t[un+4>>2],ns(e,3696,r)|0,t[Hn>>2]=2,t[Hn+4>>2]=0,t[r>>2]=t[Hn>>2],t[r+4>>2]=t[Hn+4>>2],nu(e,3706,r)|0,t[Go>>2]=1,t[Go+4>>2]=0,t[r>>2]=t[Go>>2],t[r+4>>2]=t[Go+4>>2],Ul(e,3722,r)|0,t[du>>2]=2,t[du+4>>2]=0,t[r>>2]=t[du>>2],t[r+4>>2]=t[du+4>>2],Ul(e,3734,r)|0,t[_o>>2]=3,t[_o+4>>2]=0,t[r>>2]=t[_o>>2],t[r+4>>2]=t[_o+4>>2],nu(e,3753,r)|0,t[Ri>>2]=4,t[Ri+4>>2]=0,t[r>>2]=t[Ri>>2],t[r+4>>2]=t[Ri+4>>2],nu(e,3769,r)|0,t[Un>>2]=5,t[Un+4>>2]=0,t[r>>2]=t[Un>>2],t[r+4>>2]=t[Un+4>>2],nu(e,3783,r)|0,t[pf>>2]=6,t[pf+4>>2]=0,t[r>>2]=t[pf>>2],t[r+4>>2]=t[pf+4>>2],nu(e,3796,r)|0,t[df>>2]=7,t[df+4>>2]=0,t[r>>2]=t[df>>2],t[r+4>>2]=t[df+4>>2],nu(e,3813,r)|0,t[cf>>2]=8,t[cf+4>>2]=0,t[r>>2]=t[cf>>2],t[r+4>>2]=t[cf+4>>2],nu(e,3825,r)|0,t[ta>>2]=3,t[ta+4>>2]=0,t[r>>2]=t[ta>>2],t[r+4>>2]=t[ta+4>>2],Ul(e,3843,r)|0,t[Vo>>2]=4,t[Vo+4>>2]=0,t[r>>2]=t[Vo>>2],t[r+4>>2]=t[Vo+4>>2],Ul(e,3853,r)|0,t[ba>>2]=9,t[ba+4>>2]=0,t[r>>2]=t[ba>>2],t[r+4>>2]=t[ba+4>>2],nu(e,3870,r)|0,t[ff>>2]=10,t[ff+4>>2]=0,t[r>>2]=t[ff>>2],t[r+4>>2]=t[ff+4>>2],nu(e,3884,r)|0,t[sf>>2]=11,t[sf+4>>2]=0,t[r>>2]=t[sf>>2],t[r+4>>2]=t[sf+4>>2],nu(e,3896,r)|0,t[La>>2]=1,t[La+4>>2]=0,t[r>>2]=t[La>>2],t[r+4>>2]=t[La+4>>2],c0(e,3907,r)|0,t[cu>>2]=2,t[cu+4>>2]=0,t[r>>2]=t[cu>>2],t[r+4>>2]=t[cu+4>>2],c0(e,3915,r)|0,t[Fa>>2]=3,t[Fa+4>>2]=0,t[r>>2]=t[Fa>>2],t[r+4>>2]=t[Fa+4>>2],c0(e,3928,r)|0,t[fu>>2]=4,t[fu+4>>2]=0,t[r>>2]=t[fu>>2],t[r+4>>2]=t[fu+4>>2],c0(e,3948,r)|0,t[af>>2]=5,t[af+4>>2]=0,t[r>>2]=t[af>>2],t[r+4>>2]=t[af+4>>2],c0(e,3960,r)|0,t[si>>2]=6,t[si+4>>2]=0,t[r>>2]=t[si>>2],t[r+4>>2]=t[si+4>>2],c0(e,3974,r)|0,t[ea>>2]=7,t[ea+4>>2]=0,t[r>>2]=t[ea>>2],t[r+4>>2]=t[ea+4>>2],c0(e,3983,r)|0,t[go>>2]=20,t[go+4>>2]=0,t[r>>2]=t[go>>2],t[r+4>>2]=t[go+4>>2],Sa(e,3999,r)|0,t[Wo>>2]=8,t[Wo+4>>2]=0,t[r>>2]=t[Wo>>2],t[r+4>>2]=t[Wo+4>>2],c0(e,4012,r)|0,t[lf>>2]=9,t[lf+4>>2]=0,t[r>>2]=t[lf>>2],t[r+4>>2]=t[lf+4>>2],c0(e,4022,r)|0,t[uf>>2]=21,t[uf+4>>2]=0,t[r>>2]=t[uf>>2],t[r+4>>2]=t[uf+4>>2],Sa(e,4039,r)|0,t[_s>>2]=10,t[_s+4>>2]=0,t[r>>2]=t[_s>>2],t[r+4>>2]=t[_s+4>>2],c0(e,4053,r)|0,t[of>>2]=11,t[of+4>>2]=0,t[r>>2]=t[of>>2],t[r+4>>2]=t[of+4>>2],c0(e,4065,r)|0,t[rf>>2]=12,t[rf+4>>2]=0,t[r>>2]=t[rf>>2],t[r+4>>2]=t[rf+4>>2],c0(e,4084,r)|0,t[$l>>2]=13,t[$l+4>>2]=0,t[r>>2]=t[$l>>2],t[r+4>>2]=t[$l+4>>2],c0(e,4097,r)|0,t[Mu>>2]=14,t[Mu+4>>2]=0,t[r>>2]=t[Mu>>2],t[r+4>>2]=t[Mu+4>>2],c0(e,4117,r)|0,t[El>>2]=15,t[El+4>>2]=0,t[r>>2]=t[El>>2],t[r+4>>2]=t[El+4>>2],c0(e,4129,r)|0,t[Ho>>2]=16,t[Ho+4>>2]=0,t[r>>2]=t[Ho>>2],t[r+4>>2]=t[Ho+4>>2],c0(e,4148,r)|0,t[Na>>2]=17,t[Na+4>>2]=0,t[r>>2]=t[Na>>2],t[r+4>>2]=t[Na+4>>2],c0(e,4161,r)|0,t[gs>>2]=18,t[gs+4>>2]=0,t[r>>2]=t[gs>>2],t[r+4>>2]=t[gs+4>>2],c0(e,4181,r)|0,t[ys>>2]=5,t[ys+4>>2]=0,t[r>>2]=t[ys>>2],t[r+4>>2]=t[ys+4>>2],Ul(e,4196,r)|0,t[ac>>2]=6,t[ac+4>>2]=0,t[r>>2]=t[ac>>2],t[r+4>>2]=t[ac+4>>2],Ul(e,4206,r)|0,t[lc>>2]=7,t[lc+4>>2]=0,t[r>>2]=t[lc>>2],t[r+4>>2]=t[lc+4>>2],Ul(e,4217,r)|0,t[Ma>>2]=3,t[Ma+4>>2]=0,t[r>>2]=t[Ma>>2],t[r+4>>2]=t[Ma+4>>2],Wu(e,4235,r)|0,t[uc>>2]=1,t[uc+4>>2]=0,t[r>>2]=t[uc>>2],t[r+4>>2]=t[uc+4>>2],wc(e,4251,r)|0,t[Zl>>2]=4,t[Zl+4>>2]=0,t[r>>2]=t[Zl>>2],t[r+4>>2]=t[Zl+4>>2],Wu(e,4263,r)|0,t[_r>>2]=5,t[_r+4>>2]=0,t[r>>2]=t[_r>>2],t[r+4>>2]=t[_r+4>>2],Wu(e,4279,r)|0,t[oc>>2]=6,t[oc+4>>2]=0,t[r>>2]=t[oc>>2],t[r+4>>2]=t[oc+4>>2],Wu(e,4293,r)|0,t[ic>>2]=7,t[ic+4>>2]=0,t[r>>2]=t[ic>>2],t[r+4>>2]=t[ic+4>>2],Wu(e,4306,r)|0,t[rc>>2]=8,t[rc+4>>2]=0,t[r>>2]=t[rc>>2],t[r+4>>2]=t[rc+4>>2],Wu(e,4323,r)|0,t[ms>>2]=9,t[ms+4>>2]=0,t[r>>2]=t[ms>>2],t[r+4>>2]=t[ms+4>>2],Wu(e,4335,r)|0,t[vs>>2]=2,t[vs+4>>2]=0,t[r>>2]=t[vs>>2],t[r+4>>2]=t[vs+4>>2],wc(e,4353,r)|0,t[nc>>2]=12,t[nc+4>>2]=0,t[r>>2]=t[nc>>2],t[r+4>>2]=t[nc+4>>2],Vu(e,4363,r)|0,t[Jl>>2]=1,t[Jl+4>>2]=0,t[r>>2]=t[Jl>>2],t[r+4>>2]=t[Jl+4>>2],Su(e,4376,r)|0,t[tc>>2]=2,t[tc+4>>2]=0,t[r>>2]=t[tc>>2],t[r+4>>2]=t[tc+4>>2],Su(e,4388,r)|0,t[ec>>2]=13,t[ec+4>>2]=0,t[r>>2]=t[ec>>2],t[r+4>>2]=t[ec+4>>2],Vu(e,4402,r)|0,t[Zu>>2]=14,t[Zu+4>>2]=0,t[r>>2]=t[Zu>>2],t[r+4>>2]=t[Zu+4>>2],Vu(e,4411,r)|0,t[su>>2]=15,t[su+4>>2]=0,t[r>>2]=t[su>>2],t[r+4>>2]=t[su+4>>2],Vu(e,4421,r)|0,t[au>>2]=16,t[au+4>>2]=0,t[r>>2]=t[au>>2],t[r+4>>2]=t[au+4>>2],Vu(e,4433,r)|0,t[lu>>2]=17,t[lu+4>>2]=0,t[r>>2]=t[lu>>2],t[r+4>>2]=t[lu+4>>2],Vu(e,4446,r)|0,t[$r>>2]=18,t[$r+4>>2]=0,t[r>>2]=t[$r>>2],t[r+4>>2]=t[$r+4>>2],Vu(e,4458,r)|0,t[tn>>2]=3,t[tn+4>>2]=0,t[r>>2]=t[tn>>2],t[r+4>>2]=t[tn+4>>2],Su(e,4471,r)|0,t[Qn>>2]=1,t[Qn+4>>2]=0,t[r>>2]=t[Qn>>2],t[r+4>>2]=t[Qn+4>>2],Sc(e,4486,r)|0,t[Pn>>2]=10,t[Pn+4>>2]=0,t[r>>2]=t[Pn>>2],t[r+4>>2]=t[Pn+4>>2],Wu(e,4496,r)|0,t[Yt>>2]=11,t[Yt+4>>2]=0,t[r>>2]=t[Yt>>2],t[r+4>>2]=t[Yt+4>>2],Wu(e,4508,r)|0,t[on>>2]=3,t[on+4>>2]=0,t[r>>2]=t[on>>2],t[r+4>>2]=t[on+4>>2],wc(e,4519,r)|0,t[Zn>>2]=4,t[Zn+4>>2]=0,t[r>>2]=t[Zn>>2],t[r+4>>2]=t[Zn+4>>2],wd(e,4530,r)|0,t[At>>2]=19,t[At+4>>2]=0,t[r>>2]=t[At>>2],t[r+4>>2]=t[At+4>>2],t4(e,4542,r)|0,t[Ce>>2]=12,t[Ce+4>>2]=0,t[r>>2]=t[Ce>>2],t[r+4>>2]=t[Ce+4>>2],Mv(e,4554,r)|0,t[me>>2]=13,t[me+4>>2]=0,t[r>>2]=t[me>>2],t[r+4>>2]=t[me+4>>2],Sd(e,4568,r)|0,t[Ve>>2]=2,t[Ve+4>>2]=0,t[r>>2]=t[Ve>>2],t[r+4>>2]=t[Ve+4>>2],Tc(e,4578,r)|0,t[be>>2]=20,t[be+4>>2]=0,t[r>>2]=t[be>>2],t[r+4>>2]=t[be+4>>2],Gu(e,4587,r)|0,t[Be>>2]=22,t[Be+4>>2]=0,t[r>>2]=t[Be>>2],t[r+4>>2]=t[Be+4>>2],Sa(e,4602,r)|0,t[ue>>2]=23,t[ue+4>>2]=0,t[r>>2]=t[ue>>2],t[r+4>>2]=t[ue+4>>2],Sa(e,4619,r)|0,t[ce>>2]=14,t[ce+4>>2]=0,t[r>>2]=t[ce>>2],t[r+4>>2]=t[ce+4>>2],B1(e,4629,r)|0,t[xe>>2]=1,t[xe+4>>2]=0,t[r>>2]=t[xe>>2],t[r+4>>2]=t[xe+4>>2],Lf(e,4637,r)|0,t[H>>2]=4,t[H+4>>2]=0,t[r>>2]=t[H>>2],t[r+4>>2]=t[H+4>>2],Su(e,4653,r)|0,t[F>>2]=5,t[F+4>>2]=0,t[r>>2]=t[F>>2],t[r+4>>2]=t[F+4>>2],Su(e,4669,r)|0,t[R>>2]=6,t[R+4>>2]=0,t[r>>2]=t[R>>2],t[r+4>>2]=t[R+4>>2],Su(e,4686,r)|0,t[k>>2]=7,t[k+4>>2]=0,t[r>>2]=t[k>>2],t[r+4>>2]=t[k+4>>2],Su(e,4701,r)|0,t[D>>2]=8,t[D+4>>2]=0,t[r>>2]=t[D>>2],t[r+4>>2]=t[D+4>>2],Su(e,4719,r)|0,t[E>>2]=9,t[E+4>>2]=0,t[r>>2]=t[E>>2],t[r+4>>2]=t[E+4>>2],Su(e,4736,r)|0,t[h>>2]=21,t[h+4>>2]=0,t[r>>2]=t[h>>2],t[r+4>>2]=t[h+4>>2],Td(e,4754,r)|0,t[s>>2]=2,t[s+4>>2]=0,t[r>>2]=t[s>>2],t[r+4>>2]=t[s+4>>2],Sc(e,4772,r)|0,t[a>>2]=3,t[a+4>>2]=0,t[r>>2]=t[a>>2],t[r+4>>2]=t[a+4>>2],Sc(e,4790,r)|0,t[o>>2]=4,t[o+4>>2]=0,t[r>>2]=t[o>>2],t[r+4>>2]=t[o+4>>2],Sc(e,4808,r)|0,v=n}function Bs(e,n){e=e|0,n=n|0;var r=0;r=Ql()|0,t[e>>2]=r,J0(r,n),Jf(t[e>>2]|0)}function I1(e,n,r){return e=e|0,n=n|0,r=r|0,pt(e,ar(n)|0,r,0),e|0}function $g(e,n,r){return e=e|0,n=n|0,r=r|0,d(e,ar(n)|0,r,0),e|0}function e4(e,n,r){return e=e|0,n=n|0,r=r|0,vE(e,ar(n)|0,r,0),e|0}function Sa(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],lE(e,n,a),v=o,e|0}function ns(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],X_(e,n,a),v=o,e|0}function nu(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Bp(e,n,a),v=o,e|0}function Ul(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Vm(e,n,a),v=o,e|0}function c0(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],T_(e,n,a),v=o,e|0}function Wu(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],p2(e,n,a),v=o,e|0}function wc(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Ap(e,n,a),v=o,e|0}function Vu(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],N0(e,n,a),v=o,e|0}function Su(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Am(e,n,a),v=o,e|0}function Sc(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],K4(e,n,a),v=o,e|0}function wd(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],U4(e,n,a),v=o,e|0}function t4(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Q1(e,n,a),v=o,e|0}function Mv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],R4(e,n,a),v=o,e|0}function Sd(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],$d(e,n,a),v=o,e|0}function Tc(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Kd(e,n,a),v=o,e|0}function Gu(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],ls(e,n,a),v=o,e|0}function B1(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Bd(e,n,a),v=o,e|0}function Lf(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Lv(e,n,a),v=o,e|0}function Td(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],n4(e,n,a),v=o,e|0}function n4(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],bf(e,r,a,1),v=o}function ar(e){return e=e|0,e|0}function bf(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=Cd()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=U1(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,r4(s,o)|0,o),v=a}function Cd(){var e=0,n=0;if(p[7616]|0||(Uf(9136),xt(24,9136,le|0)|0,n=7616,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9136)|0)){e=9136,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Uf(9136)}return 9136}function U1(e){return e=e|0,0}function r4(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=Cd()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],Pf(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(If(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Nr(e,n,r,o,a,s){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0;var h=0,E=0,D=0,k=0,R=0,F=0,H=0,xe=0;h=v,v=v+32|0,H=h+24|0,F=h+20|0,D=h+16|0,R=h+12|0,k=h+8|0,E=h+4|0,xe=h,t[F>>2]=n,t[D>>2]=r,t[R>>2]=o,t[k>>2]=a,t[E>>2]=s,s=e+28|0,t[xe>>2]=t[s>>2],t[H>>2]=t[xe>>2],i4(e+24|0,H,F,R,k,D,E)|0,t[s>>2]=t[t[s>>2]>>2],v=h}function i4(e,n,r,o,a,s,h){return e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0,h=h|0,e=o4(n)|0,n=Bt(24)|0,xd(n+4|0,t[r>>2]|0,t[o>>2]|0,t[a>>2]|0,t[s>>2]|0,t[h>>2]|0),t[n>>2]=t[e>>2],t[e>>2]=n,n|0}function o4(e){return e=e|0,t[e>>2]|0}function xd(e,n,r,o,a,s){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0,t[e>>2]=n,t[e+4>>2]=r,t[e+8>>2]=o,t[e+12>>2]=a,t[e+16>>2]=s}function en(e,n){return e=e|0,n=n|0,n|e|0}function Pf(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function If(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=u4(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,Bf(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],Pf(s,o,r),t[D>>2]=(t[D>>2]|0)+12,Nv(e,E),l4(E),v=k;return}}function u4(e){return e=e|0,357913941}function Bf(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function Nv(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function l4(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function Uf(e){e=e|0,Yu(e)}function Rd(e){e=e|0,Dn(e+24|0)}function Bn(e){return e=e|0,t[e>>2]|0}function Dn(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function Yu(e){e=e|0;var n=0;n=tr()|0,gn(e,2,3,n,Cc()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function tr(){return 9228}function Cc(){return 1140}function cl(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0;return r=v,v=v+16|0,o=r+8|0,a=r,s=jl(e)|0,e=t[s+4>>2]|0,t[a>>2]=t[s>>2],t[a+4>>2]=e,t[o>>2]=t[a>>2],t[o+4>>2]=t[a+4>>2],n=jf(n,o)|0,v=r,n|0}function gn(e,n,r,o,a,s){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0,t[e>>2]=n,t[e+4>>2]=r,t[e+8>>2]=o,t[e+12>>2]=a,t[e+16>>2]=s}function jl(e){return e=e|0,(t[(Cd()|0)+24>>2]|0)+(e*12|0)|0}function jf(e,n){e=e|0,n=n|0;var r=0,o=0,a=0;return a=v,v=v+48|0,o=a,r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),nf[r&31](o,e),o=zo(o)|0,v=a,o|0}function zo(e){e=e|0;var n=0,r=0,o=0,a=0;return a=v,v=v+32|0,n=a+12|0,r=a,o=rs(Us()|0)|0,o?(Ku(n,o),js(r,n),xc(e,r),e=dl(n)|0):e=Rc(e)|0,v=a,e|0}function Us(){var e=0;return p[7632]|0||(kd(9184),xt(25,9184,le|0)|0,e=7632,t[e>>2]=1,t[e+4>>2]=0),9184}function rs(e){return e=e|0,t[e+36>>2]|0}function Ku(e,n){e=e|0,n=n|0,t[e>>2]=n,t[e+4>>2]=e,t[e+8>>2]=0}function js(e,n){e=e|0,n=n|0,t[e>>2]=t[n>>2],t[e+4>>2]=t[n+4>>2],t[e+8>>2]=0}function xc(e,n){e=e|0,n=n|0,Ad(n,e,e+8|0,e+16|0,e+24|0,e+32|0,e+40|0)|0}function dl(e){return e=e|0,t[(t[e+4>>2]|0)+8>>2]|0}function Rc(e){e=e|0;var n=0,r=0,o=0,a=0,s=0,h=0,E=0,D=0;D=v,v=v+16|0,r=D+4|0,o=D,a=ml(8)|0,s=a,h=Bt(48)|0,E=h,n=E+48|0;do t[E>>2]=t[e>>2],E=E+4|0,e=e+4|0;while((E|0)<(n|0));return n=s+4|0,t[n>>2]=h,E=Bt(8)|0,h=t[n>>2]|0,t[o>>2]=0,t[r>>2]=t[o>>2],Fv(E,h,r),t[a>>2]=E,v=D,s|0}function Fv(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=Bt(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1092,t[r+12>>2]=n,t[e+4>>2]=r}function qt(e){e=e|0,C2(e),$e(e)}function Xu(e){e=e|0,e=t[e+12>>2]|0,e|0&&$e(e)}function is(e){e=e|0,$e(e)}function Ad(e,n,r,o,a,s,h){return e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0,h=h|0,s=wi(t[e>>2]|0,n,r,o,a,s,h)|0,h=e+4|0,t[(t[h>>2]|0)+8>>2]=s,t[(t[h>>2]|0)+8>>2]|0}function wi(e,n,r,o,a,s,h){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0,h=h|0;var E=0,D=0;return E=v,v=v+16|0,D=E,yl(D),e=jo(e)|0,h=dr(e,+P[n>>3],+P[r>>3],+P[o>>3],+P[a>>3],+P[s>>3],+P[h>>3])|0,gl(D),v=E,h|0}function dr(e,n,r,o,a,s,h){e=e|0,n=+n,r=+r,o=+o,a=+a,s=+s,h=+h;var E=0;return E=ho(Ac()|0)|0,n=+fl(n),r=+fl(r),o=+fl(o),a=+fl(a),s=+fl(s),S0(0,E|0,e|0,+n,+r,+o,+a,+s,+ +fl(h))|0}function Ac(){var e=0;return p[7624]|0||(a4(9172),e=7624,t[e>>2]=1,t[e+4>>2]=0),9172}function a4(e){e=e|0,tu(e,Tu()|0,6)}function Tu(){return 1112}function kd(e){e=e|0,os(e)}function zf(e){e=e|0,Od(e+24|0),j1(e+16|0)}function Od(e){e=e|0,kc(e)}function j1(e){e=e|0,qf(e)}function qf(e){e=e|0;var n=0,r=0;if(n=t[e>>2]|0,n|0)do r=n,n=t[n>>2]|0,$e(r);while((n|0)!=0);t[e>>2]=0}function kc(e){e=e|0;var n=0,r=0;if(n=t[e>>2]|0,n|0)do r=n,n=t[n>>2]|0,$e(r);while((n|0)!=0);t[e>>2]=0}function os(e){e=e|0;var n=0;t[e+16>>2]=0,t[e+20>>2]=0,n=e+24|0,t[n>>2]=0,t[e+28>>2]=n,t[e+36>>2]=0,p[e+40>>0]=0,p[e+41>>0]=0}function Lv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Md(e,r,a,0),v=o}function Md(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=Oc()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=Mc(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,z1(s,o)|0,o),v=a}function Oc(){var e=0,n=0;if(p[7640]|0||(W1(9232),xt(26,9232,le|0)|0,n=7640,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9232)|0)){e=9232,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));W1(9232)}return 9232}function Mc(e){return e=e|0,0}function z1(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=Oc()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],q1(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Nd(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function q1(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function Nd(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=bv(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,Fd(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],q1(s,o,r),t[D>>2]=(t[D>>2]|0)+12,Ld(e,E),H1(E),v=k;return}}function bv(e){return e=e|0,357913941}function Fd(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function Ld(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function H1(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function W1(e){e=e|0,Iv(e)}function bd(e){e=e|0,Pv(e+24|0)}function Pv(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function Iv(e){e=e|0;var n=0;n=tr()|0,gn(e,2,1,n,Pd()|0,3),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Pd(){return 1144}function Bv(e,n,r,o,a){e=e|0,n=n|0,r=+r,o=+o,a=a|0;var s=0,h=0,E=0,D=0;s=v,v=v+16|0,h=s+8|0,E=s,D=s4(e)|0,e=t[D+4>>2]|0,t[E>>2]=t[D>>2],t[E+4>>2]=e,t[h>>2]=t[E>>2],t[h+4>>2]=t[E+4>>2],Uv(n,h,r,o,a),v=s}function s4(e){return e=e|0,(t[(Oc()|0)+24>>2]|0)+(e*12|0)|0}function Uv(e,n,r,o,a){e=e|0,n=n|0,r=+r,o=+o,a=a|0;var s=0,h=0,E=0,D=0,k=0;k=v,v=v+16|0,h=k+2|0,E=k+1|0,D=k,s=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(s=t[(t[e>>2]|0)+s>>2]|0),Cu(h,r),r=+Qu(h,r),Cu(E,o),o=+Qu(E,o),pl(D,a),D=zl(D,a)|0,cS[s&1](e,r,o,D),v=k}function Cu(e,n){e=e|0,n=+n}function Qu(e,n){return e=e|0,n=+n,+ +jv(n)}function pl(e,n){e=e|0,n=n|0}function zl(e,n){return e=e|0,n=n|0,Id(n)|0}function Id(e){return e=e|0,e|0}function jv(e){return e=+e,+e}function Bd(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],zv(e,r,a,1),v=o}function zv(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=V1()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=G1(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,qv(s,o)|0,o),v=a}function V1(){var e=0,n=0;if(p[7648]|0||(Nc(9268),xt(27,9268,le|0)|0,n=7648,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9268)|0)){e=9268,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Nc(9268)}return 9268}function G1(e){return e=e|0,0}function qv(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=V1()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],Ud(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(jd(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Ud(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function jd(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=ql(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,us(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],Ud(s,o,r),t[D>>2]=(t[D>>2]|0)+12,Hv(e,E),Si(E),v=k;return}}function ql(e){return e=e|0,357913941}function us(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function Hv(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function Si(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function Nc(e){e=e|0,Vv(e)}function Wv(e){e=e|0,Fc(e+24|0)}function Fc(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function Vv(e){e=e|0;var n=0;n=tr()|0,gn(e,2,4,n,Gv()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Gv(){return 1160}function zd(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0;return r=v,v=v+16|0,o=r+8|0,a=r,s=Yv(e)|0,e=t[s+4>>2]|0,t[a>>2]=t[s>>2],t[a+4>>2]=e,t[o>>2]=t[a>>2],t[o+4>>2]=t[a+4>>2],n=Y1(n,o)|0,v=r,n|0}function Yv(e){return e=e|0,(t[(V1()|0)+24>>2]|0)+(e*12|0)|0}function Y1(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),xu(e1[r&31](e)|0)|0}function xu(e){return e=e|0,e&1|0}function ls(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Ta(e,r,a,0),v=o}function Ta(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=qd()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=f4(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,c4(s,o)|0,o),v=a}function qd(){var e=0,n=0;if(p[7656]|0||(Qv(9304),xt(28,9304,le|0)|0,n=7656,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9304)|0)){e=9304,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Qv(9304)}return 9304}function f4(e){return e=e|0,0}function c4(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=qd()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],Hd(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Kv(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Hd(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function Kv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=Xv(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,Wd(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],Hd(s,o,r),t[D>>2]=(t[D>>2]|0)+12,d4(e,E),p4(E),v=k;return}}function Xv(e){return e=e|0,357913941}function Wd(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function d4(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function p4(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function Qv(e){e=e|0,Lc(e)}function h4(e){e=e|0,Vd(e+24|0)}function Vd(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function Lc(e){e=e|0;var n=0;n=tr()|0,gn(e,2,5,n,bc()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function bc(){return 1164}function Pc(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;o=v,v=v+16|0,a=o+8|0,s=o,h=Ca(e)|0,e=t[h+4>>2]|0,t[s>>2]=t[h>>2],t[s+4>>2]=e,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Gd(n,a,r),v=o}function Ca(e){return e=e|0,(t[(qd()|0)+24>>2]|0)+(e*12|0)|0}function Gd(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0;s=v,v=v+16|0,a=s,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),Hl(a,r),r=Wl(a,r)|0,nf[o&31](e,r),Vl(a),v=s}function Hl(e,n){e=e|0,n=n|0,Yd(e,n)}function Wl(e,n){return e=e|0,n=n|0,e|0}function Vl(e){e=e|0,ma(e)}function Yd(e,n){e=e|0,n=n|0,xa(e,n)}function xa(e,n){e=e|0,n=n|0,t[e>>2]=n}function Kd(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Xd(e,r,a,0),v=o}function Xd(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=Hf()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=Qd(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,vo(s,o)|0,o),v=a}function Hf(){var e=0,n=0;if(p[7664]|0||(tm(9340),xt(29,9340,le|0)|0,n=7664,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9340)|0)){e=9340,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));tm(9340)}return 9340}function Qd(e){return e=e|0,0}function vo(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=Hf()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],Jv(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Zv(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Jv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function Zv(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=$v(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,em(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],Jv(s,o,r),t[D>>2]=(t[D>>2]|0)+12,v4(e,E),m4(E),v=k;return}}function $v(e){return e=e|0,357913941}function em(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function v4(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function m4(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function tm(e){e=e|0,rm(e)}function nm(e){e=e|0,Jd(e+24|0)}function Jd(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function rm(e){e=e|0;var n=0;n=tr()|0,gn(e,2,4,n,Zd()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Zd(){return 1180}function im(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=y4(e)|0,e=t[h+4>>2]|0,t[s>>2]=t[h>>2],t[s+4>>2]=e,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],r=g4(n,a,r)|0,v=o,r|0}function y4(e){return e=e|0,(t[(Hf()|0)+24>>2]|0)+(e*12|0)|0}function g4(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0;return s=v,v=v+16|0,a=s,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),zs(a,r),a=qs(a,r)|0,a=K1(nD[o&15](e,a)|0)|0,v=s,a|0}function zs(e,n){e=e|0,n=n|0}function qs(e,n){return e=e|0,n=n|0,_4(n)|0}function K1(e){return e=e|0,e|0}function _4(e){return e=e|0,e|0}function $d(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],X1(e,r,a,0),v=o}function X1(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=ep()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=om(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,tp(s,o)|0,o),v=a}function ep(){var e=0,n=0;if(p[7672]|0||(am(9376),xt(30,9376,le|0)|0,n=7672,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9376)|0)){e=9376,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));am(9376)}return 9376}function om(e){return e=e|0,0}function tp(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=ep()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],um(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(E4(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function um(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function E4(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=lm(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,D4(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],um(s,o,r),t[D>>2]=(t[D>>2]|0)+12,w4(e,E),S4(E),v=k;return}}function lm(e){return e=e|0,357913941}function D4(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function w4(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function S4(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function am(e){e=e|0,np(e)}function sm(e){e=e|0,T4(e+24|0)}function T4(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function np(e){e=e|0;var n=0;n=tr()|0,gn(e,2,5,n,rp()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function rp(){return 1196}function C4(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0;return r=v,v=v+16|0,o=r+8|0,a=r,s=x4(e)|0,e=t[s+4>>2]|0,t[a>>2]=t[s>>2],t[a+4>>2]=e,t[o>>2]=t[a>>2],t[o+4>>2]=t[a+4>>2],n=fm(n,o)|0,v=r,n|0}function x4(e){return e=e|0,(t[(ep()|0)+24>>2]|0)+(e*12|0)|0}function fm(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),K1(e1[r&31](e)|0)|0}function R4(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],A4(e,r,a,1),v=o}function A4(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=ip()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=op(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,Ra(s,o)|0,o),v=a}function ip(){var e=0,n=0;if(p[7680]|0||(dm(9412),xt(31,9412,le|0)|0,n=7680,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9412)|0)){e=9412,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));dm(9412)}return 9412}function op(e){return e=e|0,0}function Ra(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=ip()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],cm(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(up(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function cm(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function up(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=k4(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,lp(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],cm(s,o,r),t[D>>2]=(t[D>>2]|0)+12,ap(e,E),O4(E),v=k;return}}function k4(e){return e=e|0,357913941}function lp(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function ap(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function O4(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function dm(e){e=e|0,hm(e)}function M4(e){e=e|0,pm(e+24|0)}function pm(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function hm(e){e=e|0;var n=0;n=tr()|0,gn(e,2,6,n,vm()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function vm(){return 1200}function sp(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0;return r=v,v=v+16|0,o=r+8|0,a=r,s=N4(e)|0,e=t[s+4>>2]|0,t[a>>2]=t[s>>2],t[a+4>>2]=e,t[o>>2]=t[a>>2],t[o+4>>2]=t[a+4>>2],n=F4(n,o)|0,v=r,n|0}function N4(e){return e=e|0,(t[(ip()|0)+24>>2]|0)+(e*12|0)|0}function F4(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),P0(e1[r&31](e)|0)|0}function P0(e){return e=e|0,e|0}function Q1(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Hs(e,r,a,0),v=o}function Hs(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=Ws()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=J1(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,Z1(s,o)|0,o),v=a}function Ws(){var e=0,n=0;if(p[7688]|0||(dp(9448),xt(32,9448,le|0)|0,n=7688,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9448)|0)){e=9448,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));dp(9448)}return 9448}function J1(e){return e=e|0,0}function Z1(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=Ws()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],fp(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):($1(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function fp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function $1(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=mm(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,L4(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],fp(s,o,r),t[D>>2]=(t[D>>2]|0)+12,ym(e,E),cp(E),v=k;return}}function mm(e){return e=e|0,357913941}function L4(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function ym(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function cp(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function dp(e){e=e|0,P4(e)}function pp(e){e=e|0,b4(e+24|0)}function b4(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function P4(e){e=e|0;var n=0;n=tr()|0,gn(e,2,6,n,Wf()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Wf(){return 1204}function e2(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;o=v,v=v+16|0,a=o+8|0,s=o,h=I4(e)|0,e=t[h+4>>2]|0,t[s>>2]=t[h>>2],t[s+4>>2]=e,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],as(n,a,r),v=o}function I4(e){return e=e|0,(t[(Ws()|0)+24>>2]|0)+(e*12|0)|0}function as(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0;s=v,v=v+16|0,a=s,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),Gl(a,r),a=Yl(a,r)|0,nf[o&31](e,a),v=s}function Gl(e,n){e=e|0,n=n|0}function Yl(e,n){return e=e|0,n=n|0,B4(n)|0}function B4(e){return e=e|0,e|0}function U4(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],gm(e,r,a,0),v=o}function gm(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=hp()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=vp(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,j4(s,o)|0,o),v=a}function hp(){var e=0,n=0;if(p[7696]|0||(Em(9484),xt(33,9484,le|0)|0,n=7696,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9484)|0)){e=9484,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Em(9484)}return 9484}function vp(e){return e=e|0,0}function j4(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=hp()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],_m(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(mp(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function _m(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function mp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=z4(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,q4(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],_m(s,o,r),t[D>>2]=(t[D>>2]|0)+12,Vf(e,E),H4(E),v=k;return}}function z4(e){return e=e|0,357913941}function q4(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function Vf(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function H4(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function Em(e){e=e|0,G4(e)}function W4(e){e=e|0,V4(e+24|0)}function V4(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function G4(e){e=e|0;var n=0;n=tr()|0,gn(e,2,1,n,Dm()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Dm(){return 1212}function yp(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0;a=v,v=v+16|0,s=a+8|0,h=a,E=wm(e)|0,e=t[E+4>>2]|0,t[h>>2]=t[E>>2],t[h+4>>2]=e,t[s>>2]=t[h>>2],t[s+4>>2]=t[h+4>>2],Y4(n,s,r,o),v=a}function wm(e){return e=e|0,(t[(hp()|0)+24>>2]|0)+(e*12|0)|0}function Y4(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0;E=v,v=v+16|0,s=E+1|0,h=E,a=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(a=t[(t[e>>2]|0)+a>>2]|0),Gl(s,r),s=Yl(s,r)|0,zs(h,o),h=qs(h,o)|0,lh[a&15](e,s,h),v=E}function K4(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],X4(e,r,a,1),v=o}function X4(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=t2()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=Q4(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,Sm(s,o)|0,o),v=a}function t2(){var e=0,n=0;if(p[7704]|0||(Cm(9520),xt(34,9520,le|0)|0,n=7704,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9520)|0)){e=9520,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Cm(9520)}return 9520}function Q4(e){return e=e|0,0}function Sm(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=t2()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],gp(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(J4(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function gp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function J4(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=_p(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,Tm(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],gp(s,o,r),t[D>>2]=(t[D>>2]|0)+12,Z4(e,E),n2(E),v=k;return}}function _p(e){return e=e|0,357913941}function Tm(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function Z4(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function n2(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function Cm(e){e=e|0,Rm(e)}function $4(e){e=e|0,xm(e+24|0)}function xm(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function Rm(e){e=e|0;var n=0;n=tr()|0,gn(e,2,1,n,e_()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function e_(){return 1224}function t_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;return a=v,v=v+16|0,s=a+8|0,h=a,E=n_(e)|0,e=t[E+4>>2]|0,t[h>>2]=t[E>>2],t[h+4>>2]=e,t[s>>2]=t[h>>2],t[s+4>>2]=t[h+4>>2],o=+Ep(n,s,r),v=a,+o}function n_(e){return e=e|0,(t[(t2()|0)+24>>2]|0)+(e*12|0)|0}function Ep(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return s=v,v=v+16|0,a=s,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),pl(a,r),a=zl(a,r)|0,h=+M1(+pS[o&7](e,a)),v=s,+h}function Am(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Dp(e,r,a,1),v=o}function Dp(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=Oi()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=Ic(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,r_(s,o)|0,o),v=a}function Oi(){var e=0,n=0;if(p[7712]|0||(Tp(9556),xt(35,9556,le|0)|0,n=7712,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9556)|0)){e=9556,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Tp(9556)}return 9556}function Ic(e){return e=e|0,0}function r_(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=Oi()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],wp(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Sp(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function wp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function Sp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=Ru(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,hl(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],wp(s,o,r),t[D>>2]=(t[D>>2]|0)+12,Vs(e,E),r2(E),v=k;return}}function Ru(e){return e=e|0,357913941}function hl(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function Vs(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function r2(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function Tp(e){e=e|0,Cp(e)}function Bc(e){e=e|0,Uc(e+24|0)}function Uc(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function Cp(e){e=e|0;var n=0;n=tr()|0,gn(e,2,5,n,Rn()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Rn(){return 1232}function ru(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=_n(e)|0,e=t[h+4>>2]|0,t[s>>2]=t[h>>2],t[s+4>>2]=e,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],r=+I0(n,a),v=o,+r}function _n(e){return e=e|0,(t[(Oi()|0)+24>>2]|0)+(e*12|0)|0}function I0(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),+ +M1(+dS[r&15](e))}function N0(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],i2(e,r,a,1),v=o}function i2(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=vl()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=jc(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,o2(s,o)|0,o),v=a}function vl(){var e=0,n=0;if(p[7720]|0||(a2(9592),xt(36,9592,le|0)|0,n=7720,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9592)|0)){e=9592,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));a2(9592)}return 9592}function jc(e){return e=e|0,0}function o2(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=vl()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],Gf(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(u2(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Gf(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function u2(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=xp(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,km(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],Gf(s,o,r),t[D>>2]=(t[D>>2]|0)+12,sn(e,E),l2(E),v=k;return}}function xp(e){return e=e|0,357913941}function km(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function sn(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function l2(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function a2(e){e=e|0,Kf(e)}function Yf(e){e=e|0,zc(e+24|0)}function zc(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function Kf(e){e=e|0;var n=0;n=tr()|0,gn(e,2,7,n,qc()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function qc(){return 1276}function Rp(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0;return r=v,v=v+16|0,o=r+8|0,a=r,s=Gs(e)|0,e=t[s+4>>2]|0,t[a>>2]=t[s>>2],t[a+4>>2]=e,t[o>>2]=t[a>>2],t[o+4>>2]=t[a+4>>2],n=i_(n,o)|0,v=r,n|0}function Gs(e){return e=e|0,(t[(vl()|0)+24>>2]|0)+(e*12|0)|0}function i_(e,n){e=e|0,n=n|0;var r=0,o=0,a=0;return a=v,v=v+16|0,o=a,r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),nf[r&31](o,e),o=Xf(o)|0,v=a,o|0}function Xf(e){e=e|0;var n=0,r=0,o=0,a=0;return a=v,v=v+32|0,n=a+12|0,r=a,o=rs(s2()|0)|0,o?(Ku(n,o),js(r,n),o_(e,r),e=dl(n)|0):e=f2(e)|0,v=a,e|0}function s2(){var e=0;return p[7736]|0||(ou(9640),xt(25,9640,le|0)|0,e=7736,t[e>>2]=1,t[e+4>>2]=0),9640}function o_(e,n){e=e|0,n=n|0,u_(n,e,e+8|0)|0}function f2(e){e=e|0;var n=0,r=0,o=0,a=0,s=0,h=0,E=0;return r=v,v=v+16|0,a=r+4|0,h=r,o=ml(8)|0,n=o,E=Bt(16)|0,t[E>>2]=t[e>>2],t[E+4>>2]=t[e+4>>2],t[E+8>>2]=t[e+8>>2],t[E+12>>2]=t[e+12>>2],s=n+4|0,t[s>>2]=E,e=Bt(8)|0,s=t[s>>2]|0,t[h>>2]=0,t[a>>2]=t[h>>2],Ys(e,s,a),t[o>>2]=e,v=r,n|0}function Ys(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=Bt(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1244,t[r+12>>2]=n,t[e+4>>2]=r}function Ks(e){e=e|0,C2(e),$e(e)}function Hc(e){e=e|0,e=t[e+12>>2]|0,e|0&&$e(e)}function Au(e){e=e|0,$e(e)}function u_(e,n,r){return e=e|0,n=n|0,r=r|0,n=Xs(t[e>>2]|0,n,r)|0,r=e+4|0,t[(t[r>>2]|0)+8>>2]=n,t[(t[r>>2]|0)+8>>2]|0}function Xs(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0;return o=v,v=v+16|0,a=o,yl(a),e=jo(e)|0,r=l_(e,t[n>>2]|0,+P[r>>3])|0,gl(a),v=o,r|0}function l_(e,n,r){e=e|0,n=n|0,r=+r;var o=0;return o=ho(iu()|0)|0,n=sd(n)|0,or(0,o|0,e|0,n|0,+ +fl(r))|0}function iu(){var e=0;return p[7728]|0||(c2(9628),e=7728,t[e>>2]=1,t[e+4>>2]=0),9628}function c2(e){e=e|0,tu(e,d2()|0,2)}function d2(){return 1264}function ou(e){e=e|0,os(e)}function Ap(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],a_(e,r,a,1),v=o}function a_(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=Wc()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=s_(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,f_(s,o)|0,o),v=a}function Wc(){var e=0,n=0;if(p[7744]|0||(Nm(9684),xt(37,9684,le|0)|0,n=7744,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9684)|0)){e=9684,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Nm(9684)}return 9684}function s_(e){return e=e|0,0}function f_(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=Wc()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],Om(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(c_(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Om(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function c_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=Mm(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,d_(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],Om(s,o,r),t[D>>2]=(t[D>>2]|0)+12,p_(e,E),h_(E),v=k;return}}function Mm(e){return e=e|0,357913941}function d_(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function p_(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function h_(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function Nm(e){e=e|0,m_(e)}function v_(e){e=e|0,kp(e+24|0)}function kp(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function m_(e){e=e|0;var n=0;n=tr()|0,gn(e,2,5,n,Qs()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Qs(){return 1280}function Fm(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=Lm(e)|0,e=t[h+4>>2]|0,t[s>>2]=t[h>>2],t[s+4>>2]=e,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],r=bm(n,a,r)|0,v=o,r|0}function Lm(e){return e=e|0,(t[(Wc()|0)+24>>2]|0)+(e*12|0)|0}function bm(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return h=v,v=v+32|0,a=h,s=h+16|0,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),pl(s,r),s=zl(s,r)|0,lh[o&15](a,e,s),s=Xf(a)|0,v=h,s|0}function p2(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],h2(e,r,a,1),v=o}function h2(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=Op()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=Pm(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,v2(s,o)|0,o),v=a}function Op(){var e=0,n=0;if(p[7752]|0||(Um(9720),xt(38,9720,le|0)|0,n=7752,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9720)|0)){e=9720,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Um(9720)}return 9720}function Pm(e){return e=e|0,0}function v2(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=Op()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],Im(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Bm(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Im(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function Bm(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=y_(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,g_(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],Im(s,o,r),t[D>>2]=(t[D>>2]|0)+12,__(e,E),E_(E),v=k;return}}function y_(e){return e=e|0,357913941}function g_(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function __(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function E_(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function Um(e){e=e|0,zm(e)}function D_(e){e=e|0,jm(e+24|0)}function jm(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function zm(e){e=e|0;var n=0;n=tr()|0,gn(e,2,8,n,Mp()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Mp(){return 1288}function w_(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0;return r=v,v=v+16|0,o=r+8|0,a=r,s=ss(e)|0,e=t[s+4>>2]|0,t[a>>2]=t[s>>2],t[a+4>>2]=e,t[o>>2]=t[a>>2],t[o+4>>2]=t[a+4>>2],n=S_(n,o)|0,v=r,n|0}function ss(e){return e=e|0,(t[(Op()|0)+24>>2]|0)+(e*12|0)|0}function S_(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),O1(e1[r&31](e)|0)|0}function T_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],C_(e,r,a,0),v=o}function C_(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=Np()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=fs(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,x_(s,o)|0,o),v=a}function Np(){var e=0,n=0;if(p[7760]|0||(Hm(9756),xt(39,9756,le|0)|0,n=7760,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9756)|0)){e=9756,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Hm(9756)}return 9756}function fs(e){return e=e|0,0}function x_(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=Np()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],Fp(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(R_(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Fp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function R_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=A_(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,k_(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],Fp(s,o,r),t[D>>2]=(t[D>>2]|0)+12,qm(e,E),Js(E),v=k;return}}function A_(e){return e=e|0,357913941}function k_(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function qm(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function Js(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function Hm(e){e=e|0,M_(e)}function Wm(e){e=e|0,O_(e+24|0)}function O_(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function M_(e){e=e|0;var n=0;n=tr()|0,gn(e,2,8,n,N_()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function N_(){return 1292}function F_(e,n,r){e=e|0,n=n|0,r=+r;var o=0,a=0,s=0,h=0;o=v,v=v+16|0,a=o+8|0,s=o,h=L_(e)|0,e=t[h+4>>2]|0,t[s>>2]=t[h>>2],t[s+4>>2]=e,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],b_(n,a,r),v=o}function L_(e){return e=e|0,(t[(Np()|0)+24>>2]|0)+(e*12|0)|0}function b_(e,n,r){e=e|0,n=n|0,r=+r;var o=0,a=0,s=0;s=v,v=v+16|0,a=s,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),Cu(a,r),r=+Qu(a,r),sS[o&31](e,r),v=s}function Vm(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Lp(e,r,a,0),v=o}function Lp(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=bp()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=m2(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,P_(s,o)|0,o),v=a}function bp(){var e=0,n=0;if(p[7768]|0||(Pp(9792),xt(40,9792,le|0)|0,n=7768,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9792)|0)){e=9792,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Pp(9792)}return 9792}function m2(e){return e=e|0,0}function P_(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=bp()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],Vc(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(I_(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Vc(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function I_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=Gm(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,Ym(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],Vc(s,o,r),t[D>>2]=(t[D>>2]|0)+12,B_(e,E),Zs(E),v=k;return}}function Gm(e){return e=e|0,357913941}function Ym(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function B_(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function Zs(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function Pp(e){e=e|0,j_(e)}function Km(e){e=e|0,U_(e+24|0)}function U_(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function j_(e){e=e|0;var n=0;n=tr()|0,gn(e,2,1,n,Ip()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Ip(){return 1300}function z_(e,n,r,o){e=e|0,n=n|0,r=r|0,o=+o;var a=0,s=0,h=0,E=0;a=v,v=v+16|0,s=a+8|0,h=a,E=Kl(e)|0,e=t[E+4>>2]|0,t[h>>2]=t[E>>2],t[h+4>>2]=e,t[s>>2]=t[h>>2],t[s+4>>2]=t[h+4>>2],q_(n,s,r,o),v=a}function Kl(e){return e=e|0,(t[(bp()|0)+24>>2]|0)+(e*12|0)|0}function q_(e,n,r,o){e=e|0,n=n|0,r=r|0,o=+o;var a=0,s=0,h=0,E=0;E=v,v=v+16|0,s=E+1|0,h=E,a=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(a=t[(t[e>>2]|0)+a>>2]|0),pl(s,r),s=zl(s,r)|0,Cu(h,o),o=+Qu(h,o),yS[a&15](e,s,o),v=E}function Bp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Up(e,r,a,0),v=o}function Up(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=cs()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=Xm(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,ds(s,o)|0,o),v=a}function cs(){var e=0,n=0;if(p[7776]|0||(Jm(9828),xt(41,9828,le|0)|0,n=7776,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9828)|0)){e=9828,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Jm(9828)}return 9828}function Xm(e){return e=e|0,0}function ds(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=cs()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],jp(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Qm(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function jp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function Qm(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=zp(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,qp(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],jp(s,o,r),t[D>>2]=(t[D>>2]|0)+12,y2(e,E),H_(E),v=k;return}}function zp(e){return e=e|0,357913941}function qp(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function y2(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function H_(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function Jm(e){e=e|0,Hp(e)}function W_(e){e=e|0,V_(e+24|0)}function V_(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function Hp(e){e=e|0;var n=0;n=tr()|0,gn(e,2,7,n,Zm()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Zm(){return 1312}function G_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;o=v,v=v+16|0,a=o+8|0,s=o,h=Y_(e)|0,e=t[h+4>>2]|0,t[s>>2]=t[h>>2],t[s+4>>2]=e,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],K_(n,a,r),v=o}function Y_(e){return e=e|0,(t[(cs()|0)+24>>2]|0)+(e*12|0)|0}function K_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0;s=v,v=v+16|0,a=s,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),pl(a,r),a=zl(a,r)|0,nf[o&31](e,a),v=s}function X_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],uu(e,r,a,0),v=o}function uu(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=Gc()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=Q_(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,J_(s,o)|0,o),v=a}function Gc(){var e=0,n=0;if(p[7784]|0||($m(9864),xt(42,9864,le|0)|0,n=7784,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9864)|0)){e=9864,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));$m(9864)}return 9864}function Q_(e){return e=e|0,0}function J_(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=Gc()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],ps(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Z_(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function ps(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function Z_(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=$_(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,Wp(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],ps(s,o,r),t[D>>2]=(t[D>>2]|0)+12,Vp(e,E),Xl(E),v=k;return}}function $_(e){return e=e|0,357913941}function Wp(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function Vp(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function Xl(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function $m(e){e=e|0,nE(e)}function eE(e){e=e|0,tE(e+24|0)}function tE(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function nE(e){e=e|0;var n=0;n=tr()|0,gn(e,2,8,n,rE()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function rE(){return 1320}function Gp(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;o=v,v=v+16|0,a=o+8|0,s=o,h=iE(e)|0,e=t[h+4>>2]|0,t[s>>2]=t[h>>2],t[s+4>>2]=e,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],oE(n,a,r),v=o}function iE(e){return e=e|0,(t[(Gc()|0)+24>>2]|0)+(e*12|0)|0}function oE(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0;s=v,v=v+16|0,a=s,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),Yp(a,r),a=ey(a,r)|0,nf[o&31](e,a),v=s}function Yp(e,n){e=e|0,n=n|0}function ey(e,n){return e=e|0,n=n|0,uE(n)|0}function uE(e){return e=e|0,e|0}function lE(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],ty(e,r,a,0),v=o}function ty(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=Aa()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=ny(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,aE(s,o)|0,o),v=a}function Aa(){var e=0,n=0;if(p[7792]|0||(Qp(9900),xt(43,9900,le|0)|0,n=7792,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9900)|0)){e=9900,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Qp(9900)}return 9900}function ny(e){return e=e|0,0}function aE(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=Aa()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],Yc(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(sE(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Yc(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function sE(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=g2(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,Kp(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],Yc(s,o,r),t[D>>2]=(t[D>>2]|0)+12,Xp(e,E),fE(E),v=k;return}}function g2(e){return e=e|0,357913941}function Kp(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function Xp(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function fE(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function Qp(e){e=e|0,ry(e)}function cE(e){e=e|0,dE(e+24|0)}function dE(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function ry(e){e=e|0;var n=0;n=tr()|0,gn(e,2,22,n,pE()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function pE(){return 1344}function hE(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0;r=v,v=v+16|0,o=r+8|0,a=r,s=iy(e)|0,e=t[s+4>>2]|0,t[a>>2]=t[s>>2],t[a+4>>2]=e,t[o>>2]=t[a>>2],t[o+4>>2]=t[a+4>>2],_2(n,o),v=r}function iy(e){return e=e|0,(t[(Aa()|0)+24>>2]|0)+(e*12|0)|0}function _2(e,n){e=e|0,n=n|0;var r=0;r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),tf[r&127](e)}function vE(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0;s=t[e>>2]|0,a=Jp()|0,e=mE(r)|0,Nr(s,n,a,e,yE(r,o)|0,o)}function Jp(){var e=0,n=0;if(p[7800]|0||($p(9936),xt(44,9936,le|0)|0,n=7800,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9936)|0)){e=9936,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));$p(9936)}return 9936}function mE(e){return e=e|0,e|0}function yE(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;return E=v,v=v+16|0,a=E,s=E+4|0,t[a>>2]=e,D=Jp()|0,h=D+24|0,n=en(n,4)|0,t[s>>2]=n,r=D+28|0,o=t[r>>2]|0,o>>>0<(t[D+32>>2]|0)>>>0?(Zp(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(oy(h,a,s),n=t[r>>2]|0),v=E,(n-(t[h>>2]|0)>>3)+-1|0}function Zp(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function oy(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0;if(E=v,v=v+32|0,a=E,s=e+4|0,h=((t[s>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=uy(e)|0,o>>>0>>0)gr(e);else{D=t[e>>2]|0,R=(t[e+8>>2]|0)-D|0,k=R>>2,ly(a,R>>3>>>0>>1>>>0?k>>>0>>0?h:k:o,(t[s>>2]|0)-D>>3,e+8|0),h=a+8|0,Zp(t[h>>2]|0,t[n>>2]|0,t[r>>2]|0),t[h>>2]=(t[h>>2]|0)+8,ay(e,a),sy(a),v=E;return}}function uy(e){return e=e|0,536870911}function ly(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)Tn();else{a=Bt(n<<3)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<3)}function ay(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>3)<<3)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function sy(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&$e(e)}function $p(e){e=e|0,cy(e)}function fy(e){e=e|0,gE(e+24|0)}function gE(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function cy(e){e=e|0;var n=0;n=tr()|0,gn(e,1,23,n,Wf()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function _E(e,n){e=e|0,n=n|0,f(t[(EE(e)|0)>>2]|0,n)}function EE(e){return e=e|0,(t[(Jp()|0)+24>>2]|0)+(e<<3)|0}function f(e,n){e=e|0,n=n|0;var r=0,o=0;r=v,v=v+16|0,o=r,Gl(o,n),n=Yl(o,n)|0,tf[e&127](n),v=r}function d(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0;s=t[e>>2]|0,a=g()|0,e=S(r)|0,Nr(s,n,a,e,x(r,o)|0,o)}function g(){var e=0,n=0;if(p[7808]|0||(Ze(9972),xt(45,9972,le|0)|0,n=7808,t[n>>2]=1,t[n+4>>2]=0),!(Bn(9972)|0)){e=9972,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Ze(9972)}return 9972}function S(e){return e=e|0,e|0}function x(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;return E=v,v=v+16|0,a=E,s=E+4|0,t[a>>2]=e,D=g()|0,h=D+24|0,n=en(n,4)|0,t[s>>2]=n,r=D+28|0,o=t[r>>2]|0,o>>>0<(t[D+32>>2]|0)>>>0?(I(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(j(h,a,s),n=t[r>>2]|0),v=E,(n-(t[h>>2]|0)>>3)+-1|0}function I(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function j(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0;if(E=v,v=v+32|0,a=E,s=e+4|0,h=((t[s>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=X(e)|0,o>>>0>>0)gr(e);else{D=t[e>>2]|0,R=(t[e+8>>2]|0)-D|0,k=R>>2,$(a,R>>3>>>0>>1>>>0?k>>>0>>0?h:k:o,(t[s>>2]|0)-D>>3,e+8|0),h=a+8|0,I(t[h>>2]|0,t[n>>2]|0,t[r>>2]|0),t[h>>2]=(t[h>>2]|0)+8,Re(e,a),Pe(a),v=E;return}}function X(e){return e=e|0,536870911}function $(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)Tn();else{a=Bt(n<<3)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<3)}function Re(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>3)<<3)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function Pe(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&$e(e)}function Ze(e){e=e|0,St(e)}function vt(e){e=e|0,Tt(e+24|0)}function Tt(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function St(e){e=e|0;var n=0;n=tr()|0,gn(e,1,9,n,Ht()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Ht(){return 1348}function Yn(e,n){return e=e|0,n=n|0,Ar(t[(pr(e)|0)>>2]|0,n)|0}function pr(e){return e=e|0,(t[(g()|0)+24>>2]|0)+(e<<3)|0}function Ar(e,n){e=e|0,n=n|0;var r=0,o=0;return r=v,v=v+16|0,o=r,d0(o,n),n=Jr(o,n)|0,n=K1(e1[e&31](n)|0)|0,v=r,n|0}function d0(e,n){e=e|0,n=n|0}function Jr(e,n){return e=e|0,n=n|0,We(n)|0}function We(e){return e=e|0,e|0}function pt(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0;s=t[e>>2]|0,a=Ue()|0,e=_t(r)|0,Nr(s,n,a,e,rn(r,o)|0,o)}function Ue(){var e=0,n=0;if(p[7816]|0||(rr(10008),xt(46,10008,le|0)|0,n=7816,t[n>>2]=1,t[n+4>>2]=0),!(Bn(10008)|0)){e=10008,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));rr(10008)}return 10008}function _t(e){return e=e|0,e|0}function rn(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;return E=v,v=v+16|0,a=E,s=E+4|0,t[a>>2]=e,D=Ue()|0,h=D+24|0,n=en(n,4)|0,t[s>>2]=n,r=D+28|0,o=t[r>>2]|0,o>>>0<(t[D+32>>2]|0)>>>0?(Ut(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(Gr(h,a,s),n=t[r>>2]|0),v=E,(n-(t[h>>2]|0)>>3)+-1|0}function Ut(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function Gr(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0;if(E=v,v=v+32|0,a=E,s=e+4|0,h=((t[s>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=yr(e)|0,o>>>0>>0)gr(e);else{D=t[e>>2]|0,R=(t[e+8>>2]|0)-D|0,k=R>>2,Mi(a,R>>3>>>0>>1>>>0?k>>>0>>0?h:k:o,(t[s>>2]|0)-D>>3,e+8|0),h=a+8|0,Ut(t[h>>2]|0,t[n>>2]|0,t[r>>2]|0),t[h>>2]=(t[h>>2]|0)+8,Mn(e,a),ai(a),v=E;return}}function yr(e){return e=e|0,536870911}function Mi(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)Tn();else{a=Bt(n<<3)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<3)}function Mn(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>3)<<3)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function ai(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&$e(e)}function rr(e){e=e|0,w0(e)}function Ti(e){e=e|0,Zi(e+24|0)}function Zi(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function w0(e){e=e|0;var n=0;n=tr()|0,gn(e,1,15,n,rp()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function ku(e){return e=e|0,mo(t[(Ni(e)|0)>>2]|0)|0}function Ni(e){return e=e|0,(t[(Ue()|0)+24>>2]|0)+(e<<3)|0}function mo(e){return e=e|0,K1(Ay[e&7]()|0)|0}function Ql(){var e=0;return p[7832]|0||(py(10052),xt(25,10052,le|0)|0,e=7832,t[e>>2]=1,t[e+4>>2]=0),10052}function J0(e,n){e=e|0,n=n|0,t[e>>2]=Ou()|0,t[e+4>>2]=Qf()|0,t[e+12>>2]=n,t[e+8>>2]=ka()|0,t[e+32>>2]=2}function Ou(){return 11709}function Qf(){return 1188}function ka(){return $s()|0}function hs(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(qo(o,896)|0)==512?r|0&&(Z0(r),$e(r)):n|0&&(sl(n),$e(n))}function qo(e,n){return e=e|0,n=n|0,n&e|0}function Z0(e){e=e|0,e=t[e+4>>2]|0,e|0&&Zf(e)}function $s(){var e=0;return p[7824]|0||(t[2511]=dy()|0,t[2512]=0,e=7824,t[e>>2]=1,t[e+4>>2]=0),10044}function dy(){return 0}function py(e){e=e|0,os(e)}function DE(e){e=e|0;var n=0,r=0,o=0,a=0,s=0;n=v,v=v+32|0,r=n+24|0,s=n+16|0,a=n+8|0,o=n,hy(e,4827),wE(e,4834,3)|0,SE(e,3682,47)|0,t[s>>2]=9,t[s+4>>2]=0,t[r>>2]=t[s>>2],t[r+4>>2]=t[s+4>>2],eh(e,4841,r)|0,t[a>>2]=1,t[a+4>>2]=0,t[r>>2]=t[a>>2],t[r+4>>2]=t[a+4>>2],vy(e,4871,r)|0,t[o>>2]=10,t[o+4>>2]=0,t[r>>2]=t[o>>2],t[r+4>>2]=t[o+4>>2],TE(e,4891,r)|0,v=n}function hy(e,n){e=e|0,n=n|0;var r=0;r=lM()|0,t[e>>2]=r,aM(r,n),Jf(t[e>>2]|0)}function wE(e,n,r){return e=e|0,n=n|0,r=r|0,VO(e,ar(n)|0,r,0),e|0}function SE(e,n,r){return e=e|0,n=n|0,r=r|0,OO(e,ar(n)|0,r,0),e|0}function eh(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],cO(e,n,a),v=o,e|0}function vy(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Gk(e,n,a),v=o,e|0}function TE(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=t[r+4>>2]|0,t[s>>2]=t[r>>2],t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],CE(e,n,a),v=o,e|0}function CE(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],xE(e,r,a,1),v=o}function xE(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=RE()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=Nk(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,Fk(s,o)|0,o),v=a}function RE(){var e=0,n=0;if(p[7840]|0||(G8(10100),xt(48,10100,le|0)|0,n=7840,t[n>>2]=1,t[n+4>>2]=0),!(Bn(10100)|0)){e=10100,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));G8(10100)}return 10100}function Nk(e){return e=e|0,0}function Fk(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=RE()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],V8(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Lk(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function V8(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function Lk(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=bk(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,Pk(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],V8(s,o,r),t[D>>2]=(t[D>>2]|0)+12,Ik(e,E),Bk(E),v=k;return}}function bk(e){return e=e|0,357913941}function Pk(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function Ik(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function Bk(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function G8(e){e=e|0,zk(e)}function Uk(e){e=e|0,jk(e+24|0)}function jk(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function zk(e){e=e|0;var n=0;n=tr()|0,gn(e,2,6,n,qk()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function qk(){return 1364}function Hk(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;return o=v,v=v+16|0,a=o+8|0,s=o,h=Wk(e)|0,e=t[h+4>>2]|0,t[s>>2]=t[h>>2],t[s+4>>2]=e,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],r=Vk(n,a,r)|0,v=o,r|0}function Wk(e){return e=e|0,(t[(RE()|0)+24>>2]|0)+(e*12|0)|0}function Vk(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0;return s=v,v=v+16|0,a=s,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),pl(a,r),a=zl(a,r)|0,a=xu(nD[o&15](e,a)|0)|0,v=s,a|0}function Gk(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],Yk(e,r,a,0),v=o}function Yk(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=AE()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=Kk(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,Xk(s,o)|0,o),v=a}function AE(){var e=0,n=0;if(p[7848]|0||(K8(10136),xt(49,10136,le|0)|0,n=7848,t[n>>2]=1,t[n+4>>2]=0),!(Bn(10136)|0)){e=10136,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));K8(10136)}return 10136}function Kk(e){return e=e|0,0}function Xk(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=AE()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],Y8(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Qk(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function Y8(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function Qk(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=Jk(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,Zk(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],Y8(s,o,r),t[D>>2]=(t[D>>2]|0)+12,$k(e,E),eO(E),v=k;return}}function Jk(e){return e=e|0,357913941}function Zk(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function $k(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function eO(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function K8(e){e=e|0,rO(e)}function tO(e){e=e|0,nO(e+24|0)}function nO(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function rO(e){e=e|0;var n=0;n=tr()|0,gn(e,2,9,n,iO()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function iO(){return 1372}function oO(e,n,r){e=e|0,n=n|0,r=+r;var o=0,a=0,s=0,h=0;o=v,v=v+16|0,a=o+8|0,s=o,h=uO(e)|0,e=t[h+4>>2]|0,t[s>>2]=t[h>>2],t[s+4>>2]=e,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],lO(n,a,r),v=o}function uO(e){return e=e|0,(t[(AE()|0)+24>>2]|0)+(e*12|0)|0}function lO(e,n,r){e=e|0,n=n|0,r=+r;var o=0,a=0,s=0,h=lt;s=v,v=v+16|0,a=s,o=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(o=t[(t[e>>2]|0)+o>>2]|0),aO(a,r),h=w(sO(a,r)),aS[o&1](e,h),v=s}function aO(e,n){e=e|0,n=+n}function sO(e,n){return e=e|0,n=+n,w(fO(n))}function fO(e){return e=+e,w(e)}function cO(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,a=o+8|0,s=o,E=t[r>>2]|0,h=t[r+4>>2]|0,r=ar(n)|0,t[s>>2]=E,t[s+4>>2]=h,t[a>>2]=t[s>>2],t[a+4>>2]=t[s+4>>2],dO(e,r,a,0),v=o}function dO(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0,D=0,k=0,R=0;a=v,v=v+32|0,s=a+16|0,R=a+8|0,E=a,k=t[r>>2]|0,D=t[r+4>>2]|0,h=t[e>>2]|0,e=kE()|0,t[R>>2]=k,t[R+4>>2]=D,t[s>>2]=t[R>>2],t[s+4>>2]=t[R+4>>2],r=pO(s)|0,t[E>>2]=k,t[E+4>>2]=D,t[s>>2]=t[E>>2],t[s+4>>2]=t[E+4>>2],Nr(h,n,e,r,hO(s,o)|0,o),v=a}function kE(){var e=0,n=0;if(p[7856]|0||(Q8(10172),xt(50,10172,le|0)|0,n=7856,t[n>>2]=1,t[n+4>>2]=0),!(Bn(10172)|0)){e=10172,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Q8(10172)}return 10172}function pO(e){return e=e|0,0}function hO(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0;return R=v,v=v+32|0,a=R+24|0,h=R+16|0,E=R,D=R+8|0,s=t[e>>2]|0,o=t[e+4>>2]|0,t[E>>2]=s,t[E+4>>2]=o,F=kE()|0,k=F+24|0,e=en(n,4)|0,t[D>>2]=e,n=F+28|0,r=t[n>>2]|0,r>>>0<(t[F+32>>2]|0)>>>0?(t[h>>2]=s,t[h+4>>2]=o,t[a>>2]=t[h>>2],t[a+4>>2]=t[h+4>>2],X8(r,a,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(vO(k,E,D),e=t[n>>2]|0),v=R,((e-(t[k>>2]|0)|0)/12|0)+-1|0}function X8(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=o,t[e+8>>2]=r}function vO(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;if(k=v,v=v+48|0,o=k+32|0,h=k+24|0,E=k,D=e+4|0,a=(((t[D>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,s=mO(e)|0,s>>>0>>0)gr(e);else{R=t[e>>2]|0,H=((t[e+8>>2]|0)-R|0)/12|0,F=H<<1,yO(E,H>>>0>>1>>>0?F>>>0>>0?a:F:s,((t[D>>2]|0)-R|0)/12|0,e+8|0),D=E+8|0,s=t[D>>2]|0,a=t[n+4>>2]|0,r=t[r>>2]|0,t[h>>2]=t[n>>2],t[h+4>>2]=a,t[o>>2]=t[h>>2],t[o+4>>2]=t[h+4>>2],X8(s,o,r),t[D>>2]=(t[D>>2]|0)+12,gO(e,E),_O(E),v=k;return}}function mO(e){return e=e|0,357913941}function yO(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>357913941)Tn();else{a=Bt(n*12|0)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r*12|0)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n*12|0)}function gO(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(((a|0)/-12|0)*12|0)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function _O(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~(((o+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&$e(e)}function Q8(e){e=e|0,wO(e)}function EO(e){e=e|0,DO(e+24|0)}function DO(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-o|0)>>>0)/12|0)*12|0)),$e(r))}function wO(e){e=e|0;var n=0;n=tr()|0,gn(e,2,3,n,SO()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function SO(){return 1380}function TO(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0;a=v,v=v+16|0,s=a+8|0,h=a,E=CO(e)|0,e=t[E+4>>2]|0,t[h>>2]=t[E>>2],t[h+4>>2]=e,t[s>>2]=t[h>>2],t[s+4>>2]=t[h+4>>2],xO(n,s,r,o),v=a}function CO(e){return e=e|0,(t[(kE()|0)+24>>2]|0)+(e*12|0)|0}function xO(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0;E=v,v=v+16|0,s=E+1|0,h=E,a=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(a=t[(t[e>>2]|0)+a>>2]|0),pl(s,r),s=zl(s,r)|0,RO(h,o),h=AO(h,o)|0,lh[a&15](e,s,h),v=E}function RO(e,n){e=e|0,n=n|0}function AO(e,n){return e=e|0,n=n|0,kO(n)|0}function kO(e){return e=e|0,(e|0)!=0|0}function OO(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0;s=t[e>>2]|0,a=OE()|0,e=MO(r)|0,Nr(s,n,a,e,NO(r,o)|0,o)}function OE(){var e=0,n=0;if(p[7864]|0||(Z8(10208),xt(51,10208,le|0)|0,n=7864,t[n>>2]=1,t[n+4>>2]=0),!(Bn(10208)|0)){e=10208,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Z8(10208)}return 10208}function MO(e){return e=e|0,e|0}function NO(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;return E=v,v=v+16|0,a=E,s=E+4|0,t[a>>2]=e,D=OE()|0,h=D+24|0,n=en(n,4)|0,t[s>>2]=n,r=D+28|0,o=t[r>>2]|0,o>>>0<(t[D+32>>2]|0)>>>0?(J8(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(FO(h,a,s),n=t[r>>2]|0),v=E,(n-(t[h>>2]|0)>>3)+-1|0}function J8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function FO(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0;if(E=v,v=v+32|0,a=E,s=e+4|0,h=((t[s>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=LO(e)|0,o>>>0>>0)gr(e);else{D=t[e>>2]|0,R=(t[e+8>>2]|0)-D|0,k=R>>2,bO(a,R>>3>>>0>>1>>>0?k>>>0>>0?h:k:o,(t[s>>2]|0)-D>>3,e+8|0),h=a+8|0,J8(t[h>>2]|0,t[n>>2]|0,t[r>>2]|0),t[h>>2]=(t[h>>2]|0)+8,PO(e,a),IO(a),v=E;return}}function LO(e){return e=e|0,536870911}function bO(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)Tn();else{a=Bt(n<<3)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<3)}function PO(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>3)<<3)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function IO(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&$e(e)}function Z8(e){e=e|0,jO(e)}function BO(e){e=e|0,UO(e+24|0)}function UO(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function jO(e){e=e|0;var n=0;n=tr()|0,gn(e,1,24,n,zO()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function zO(){return 1392}function qO(e,n){e=e|0,n=n|0,WO(t[(HO(e)|0)>>2]|0,n)}function HO(e){return e=e|0,(t[(OE()|0)+24>>2]|0)+(e<<3)|0}function WO(e,n){e=e|0,n=n|0;var r=0,o=0;r=v,v=v+16|0,o=r,d0(o,n),n=Jr(o,n)|0,tf[e&127](n),v=r}function VO(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0;s=t[e>>2]|0,a=ME()|0,e=GO(r)|0,Nr(s,n,a,e,YO(r,o)|0,o)}function ME(){var e=0,n=0;if(p[7872]|0||(ew(10244),xt(52,10244,le|0)|0,n=7872,t[n>>2]=1,t[n+4>>2]=0),!(Bn(10244)|0)){e=10244,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));ew(10244)}return 10244}function GO(e){return e=e|0,e|0}function YO(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;return E=v,v=v+16|0,a=E,s=E+4|0,t[a>>2]=e,D=ME()|0,h=D+24|0,n=en(n,4)|0,t[s>>2]=n,r=D+28|0,o=t[r>>2]|0,o>>>0<(t[D+32>>2]|0)>>>0?($8(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(KO(h,a,s),n=t[r>>2]|0),v=E,(n-(t[h>>2]|0)>>3)+-1|0}function $8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function KO(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0;if(E=v,v=v+32|0,a=E,s=e+4|0,h=((t[s>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=XO(e)|0,o>>>0>>0)gr(e);else{D=t[e>>2]|0,R=(t[e+8>>2]|0)-D|0,k=R>>2,QO(a,R>>3>>>0>>1>>>0?k>>>0>>0?h:k:o,(t[s>>2]|0)-D>>3,e+8|0),h=a+8|0,$8(t[h>>2]|0,t[n>>2]|0,t[r>>2]|0),t[h>>2]=(t[h>>2]|0)+8,JO(e,a),ZO(a),v=E;return}}function XO(e){return e=e|0,536870911}function QO(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)Tn();else{a=Bt(n<<3)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<3)}function JO(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>3)<<3)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function ZO(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&$e(e)}function ew(e){e=e|0,tM(e)}function $O(e){e=e|0,eM(e+24|0)}function eM(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function tM(e){e=e|0;var n=0;n=tr()|0,gn(e,1,16,n,nM()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function nM(){return 1400}function rM(e){return e=e|0,oM(t[(iM(e)|0)>>2]|0)|0}function iM(e){return e=e|0,(t[(ME()|0)+24>>2]|0)+(e<<3)|0}function oM(e){return e=e|0,uM(Ay[e&7]()|0)|0}function uM(e){return e=e|0,e|0}function lM(){var e=0;return p[7880]|0||(hM(10280),xt(25,10280,le|0)|0,e=7880,t[e>>2]=1,t[e+4>>2]=0),10280}function aM(e,n){e=e|0,n=n|0,t[e>>2]=sM()|0,t[e+4>>2]=fM()|0,t[e+12>>2]=n,t[e+8>>2]=cM()|0,t[e+32>>2]=4}function sM(){return 11711}function fM(){return 1356}function cM(){return $s()|0}function dM(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(qo(o,896)|0)==512?r|0&&(pM(r),$e(r)):n|0&&(Q0(n),$e(n))}function pM(e){e=e|0,e=t[e+4>>2]|0,e|0&&Zf(e)}function hM(e){e=e|0,os(e)}function vM(e){e=e|0,mM(e,4920),yM(e)|0,gM(e)|0}function mM(e,n){e=e|0,n=n|0;var r=0;r=s2()|0,t[e>>2]=r,UM(r,n),Jf(t[e>>2]|0)}function yM(e){e=e|0;var n=0;return n=t[e>>2]|0,Kc(n,kM()|0),e|0}function gM(e){e=e|0;var n=0;return n=t[e>>2]|0,Kc(n,_M()|0),e|0}function _M(){var e=0;return p[7888]|0||(tw(10328),xt(53,10328,le|0)|0,e=7888,t[e>>2]=1,t[e+4>>2]=0),Bn(10328)|0||tw(10328),10328}function Kc(e,n){e=e|0,n=n|0,Nr(e,0,n,0,0,0)}function tw(e){e=e|0,wM(e),Xc(e,10)}function EM(e){e=e|0,DM(e+24|0)}function DM(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function wM(e){e=e|0;var n=0;n=tr()|0,gn(e,5,1,n,xM()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function SM(e,n,r){e=e|0,n=n|0,r=+r,TM(e,n,r)}function Xc(e,n){e=e|0,n=n|0,t[e+20>>2]=n}function TM(e,n,r){e=e|0,n=n|0,r=+r;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+16|0,s=o+8|0,E=o+13|0,a=o,h=o+12|0,pl(E,n),t[s>>2]=zl(E,n)|0,Cu(h,r),P[a>>3]=+Qu(h,r),CM(e,s,a),v=o}function CM(e,n,r){e=e|0,n=n|0,r=r|0,L(e+8|0,t[n>>2]|0,+P[r>>3]),p[e+24>>0]=1}function xM(){return 1404}function RM(e,n){return e=e|0,n=+n,AM(e,n)|0}function AM(e,n){e=e|0,n=+n;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;return o=v,v=v+16|0,s=o+4|0,h=o+8|0,E=o,a=ml(8)|0,r=a,D=Bt(16)|0,pl(s,e),e=zl(s,e)|0,Cu(h,n),L(D,e,+Qu(h,n)),h=r+4|0,t[h>>2]=D,e=Bt(8)|0,h=t[h>>2]|0,t[E>>2]=0,t[s>>2]=t[E>>2],Ys(e,h,s),t[a>>2]=e,v=o,r|0}function kM(){var e=0;return p[7896]|0||(nw(10364),xt(54,10364,le|0)|0,e=7896,t[e>>2]=1,t[e+4>>2]=0),Bn(10364)|0||nw(10364),10364}function nw(e){e=e|0,NM(e),Xc(e,55)}function OM(e){e=e|0,MM(e+24|0)}function MM(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function NM(e){e=e|0;var n=0;n=tr()|0,gn(e,5,4,n,PM()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function FM(e){e=e|0,LM(e)}function LM(e){e=e|0,bM(e)}function bM(e){e=e|0,rw(e+8|0),p[e+24>>0]=1}function rw(e){e=e|0,t[e>>2]=0,P[e+8>>3]=0}function PM(){return 1424}function IM(){return BM()|0}function BM(){var e=0,n=0,r=0,o=0,a=0,s=0,h=0;return n=v,v=v+16|0,a=n+4|0,h=n,r=ml(8)|0,e=r,o=Bt(16)|0,rw(o),s=e+4|0,t[s>>2]=o,o=Bt(8)|0,s=t[s>>2]|0,t[h>>2]=0,t[a>>2]=t[h>>2],Ys(o,s,a),t[r>>2]=o,v=n,e|0}function UM(e,n){e=e|0,n=n|0,t[e>>2]=jM()|0,t[e+4>>2]=zM()|0,t[e+12>>2]=n,t[e+8>>2]=qM()|0,t[e+32>>2]=5}function jM(){return 11710}function zM(){return 1416}function qM(){return my()|0}function HM(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(qo(o,896)|0)==512?r|0&&(WM(r),$e(r)):n|0&&$e(n)}function WM(e){e=e|0,e=t[e+4>>2]|0,e|0&&Zf(e)}function my(){var e=0;return p[7904]|0||(t[2600]=VM()|0,t[2601]=0,e=7904,t[e>>2]=1,t[e+4>>2]=0),10400}function VM(){return t[357]|0}function GM(e){e=e|0,YM(e,4926),KM(e)|0}function YM(e,n){e=e|0,n=n|0;var r=0;r=Us()|0,t[e>>2]=r,oN(r,n),Jf(t[e>>2]|0)}function KM(e){e=e|0;var n=0;return n=t[e>>2]|0,Kc(n,XM()|0),e|0}function XM(){var e=0;return p[7912]|0||(iw(10412),xt(56,10412,le|0)|0,e=7912,t[e>>2]=1,t[e+4>>2]=0),Bn(10412)|0||iw(10412),10412}function iw(e){e=e|0,ZM(e),Xc(e,57)}function QM(e){e=e|0,JM(e+24|0)}function JM(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function ZM(e){e=e|0;var n=0;n=tr()|0,gn(e,5,5,n,nN()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function $M(e){e=e|0,eN(e)}function eN(e){e=e|0,tN(e)}function tN(e){e=e|0;var n=0,r=0;n=e+8|0,r=n+48|0;do t[n>>2]=0,n=n+4|0;while((n|0)<(r|0));p[e+56>>0]=1}function nN(){return 1432}function rN(){return iN()|0}function iN(){var e=0,n=0,r=0,o=0,a=0,s=0,h=0,E=0;h=v,v=v+16|0,e=h+4|0,n=h,r=ml(8)|0,o=r,a=Bt(48)|0,s=a,E=s+48|0;do t[s>>2]=0,s=s+4|0;while((s|0)<(E|0));return s=o+4|0,t[s>>2]=a,E=Bt(8)|0,s=t[s>>2]|0,t[n>>2]=0,t[e>>2]=t[n>>2],Fv(E,s,e),t[r>>2]=E,v=h,o|0}function oN(e,n){e=e|0,n=n|0,t[e>>2]=uN()|0,t[e+4>>2]=lN()|0,t[e+12>>2]=n,t[e+8>>2]=aN()|0,t[e+32>>2]=6}function uN(){return 11704}function lN(){return 1436}function aN(){return my()|0}function sN(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(qo(o,896)|0)==512?r|0&&(fN(r),$e(r)):n|0&&$e(n)}function fN(e){e=e|0,e=t[e+4>>2]|0,e|0&&Zf(e)}function cN(e){e=e|0,dN(e,4933),pN(e)|0,hN(e)|0}function dN(e,n){e=e|0,n=n|0;var r=0;r=BN()|0,t[e>>2]=r,UN(r,n),Jf(t[e>>2]|0)}function pN(e){e=e|0;var n=0;return n=t[e>>2]|0,Kc(n,AN()|0),e|0}function hN(e){e=e|0;var n=0;return n=t[e>>2]|0,Kc(n,vN()|0),e|0}function vN(){var e=0;return p[7920]|0||(ow(10452),xt(58,10452,le|0)|0,e=7920,t[e>>2]=1,t[e+4>>2]=0),Bn(10452)|0||ow(10452),10452}function ow(e){e=e|0,gN(e),Xc(e,1)}function mN(e){e=e|0,yN(e+24|0)}function yN(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function gN(e){e=e|0;var n=0;n=tr()|0,gn(e,5,1,n,wN()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function _N(e,n,r){e=e|0,n=+n,r=+r,EN(e,n,r)}function EN(e,n,r){e=e|0,n=+n,r=+r;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+32|0,s=o+8|0,E=o+17|0,a=o,h=o+16|0,Cu(E,n),P[s>>3]=+Qu(E,n),Cu(h,r),P[a>>3]=+Qu(h,r),DN(e,s,a),v=o}function DN(e,n,r){e=e|0,n=n|0,r=r|0,uw(e+8|0,+P[n>>3],+P[r>>3]),p[e+24>>0]=1}function uw(e,n,r){e=e|0,n=+n,r=+r,P[e>>3]=n,P[e+8>>3]=r}function wN(){return 1472}function SN(e,n){return e=+e,n=+n,TN(e,n)|0}function TN(e,n){e=+e,n=+n;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;return o=v,v=v+16|0,h=o+4|0,E=o+8|0,D=o,a=ml(8)|0,r=a,s=Bt(16)|0,Cu(h,e),e=+Qu(h,e),Cu(E,n),uw(s,e,+Qu(E,n)),E=r+4|0,t[E>>2]=s,s=Bt(8)|0,E=t[E>>2]|0,t[D>>2]=0,t[h>>2]=t[D>>2],lw(s,E,h),t[a>>2]=s,v=o,r|0}function lw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=Bt(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1452,t[r+12>>2]=n,t[e+4>>2]=r}function CN(e){e=e|0,C2(e),$e(e)}function xN(e){e=e|0,e=t[e+12>>2]|0,e|0&&$e(e)}function RN(e){e=e|0,$e(e)}function AN(){var e=0;return p[7928]|0||(aw(10488),xt(59,10488,le|0)|0,e=7928,t[e>>2]=1,t[e+4>>2]=0),Bn(10488)|0||aw(10488),10488}function aw(e){e=e|0,MN(e),Xc(e,60)}function kN(e){e=e|0,ON(e+24|0)}function ON(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function MN(e){e=e|0;var n=0;n=tr()|0,gn(e,5,6,n,bN()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function NN(e){e=e|0,FN(e)}function FN(e){e=e|0,LN(e)}function LN(e){e=e|0,sw(e+8|0),p[e+24>>0]=1}function sw(e){e=e|0,t[e>>2]=0,t[e+4>>2]=0,t[e+8>>2]=0,t[e+12>>2]=0}function bN(){return 1492}function PN(){return IN()|0}function IN(){var e=0,n=0,r=0,o=0,a=0,s=0,h=0;return n=v,v=v+16|0,a=n+4|0,h=n,r=ml(8)|0,e=r,o=Bt(16)|0,sw(o),s=e+4|0,t[s>>2]=o,o=Bt(8)|0,s=t[s>>2]|0,t[h>>2]=0,t[a>>2]=t[h>>2],lw(o,s,a),t[r>>2]=o,v=n,e|0}function BN(){var e=0;return p[7936]|0||(VN(10524),xt(25,10524,le|0)|0,e=7936,t[e>>2]=1,t[e+4>>2]=0),10524}function UN(e,n){e=e|0,n=n|0,t[e>>2]=jN()|0,t[e+4>>2]=zN()|0,t[e+12>>2]=n,t[e+8>>2]=qN()|0,t[e+32>>2]=7}function jN(){return 11700}function zN(){return 1484}function qN(){return my()|0}function HN(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(qo(o,896)|0)==512?r|0&&(WN(r),$e(r)):n|0&&$e(n)}function WN(e){e=e|0,e=t[e+4>>2]|0,e|0&&Zf(e)}function VN(e){e=e|0,os(e)}function GN(e,n,r){e=e|0,n=n|0,r=r|0,e=ar(n)|0,n=YN(r)|0,r=KN(r,0)|0,TF(e,n,r,NE()|0,0)}function YN(e){return e=e|0,e|0}function KN(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;return E=v,v=v+16|0,a=E,s=E+4|0,t[a>>2]=e,D=NE()|0,h=D+24|0,n=en(n,4)|0,t[s>>2]=n,r=D+28|0,o=t[r>>2]|0,o>>>0<(t[D+32>>2]|0)>>>0?(cw(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(tF(h,a,s),n=t[r>>2]|0),v=E,(n-(t[h>>2]|0)>>3)+-1|0}function NE(){var e=0,n=0;if(p[7944]|0||(fw(10568),xt(61,10568,le|0)|0,n=7944,t[n>>2]=1,t[n+4>>2]=0),!(Bn(10568)|0)){e=10568,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));fw(10568)}return 10568}function fw(e){e=e|0,JN(e)}function XN(e){e=e|0,QN(e+24|0)}function QN(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function JN(e){e=e|0;var n=0;n=tr()|0,gn(e,1,17,n,vm()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function ZN(e){return e=e|0,eF(t[($N(e)|0)>>2]|0)|0}function $N(e){return e=e|0,(t[(NE()|0)+24>>2]|0)+(e<<3)|0}function eF(e){return e=e|0,P0(Ay[e&7]()|0)|0}function cw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function tF(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0;if(E=v,v=v+32|0,a=E,s=e+4|0,h=((t[s>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=nF(e)|0,o>>>0>>0)gr(e);else{D=t[e>>2]|0,R=(t[e+8>>2]|0)-D|0,k=R>>2,rF(a,R>>3>>>0>>1>>>0?k>>>0>>0?h:k:o,(t[s>>2]|0)-D>>3,e+8|0),h=a+8|0,cw(t[h>>2]|0,t[n>>2]|0,t[r>>2]|0),t[h>>2]=(t[h>>2]|0)+8,iF(e,a),oF(a),v=E;return}}function nF(e){return e=e|0,536870911}function rF(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)Tn();else{a=Bt(n<<3)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<3)}function iF(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>3)<<3)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function oF(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&$e(e)}function uF(){lF()}function lF(){aF(10604)}function aF(e){e=e|0,sF(e,4955)}function sF(e,n){e=e|0,n=n|0;var r=0;r=fF()|0,t[e>>2]=r,cF(r,n),Jf(t[e>>2]|0)}function fF(){var e=0;return p[7952]|0||(EF(10612),xt(25,10612,le|0)|0,e=7952,t[e>>2]=1,t[e+4>>2]=0),10612}function cF(e,n){e=e|0,n=n|0,t[e>>2]=vF()|0,t[e+4>>2]=mF()|0,t[e+12>>2]=n,t[e+8>>2]=yF()|0,t[e+32>>2]=8}function Jf(e){e=e|0;var n=0,r=0;n=v,v=v+16|0,r=n,E2()|0,t[r>>2]=e,dF(10608,r),v=n}function E2(){return p[11714]|0||(t[2652]=0,xt(62,10608,le|0)|0,p[11714]=1),10608}function dF(e,n){e=e|0,n=n|0;var r=0;r=Bt(8)|0,t[r+4>>2]=t[n>>2],t[r>>2]=t[e>>2],t[e>>2]=r}function pF(e){e=e|0,hF(e)}function hF(e){e=e|0;var n=0,r=0;if(n=t[e>>2]|0,n|0)do r=n,n=t[n>>2]|0,$e(r);while((n|0)!=0);t[e>>2]=0}function vF(){return 11715}function mF(){return 1496}function yF(){return $s()|0}function gF(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(qo(o,896)|0)==512?r|0&&(_F(r),$e(r)):n|0&&$e(n)}function _F(e){e=e|0,e=t[e+4>>2]|0,e|0&&Zf(e)}function EF(e){e=e|0,os(e)}function DF(e,n){e=e|0,n=n|0;var r=0,o=0;E2()|0,r=t[2652]|0;e:do if(r|0){for(;o=t[r+4>>2]|0,!(o|0&&(Gw(FE(o)|0,e)|0)==0);)if(r=t[r>>2]|0,!r)break e;wF(o,n)}while(0)}function FE(e){return e=e|0,t[e+12>>2]|0}function wF(e,n){e=e|0,n=n|0;var r=0;e=e+36|0,r=t[e>>2]|0,r|0&&(ma(r),$e(r)),r=Bt(4)|0,Ff(r,n),t[e>>2]=r}function LE(){return p[11716]|0||(t[2664]=0,xt(63,10656,le|0)|0,p[11716]=1),10656}function dw(){var e=0;return p[11717]|0?e=t[2665]|0:(SF(),t[2665]=1504,p[11717]=1,e=1504),e|0}function SF(){p[11740]|0||(p[11718]=en(en(8,0)|0,0)|0,p[11719]=en(en(0,0)|0,0)|0,p[11720]=en(en(0,16)|0,0)|0,p[11721]=en(en(8,0)|0,0)|0,p[11722]=en(en(0,0)|0,0)|0,p[11723]=en(en(8,0)|0,0)|0,p[11724]=en(en(0,0)|0,0)|0,p[11725]=en(en(8,0)|0,0)|0,p[11726]=en(en(0,0)|0,0)|0,p[11727]=en(en(8,0)|0,0)|0,p[11728]=en(en(0,0)|0,0)|0,p[11729]=en(en(0,0)|0,32)|0,p[11730]=en(en(0,0)|0,32)|0,p[11740]=1)}function pw(){return 1572}function TF(e,n,r,o,a){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0;var s=0,h=0,E=0,D=0,k=0,R=0;s=v,v=v+32|0,R=s+16|0,k=s+12|0,D=s+8|0,E=s+4|0,h=s,t[R>>2]=e,t[k>>2]=n,t[D>>2]=r,t[E>>2]=o,t[h>>2]=a,LE()|0,CF(10656,R,k,D,E,h),v=s}function CF(e,n,r,o,a,s){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0;var h=0;h=Bt(24)|0,xd(h+4|0,t[n>>2]|0,t[r>>2]|0,t[o>>2]|0,t[a>>2]|0,t[s>>2]|0),t[h>>2]=t[e>>2],t[e>>2]=h}function hw(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0,xe=0,ce=0,ue=0,Be=0,be=0,Ve=0;if(Ve=v,v=v+32|0,ce=Ve+20|0,ue=Ve+8|0,Be=Ve+4|0,be=Ve,n=t[n>>2]|0,n|0){xe=ce+4|0,D=ce+8|0,k=ue+4|0,R=ue+8|0,F=ue+8|0,H=ce+8|0;do{if(h=n+4|0,E=bE(h)|0,E|0){if(a=th(E)|0,t[ce>>2]=0,t[xe>>2]=0,t[D>>2]=0,o=(nh(E)|0)+1|0,xF(ce,o),o|0)for(;o=o+-1|0,Oa(ue,t[a>>2]|0),s=t[xe>>2]|0,s>>>0<(t[H>>2]|0)>>>0?(t[s>>2]=t[ue>>2],t[xe>>2]=(t[xe>>2]|0)+4):PE(ce,ue),o;)a=a+4|0;o=rh(E)|0,t[ue>>2]=0,t[k>>2]=0,t[R>>2]=0;e:do if(t[o>>2]|0)for(a=0,s=0;;){if((a|0)==(s|0)?RF(ue,o):(t[a>>2]=t[o>>2],t[k>>2]=(t[k>>2]|0)+4),o=o+4|0,!(t[o>>2]|0))break e;a=t[k>>2]|0,s=t[F>>2]|0}while(0);t[Be>>2]=yy(h)|0,t[be>>2]=Bn(E)|0,AF(r,e,Be,be,ce,ue),IE(ue),ef(ce)}n=t[n>>2]|0}while((n|0)!=0)}v=Ve}function bE(e){return e=e|0,t[e+12>>2]|0}function th(e){return e=e|0,t[e+12>>2]|0}function nh(e){return e=e|0,t[e+16>>2]|0}function xF(e,n){e=e|0,n=n|0;var r=0,o=0,a=0;a=v,v=v+32|0,r=a,o=t[e>>2]|0,(t[e+8>>2]|0)-o>>2>>>0>>0&&(ww(r,n,(t[e+4>>2]|0)-o>>2,e+8|0),Sw(e,r),Tw(r)),v=a}function PE(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0;if(h=v,v=v+32|0,r=h,o=e+4|0,a=((t[o>>2]|0)-(t[e>>2]|0)>>2)+1|0,s=Dw(e)|0,s>>>0>>0)gr(e);else{E=t[e>>2]|0,k=(t[e+8>>2]|0)-E|0,D=k>>1,ww(r,k>>2>>>0>>1>>>0?D>>>0>>0?a:D:s,(t[o>>2]|0)-E>>2,e+8|0),s=r+8|0,t[t[s>>2]>>2]=t[n>>2],t[s>>2]=(t[s>>2]|0)+4,Sw(e,r),Tw(r),v=h;return}}function rh(e){return e=e|0,t[e+8>>2]|0}function RF(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0;if(h=v,v=v+32|0,r=h,o=e+4|0,a=((t[o>>2]|0)-(t[e>>2]|0)>>2)+1|0,s=Ew(e)|0,s>>>0>>0)gr(e);else{E=t[e>>2]|0,k=(t[e+8>>2]|0)-E|0,D=k>>1,YF(r,k>>2>>>0>>1>>>0?D>>>0>>0?a:D:s,(t[o>>2]|0)-E>>2,e+8|0),s=r+8|0,t[t[s>>2]>>2]=t[n>>2],t[s>>2]=(t[s>>2]|0)+4,KF(e,r),XF(r),v=h;return}}function yy(e){return e=e|0,t[e>>2]|0}function AF(e,n,r,o,a,s){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0,kF(e,n,r,o,a,s)}function IE(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-4-o|0)>>>2)<<2)),$e(r))}function ef(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-4-o|0)>>>2)<<2)),$e(r))}function kF(e,n,r,o,a,s){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0;var h=0,E=0,D=0,k=0,R=0,F=0;h=v,v=v+48|0,R=h+40|0,E=h+32|0,F=h+24|0,D=h+12|0,k=h,yl(E),e=jo(e)|0,t[F>>2]=t[n>>2],r=t[r>>2]|0,o=t[o>>2]|0,BE(D,a),OF(k,s),t[R>>2]=t[F>>2],MF(e,R,r,o,D,k),IE(k),ef(D),gl(E),v=h}function BE(e,n){e=e|0,n=n|0;var r=0,o=0;t[e>>2]=0,t[e+4>>2]=0,t[e+8>>2]=0,r=n+4|0,o=(t[r>>2]|0)-(t[n>>2]|0)>>2,o|0&&(VF(e,o),GF(e,t[n>>2]|0,t[r>>2]|0,o))}function OF(e,n){e=e|0,n=n|0;var r=0,o=0;t[e>>2]=0,t[e+4>>2]=0,t[e+8>>2]=0,r=n+4|0,o=(t[r>>2]|0)-(t[n>>2]|0)>>2,o|0&&(HF(e,o),WF(e,t[n>>2]|0,t[r>>2]|0,o))}function MF(e,n,r,o,a,s){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0;var h=0,E=0,D=0,k=0,R=0,F=0;h=v,v=v+32|0,R=h+28|0,F=h+24|0,E=h+12|0,D=h,k=ho(NF()|0)|0,t[F>>2]=t[n>>2],t[R>>2]=t[F>>2],n=Qc(R)|0,r=vw(r)|0,o=UE(o)|0,t[E>>2]=t[a>>2],R=a+4|0,t[E+4>>2]=t[R>>2],F=a+8|0,t[E+8>>2]=t[F>>2],t[F>>2]=0,t[R>>2]=0,t[a>>2]=0,a=jE(E)|0,t[D>>2]=t[s>>2],R=s+4|0,t[D+4>>2]=t[R>>2],F=s+8|0,t[D+8>>2]=t[F>>2],t[F>>2]=0,t[R>>2]=0,t[s>>2]=0,j0(0,k|0,e|0,n|0,r|0,o|0,a|0,FF(D)|0)|0,IE(D),ef(E),v=h}function NF(){var e=0;return p[7968]|0||(zF(10708),e=7968,t[e>>2]=1,t[e+4>>2]=0),10708}function Qc(e){return e=e|0,yw(e)|0}function vw(e){return e=e|0,mw(e)|0}function UE(e){return e=e|0,P0(e)|0}function jE(e){return e=e|0,bF(e)|0}function FF(e){return e=e|0,LF(e)|0}function LF(e){e=e|0;var n=0,r=0,o=0;if(o=(t[e+4>>2]|0)-(t[e>>2]|0)|0,r=o>>2,o=ml(o+4|0)|0,t[o>>2]=r,r|0){n=0;do t[o+4+(n<<2)>>2]=mw(t[(t[e>>2]|0)+(n<<2)>>2]|0)|0,n=n+1|0;while((n|0)!=(r|0))}return o|0}function mw(e){return e=e|0,e|0}function bF(e){e=e|0;var n=0,r=0,o=0;if(o=(t[e+4>>2]|0)-(t[e>>2]|0)|0,r=o>>2,o=ml(o+4|0)|0,t[o>>2]=r,r|0){n=0;do t[o+4+(n<<2)>>2]=yw((t[e>>2]|0)+(n<<2)|0)|0,n=n+1|0;while((n|0)!=(r|0))}return o|0}function yw(e){e=e|0;var n=0,r=0,o=0,a=0;return a=v,v=v+32|0,n=a+12|0,r=a,o=rs(gw()|0)|0,o?(Ku(n,o),js(r,n),_I(e,r),e=dl(n)|0):e=PF(e)|0,v=a,e|0}function gw(){var e=0;return p[7960]|0||(jF(10664),xt(25,10664,le|0)|0,e=7960,t[e>>2]=1,t[e+4>>2]=0),10664}function PF(e){e=e|0;var n=0,r=0,o=0,a=0,s=0,h=0,E=0;return r=v,v=v+16|0,a=r+4|0,h=r,o=ml(8)|0,n=o,E=Bt(4)|0,t[E>>2]=t[e>>2],s=n+4|0,t[s>>2]=E,e=Bt(8)|0,s=t[s>>2]|0,t[h>>2]=0,t[a>>2]=t[h>>2],_w(e,s,a),t[o>>2]=e,v=r,n|0}function _w(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=Bt(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1656,t[r+12>>2]=n,t[e+4>>2]=r}function IF(e){e=e|0,C2(e),$e(e)}function BF(e){e=e|0,e=t[e+12>>2]|0,e|0&&$e(e)}function UF(e){e=e|0,$e(e)}function jF(e){e=e|0,os(e)}function zF(e){e=e|0,tu(e,qF()|0,5)}function qF(){return 1676}function HF(e,n){e=e|0,n=n|0;var r=0;if((Ew(e)|0)>>>0>>0&&gr(e),n>>>0>1073741823)Tn();else{r=Bt(n<<2)|0,t[e+4>>2]=r,t[e>>2]=r,t[e+8>>2]=r+(n<<2);return}}function WF(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,o=e+4|0,e=r-n|0,(e|0)>0&&(bn(t[o>>2]|0,n|0,e|0)|0,t[o>>2]=(t[o>>2]|0)+(e>>>2<<2))}function Ew(e){return e=e|0,1073741823}function VF(e,n){e=e|0,n=n|0;var r=0;if((Dw(e)|0)>>>0>>0&&gr(e),n>>>0>1073741823)Tn();else{r=Bt(n<<2)|0,t[e+4>>2]=r,t[e>>2]=r,t[e+8>>2]=r+(n<<2);return}}function GF(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,o=e+4|0,e=r-n|0,(e|0)>0&&(bn(t[o>>2]|0,n|0,e|0)|0,t[o>>2]=(t[o>>2]|0)+(e>>>2<<2))}function Dw(e){return e=e|0,1073741823}function YF(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>1073741823)Tn();else{a=Bt(n<<2)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<2)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<2)}function KF(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>2)<<2)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function XF(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-4-n|0)>>>2)<<2)),e=t[e>>2]|0,e|0&&$e(e)}function ww(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>1073741823)Tn();else{a=Bt(n<<2)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<2)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<2)}function Sw(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>2)<<2)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function Tw(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-4-n|0)>>>2)<<2)),e=t[e>>2]|0,e|0&&$e(e)}function QF(e,n,r,o,a){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0;var s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0,xe=0,ce=0,ue=0;if(ue=v,v=v+32|0,R=ue+20|0,F=ue+12|0,k=ue+16|0,H=ue+4|0,xe=ue,ce=ue+8|0,E=dw()|0,s=t[E>>2]|0,h=t[s>>2]|0,h|0)for(D=t[E+8>>2]|0,E=t[E+4>>2]|0;Oa(R,h),JF(e,R,E,D),s=s+4|0,h=t[s>>2]|0,h;)D=D+1|0,E=E+1|0;if(s=pw()|0,h=t[s>>2]|0,h|0)do Oa(R,h),t[F>>2]=t[s+4>>2],ZF(n,R,F),s=s+8|0,h=t[s>>2]|0;while((h|0)!=0);if(s=t[(E2()|0)>>2]|0,s|0)do n=t[s+4>>2]|0,Oa(R,t[(D2(n)|0)>>2]|0),t[F>>2]=FE(n)|0,$F(r,R,F),s=t[s>>2]|0;while((s|0)!=0);if(Oa(k,0),s=LE()|0,t[R>>2]=t[k>>2],hw(R,s,a),s=t[(E2()|0)>>2]|0,s|0){e=R+4|0,n=R+8|0,r=R+8|0;do{if(D=t[s+4>>2]|0,Oa(F,t[(D2(D)|0)>>2]|0),eL(H,Cw(D)|0),h=t[H>>2]|0,h|0){t[R>>2]=0,t[e>>2]=0,t[n>>2]=0;do Oa(xe,t[(D2(t[h+4>>2]|0)|0)>>2]|0),E=t[e>>2]|0,E>>>0<(t[r>>2]|0)>>>0?(t[E>>2]=t[xe>>2],t[e>>2]=(t[e>>2]|0)+4):PE(R,xe),h=t[h>>2]|0;while((h|0)!=0);tL(o,F,R),ef(R)}t[ce>>2]=t[F>>2],k=xw(D)|0,t[R>>2]=t[ce>>2],hw(R,k,a),j1(H),s=t[s>>2]|0}while((s|0)!=0)}v=ue}function JF(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,pL(e,n,r,o)}function ZF(e,n,r){e=e|0,n=n|0,r=r|0,dL(e,n,r)}function D2(e){return e=e|0,e|0}function $F(e,n,r){e=e|0,n=n|0,r=r|0,aL(e,n,r)}function Cw(e){return e=e|0,e+16|0}function eL(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;if(s=v,v=v+16|0,a=s+8|0,r=s,t[e>>2]=0,o=t[n>>2]|0,t[a>>2]=o,t[r>>2]=e,r=lL(r)|0,o|0){if(o=Bt(12)|0,h=(Rw(a)|0)+4|0,e=t[h+4>>2]|0,n=o+4|0,t[n>>2]=t[h>>2],t[n+4>>2]=e,n=t[t[a>>2]>>2]|0,t[a>>2]=n,!n)e=o;else for(n=o;e=Bt(12)|0,D=(Rw(a)|0)+4|0,E=t[D+4>>2]|0,h=e+4|0,t[h>>2]=t[D>>2],t[h+4>>2]=E,t[n>>2]=e,h=t[t[a>>2]>>2]|0,t[a>>2]=h,h;)n=e;t[e>>2]=t[r>>2],t[r>>2]=o}v=s}function tL(e,n,r){e=e|0,n=n|0,r=r|0,nL(e,n,r)}function xw(e){return e=e|0,e+24|0}function nL(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+32|0,h=o+24|0,a=o+16|0,E=o+12|0,s=o,yl(a),e=jo(e)|0,t[E>>2]=t[n>>2],BE(s,r),t[h>>2]=t[E>>2],rL(e,h,s),ef(s),gl(a),v=o}function rL(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=v,v=v+32|0,h=o+16|0,E=o+12|0,a=o,s=ho(iL()|0)|0,t[E>>2]=t[n>>2],t[h>>2]=t[E>>2],n=Qc(h)|0,t[a>>2]=t[r>>2],h=r+4|0,t[a+4>>2]=t[h>>2],E=r+8|0,t[a+8>>2]=t[E>>2],t[E>>2]=0,t[h>>2]=0,t[r>>2]=0,F0(0,s|0,e|0,n|0,jE(a)|0)|0,ef(a),v=o}function iL(){var e=0;return p[7976]|0||(oL(10720),e=7976,t[e>>2]=1,t[e+4>>2]=0),10720}function oL(e){e=e|0,tu(e,uL()|0,2)}function uL(){return 1732}function lL(e){return e=e|0,t[e>>2]|0}function Rw(e){return e=e|0,t[e>>2]|0}function aL(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;o=v,v=v+32|0,s=o+16|0,a=o+8|0,h=o,yl(a),e=jo(e)|0,t[h>>2]=t[n>>2],r=t[r>>2]|0,t[s>>2]=t[h>>2],Aw(e,s,r),gl(a),v=o}function Aw(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;o=v,v=v+16|0,s=o+4|0,h=o,a=ho(sL()|0)|0,t[h>>2]=t[n>>2],t[s>>2]=t[h>>2],n=Qc(s)|0,F0(0,a|0,e|0,n|0,vw(r)|0)|0,v=o}function sL(){var e=0;return p[7984]|0||(fL(10732),e=7984,t[e>>2]=1,t[e+4>>2]=0),10732}function fL(e){e=e|0,tu(e,cL()|0,2)}function cL(){return 1744}function dL(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;o=v,v=v+32|0,s=o+16|0,a=o+8|0,h=o,yl(a),e=jo(e)|0,t[h>>2]=t[n>>2],r=t[r>>2]|0,t[s>>2]=t[h>>2],Aw(e,s,r),gl(a),v=o}function pL(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0;a=v,v=v+32|0,h=a+16|0,s=a+8|0,E=a,yl(s),e=jo(e)|0,t[E>>2]=t[n>>2],r=p[r>>0]|0,o=p[o>>0]|0,t[h>>2]=t[E>>2],hL(e,h,r,o),gl(s),v=a}function hL(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0;a=v,v=v+16|0,h=a+4|0,E=a,s=ho(vL()|0)|0,t[E>>2]=t[n>>2],t[h>>2]=t[E>>2],n=Qc(h)|0,r=w2(r)|0,mn(0,s|0,e|0,n|0,r|0,w2(o)|0)|0,v=a}function vL(){var e=0;return p[7992]|0||(yL(10744),e=7992,t[e>>2]=1,t[e+4>>2]=0),10744}function w2(e){return e=e|0,mL(e)|0}function mL(e){return e=e|0,e&255|0}function yL(e){e=e|0,tu(e,gL()|0,3)}function gL(){return 1756}function _L(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;switch(H=v,v=v+32|0,E=H+8|0,D=H+4|0,k=H+20|0,R=H,xa(e,0),o=gI(n)|0,t[E>>2]=0,F=E+4|0,t[F>>2]=0,t[E+8>>2]=0,o<<24>>24){case 0:{p[k>>0]=0,EL(D,r,k),gy(e,D)|0,Pl(D);break}case 8:{F=GE(n)|0,p[k>>0]=8,Oa(R,t[F+4>>2]|0),DL(D,r,k,R,F+8|0),gy(e,D)|0,Pl(D);break}case 9:{if(s=GE(n)|0,n=t[s+4>>2]|0,n|0)for(h=E+8|0,a=s+12|0;n=n+-1|0,Oa(D,t[a>>2]|0),o=t[F>>2]|0,o>>>0<(t[h>>2]|0)>>>0?(t[o>>2]=t[D>>2],t[F>>2]=(t[F>>2]|0)+4):PE(E,D),n;)a=a+4|0;p[k>>0]=9,Oa(R,t[s+8>>2]|0),wL(D,r,k,R,E),gy(e,D)|0,Pl(D);break}default:F=GE(n)|0,p[k>>0]=o,Oa(R,t[F+4>>2]|0),SL(D,r,k,R),gy(e,D)|0,Pl(D)}ef(E),v=H}function EL(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0;o=v,v=v+16|0,a=o,yl(a),n=jo(n)|0,PL(e,n,p[r>>0]|0),gl(a),v=o}function gy(e,n){e=e|0,n=n|0;var r=0;return r=t[e>>2]|0,r|0&&vr(r|0),t[e>>2]=t[n>>2],t[n>>2]=0,e|0}function DL(e,n,r,o,a){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0;var s=0,h=0,E=0,D=0;s=v,v=v+32|0,E=s+16|0,h=s+8|0,D=s,yl(h),n=jo(n)|0,r=p[r>>0]|0,t[D>>2]=t[o>>2],a=t[a>>2]|0,t[E>>2]=t[D>>2],NL(e,n,r,E,a),gl(h),v=s}function wL(e,n,r,o,a){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0;var s=0,h=0,E=0,D=0,k=0;s=v,v=v+32|0,D=s+24|0,h=s+16|0,k=s+12|0,E=s,yl(h),n=jo(n)|0,r=p[r>>0]|0,t[k>>2]=t[o>>2],BE(E,a),t[D>>2]=t[k>>2],AL(e,n,r,D,E),ef(E),gl(h),v=s}function SL(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0;a=v,v=v+32|0,h=a+16|0,s=a+8|0,E=a,yl(s),n=jo(n)|0,r=p[r>>0]|0,t[E>>2]=t[o>>2],t[h>>2]=t[E>>2],TL(e,n,r,h),gl(s),v=a}function TL(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0,h=0,E=0;a=v,v=v+16|0,s=a+4|0,E=a,h=ho(CL()|0)|0,r=w2(r)|0,t[E>>2]=t[o>>2],t[s>>2]=t[E>>2],_y(e,F0(0,h|0,n|0,r|0,Qc(s)|0)|0),v=a}function CL(){var e=0;return p[8e3]|0||(xL(10756),e=8e3,t[e>>2]=1,t[e+4>>2]=0),10756}function _y(e,n){e=e|0,n=n|0,xa(e,n)}function xL(e){e=e|0,tu(e,RL()|0,2)}function RL(){return 1772}function AL(e,n,r,o,a){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0;var s=0,h=0,E=0,D=0,k=0;s=v,v=v+32|0,D=s+16|0,k=s+12|0,h=s,E=ho(kL()|0)|0,r=w2(r)|0,t[k>>2]=t[o>>2],t[D>>2]=t[k>>2],o=Qc(D)|0,t[h>>2]=t[a>>2],D=a+4|0,t[h+4>>2]=t[D>>2],k=a+8|0,t[h+8>>2]=t[k>>2],t[k>>2]=0,t[D>>2]=0,t[a>>2]=0,_y(e,mn(0,E|0,n|0,r|0,o|0,jE(h)|0)|0),ef(h),v=s}function kL(){var e=0;return p[8008]|0||(OL(10768),e=8008,t[e>>2]=1,t[e+4>>2]=0),10768}function OL(e){e=e|0,tu(e,ML()|0,3)}function ML(){return 1784}function NL(e,n,r,o,a){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0;var s=0,h=0,E=0,D=0;s=v,v=v+16|0,E=s+4|0,D=s,h=ho(FL()|0)|0,r=w2(r)|0,t[D>>2]=t[o>>2],t[E>>2]=t[D>>2],o=Qc(E)|0,_y(e,mn(0,h|0,n|0,r|0,o|0,UE(a)|0)|0),v=s}function FL(){var e=0;return p[8016]|0||(LL(10780),e=8016,t[e>>2]=1,t[e+4>>2]=0),10780}function LL(e){e=e|0,tu(e,bL()|0,3)}function bL(){return 1800}function PL(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;o=ho(IL()|0)|0,_y(e,ni(0,o|0,n|0,w2(r)|0)|0)}function IL(){var e=0;return p[8024]|0||(BL(10792),e=8024,t[e>>2]=1,t[e+4>>2]=0),10792}function BL(e){e=e|0,tu(e,UL()|0,1)}function UL(){return 1816}function jL(){zL(),qL(),HL()}function zL(){t[2702]=nS(65536)|0}function qL(){fb(10856)}function HL(){WL(10816)}function WL(e){e=e|0,VL(e,5044),YL(e)|0}function VL(e,n){e=e|0,n=n|0;var r=0;r=gw()|0,t[e>>2]=r,ib(r,n),Jf(t[e>>2]|0)}function YL(e){e=e|0;var n=0;return n=t[e>>2]|0,Kc(n,KL()|0),e|0}function KL(){var e=0;return p[8032]|0||(kw(10820),xt(64,10820,le|0)|0,e=8032,t[e>>2]=1,t[e+4>>2]=0),Bn(10820)|0||kw(10820),10820}function kw(e){e=e|0,JL(e),Xc(e,25)}function XL(e){e=e|0,QL(e+24|0)}function QL(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function JL(e){e=e|0;var n=0;n=tr()|0,gn(e,5,18,n,tb()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function ZL(e,n){e=e|0,n=n|0,$L(e,n)}function $L(e,n){e=e|0,n=n|0;var r=0,o=0,a=0;r=v,v=v+16|0,o=r,a=r+4|0,zs(a,n),t[o>>2]=qs(a,n)|0,eb(e,o),v=r}function eb(e,n){e=e|0,n=n|0,Ow(e+4|0,t[n>>2]|0),p[e+8>>0]=1}function Ow(e,n){e=e|0,n=n|0,t[e>>2]=n}function tb(){return 1824}function nb(e){return e=e|0,rb(e)|0}function rb(e){e=e|0;var n=0,r=0,o=0,a=0,s=0,h=0,E=0;return r=v,v=v+16|0,a=r+4|0,h=r,o=ml(8)|0,n=o,E=Bt(4)|0,zs(a,e),Ow(E,qs(a,e)|0),s=n+4|0,t[s>>2]=E,e=Bt(8)|0,s=t[s>>2]|0,t[h>>2]=0,t[a>>2]=t[h>>2],_w(e,s,a),t[o>>2]=e,v=r,n|0}function ml(e){e=e|0;var n=0,r=0;return e=e+7&-8,e>>>0<=32768&&(n=t[2701]|0,e>>>0<=(65536-n|0)>>>0)?(r=(t[2702]|0)+n|0,t[2701]=n+e,e=r):(e=nS(e+8|0)|0,t[e>>2]=t[2703],t[2703]=e,e=e+8|0),e|0}function ib(e,n){e=e|0,n=n|0,t[e>>2]=ob()|0,t[e+4>>2]=ub()|0,t[e+12>>2]=n,t[e+8>>2]=lb()|0,t[e+32>>2]=9}function ob(){return 11744}function ub(){return 1832}function lb(){return my()|0}function ab(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(qo(o,896)|0)==512?r|0&&(sb(r),$e(r)):n|0&&$e(n)}function sb(e){e=e|0,e=t[e+4>>2]|0,e|0&&Zf(e)}function fb(e){e=e|0,db(e,5052),pb(e)|0,hb(e,5058,26)|0,vb(e,5069,1)|0,mb(e,5077,10)|0,yb(e,5087,19)|0,gb(e,5094,27)|0}function db(e,n){e=e|0,n=n|0;var r=0;r=fI()|0,t[e>>2]=r,cI(r,n),Jf(t[e>>2]|0)}function pb(e){e=e|0;var n=0;return n=t[e>>2]|0,Kc(n,QP()|0),e|0}function hb(e,n,r){return e=e|0,n=n|0,r=r|0,NP(e,ar(n)|0,r,0),e|0}function vb(e,n,r){return e=e|0,n=n|0,r=r|0,yP(e,ar(n)|0,r,0),e|0}function mb(e,n,r){return e=e|0,n=n|0,r=r|0,Xb(e,ar(n)|0,r,0),e|0}function yb(e,n,r){return e=e|0,n=n|0,r=r|0,Lb(e,ar(n)|0,r,0),e|0}function Mw(e,n){e=e|0,n=n|0;var r=0,o=0;e:for(;;){for(r=t[2703]|0;;){if((r|0)==(n|0))break e;if(o=t[r>>2]|0,t[2703]=o,!r)r=o;else break}$e(r)}t[2701]=e}function gb(e,n,r){return e=e|0,n=n|0,r=r|0,_b(e,ar(n)|0,r,0),e|0}function _b(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0;s=t[e>>2]|0,a=zE()|0,e=Eb(r)|0,Nr(s,n,a,e,Db(r,o)|0,o)}function zE(){var e=0,n=0;if(p[8040]|0||(Fw(10860),xt(65,10860,le|0)|0,n=8040,t[n>>2]=1,t[n+4>>2]=0),!(Bn(10860)|0)){e=10860,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Fw(10860)}return 10860}function Eb(e){return e=e|0,e|0}function Db(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;return E=v,v=v+16|0,a=E,s=E+4|0,t[a>>2]=e,D=zE()|0,h=D+24|0,n=en(n,4)|0,t[s>>2]=n,r=D+28|0,o=t[r>>2]|0,o>>>0<(t[D+32>>2]|0)>>>0?(Nw(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(wb(h,a,s),n=t[r>>2]|0),v=E,(n-(t[h>>2]|0)>>3)+-1|0}function Nw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function wb(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0;if(E=v,v=v+32|0,a=E,s=e+4|0,h=((t[s>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=Sb(e)|0,o>>>0>>0)gr(e);else{D=t[e>>2]|0,R=(t[e+8>>2]|0)-D|0,k=R>>2,Tb(a,R>>3>>>0>>1>>>0?k>>>0>>0?h:k:o,(t[s>>2]|0)-D>>3,e+8|0),h=a+8|0,Nw(t[h>>2]|0,t[n>>2]|0,t[r>>2]|0),t[h>>2]=(t[h>>2]|0)+8,Cb(e,a),xb(a),v=E;return}}function Sb(e){return e=e|0,536870911}function Tb(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)Tn();else{a=Bt(n<<3)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<3)}function Cb(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>3)<<3)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function xb(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&$e(e)}function Fw(e){e=e|0,kb(e)}function Rb(e){e=e|0,Ab(e+24|0)}function Ab(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function kb(e){e=e|0;var n=0;n=tr()|0,gn(e,1,11,n,Ob()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Ob(){return 1840}function Mb(e,n,r){e=e|0,n=n|0,r=r|0,Fb(t[(Nb(e)|0)>>2]|0,n,r)}function Nb(e){return e=e|0,(t[(zE()|0)+24>>2]|0)+(e<<3)|0}function Fb(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0;o=v,v=v+16|0,s=o+1|0,a=o,zs(s,n),n=qs(s,n)|0,zs(a,r),r=qs(a,r)|0,nf[e&31](n,r),v=o}function Lb(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0;s=t[e>>2]|0,a=qE()|0,e=bb(r)|0,Nr(s,n,a,e,Pb(r,o)|0,o)}function qE(){var e=0,n=0;if(p[8048]|0||(bw(10896),xt(66,10896,le|0)|0,n=8048,t[n>>2]=1,t[n+4>>2]=0),!(Bn(10896)|0)){e=10896,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));bw(10896)}return 10896}function bb(e){return e=e|0,e|0}function Pb(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;return E=v,v=v+16|0,a=E,s=E+4|0,t[a>>2]=e,D=qE()|0,h=D+24|0,n=en(n,4)|0,t[s>>2]=n,r=D+28|0,o=t[r>>2]|0,o>>>0<(t[D+32>>2]|0)>>>0?(Lw(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(Ib(h,a,s),n=t[r>>2]|0),v=E,(n-(t[h>>2]|0)>>3)+-1|0}function Lw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function Ib(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0;if(E=v,v=v+32|0,a=E,s=e+4|0,h=((t[s>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=Bb(e)|0,o>>>0>>0)gr(e);else{D=t[e>>2]|0,R=(t[e+8>>2]|0)-D|0,k=R>>2,Ub(a,R>>3>>>0>>1>>>0?k>>>0>>0?h:k:o,(t[s>>2]|0)-D>>3,e+8|0),h=a+8|0,Lw(t[h>>2]|0,t[n>>2]|0,t[r>>2]|0),t[h>>2]=(t[h>>2]|0)+8,jb(e,a),zb(a),v=E;return}}function Bb(e){return e=e|0,536870911}function Ub(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)Tn();else{a=Bt(n<<3)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<3)}function jb(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>3)<<3)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function zb(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&$e(e)}function bw(e){e=e|0,Wb(e)}function qb(e){e=e|0,Hb(e+24|0)}function Hb(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function Wb(e){e=e|0;var n=0;n=tr()|0,gn(e,1,11,n,Vb()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Vb(){return 1852}function Gb(e,n){return e=e|0,n=n|0,Kb(t[(Yb(e)|0)>>2]|0,n)|0}function Yb(e){return e=e|0,(t[(qE()|0)+24>>2]|0)+(e<<3)|0}function Kb(e,n){e=e|0,n=n|0;var r=0,o=0;return r=v,v=v+16|0,o=r,zs(o,n),n=qs(o,n)|0,n=P0(e1[e&31](n)|0)|0,v=r,n|0}function Xb(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0;s=t[e>>2]|0,a=HE()|0,e=Qb(r)|0,Nr(s,n,a,e,Jb(r,o)|0,o)}function HE(){var e=0,n=0;if(p[8056]|0||(Iw(10932),xt(67,10932,le|0)|0,n=8056,t[n>>2]=1,t[n+4>>2]=0),!(Bn(10932)|0)){e=10932,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Iw(10932)}return 10932}function Qb(e){return e=e|0,e|0}function Jb(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;return E=v,v=v+16|0,a=E,s=E+4|0,t[a>>2]=e,D=HE()|0,h=D+24|0,n=en(n,4)|0,t[s>>2]=n,r=D+28|0,o=t[r>>2]|0,o>>>0<(t[D+32>>2]|0)>>>0?(Pw(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(Zb(h,a,s),n=t[r>>2]|0),v=E,(n-(t[h>>2]|0)>>3)+-1|0}function Pw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function Zb(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0;if(E=v,v=v+32|0,a=E,s=e+4|0,h=((t[s>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=$b(e)|0,o>>>0>>0)gr(e);else{D=t[e>>2]|0,R=(t[e+8>>2]|0)-D|0,k=R>>2,eP(a,R>>3>>>0>>1>>>0?k>>>0>>0?h:k:o,(t[s>>2]|0)-D>>3,e+8|0),h=a+8|0,Pw(t[h>>2]|0,t[n>>2]|0,t[r>>2]|0),t[h>>2]=(t[h>>2]|0)+8,tP(e,a),nP(a),v=E;return}}function $b(e){return e=e|0,536870911}function eP(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)Tn();else{a=Bt(n<<3)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<3)}function tP(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>3)<<3)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function nP(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&$e(e)}function Iw(e){e=e|0,oP(e)}function rP(e){e=e|0,iP(e+24|0)}function iP(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function oP(e){e=e|0;var n=0;n=tr()|0,gn(e,1,7,n,uP()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function uP(){return 1860}function lP(e,n,r){return e=e|0,n=n|0,r=r|0,sP(t[(aP(e)|0)>>2]|0,n,r)|0}function aP(e){return e=e|0,(t[(HE()|0)+24>>2]|0)+(e<<3)|0}function sP(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0;return o=v,v=v+32|0,h=o+12|0,s=o+8|0,E=o,D=o+16|0,a=o+4|0,fP(D,n),cP(E,D,n),Hl(a,r),r=Wl(a,r)|0,t[h>>2]=t[E>>2],lh[e&15](s,h,r),r=dP(s)|0,Pl(s),Vl(a),v=o,r|0}function fP(e,n){e=e|0,n=n|0}function cP(e,n,r){e=e|0,n=n|0,r=r|0,pP(e,r)}function dP(e){return e=e|0,jo(e)|0}function pP(e,n){e=e|0,n=n|0;var r=0,o=0,a=0;a=v,v=v+16|0,r=a,o=n,o&1?(hP(r,0),di(o|0,r|0)|0,vP(e,r),mP(r)):t[e>>2]=t[n>>2],v=a}function hP(e,n){e=e|0,n=n|0,k1(e,n),t[e+4>>2]=0,p[e+8>>0]=0}function vP(e,n){e=e|0,n=n|0,t[e>>2]=t[n+4>>2]}function mP(e){e=e|0,p[e+8>>0]=0}function yP(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0;s=t[e>>2]|0,a=WE()|0,e=gP(r)|0,Nr(s,n,a,e,_P(r,o)|0,o)}function WE(){var e=0,n=0;if(p[8064]|0||(Uw(10968),xt(68,10968,le|0)|0,n=8064,t[n>>2]=1,t[n+4>>2]=0),!(Bn(10968)|0)){e=10968,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Uw(10968)}return 10968}function gP(e){return e=e|0,e|0}function _P(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;return E=v,v=v+16|0,a=E,s=E+4|0,t[a>>2]=e,D=WE()|0,h=D+24|0,n=en(n,4)|0,t[s>>2]=n,r=D+28|0,o=t[r>>2]|0,o>>>0<(t[D+32>>2]|0)>>>0?(Bw(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(EP(h,a,s),n=t[r>>2]|0),v=E,(n-(t[h>>2]|0)>>3)+-1|0}function Bw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function EP(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0;if(E=v,v=v+32|0,a=E,s=e+4|0,h=((t[s>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=DP(e)|0,o>>>0>>0)gr(e);else{D=t[e>>2]|0,R=(t[e+8>>2]|0)-D|0,k=R>>2,wP(a,R>>3>>>0>>1>>>0?k>>>0>>0?h:k:o,(t[s>>2]|0)-D>>3,e+8|0),h=a+8|0,Bw(t[h>>2]|0,t[n>>2]|0,t[r>>2]|0),t[h>>2]=(t[h>>2]|0)+8,SP(e,a),TP(a),v=E;return}}function DP(e){return e=e|0,536870911}function wP(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)Tn();else{a=Bt(n<<3)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<3)}function SP(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>3)<<3)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function TP(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&$e(e)}function Uw(e){e=e|0,RP(e)}function CP(e){e=e|0,xP(e+24|0)}function xP(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function RP(e){e=e|0;var n=0;n=tr()|0,gn(e,1,1,n,AP()|0,5),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function AP(){return 1872}function kP(e,n,r,o,a,s){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0,MP(t[(OP(e)|0)>>2]|0,n,r,o,a,s)}function OP(e){return e=e|0,(t[(WE()|0)+24>>2]|0)+(e<<3)|0}function MP(e,n,r,o,a,s){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0;var h=0,E=0,D=0,k=0,R=0,F=0;h=v,v=v+32|0,E=h+16|0,D=h+12|0,k=h+8|0,R=h+4|0,F=h,Hl(E,n),n=Wl(E,n)|0,Hl(D,r),r=Wl(D,r)|0,Hl(k,o),o=Wl(k,o)|0,Hl(R,a),a=Wl(R,a)|0,Hl(F,s),s=Wl(F,s)|0,lS[e&1](n,r,o,a,s),Vl(F),Vl(R),Vl(k),Vl(D),Vl(E),v=h}function NP(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0;s=t[e>>2]|0,a=VE()|0,e=FP(r)|0,Nr(s,n,a,e,LP(r,o)|0,o)}function VE(){var e=0,n=0;if(p[8072]|0||(zw(11004),xt(69,11004,le|0)|0,n=8072,t[n>>2]=1,t[n+4>>2]=0),!(Bn(11004)|0)){e=11004,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));zw(11004)}return 11004}function FP(e){return e=e|0,e|0}function LP(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0,E=0,D=0;return E=v,v=v+16|0,a=E,s=E+4|0,t[a>>2]=e,D=VE()|0,h=D+24|0,n=en(n,4)|0,t[s>>2]=n,r=D+28|0,o=t[r>>2]|0,o>>>0<(t[D+32>>2]|0)>>>0?(jw(o,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(bP(h,a,s),n=t[r>>2]|0),v=E,(n-(t[h>>2]|0)>>3)+-1|0}function jw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function bP(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0;if(E=v,v=v+32|0,a=E,s=e+4|0,h=((t[s>>2]|0)-(t[e>>2]|0)>>3)+1|0,o=PP(e)|0,o>>>0>>0)gr(e);else{D=t[e>>2]|0,R=(t[e+8>>2]|0)-D|0,k=R>>2,IP(a,R>>3>>>0>>1>>>0?k>>>0>>0?h:k:o,(t[s>>2]|0)-D>>3,e+8|0),h=a+8|0,jw(t[h>>2]|0,t[n>>2]|0,t[r>>2]|0),t[h>>2]=(t[h>>2]|0)+8,BP(e,a),UP(a),v=E;return}}function PP(e){return e=e|0,536870911}function IP(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0;t[e+12>>2]=0,t[e+16>>2]=o;do if(n)if(n>>>0>536870911)Tn();else{a=Bt(n<<3)|0;break}else a=0;while(0);t[e>>2]=a,o=a+(r<<3)|0,t[e+8>>2]=o,t[e+4>>2]=o,t[e+12>>2]=a+(n<<3)}function BP(e,n){e=e|0,n=n|0;var r=0,o=0,a=0,s=0,h=0;o=t[e>>2]|0,h=e+4|0,s=n+4|0,a=(t[h>>2]|0)-o|0,r=(t[s>>2]|0)+(0-(a>>3)<<3)|0,t[s>>2]=r,(a|0)>0?(bn(r|0,o|0,a|0)|0,o=s,r=t[s>>2]|0):o=s,s=t[e>>2]|0,t[e>>2]=r,t[o>>2]=s,s=n+8|0,a=t[h>>2]|0,t[h>>2]=t[s>>2],t[s>>2]=a,s=e+8|0,h=n+12|0,e=t[s>>2]|0,t[s>>2]=t[h>>2],t[h>>2]=e,t[n>>2]=t[o>>2]}function UP(e){e=e|0;var n=0,r=0,o=0;n=t[e+4>>2]|0,r=e+8|0,o=t[r>>2]|0,(o|0)!=(n|0)&&(t[r>>2]=o+(~((o+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&$e(e)}function zw(e){e=e|0,qP(e)}function jP(e){e=e|0,zP(e+24|0)}function zP(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function qP(e){e=e|0;var n=0;n=tr()|0,gn(e,1,12,n,HP()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function HP(){return 1896}function WP(e,n,r){e=e|0,n=n|0,r=r|0,GP(t[(VP(e)|0)>>2]|0,n,r)}function VP(e){return e=e|0,(t[(VE()|0)+24>>2]|0)+(e<<3)|0}function GP(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0;o=v,v=v+16|0,s=o+4|0,a=o,YP(s,n),n=KP(s,n)|0,Hl(a,r),r=Wl(a,r)|0,nf[e&31](n,r),Vl(a),v=o}function YP(e,n){e=e|0,n=n|0}function KP(e,n){return e=e|0,n=n|0,XP(n)|0}function XP(e){return e=e|0,e|0}function QP(){var e=0;return p[8080]|0||(qw(11040),xt(70,11040,le|0)|0,e=8080,t[e>>2]=1,t[e+4>>2]=0),Bn(11040)|0||qw(11040),11040}function qw(e){e=e|0,$P(e),Xc(e,71)}function JP(e){e=e|0,ZP(e+24|0)}function ZP(e){e=e|0;var n=0,r=0,o=0;r=t[e>>2]|0,o=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-o|0)>>>3)<<3)),$e(r))}function $P(e){e=e|0;var n=0;n=tr()|0,gn(e,5,7,n,rI()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function eI(e){e=e|0,tI(e)}function tI(e){e=e|0,nI(e)}function nI(e){e=e|0,p[e+8>>0]=1}function rI(){return 1936}function iI(){return oI()|0}function oI(){var e=0,n=0,r=0,o=0,a=0,s=0,h=0;return n=v,v=v+16|0,a=n+4|0,h=n,r=ml(8)|0,e=r,s=e+4|0,t[s>>2]=Bt(1)|0,o=Bt(8)|0,s=t[s>>2]|0,t[h>>2]=0,t[a>>2]=t[h>>2],uI(o,s,a),t[r>>2]=o,v=n,e|0}function uI(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=Bt(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1916,t[r+12>>2]=n,t[e+4>>2]=r}function lI(e){e=e|0,C2(e),$e(e)}function aI(e){e=e|0,e=t[e+12>>2]|0,e|0&&$e(e)}function sI(e){e=e|0,$e(e)}function fI(){var e=0;return p[8088]|0||(yI(11076),xt(25,11076,le|0)|0,e=8088,t[e>>2]=1,t[e+4>>2]=0),11076}function cI(e,n){e=e|0,n=n|0,t[e>>2]=dI()|0,t[e+4>>2]=pI()|0,t[e+12>>2]=n,t[e+8>>2]=hI()|0,t[e+32>>2]=10}function dI(){return 11745}function pI(){return 1940}function hI(){return $s()|0}function vI(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,(qo(o,896)|0)==512?r|0&&(mI(r),$e(r)):n|0&&$e(n)}function mI(e){e=e|0,e=t[e+4>>2]|0,e|0&&Zf(e)}function yI(e){e=e|0,os(e)}function Oa(e,n){e=e|0,n=n|0,t[e>>2]=n}function GE(e){return e=e|0,t[e>>2]|0}function gI(e){return e=e|0,p[t[e>>2]>>0]|0}function _I(e,n){e=e|0,n=n|0;var r=0,o=0;r=v,v=v+16|0,o=r,t[o>>2]=t[e>>2],EI(n,o)|0,v=r}function EI(e,n){e=e|0,n=n|0;var r=0;return r=DI(t[e>>2]|0,n)|0,n=e+4|0,t[(t[n>>2]|0)+8>>2]=r,t[(t[n>>2]|0)+8>>2]|0}function DI(e,n){e=e|0,n=n|0;var r=0,o=0;return r=v,v=v+16|0,o=r,yl(o),e=jo(e)|0,n=wI(e,t[n>>2]|0)|0,gl(o),v=r,n|0}function yl(e){e=e|0,t[e>>2]=t[2701],t[e+4>>2]=t[2703]}function wI(e,n){e=e|0,n=n|0;var r=0;return r=ho(SI()|0)|0,ni(0,r|0,e|0,UE(n)|0)|0}function gl(e){e=e|0,Mw(t[e>>2]|0,t[e+4>>2]|0)}function SI(){var e=0;return p[8096]|0||(TI(11120),e=8096,t[e>>2]=1,t[e+4>>2]=0),11120}function TI(e){e=e|0,tu(e,CI()|0,1)}function CI(){return 1948}function xI(){RI()}function RI(){var e=0,n=0,r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0,xe=0,ce=0,ue=0;if(ce=v,v=v+16|0,R=ce+4|0,F=ce,hn(65536,10804,t[2702]|0,10812),r=dw()|0,n=t[r>>2]|0,e=t[n>>2]|0,e|0)for(o=t[r+8>>2]|0,r=t[r+4>>2]|0;bu(e|0,O[r>>0]|0|0,p[o>>0]|0),n=n+4|0,e=t[n>>2]|0,e;)o=o+1|0,r=r+1|0;if(e=pw()|0,n=t[e>>2]|0,n|0)do Ko(n|0,t[e+4>>2]|0),e=e+8|0,n=t[e>>2]|0;while((n|0)!=0);Ko(AI()|0,5167),k=E2()|0,e=t[k>>2]|0;e:do if(e|0){do kI(t[e+4>>2]|0),e=t[e>>2]|0;while((e|0)!=0);if(e=t[k>>2]|0,e|0){D=k;do{for(;a=e,e=t[e>>2]|0,a=t[a+4>>2]|0,!!(OI(a)|0);)if(t[F>>2]=D,t[R>>2]=t[F>>2],MI(k,R)|0,!e)break e;if(NI(a),D=t[D>>2]|0,n=Hw(a)|0,s=io()|0,h=v,v=v+((1*(n<<2)|0)+15&-16)|0,E=v,v=v+((1*(n<<2)|0)+15&-16)|0,n=t[(Cw(a)|0)>>2]|0,n|0)for(r=h,o=E;t[r>>2]=t[(D2(t[n+4>>2]|0)|0)>>2],t[o>>2]=t[n+8>>2],n=t[n>>2]|0,n;)r=r+4|0,o=o+4|0;ue=D2(a)|0,n=FI(a)|0,r=Hw(a)|0,o=LI(a)|0,xo(ue|0,n|0,h|0,E|0,r|0,o|0,FE(a)|0),Tr(s|0)}while((e|0)!=0)}}while(0);if(e=t[(LE()|0)>>2]|0,e|0)do ue=e+4|0,k=bE(ue)|0,a=rh(k)|0,s=th(k)|0,h=(nh(k)|0)+1|0,E=Ey(k)|0,D=Ww(ue)|0,k=Bn(k)|0,R=yy(ue)|0,F=YE(ue)|0,ro(0,a|0,s|0,h|0,E|0,D|0,k|0,R|0,F|0,KE(ue)|0),e=t[e>>2]|0;while((e|0)!=0);e=t[(E2()|0)>>2]|0;e:do if(e|0){t:for(;;){if(n=t[e+4>>2]|0,n|0&&(H=t[(D2(n)|0)>>2]|0,xe=t[(xw(n)|0)>>2]|0,xe|0)){r=xe;do{n=r+4|0,o=bE(n)|0;n:do if(o|0)switch(Bn(o)|0){case 0:break t;case 4:case 3:case 2:{E=rh(o)|0,D=th(o)|0,k=(nh(o)|0)+1|0,R=Ey(o)|0,F=Bn(o)|0,ue=yy(n)|0,ro(H|0,E|0,D|0,k|0,R|0,0,F|0,ue|0,YE(n)|0,KE(n)|0);break n}case 1:{h=rh(o)|0,E=th(o)|0,D=(nh(o)|0)+1|0,k=Ey(o)|0,R=Ww(n)|0,F=Bn(o)|0,ue=yy(n)|0,ro(H|0,h|0,E|0,D|0,k|0,R|0,F|0,ue|0,YE(n)|0,KE(n)|0);break n}case 5:{k=rh(o)|0,R=th(o)|0,F=(nh(o)|0)+1|0,ue=Ey(o)|0,ro(H|0,k|0,R|0,F|0,ue|0,bI(o)|0,Bn(o)|0,0,0,0);break n}default:break n}while(0);r=t[r>>2]|0}while((r|0)!=0)}if(e=t[e>>2]|0,!e)break e}Tn()}while(0);xl(),v=ce}function AI(){return 11703}function kI(e){e=e|0,p[e+40>>0]=0}function OI(e){return e=e|0,(p[e+40>>0]|0)!=0|0}function MI(e,n){return e=e|0,n=n|0,n=PI(n)|0,e=t[n>>2]|0,t[n>>2]=t[e>>2],$e(e),t[n>>2]|0}function NI(e){e=e|0,p[e+40>>0]=1}function Hw(e){return e=e|0,t[e+20>>2]|0}function FI(e){return e=e|0,t[e+8>>2]|0}function LI(e){return e=e|0,t[e+32>>2]|0}function Ey(e){return e=e|0,t[e+4>>2]|0}function Ww(e){return e=e|0,t[e+4>>2]|0}function YE(e){return e=e|0,t[e+8>>2]|0}function KE(e){return e=e|0,t[e+16>>2]|0}function bI(e){return e=e|0,t[e+20>>2]|0}function PI(e){return e=e|0,t[e>>2]|0}function Dy(e){e=e|0;var n=0,r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0,xe=0,ce=0,ue=0,Be=0,be=0,Ve=0,me=0,Ce=0,At=0;At=v,v=v+16|0,H=At;do if(e>>>0<245){if(k=e>>>0<11?16:e+11&-8,e=k>>>3,F=t[2783]|0,r=F>>>e,r&3|0)return n=(r&1^1)+e|0,e=11172+(n<<1<<2)|0,r=e+8|0,o=t[r>>2]|0,a=o+8|0,s=t[a>>2]|0,(e|0)==(s|0)?t[2783]=F&~(1<>2]=e,t[r>>2]=s),Ce=n<<3,t[o+4>>2]=Ce|3,Ce=o+Ce+4|0,t[Ce>>2]=t[Ce>>2]|1,Ce=a,v=At,Ce|0;if(R=t[2785]|0,k>>>0>R>>>0){if(r|0)return n=2<>>12&16,n=n>>>h,r=n>>>5&8,n=n>>>r,a=n>>>2&4,n=n>>>a,e=n>>>1&2,n=n>>>e,o=n>>>1&1,o=(r|h|a|e|o)+(n>>>o)|0,n=11172+(o<<1<<2)|0,e=n+8|0,a=t[e>>2]|0,h=a+8|0,r=t[h>>2]|0,(n|0)==(r|0)?(e=F&~(1<>2]=n,t[e>>2]=r,e=F),s=(o<<3)-k|0,t[a+4>>2]=k|3,o=a+k|0,t[o+4>>2]=s|1,t[o+s>>2]=s,R|0&&(a=t[2788]|0,n=R>>>3,r=11172+(n<<1<<2)|0,n=1<>2]|0):(t[2783]=e|n,n=r,e=r+8|0),t[e>>2]=a,t[n+12>>2]=a,t[a+8>>2]=n,t[a+12>>2]=r),t[2785]=s,t[2788]=o,Ce=h,v=At,Ce|0;if(E=t[2784]|0,E){if(r=(E&0-E)+-1|0,h=r>>>12&16,r=r>>>h,s=r>>>5&8,r=r>>>s,D=r>>>2&4,r=r>>>D,o=r>>>1&2,r=r>>>o,e=r>>>1&1,e=t[11436+((s|h|D|o|e)+(r>>>e)<<2)>>2]|0,r=(t[e+4>>2]&-8)-k|0,o=t[e+16+(((t[e+16>>2]|0)==0&1)<<2)>>2]|0,!o)D=e,s=r;else{do h=(t[o+4>>2]&-8)-k|0,D=h>>>0>>0,r=D?h:r,e=D?o:e,o=t[o+16+(((t[o+16>>2]|0)==0&1)<<2)>>2]|0;while((o|0)!=0);D=e,s=r}if(h=D+k|0,D>>>0>>0){a=t[D+24>>2]|0,n=t[D+12>>2]|0;do if((n|0)==(D|0)){if(e=D+20|0,n=t[e>>2]|0,!n&&(e=D+16|0,n=t[e>>2]|0,!n)){r=0;break}for(;;){if(r=n+20|0,o=t[r>>2]|0,o|0){n=o,e=r;continue}if(r=n+16|0,o=t[r>>2]|0,o)n=o,e=r;else break}t[e>>2]=0,r=n}else r=t[D+8>>2]|0,t[r+12>>2]=n,t[n+8>>2]=r,r=n;while(0);do if(a|0){if(n=t[D+28>>2]|0,e=11436+(n<<2)|0,(D|0)==(t[e>>2]|0)){if(t[e>>2]=r,!r){t[2784]=E&~(1<>2]|0)!=(D|0)&1)<<2)>>2]=r,!r)break;t[r+24>>2]=a,n=t[D+16>>2]|0,n|0&&(t[r+16>>2]=n,t[n+24>>2]=r),n=t[D+20>>2]|0,n|0&&(t[r+20>>2]=n,t[n+24>>2]=r)}while(0);return s>>>0<16?(Ce=s+k|0,t[D+4>>2]=Ce|3,Ce=D+Ce+4|0,t[Ce>>2]=t[Ce>>2]|1):(t[D+4>>2]=k|3,t[h+4>>2]=s|1,t[h+s>>2]=s,R|0&&(o=t[2788]|0,n=R>>>3,r=11172+(n<<1<<2)|0,n=1<>2]|0):(t[2783]=F|n,n=r,e=r+8|0),t[e>>2]=o,t[n+12>>2]=o,t[o+8>>2]=n,t[o+12>>2]=r),t[2785]=s,t[2788]=h),Ce=D+8|0,v=At,Ce|0}else F=k}else F=k}else F=k}else if(e>>>0<=4294967231)if(e=e+11|0,k=e&-8,D=t[2784]|0,D){o=0-k|0,e=e>>>8,e?k>>>0>16777215?E=31:(F=(e+1048320|0)>>>16&8,me=e<>>16&4,me=me<>>16&2,E=14-(R|F|E)+(me<>>15)|0,E=k>>>(E+7|0)&1|E<<1):E=0,r=t[11436+(E<<2)>>2]|0;e:do if(!r)r=0,e=0,me=57;else for(e=0,h=k<<((E|0)==31?0:25-(E>>>1)|0),s=0;;){if(a=(t[r+4>>2]&-8)-k|0,a>>>0>>0)if(a)e=r,o=a;else{e=r,o=0,a=r,me=61;break e}if(a=t[r+20>>2]|0,r=t[r+16+(h>>>31<<2)>>2]|0,s=(a|0)==0|(a|0)==(r|0)?s:a,a=(r|0)==0,a){r=s,me=57;break}else h=h<<((a^1)&1)}while(0);if((me|0)==57){if((r|0)==0&(e|0)==0){if(e=2<>>12&16,F=F>>>h,s=F>>>5&8,F=F>>>s,E=F>>>2&4,F=F>>>E,R=F>>>1&2,F=F>>>R,r=F>>>1&1,e=0,r=t[11436+((s|h|E|R|r)+(F>>>r)<<2)>>2]|0}r?(a=r,me=61):(E=e,h=o)}if((me|0)==61)for(;;)if(me=0,r=(t[a+4>>2]&-8)-k|0,F=r>>>0>>0,r=F?r:o,e=F?a:e,a=t[a+16+(((t[a+16>>2]|0)==0&1)<<2)>>2]|0,a)o=r,me=61;else{E=e,h=r;break}if((E|0)!=0&&h>>>0<((t[2785]|0)-k|0)>>>0){if(s=E+k|0,E>>>0>=s>>>0)return Ce=0,v=At,Ce|0;a=t[E+24>>2]|0,n=t[E+12>>2]|0;do if((n|0)==(E|0)){if(e=E+20|0,n=t[e>>2]|0,!n&&(e=E+16|0,n=t[e>>2]|0,!n)){n=0;break}for(;;){if(r=n+20|0,o=t[r>>2]|0,o|0){n=o,e=r;continue}if(r=n+16|0,o=t[r>>2]|0,o)n=o,e=r;else break}t[e>>2]=0}else Ce=t[E+8>>2]|0,t[Ce+12>>2]=n,t[n+8>>2]=Ce;while(0);do if(a){if(e=t[E+28>>2]|0,r=11436+(e<<2)|0,(E|0)==(t[r>>2]|0)){if(t[r>>2]=n,!n){o=D&~(1<>2]|0)!=(E|0)&1)<<2)>>2]=n,!n){o=D;break}t[n+24>>2]=a,e=t[E+16>>2]|0,e|0&&(t[n+16>>2]=e,t[e+24>>2]=n),e=t[E+20>>2]|0,e&&(t[n+20>>2]=e,t[e+24>>2]=n),o=D}else o=D;while(0);do if(h>>>0>=16){if(t[E+4>>2]=k|3,t[s+4>>2]=h|1,t[s+h>>2]=h,n=h>>>3,h>>>0<256){r=11172+(n<<1<<2)|0,e=t[2783]|0,n=1<>2]|0):(t[2783]=e|n,n=r,e=r+8|0),t[e>>2]=s,t[n+12>>2]=s,t[s+8>>2]=n,t[s+12>>2]=r;break}if(n=h>>>8,n?h>>>0>16777215?n=31:(me=(n+1048320|0)>>>16&8,Ce=n<>>16&4,Ce=Ce<>>16&2,n=14-(Ve|me|n)+(Ce<>>15)|0,n=h>>>(n+7|0)&1|n<<1):n=0,r=11436+(n<<2)|0,t[s+28>>2]=n,e=s+16|0,t[e+4>>2]=0,t[e>>2]=0,e=1<>2]=s,t[s+24>>2]=r,t[s+12>>2]=s,t[s+8>>2]=s;break}for(e=h<<((n|0)==31?0:25-(n>>>1)|0),r=t[r>>2]|0;;){if((t[r+4>>2]&-8|0)==(h|0)){me=97;break}if(o=r+16+(e>>>31<<2)|0,n=t[o>>2]|0,n)e=e<<1,r=n;else{me=96;break}}if((me|0)==96){t[o>>2]=s,t[s+24>>2]=r,t[s+12>>2]=s,t[s+8>>2]=s;break}else if((me|0)==97){me=r+8|0,Ce=t[me>>2]|0,t[Ce+12>>2]=s,t[me>>2]=s,t[s+8>>2]=Ce,t[s+12>>2]=r,t[s+24>>2]=0;break}}else Ce=h+k|0,t[E+4>>2]=Ce|3,Ce=E+Ce+4|0,t[Ce>>2]=t[Ce>>2]|1;while(0);return Ce=E+8|0,v=At,Ce|0}else F=k}else F=k;else F=-1;while(0);if(r=t[2785]|0,r>>>0>=F>>>0)return n=r-F|0,e=t[2788]|0,n>>>0>15?(Ce=e+F|0,t[2788]=Ce,t[2785]=n,t[Ce+4>>2]=n|1,t[Ce+n>>2]=n,t[e+4>>2]=F|3):(t[2785]=0,t[2788]=0,t[e+4>>2]=r|3,Ce=e+r+4|0,t[Ce>>2]=t[Ce>>2]|1),Ce=e+8|0,v=At,Ce|0;if(h=t[2786]|0,h>>>0>F>>>0)return Ve=h-F|0,t[2786]=Ve,Ce=t[2789]|0,me=Ce+F|0,t[2789]=me,t[me+4>>2]=Ve|1,t[Ce+4>>2]=F|3,Ce=Ce+8|0,v=At,Ce|0;if(t[2901]|0?e=t[2903]|0:(t[2903]=4096,t[2902]=4096,t[2904]=-1,t[2905]=-1,t[2906]=0,t[2894]=0,e=H&-16^1431655768,t[H>>2]=e,t[2901]=e,e=4096),E=F+48|0,D=F+47|0,s=e+D|0,a=0-e|0,k=s&a,k>>>0<=F>>>0||(e=t[2893]|0,e|0&&(R=t[2891]|0,H=R+k|0,H>>>0<=R>>>0|H>>>0>e>>>0)))return Ce=0,v=At,Ce|0;e:do if(t[2894]&4)n=0,me=133;else{r=t[2789]|0;t:do if(r){for(o=11580;e=t[o>>2]|0,!(e>>>0<=r>>>0&&(ue=o+4|0,(e+(t[ue>>2]|0)|0)>>>0>r>>>0));)if(e=t[o+8>>2]|0,e)o=e;else{me=118;break t}if(n=s-h&a,n>>>0<2147483647)if(e=$f(n|0)|0,(e|0)==((t[o>>2]|0)+(t[ue>>2]|0)|0)){if((e|0)!=-1){h=n,s=e,me=135;break e}}else o=e,me=126;else n=0}else me=118;while(0);do if((me|0)==118)if(r=$f(0)|0,(r|0)!=-1&&(n=r,xe=t[2902]|0,ce=xe+-1|0,n=((ce&n|0)==0?0:(ce+n&0-xe)-n|0)+k|0,xe=t[2891]|0,ce=n+xe|0,n>>>0>F>>>0&n>>>0<2147483647)){if(ue=t[2893]|0,ue|0&&ce>>>0<=xe>>>0|ce>>>0>ue>>>0){n=0;break}if(e=$f(n|0)|0,(e|0)==(r|0)){h=n,s=r,me=135;break e}else o=e,me=126}else n=0;while(0);do if((me|0)==126){if(r=0-n|0,!(E>>>0>n>>>0&(n>>>0<2147483647&(o|0)!=-1)))if((o|0)==-1){n=0;break}else{h=n,s=o,me=135;break e}if(e=t[2903]|0,e=D-n+e&0-e,e>>>0>=2147483647){h=n,s=o,me=135;break e}if(($f(e|0)|0)==-1){$f(r|0)|0,n=0;break}else{h=e+n|0,s=o,me=135;break e}}while(0);t[2894]=t[2894]|4,me=133}while(0);if((me|0)==133&&k>>>0<2147483647&&(Ve=$f(k|0)|0,ue=$f(0)|0,Be=ue-Ve|0,be=Be>>>0>(F+40|0)>>>0,!((Ve|0)==-1|be^1|Ve>>>0>>0&((Ve|0)!=-1&(ue|0)!=-1)^1))&&(h=be?Be:n,s=Ve,me=135),(me|0)==135){n=(t[2891]|0)+h|0,t[2891]=n,n>>>0>(t[2892]|0)>>>0&&(t[2892]=n),D=t[2789]|0;do if(D){for(n=11580;;){if(e=t[n>>2]|0,r=n+4|0,o=t[r>>2]|0,(s|0)==(e+o|0)){me=145;break}if(a=t[n+8>>2]|0,a)n=a;else break}if((me|0)==145&&(t[n+12>>2]&8|0)==0&&D>>>0>>0&D>>>0>=e>>>0){t[r>>2]=o+h,Ce=D+8|0,Ce=(Ce&7|0)==0?0:0-Ce&7,me=D+Ce|0,Ce=(t[2786]|0)+(h-Ce)|0,t[2789]=me,t[2786]=Ce,t[me+4>>2]=Ce|1,t[me+Ce+4>>2]=40,t[2790]=t[2905];break}for(s>>>0<(t[2787]|0)>>>0&&(t[2787]=s),r=s+h|0,n=11580;;){if((t[n>>2]|0)==(r|0)){me=153;break}if(e=t[n+8>>2]|0,e)n=e;else break}if((me|0)==153&&(t[n+12>>2]&8|0)==0){t[n>>2]=s,R=n+4|0,t[R>>2]=(t[R>>2]|0)+h,R=s+8|0,R=s+((R&7|0)==0?0:0-R&7)|0,n=r+8|0,n=r+((n&7|0)==0?0:0-n&7)|0,k=R+F|0,E=n-R-F|0,t[R+4>>2]=F|3;do if((n|0)!=(D|0)){if((n|0)==(t[2788]|0)){Ce=(t[2785]|0)+E|0,t[2785]=Ce,t[2788]=k,t[k+4>>2]=Ce|1,t[k+Ce>>2]=Ce;break}if(e=t[n+4>>2]|0,(e&3|0)==1){h=e&-8,o=e>>>3;e:do if(e>>>0<256)if(e=t[n+8>>2]|0,r=t[n+12>>2]|0,(r|0)==(e|0)){t[2783]=t[2783]&~(1<>2]=r,t[r+8>>2]=e;break}else{s=t[n+24>>2]|0,e=t[n+12>>2]|0;do if((e|0)==(n|0)){if(o=n+16|0,r=o+4|0,e=t[r>>2]|0,!e)if(e=t[o>>2]|0,e)r=o;else{e=0;break}for(;;){if(o=e+20|0,a=t[o>>2]|0,a|0){e=a,r=o;continue}if(o=e+16|0,a=t[o>>2]|0,a)e=a,r=o;else break}t[r>>2]=0}else Ce=t[n+8>>2]|0,t[Ce+12>>2]=e,t[e+8>>2]=Ce;while(0);if(!s)break;r=t[n+28>>2]|0,o=11436+(r<<2)|0;do if((n|0)!=(t[o>>2]|0)){if(t[s+16+(((t[s+16>>2]|0)!=(n|0)&1)<<2)>>2]=e,!e)break e}else{if(t[o>>2]=e,e|0)break;t[2784]=t[2784]&~(1<>2]=s,r=n+16|0,o=t[r>>2]|0,o|0&&(t[e+16>>2]=o,t[o+24>>2]=e),r=t[r+4>>2]|0,!r)break;t[e+20>>2]=r,t[r+24>>2]=e}while(0);n=n+h|0,a=h+E|0}else a=E;if(n=n+4|0,t[n>>2]=t[n>>2]&-2,t[k+4>>2]=a|1,t[k+a>>2]=a,n=a>>>3,a>>>0<256){r=11172+(n<<1<<2)|0,e=t[2783]|0,n=1<>2]|0):(t[2783]=e|n,n=r,e=r+8|0),t[e>>2]=k,t[n+12>>2]=k,t[k+8>>2]=n,t[k+12>>2]=r;break}n=a>>>8;do if(!n)n=0;else{if(a>>>0>16777215){n=31;break}me=(n+1048320|0)>>>16&8,Ce=n<>>16&4,Ce=Ce<>>16&2,n=14-(Ve|me|n)+(Ce<>>15)|0,n=a>>>(n+7|0)&1|n<<1}while(0);if(o=11436+(n<<2)|0,t[k+28>>2]=n,e=k+16|0,t[e+4>>2]=0,t[e>>2]=0,e=t[2784]|0,r=1<>2]=k,t[k+24>>2]=o,t[k+12>>2]=k,t[k+8>>2]=k;break}for(e=a<<((n|0)==31?0:25-(n>>>1)|0),r=t[o>>2]|0;;){if((t[r+4>>2]&-8|0)==(a|0)){me=194;break}if(o=r+16+(e>>>31<<2)|0,n=t[o>>2]|0,n)e=e<<1,r=n;else{me=193;break}}if((me|0)==193){t[o>>2]=k,t[k+24>>2]=r,t[k+12>>2]=k,t[k+8>>2]=k;break}else if((me|0)==194){me=r+8|0,Ce=t[me>>2]|0,t[Ce+12>>2]=k,t[me>>2]=k,t[k+8>>2]=Ce,t[k+12>>2]=r,t[k+24>>2]=0;break}}else Ce=(t[2786]|0)+E|0,t[2786]=Ce,t[2789]=k,t[k+4>>2]=Ce|1;while(0);return Ce=R+8|0,v=At,Ce|0}for(n=11580;e=t[n>>2]|0,!(e>>>0<=D>>>0&&(Ce=e+(t[n+4>>2]|0)|0,Ce>>>0>D>>>0));)n=t[n+8>>2]|0;a=Ce+-47|0,e=a+8|0,e=a+((e&7|0)==0?0:0-e&7)|0,a=D+16|0,e=e>>>0>>0?D:e,n=e+8|0,r=s+8|0,r=(r&7|0)==0?0:0-r&7,me=s+r|0,r=h+-40-r|0,t[2789]=me,t[2786]=r,t[me+4>>2]=r|1,t[me+r+4>>2]=40,t[2790]=t[2905],r=e+4|0,t[r>>2]=27,t[n>>2]=t[2895],t[n+4>>2]=t[2896],t[n+8>>2]=t[2897],t[n+12>>2]=t[2898],t[2895]=s,t[2896]=h,t[2898]=0,t[2897]=n,n=e+24|0;do me=n,n=n+4|0,t[n>>2]=7;while((me+8|0)>>>0>>0);if((e|0)!=(D|0)){if(s=e-D|0,t[r>>2]=t[r>>2]&-2,t[D+4>>2]=s|1,t[e>>2]=s,n=s>>>3,s>>>0<256){r=11172+(n<<1<<2)|0,e=t[2783]|0,n=1<>2]|0):(t[2783]=e|n,n=r,e=r+8|0),t[e>>2]=D,t[n+12>>2]=D,t[D+8>>2]=n,t[D+12>>2]=r;break}if(n=s>>>8,n?s>>>0>16777215?r=31:(me=(n+1048320|0)>>>16&8,Ce=n<>>16&4,Ce=Ce<>>16&2,r=14-(Ve|me|r)+(Ce<>>15)|0,r=s>>>(r+7|0)&1|r<<1):r=0,o=11436+(r<<2)|0,t[D+28>>2]=r,t[D+20>>2]=0,t[a>>2]=0,n=t[2784]|0,e=1<>2]=D,t[D+24>>2]=o,t[D+12>>2]=D,t[D+8>>2]=D;break}for(e=s<<((r|0)==31?0:25-(r>>>1)|0),r=t[o>>2]|0;;){if((t[r+4>>2]&-8|0)==(s|0)){me=216;break}if(o=r+16+(e>>>31<<2)|0,n=t[o>>2]|0,n)e=e<<1,r=n;else{me=215;break}}if((me|0)==215){t[o>>2]=D,t[D+24>>2]=r,t[D+12>>2]=D,t[D+8>>2]=D;break}else if((me|0)==216){me=r+8|0,Ce=t[me>>2]|0,t[Ce+12>>2]=D,t[me>>2]=D,t[D+8>>2]=Ce,t[D+12>>2]=r,t[D+24>>2]=0;break}}}else{Ce=t[2787]|0,(Ce|0)==0|s>>>0>>0&&(t[2787]=s),t[2895]=s,t[2896]=h,t[2898]=0,t[2792]=t[2901],t[2791]=-1,n=0;do Ce=11172+(n<<1<<2)|0,t[Ce+12>>2]=Ce,t[Ce+8>>2]=Ce,n=n+1|0;while((n|0)!=32);Ce=s+8|0,Ce=(Ce&7|0)==0?0:0-Ce&7,me=s+Ce|0,Ce=h+-40-Ce|0,t[2789]=me,t[2786]=Ce,t[me+4>>2]=Ce|1,t[me+Ce+4>>2]=40,t[2790]=t[2905]}while(0);if(n=t[2786]|0,n>>>0>F>>>0)return Ve=n-F|0,t[2786]=Ve,Ce=t[2789]|0,me=Ce+F|0,t[2789]=me,t[me+4>>2]=Ve|1,t[Ce+4>>2]=F|3,Ce=Ce+8|0,v=At,Ce|0}return t[(S2()|0)>>2]=12,Ce=0,v=At,Ce|0}function wy(e){e=e|0;var n=0,r=0,o=0,a=0,s=0,h=0,E=0,D=0;if(!!e){r=e+-8|0,a=t[2787]|0,e=t[e+-4>>2]|0,n=e&-8,D=r+n|0;do if(e&1)E=r,h=r;else{if(o=t[r>>2]|0,!(e&3)||(h=r+(0-o)|0,s=o+n|0,h>>>0>>0))return;if((h|0)==(t[2788]|0)){if(e=D+4|0,n=t[e>>2]|0,(n&3|0)!=3){E=h,n=s;break}t[2785]=s,t[e>>2]=n&-2,t[h+4>>2]=s|1,t[h+s>>2]=s;return}if(r=o>>>3,o>>>0<256)if(e=t[h+8>>2]|0,n=t[h+12>>2]|0,(n|0)==(e|0)){t[2783]=t[2783]&~(1<>2]=n,t[n+8>>2]=e,E=h,n=s;break}a=t[h+24>>2]|0,e=t[h+12>>2]|0;do if((e|0)==(h|0)){if(r=h+16|0,n=r+4|0,e=t[n>>2]|0,!e)if(e=t[r>>2]|0,e)n=r;else{e=0;break}for(;;){if(r=e+20|0,o=t[r>>2]|0,o|0){e=o,n=r;continue}if(r=e+16|0,o=t[r>>2]|0,o)e=o,n=r;else break}t[n>>2]=0}else E=t[h+8>>2]|0,t[E+12>>2]=e,t[e+8>>2]=E;while(0);if(a){if(n=t[h+28>>2]|0,r=11436+(n<<2)|0,(h|0)==(t[r>>2]|0)){if(t[r>>2]=e,!e){t[2784]=t[2784]&~(1<>2]|0)!=(h|0)&1)<<2)>>2]=e,!e){E=h,n=s;break}t[e+24>>2]=a,n=h+16|0,r=t[n>>2]|0,r|0&&(t[e+16>>2]=r,t[r+24>>2]=e),n=t[n+4>>2]|0,n?(t[e+20>>2]=n,t[n+24>>2]=e,E=h,n=s):(E=h,n=s)}else E=h,n=s}while(0);if(!(h>>>0>=D>>>0)&&(e=D+4|0,o=t[e>>2]|0,!!(o&1))){if(o&2)t[e>>2]=o&-2,t[E+4>>2]=n|1,t[h+n>>2]=n,a=n;else{if(e=t[2788]|0,(D|0)==(t[2789]|0)){if(D=(t[2786]|0)+n|0,t[2786]=D,t[2789]=E,t[E+4>>2]=D|1,(E|0)!=(e|0))return;t[2788]=0,t[2785]=0;return}if((D|0)==(e|0)){D=(t[2785]|0)+n|0,t[2785]=D,t[2788]=h,t[E+4>>2]=D|1,t[h+D>>2]=D;return}a=(o&-8)+n|0,r=o>>>3;do if(o>>>0<256)if(n=t[D+8>>2]|0,e=t[D+12>>2]|0,(e|0)==(n|0)){t[2783]=t[2783]&~(1<>2]=e,t[e+8>>2]=n;break}else{s=t[D+24>>2]|0,e=t[D+12>>2]|0;do if((e|0)==(D|0)){if(r=D+16|0,n=r+4|0,e=t[n>>2]|0,!e)if(e=t[r>>2]|0,e)n=r;else{r=0;break}for(;;){if(r=e+20|0,o=t[r>>2]|0,o|0){e=o,n=r;continue}if(r=e+16|0,o=t[r>>2]|0,o)e=o,n=r;else break}t[n>>2]=0,r=e}else r=t[D+8>>2]|0,t[r+12>>2]=e,t[e+8>>2]=r,r=e;while(0);if(s|0){if(e=t[D+28>>2]|0,n=11436+(e<<2)|0,(D|0)==(t[n>>2]|0)){if(t[n>>2]=r,!r){t[2784]=t[2784]&~(1<>2]|0)!=(D|0)&1)<<2)>>2]=r,!r)break;t[r+24>>2]=s,e=D+16|0,n=t[e>>2]|0,n|0&&(t[r+16>>2]=n,t[n+24>>2]=r),e=t[e+4>>2]|0,e|0&&(t[r+20>>2]=e,t[e+24>>2]=r)}}while(0);if(t[E+4>>2]=a|1,t[h+a>>2]=a,(E|0)==(t[2788]|0)){t[2785]=a;return}}if(e=a>>>3,a>>>0<256){r=11172+(e<<1<<2)|0,n=t[2783]|0,e=1<>2]|0):(t[2783]=n|e,e=r,n=r+8|0),t[n>>2]=E,t[e+12>>2]=E,t[E+8>>2]=e,t[E+12>>2]=r;return}e=a>>>8,e?a>>>0>16777215?e=31:(h=(e+1048320|0)>>>16&8,D=e<>>16&4,D=D<>>16&2,e=14-(s|h|e)+(D<>>15)|0,e=a>>>(e+7|0)&1|e<<1):e=0,o=11436+(e<<2)|0,t[E+28>>2]=e,t[E+20>>2]=0,t[E+16>>2]=0,n=t[2784]|0,r=1<>>1)|0),r=t[o>>2]|0;;){if((t[r+4>>2]&-8|0)==(a|0)){e=73;break}if(o=r+16+(n>>>31<<2)|0,e=t[o>>2]|0,e)n=n<<1,r=e;else{e=72;break}}if((e|0)==72){t[o>>2]=E,t[E+24>>2]=r,t[E+12>>2]=E,t[E+8>>2]=E;break}else if((e|0)==73){h=r+8|0,D=t[h>>2]|0,t[D+12>>2]=E,t[h>>2]=E,t[E+8>>2]=D,t[E+12>>2]=r,t[E+24>>2]=0;break}}else t[2784]=n|r,t[o>>2]=E,t[E+24>>2]=o,t[E+12>>2]=E,t[E+8>>2]=E;while(0);if(D=(t[2791]|0)+-1|0,t[2791]=D,!D)e=11588;else return;for(;e=t[e>>2]|0,e;)e=e+8|0;t[2791]=-1}}}function II(){return 11628}function BI(e){e=e|0;var n=0,r=0;return n=v,v=v+16|0,r=n,t[r>>2]=zI(t[e+60>>2]|0)|0,e=Sy(bi(6,r|0)|0)|0,v=n,e|0}function Vw(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0,xe=0;F=v,v=v+48|0,k=F+16|0,s=F,a=F+32|0,E=e+28|0,o=t[E>>2]|0,t[a>>2]=o,D=e+20|0,o=(t[D>>2]|0)-o|0,t[a+4>>2]=o,t[a+8>>2]=n,t[a+12>>2]=r,o=o+r|0,h=e+60|0,t[s>>2]=t[h>>2],t[s+4>>2]=a,t[s+8>>2]=2,s=Sy(T0(146,s|0)|0)|0;e:do if((o|0)!=(s|0)){for(n=2;!((s|0)<0);)if(o=o-s|0,xe=t[a+4>>2]|0,H=s>>>0>xe>>>0,a=H?a+8|0:a,n=(H<<31>>31)+n|0,xe=s-(H?xe:0)|0,t[a>>2]=(t[a>>2]|0)+xe,H=a+4|0,t[H>>2]=(t[H>>2]|0)-xe,t[k>>2]=t[h>>2],t[k+4>>2]=a,t[k+8>>2]=n,s=Sy(T0(146,k|0)|0)|0,(o|0)==(s|0)){R=3;break e}t[e+16>>2]=0,t[E>>2]=0,t[D>>2]=0,t[e>>2]=t[e>>2]|32,(n|0)==2?r=0:r=r-(t[a+4>>2]|0)|0}else R=3;while(0);return(R|0)==3&&(xe=t[e+44>>2]|0,t[e+16>>2]=xe+(t[e+48>>2]|0),t[E>>2]=xe,t[D>>2]=xe),v=F,r|0}function UI(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0;return a=v,v=v+32|0,s=a,o=a+20|0,t[s>>2]=t[e+60>>2],t[s+4>>2]=0,t[s+8>>2]=n,t[s+12>>2]=o,t[s+16>>2]=r,(Sy(Xr(140,s|0)|0)|0)<0?(t[o>>2]=-1,e=-1):e=t[o>>2]|0,v=a,e|0}function Sy(e){return e=e|0,e>>>0>4294963200&&(t[(S2()|0)>>2]=0-e,e=-1),e|0}function S2(){return(jI()|0)+64|0}function jI(){return XE()|0}function XE(){return 2084}function zI(e){return e=e|0,e|0}function qI(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0;return a=v,v=v+32|0,o=a,t[e+36>>2]=1,(t[e>>2]&64|0)==0&&(t[o>>2]=t[e+60>>2],t[o+4>>2]=21523,t[o+8>>2]=a+16,Ro(54,o|0)|0)&&(p[e+75>>0]=-1),o=Vw(e,n,r)|0,v=a,o|0}function Gw(e,n){e=e|0,n=n|0;var r=0,o=0;if(r=p[e>>0]|0,o=p[n>>0]|0,r<<24>>24==0||r<<24>>24!=o<<24>>24)e=o;else{do e=e+1|0,n=n+1|0,r=p[e>>0]|0,o=p[n>>0]|0;while(!(r<<24>>24==0||r<<24>>24!=o<<24>>24));e=o}return(r&255)-(e&255)|0}function HI(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0;e:do if(!r)e=0;else{for(;o=p[e>>0]|0,a=p[n>>0]|0,o<<24>>24==a<<24>>24;)if(r=r+-1|0,r)e=e+1|0,n=n+1|0;else{e=0;break e}e=(o&255)-(a&255)|0}while(0);return e|0}function Yw(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0,xe=0,ce=0,ue=0;ue=v,v=v+224|0,R=ue+120|0,F=ue+80|0,xe=ue,ce=ue+136|0,o=F,a=o+40|0;do t[o>>2]=0,o=o+4|0;while((o|0)<(a|0));return t[R>>2]=t[r>>2],(QE(0,n,R,xe,F)|0)<0?r=-1:((t[e+76>>2]|0)>-1?H=WI(e)|0:H=0,r=t[e>>2]|0,k=r&32,(p[e+74>>0]|0)<1&&(t[e>>2]=r&-33),o=e+48|0,t[o>>2]|0?r=QE(e,n,R,xe,F)|0:(a=e+44|0,s=t[a>>2]|0,t[a>>2]=ce,h=e+28|0,t[h>>2]=ce,E=e+20|0,t[E>>2]=ce,t[o>>2]=80,D=e+16|0,t[D>>2]=ce+80,r=QE(e,n,R,xe,F)|0,s&&(Ry[t[e+36>>2]&7](e,0,0)|0,r=(t[E>>2]|0)==0?-1:r,t[a>>2]=s,t[o>>2]=0,t[D>>2]=0,t[h>>2]=0,t[E>>2]=0)),o=t[e>>2]|0,t[e>>2]=o|k,H|0&&VI(e),r=(o&32|0)==0?r:-1),v=ue,r|0}function QE(e,n,r,o,a){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0;var s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0,xe=0,ce=0,ue=0,Be=0,be=0,Ve=0,me=0,Ce=0,At=0,Zn=0,on=0,Yt=0,Pn=0,Qn=0,tn=0;tn=v,v=v+64|0,on=tn+16|0,Yt=tn,At=tn+24|0,Pn=tn+8|0,Qn=tn+20|0,t[on>>2]=n,Ve=(e|0)!=0,me=At+40|0,Ce=me,At=At+39|0,Zn=Pn+4|0,h=0,s=0,R=0;e:for(;;){do if((s|0)>-1)if((h|0)>(2147483647-s|0)){t[(S2()|0)>>2]=75,s=-1;break}else{s=h+s|0;break}while(0);if(h=p[n>>0]|0,h<<24>>24)E=n;else{be=87;break}t:for(;;){switch(h<<24>>24){case 37:{h=E,be=9;break t}case 0:{h=E;break t}default:}Be=E+1|0,t[on>>2]=Be,h=p[Be>>0]|0,E=Be}t:do if((be|0)==9)for(;;){if(be=0,(p[E+1>>0]|0)!=37)break t;if(h=h+1|0,E=E+2|0,t[on>>2]=E,(p[E>>0]|0)==37)be=9;else break}while(0);if(h=h-n|0,Ve&&$0(e,n,h),h|0){n=E;continue}D=E+1|0,h=(p[D>>0]|0)+-48|0,h>>>0<10?(Be=(p[E+2>>0]|0)==36,ue=Be?h:-1,R=Be?1:R,D=Be?E+3|0:D):ue=-1,t[on>>2]=D,h=p[D>>0]|0,E=(h<<24>>24)+-32|0;t:do if(E>>>0<32)for(k=0,F=h;;){if(h=1<>2]=D,h=p[D>>0]|0,E=(h<<24>>24)+-32|0,E>>>0>=32)break;F=h}else k=0;while(0);if(h<<24>>24==42){if(E=D+1|0,h=(p[E>>0]|0)+-48|0,h>>>0<10&&(p[D+2>>0]|0)==36)t[a+(h<<2)>>2]=10,h=t[o+((p[E>>0]|0)+-48<<3)>>2]|0,R=1,D=D+3|0;else{if(R|0){s=-1;break}Ve?(R=(t[r>>2]|0)+(4-1)&~(4-1),h=t[R>>2]|0,t[r>>2]=R+4,R=0,D=E):(h=0,R=0,D=E)}t[on>>2]=D,Be=(h|0)<0,h=Be?0-h|0:h,k=Be?k|8192:k}else{if(h=Kw(on)|0,(h|0)<0){s=-1;break}D=t[on>>2]|0}do if((p[D>>0]|0)==46){if((p[D+1>>0]|0)!=42){t[on>>2]=D+1,E=Kw(on)|0,D=t[on>>2]|0;break}if(F=D+2|0,E=(p[F>>0]|0)+-48|0,E>>>0<10&&(p[D+3>>0]|0)==36){t[a+(E<<2)>>2]=10,E=t[o+((p[F>>0]|0)+-48<<3)>>2]|0,D=D+4|0,t[on>>2]=D;break}if(R|0){s=-1;break e}Ve?(Be=(t[r>>2]|0)+(4-1)&~(4-1),E=t[Be>>2]|0,t[r>>2]=Be+4):E=0,t[on>>2]=F,D=F}else E=-1;while(0);for(ce=0;;){if(((p[D>>0]|0)+-65|0)>>>0>57){s=-1;break e}if(Be=D+1|0,t[on>>2]=Be,F=p[(p[D>>0]|0)+-65+(5178+(ce*58|0))>>0]|0,H=F&255,(H+-1|0)>>>0<8)ce=H,D=Be;else break}if(!(F<<24>>24)){s=-1;break}xe=(ue|0)>-1;do if(F<<24>>24==19)if(xe){s=-1;break e}else be=49;else{if(xe){t[a+(ue<<2)>>2]=H,xe=o+(ue<<3)|0,ue=t[xe+4>>2]|0,be=Yt,t[be>>2]=t[xe>>2],t[be+4>>2]=ue,be=49;break}if(!Ve){s=0;break e}Xw(Yt,H,r)}while(0);if((be|0)==49&&(be=0,!Ve)){h=0,n=Be;continue}D=p[D>>0]|0,D=(ce|0)!=0&(D&15|0)==3?D&-33:D,xe=k&-65537,ue=(k&8192|0)==0?k:xe;t:do switch(D|0){case 110:switch((ce&255)<<24>>24){case 0:{t[t[Yt>>2]>>2]=s,h=0,n=Be;continue e}case 1:{t[t[Yt>>2]>>2]=s,h=0,n=Be;continue e}case 2:{h=t[Yt>>2]|0,t[h>>2]=s,t[h+4>>2]=((s|0)<0)<<31>>31,h=0,n=Be;continue e}case 3:{_[t[Yt>>2]>>1]=s,h=0,n=Be;continue e}case 4:{p[t[Yt>>2]>>0]=s,h=0,n=Be;continue e}case 6:{t[t[Yt>>2]>>2]=s,h=0,n=Be;continue e}case 7:{h=t[Yt>>2]|0,t[h>>2]=s,t[h+4>>2]=((s|0)<0)<<31>>31,h=0,n=Be;continue e}default:{h=0,n=Be;continue e}}case 112:{D=120,E=E>>>0>8?E:8,n=ue|8,be=61;break}case 88:case 120:{n=ue,be=61;break}case 111:{D=Yt,n=t[D>>2]|0,D=t[D+4>>2]|0,H=YI(n,D,me)|0,xe=Ce-H|0,k=0,F=5642,E=(ue&8|0)==0|(E|0)>(xe|0)?E:xe+1|0,xe=ue,be=67;break}case 105:case 100:if(D=Yt,n=t[D>>2]|0,D=t[D+4>>2]|0,(D|0)<0){n=Ty(0,0,n|0,D|0)|0,D=Xe,k=Yt,t[k>>2]=n,t[k+4>>2]=D,k=1,F=5642,be=66;break t}else{k=(ue&2049|0)!=0&1,F=(ue&2048|0)==0?(ue&1|0)==0?5642:5644:5643,be=66;break t}case 117:{D=Yt,k=0,F=5642,n=t[D>>2]|0,D=t[D+4>>2]|0,be=66;break}case 99:{p[At>>0]=t[Yt>>2],n=At,k=0,F=5642,H=me,D=1,E=xe;break}case 109:{D=KI(t[(S2()|0)>>2]|0)|0,be=71;break}case 115:{D=t[Yt>>2]|0,D=D|0?D:5652,be=71;break}case 67:{t[Pn>>2]=t[Yt>>2],t[Zn>>2]=0,t[Yt>>2]=Pn,H=-1,D=Pn,be=75;break}case 83:{n=t[Yt>>2]|0,E?(H=E,D=n,be=75):(yo(e,32,h,0,ue),n=0,be=84);break}case 65:case 71:case 70:case 69:case 97:case 103:case 102:case 101:{h=QI(e,+P[Yt>>3],h,E,ue,D)|0,n=Be;continue e}default:k=0,F=5642,H=me,D=E,E=ue}while(0);t:do if((be|0)==61)ue=Yt,ce=t[ue>>2]|0,ue=t[ue+4>>2]|0,H=GI(ce,ue,me,D&32)|0,F=(n&8|0)==0|(ce|0)==0&(ue|0)==0,k=F?0:2,F=F?5642:5642+(D>>4)|0,xe=n,n=ce,D=ue,be=67;else if((be|0)==66)H=T2(n,D,me)|0,xe=ue,be=67;else if((be|0)==71)be=0,ue=XI(D,0,E)|0,ce=(ue|0)==0,n=D,k=0,F=5642,H=ce?D+E|0:ue,D=ce?E:ue-D|0,E=xe;else if((be|0)==75){for(be=0,F=D,n=0,E=0;k=t[F>>2]|0,!(!k||(E=Qw(Qn,k)|0,(E|0)<0|E>>>0>(H-n|0)>>>0));)if(n=E+n|0,H>>>0>n>>>0)F=F+4|0;else break;if((E|0)<0){s=-1;break e}if(yo(e,32,h,n,ue),!n)n=0,be=84;else for(k=0;;){if(E=t[D>>2]|0,!E){be=84;break t}if(E=Qw(Qn,E)|0,k=E+k|0,(k|0)>(n|0)){be=84;break t}if($0(e,Qn,E),k>>>0>=n>>>0){be=84;break}else D=D+4|0}}while(0);if((be|0)==67)be=0,D=(n|0)!=0|(D|0)!=0,ue=(E|0)!=0|D,D=((D^1)&1)+(Ce-H)|0,n=ue?H:me,H=me,D=ue?(E|0)>(D|0)?E:D:E,E=(E|0)>-1?xe&-65537:xe;else if((be|0)==84){be=0,yo(e,32,h,n,ue^8192),h=(h|0)>(n|0)?h:n,n=Be;continue}ce=H-n|0,xe=(D|0)<(ce|0)?ce:D,ue=xe+k|0,h=(h|0)<(ue|0)?ue:h,yo(e,32,h,ue,E),$0(e,F,k),yo(e,48,h,ue,E^65536),yo(e,48,xe,ce,0),$0(e,n,ce),yo(e,32,h,ue,E^8192),n=Be}e:do if((be|0)==87&&!e)if(!R)s=0;else{for(s=1;n=t[a+(s<<2)>>2]|0,!!n;)if(Xw(o+(s<<3)|0,n,r),s=s+1|0,(s|0)>=10){s=1;break e}for(;;){if(t[a+(s<<2)>>2]|0){s=-1;break e}if(s=s+1|0,(s|0)>=10){s=1;break}}}while(0);return v=tn,s|0}function WI(e){return e=e|0,0}function VI(e){e=e|0}function $0(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]&32||oB(n,r,e)|0}function Kw(e){e=e|0;var n=0,r=0,o=0;if(r=t[e>>2]|0,o=(p[r>>0]|0)+-48|0,o>>>0<10){n=0;do n=o+(n*10|0)|0,r=r+1|0,t[e>>2]=r,o=(p[r>>0]|0)+-48|0;while(o>>>0<10)}else n=0;return n|0}function Xw(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0;e:do if(n>>>0<=20)do switch(n|0){case 9:{o=(t[r>>2]|0)+(4-1)&~(4-1),n=t[o>>2]|0,t[r>>2]=o+4,t[e>>2]=n;break e}case 10:{o=(t[r>>2]|0)+(4-1)&~(4-1),n=t[o>>2]|0,t[r>>2]=o+4,o=e,t[o>>2]=n,t[o+4>>2]=((n|0)<0)<<31>>31;break e}case 11:{o=(t[r>>2]|0)+(4-1)&~(4-1),n=t[o>>2]|0,t[r>>2]=o+4,o=e,t[o>>2]=n,t[o+4>>2]=0;break e}case 12:{o=(t[r>>2]|0)+(8-1)&~(8-1),n=o,a=t[n>>2]|0,n=t[n+4>>2]|0,t[r>>2]=o+8,o=e,t[o>>2]=a,t[o+4>>2]=n;break e}case 13:{a=(t[r>>2]|0)+(4-1)&~(4-1),o=t[a>>2]|0,t[r>>2]=a+4,o=(o&65535)<<16>>16,a=e,t[a>>2]=o,t[a+4>>2]=((o|0)<0)<<31>>31;break e}case 14:{a=(t[r>>2]|0)+(4-1)&~(4-1),o=t[a>>2]|0,t[r>>2]=a+4,a=e,t[a>>2]=o&65535,t[a+4>>2]=0;break e}case 15:{a=(t[r>>2]|0)+(4-1)&~(4-1),o=t[a>>2]|0,t[r>>2]=a+4,o=(o&255)<<24>>24,a=e,t[a>>2]=o,t[a+4>>2]=((o|0)<0)<<31>>31;break e}case 16:{a=(t[r>>2]|0)+(4-1)&~(4-1),o=t[a>>2]|0,t[r>>2]=a+4,a=e,t[a>>2]=o&255,t[a+4>>2]=0;break e}case 17:{a=(t[r>>2]|0)+(8-1)&~(8-1),s=+P[a>>3],t[r>>2]=a+8,P[e>>3]=s;break e}case 18:{a=(t[r>>2]|0)+(8-1)&~(8-1),s=+P[a>>3],t[r>>2]=a+8,P[e>>3]=s;break e}default:break e}while(0);while(0)}function GI(e,n,r,o){if(e=e|0,n=n|0,r=r|0,o=o|0,!((e|0)==0&(n|0)==0))do r=r+-1|0,p[r>>0]=O[5694+(e&15)>>0]|0|o,e=Cy(e|0,n|0,4)|0,n=Xe;while(!((e|0)==0&(n|0)==0));return r|0}function YI(e,n,r){if(e=e|0,n=n|0,r=r|0,!((e|0)==0&(n|0)==0))do r=r+-1|0,p[r>>0]=e&7|48,e=Cy(e|0,n|0,3)|0,n=Xe;while(!((e|0)==0&(n|0)==0));return r|0}function T2(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;if(n>>>0>0|(n|0)==0&e>>>0>4294967295){for(;o=eD(e|0,n|0,10,0)|0,r=r+-1|0,p[r>>0]=o&255|48,o=e,e=$E(e|0,n|0,10,0)|0,n>>>0>9|(n|0)==9&o>>>0>4294967295;)n=Xe;n=e}else n=e;if(n)for(;r=r+-1|0,p[r>>0]=(n>>>0)%10|0|48,!(n>>>0<10);)n=(n>>>0)/10|0;return r|0}function KI(e){return e=e|0,tB(e,t[(eB()|0)+188>>2]|0)|0}function XI(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;s=n&255,o=(r|0)!=0;e:do if(o&(e&3|0)!=0)for(a=n&255;;){if((p[e>>0]|0)==a<<24>>24){h=6;break e}if(e=e+1|0,r=r+-1|0,o=(r|0)!=0,!(o&(e&3|0)!=0)){h=5;break}}else h=5;while(0);(h|0)==5&&(o?h=6:r=0);e:do if((h|0)==6&&(a=n&255,(p[e>>0]|0)!=a<<24>>24)){o=Nn(s,16843009)|0;t:do if(r>>>0>3){for(;s=t[e>>2]^o,!((s&-2139062144^-2139062144)&s+-16843009|0);)if(e=e+4|0,r=r+-4|0,r>>>0<=3){h=11;break t}}else h=11;while(0);if((h|0)==11&&!r){r=0;break}for(;;){if((p[e>>0]|0)==a<<24>>24)break e;if(e=e+1|0,r=r+-1|0,!r){r=0;break}}}while(0);return(r|0?e:0)|0}function yo(e,n,r,o,a){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0;var s=0,h=0;if(h=v,v=v+256|0,s=h,(r|0)>(o|0)&(a&73728|0)==0){if(a=r-o|0,x2(s|0,n|0,(a>>>0<256?a:256)|0)|0,a>>>0>255){n=r-o|0;do $0(e,s,256),a=a+-256|0;while(a>>>0>255);a=n&255}$0(e,s,a)}v=h}function Qw(e,n){return e=e|0,n=n|0,e?e=ZI(e,n,0)|0:e=0,e|0}function QI(e,n,r,o,a,s){e=e|0,n=+n,r=r|0,o=o|0,a=a|0,s=s|0;var h=0,E=0,D=0,k=0,R=0,F=0,H=0,xe=0,ce=0,ue=0,Be=0,be=0,Ve=0,me=0,Ce=0,At=0,Zn=0,on=0,Yt=0,Pn=0,Qn=0,tn=0,$r=0;$r=v,v=v+560|0,D=$r+8|0,Be=$r,tn=$r+524|0,Qn=tn,k=$r+512|0,t[Be>>2]=0,Pn=k+12|0,Jw(n)|0,(Xe|0)<0?(n=-n,on=1,Zn=5659):(on=(a&2049|0)!=0&1,Zn=(a&2048|0)==0?(a&1|0)==0?5660:5665:5662),Jw(n)|0,Yt=Xe&2146435072;do if(Yt>>>0<2146435072|(Yt|0)==2146435072&0<0){if(xe=+JI(n,Be)*2,h=xe!=0,h&&(t[Be>>2]=(t[Be>>2]|0)+-1),Ve=s|32,(Ve|0)==97){ce=s&32,H=(ce|0)==0?Zn:Zn+9|0,F=on|2,h=12-o|0;do if(o>>>0>11|(h|0)==0)n=xe;else{n=8;do h=h+-1|0,n=n*16;while((h|0)!=0);if((p[H>>0]|0)==45){n=-(n+(-xe-n));break}else{n=xe+n-n;break}}while(0);E=t[Be>>2]|0,h=(E|0)<0?0-E|0:E,h=T2(h,((h|0)<0)<<31>>31,Pn)|0,(h|0)==(Pn|0)&&(h=k+11|0,p[h>>0]=48),p[h+-1>>0]=(E>>31&2)+43,R=h+-2|0,p[R>>0]=s+15,k=(o|0)<1,D=(a&8|0)==0,h=tn;do Yt=~~n,E=h+1|0,p[h>>0]=O[5694+Yt>>0]|ce,n=(n-+(Yt|0))*16,(E-Qn|0)==1&&!(D&(k&n==0))?(p[E>>0]=46,h=h+2|0):h=E;while(n!=0);Yt=h-Qn|0,Qn=Pn-R|0,Pn=(o|0)!=0&(Yt+-2|0)<(o|0)?o+2|0:Yt,h=Qn+F+Pn|0,yo(e,32,r,h,a),$0(e,H,F),yo(e,48,r,h,a^65536),$0(e,tn,Yt),yo(e,48,Pn-Yt|0,0,0),$0(e,R,Qn),yo(e,32,r,h,a^8192);break}E=(o|0)<0?6:o,h?(h=(t[Be>>2]|0)+-28|0,t[Be>>2]=h,n=xe*268435456):(n=xe,h=t[Be>>2]|0),Yt=(h|0)<0?D:D+288|0,D=Yt;do Ce=~~n>>>0,t[D>>2]=Ce,D=D+4|0,n=(n-+(Ce>>>0))*1e9;while(n!=0);if((h|0)>0)for(k=Yt,F=D;;){if(R=(h|0)<29?h:29,h=F+-4|0,h>>>0>=k>>>0){D=0;do me=rS(t[h>>2]|0,0,R|0)|0,me=ZE(me|0,Xe|0,D|0,0)|0,Ce=Xe,be=eD(me|0,Ce|0,1e9,0)|0,t[h>>2]=be,D=$E(me|0,Ce|0,1e9,0)|0,h=h+-4|0;while(h>>>0>=k>>>0);D&&(k=k+-4|0,t[k>>2]=D)}for(D=F;!(D>>>0<=k>>>0);)if(h=D+-4|0,!(t[h>>2]|0))D=h;else break;if(h=(t[Be>>2]|0)-R|0,t[Be>>2]=h,(h|0)>0)F=D;else break}else k=Yt;if((h|0)<0){o=((E+25|0)/9|0)+1|0,ue=(Ve|0)==102;do{if(ce=0-h|0,ce=(ce|0)<9?ce:9,k>>>0>>0){R=(1<>>ce,H=0,h=k;do Ce=t[h>>2]|0,t[h>>2]=(Ce>>>ce)+H,H=Nn(Ce&R,F)|0,h=h+4|0;while(h>>>0>>0);h=(t[k>>2]|0)==0?k+4|0:k,H?(t[D>>2]=H,k=h,h=D+4|0):(k=h,h=D)}else k=(t[k>>2]|0)==0?k+4|0:k,h=D;D=ue?Yt:k,D=(h-D>>2|0)>(o|0)?D+(o<<2)|0:h,h=(t[Be>>2]|0)+ce|0,t[Be>>2]=h}while((h|0)<0);h=k,o=D}else h=k,o=D;if(Ce=Yt,h>>>0>>0){if(D=(Ce-h>>2)*9|0,R=t[h>>2]|0,R>>>0>=10){k=10;do k=k*10|0,D=D+1|0;while(R>>>0>=k>>>0)}}else D=0;if(ue=(Ve|0)==103,be=(E|0)!=0,k=E-((Ve|0)!=102?D:0)+((be&ue)<<31>>31)|0,(k|0)<(((o-Ce>>2)*9|0)+-9|0)){if(k=k+9216|0,ce=Yt+4+(((k|0)/9|0)+-1024<<2)|0,k=((k|0)%9|0)+1|0,(k|0)<9){R=10;do R=R*10|0,k=k+1|0;while((k|0)!=9)}else R=10;if(F=t[ce>>2]|0,H=(F>>>0)%(R>>>0)|0,k=(ce+4|0)==(o|0),k&(H|0)==0)k=ce;else if(xe=(((F>>>0)/(R>>>0)|0)&1|0)==0?9007199254740992:9007199254740994,me=(R|0)/2|0,n=H>>>0>>0?.5:k&(H|0)==(me|0)?1:1.5,on&&(me=(p[Zn>>0]|0)==45,n=me?-n:n,xe=me?-xe:xe),k=F-H|0,t[ce>>2]=k,xe+n!=xe){if(me=k+R|0,t[ce>>2]=me,me>>>0>999999999)for(D=ce;k=D+-4|0,t[D>>2]=0,k>>>0>>0&&(h=h+-4|0,t[h>>2]=0),me=(t[k>>2]|0)+1|0,t[k>>2]=me,me>>>0>999999999;)D=k;else k=ce;if(D=(Ce-h>>2)*9|0,F=t[h>>2]|0,F>>>0>=10){R=10;do R=R*10|0,D=D+1|0;while(F>>>0>=R>>>0)}}else k=ce;k=k+4|0,k=o>>>0>k>>>0?k:o,me=h}else k=o,me=h;for(Ve=k;;){if(Ve>>>0<=me>>>0){Be=0;break}if(h=Ve+-4|0,!(t[h>>2]|0))Ve=h;else{Be=1;break}}o=0-D|0;do if(ue)if(h=((be^1)&1)+E|0,(h|0)>(D|0)&(D|0)>-5?(R=s+-1|0,E=h+-1-D|0):(R=s+-2|0,E=h+-1|0),h=a&8,h)ce=h;else{if(Be&&(At=t[Ve+-4>>2]|0,(At|0)!=0))if((At>>>0)%10|0)k=0;else{k=0,h=10;do h=h*10|0,k=k+1|0;while(!((At>>>0)%(h>>>0)|0|0))}else k=9;if(h=((Ve-Ce>>2)*9|0)+-9|0,(R|32|0)==102){ce=h-k|0,ce=(ce|0)>0?ce:0,E=(E|0)<(ce|0)?E:ce,ce=0;break}else{ce=h+D-k|0,ce=(ce|0)>0?ce:0,E=(E|0)<(ce|0)?E:ce,ce=0;break}}else R=s,ce=a&8;while(0);if(ue=E|ce,F=(ue|0)!=0&1,H=(R|32|0)==102,H)be=0,h=(D|0)>0?D:0;else{if(h=(D|0)<0?o:D,h=T2(h,((h|0)<0)<<31>>31,Pn)|0,k=Pn,(k-h|0)<2)do h=h+-1|0,p[h>>0]=48;while((k-h|0)<2);p[h+-1>>0]=(D>>31&2)+43,h=h+-2|0,p[h>>0]=R,be=h,h=k-h|0}if(h=on+1+E+F+h|0,yo(e,32,r,h,a),$0(e,Zn,on),yo(e,48,r,h,a^65536),H){R=me>>>0>Yt>>>0?Yt:me,ce=tn+9|0,F=ce,H=tn+8|0,k=R;do{if(D=T2(t[k>>2]|0,0,ce)|0,(k|0)==(R|0))(D|0)==(ce|0)&&(p[H>>0]=48,D=H);else if(D>>>0>tn>>>0){x2(tn|0,48,D-Qn|0)|0;do D=D+-1|0;while(D>>>0>tn>>>0)}$0(e,D,F-D|0),k=k+4|0}while(k>>>0<=Yt>>>0);if(ue|0&&$0(e,5710,1),k>>>0>>0&(E|0)>0)for(;;){if(D=T2(t[k>>2]|0,0,ce)|0,D>>>0>tn>>>0){x2(tn|0,48,D-Qn|0)|0;do D=D+-1|0;while(D>>>0>tn>>>0)}if($0(e,D,(E|0)<9?E:9),k=k+4|0,D=E+-9|0,k>>>0>>0&(E|0)>9)E=D;else{E=D;break}}yo(e,48,E+9|0,9,0)}else{if(ue=Be?Ve:me+4|0,(E|0)>-1){Be=tn+9|0,ce=(ce|0)==0,o=Be,F=0-Qn|0,H=tn+8|0,R=me;do{D=T2(t[R>>2]|0,0,Be)|0,(D|0)==(Be|0)&&(p[H>>0]=48,D=H);do if((R|0)==(me|0)){if(k=D+1|0,$0(e,D,1),ce&(E|0)<1){D=k;break}$0(e,5710,1),D=k}else{if(D>>>0<=tn>>>0)break;x2(tn|0,48,D+F|0)|0;do D=D+-1|0;while(D>>>0>tn>>>0)}while(0);Qn=o-D|0,$0(e,D,(E|0)>(Qn|0)?Qn:E),E=E-Qn|0,R=R+4|0}while(R>>>0>>0&(E|0)>-1)}yo(e,48,E+18|0,18,0),$0(e,be,Pn-be|0)}yo(e,32,r,h,a^8192)}else tn=(s&32|0)!=0,h=on+3|0,yo(e,32,r,h,a&-65537),$0(e,Zn,on),$0(e,n!=n|!1?tn?5686:5690:tn?5678:5682,3),yo(e,32,r,h,a^8192);while(0);return v=$r,((h|0)<(r|0)?r:h)|0}function Jw(e){e=+e;var n=0;return P[z>>3]=e,n=t[z>>2]|0,Xe=t[z+4>>2]|0,n|0}function JI(e,n){return e=+e,n=n|0,+ +Zw(e,n)}function Zw(e,n){e=+e,n=n|0;var r=0,o=0,a=0;switch(P[z>>3]=e,r=t[z>>2]|0,o=t[z+4>>2]|0,a=Cy(r|0,o|0,52)|0,a&2047){case 0:{e!=0?(e=+Zw(e*18446744073709552e3,n),r=(t[n>>2]|0)+-64|0):r=0,t[n>>2]=r;break}case 2047:break;default:t[n>>2]=(a&2047)+-1022,t[z>>2]=r,t[z+4>>2]=o&-2146435073|1071644672,e=+P[z>>3]}return+e}function ZI(e,n,r){e=e|0,n=n|0,r=r|0;do if(e){if(n>>>0<128){p[e>>0]=n,e=1;break}if(!(t[t[($I()|0)+188>>2]>>2]|0))if((n&-128|0)==57216){p[e>>0]=n,e=1;break}else{t[(S2()|0)>>2]=84,e=-1;break}if(n>>>0<2048){p[e>>0]=n>>>6|192,p[e+1>>0]=n&63|128,e=2;break}if(n>>>0<55296|(n&-8192|0)==57344){p[e>>0]=n>>>12|224,p[e+1>>0]=n>>>6&63|128,p[e+2>>0]=n&63|128,e=3;break}if((n+-65536|0)>>>0<1048576){p[e>>0]=n>>>18|240,p[e+1>>0]=n>>>12&63|128,p[e+2>>0]=n>>>6&63|128,p[e+3>>0]=n&63|128,e=4;break}else{t[(S2()|0)>>2]=84,e=-1;break}}else e=1;while(0);return e|0}function $I(){return XE()|0}function eB(){return XE()|0}function tB(e,n){e=e|0,n=n|0;var r=0,o=0;for(o=0;;){if((O[5712+o>>0]|0)==(e|0)){e=2;break}if(r=o+1|0,(r|0)==87){r=5800,o=87,e=5;break}else o=r}if((e|0)==2&&(o?(r=5800,e=5):r=5800),(e|0)==5)for(;;){do e=r,r=r+1|0;while((p[e>>0]|0)!=0);if(o=o+-1|0,o)e=5;else break}return nB(r,t[n+20>>2]|0)|0}function nB(e,n){return e=e|0,n=n|0,rB(e,n)|0}function rB(e,n){return e=e|0,n=n|0,n?n=iB(t[n>>2]|0,t[n+4>>2]|0,e)|0:n=0,(n|0?n:e)|0}function iB(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0;H=(t[e>>2]|0)+1794895138|0,s=Jc(t[e+8>>2]|0,H)|0,o=Jc(t[e+12>>2]|0,H)|0,a=Jc(t[e+16>>2]|0,H)|0;e:do if(s>>>0>>2>>>0&&(F=n-(s<<2)|0,o>>>0>>0&a>>>0>>0)&&((a|o)&3|0)==0){for(F=o>>>2,R=a>>>2,k=0;;){if(E=s>>>1,D=k+E|0,h=D<<1,a=h+F|0,o=Jc(t[e+(a<<2)>>2]|0,H)|0,a=Jc(t[e+(a+1<<2)>>2]|0,H)|0,!(a>>>0>>0&o>>>0<(n-a|0)>>>0)){o=0;break e}if(p[e+(a+o)>>0]|0){o=0;break e}if(o=Gw(r,e+a|0)|0,!o)break;if(o=(o|0)<0,(s|0)==1){o=0;break e}else k=o?k:D,s=o?E:s-E|0}o=h+R|0,a=Jc(t[e+(o<<2)>>2]|0,H)|0,o=Jc(t[e+(o+1<<2)>>2]|0,H)|0,o>>>0>>0&a>>>0<(n-o|0)>>>0?o=(p[e+(o+a)>>0]|0)==0?e+o|0:0:o=0}else o=0;while(0);return o|0}function Jc(e,n){e=e|0,n=n|0;var r=0;return r=uS(e|0)|0,((n|0)==0?e:r)|0}function oB(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0,E=0;o=r+16|0,a=t[o>>2]|0,a?s=5:uB(r)|0?o=0:(a=t[o>>2]|0,s=5);e:do if((s|0)==5){if(E=r+20|0,h=t[E>>2]|0,o=h,(a-h|0)>>>0>>0){o=Ry[t[r+36>>2]&7](r,e,n)|0;break}t:do if((p[r+75>>0]|0)>-1){for(h=n;;){if(!h){s=0,a=e;break t}if(a=h+-1|0,(p[e+a>>0]|0)==10)break;h=a}if(o=Ry[t[r+36>>2]&7](r,e,h)|0,o>>>0>>0)break e;s=h,a=e+h|0,n=n-h|0,o=t[E>>2]|0}else s=0,a=e;while(0);bn(o|0,a|0,n|0)|0,t[E>>2]=(t[E>>2]|0)+n,o=s+n|0}while(0);return o|0}function uB(e){e=e|0;var n=0,r=0;return n=e+74|0,r=p[n>>0]|0,p[n>>0]=r+255|r,n=t[e>>2]|0,n&8?(t[e>>2]=n|32,e=-1):(t[e+8>>2]=0,t[e+4>>2]=0,r=t[e+44>>2]|0,t[e+28>>2]=r,t[e+20>>2]=r,t[e+16>>2]=r+(t[e+48>>2]|0),e=0),e|0}function Ci(e,n){e=w(e),n=w(n);var r=0,o=0;r=$w(e)|0;do if((r&2147483647)>>>0<=2139095040){if(o=$w(n)|0,(o&2147483647)>>>0<=2139095040)if((o^r|0)<0){e=(r|0)<0?n:e;break}else{e=e>2]=e,t[z>>2]|0|0}function Zc(e,n){e=w(e),n=w(n);var r=0,o=0;r=eS(e)|0;do if((r&2147483647)>>>0<=2139095040){if(o=eS(n)|0,(o&2147483647)>>>0<=2139095040)if((o^r|0)<0){e=(r|0)<0?e:n;break}else{e=e>2]=e,t[z>>2]|0|0}function JE(e,n){e=w(e),n=w(n);var r=0,o=0,a=0,s=0,h=0,E=0,D=0,k=0;s=(T[z>>2]=e,t[z>>2]|0),E=(T[z>>2]=n,t[z>>2]|0),r=s>>>23&255,h=E>>>23&255,D=s&-2147483648,a=E<<1;e:do if((a|0)!=0&&!((r|0)==255|((lB(n)|0)&2147483647)>>>0>2139095040)){if(o=s<<1,o>>>0<=a>>>0)return n=w(e*w(0)),w((o|0)==(a|0)?n:e);if(r)o=s&8388607|8388608;else{if(r=s<<9,(r|0)>-1){o=r,r=0;do r=r+-1|0,o=o<<1;while((o|0)>-1)}else r=0;o=s<<1-r}if(h)E=E&8388607|8388608;else{if(s=E<<9,(s|0)>-1){a=0;do a=a+-1|0,s=s<<1;while((s|0)>-1)}else a=0;h=a,E=E<<1-a}a=o-E|0,s=(a|0)>-1;t:do if((r|0)>(h|0)){for(;;){if(s)if(a)o=a;else break;if(o=o<<1,r=r+-1|0,a=o-E|0,s=(a|0)>-1,(r|0)<=(h|0))break t}n=w(e*w(0));break e}while(0);if(s)if(a)o=a;else{n=w(e*w(0));break}if(o>>>0<8388608)do o=o<<1,r=r+-1|0;while(o>>>0<8388608);(r|0)>0?r=o+-8388608|r<<23:r=o>>>(1-r|0),n=(t[z>>2]=r|D,w(T[z>>2]))}else k=3;while(0);return(k|0)==3&&(n=w(e*n),n=w(n/n)),w(n)}function lB(e){return e=w(e),T[z>>2]=e,t[z>>2]|0|0}function aB(e,n){return e=e|0,n=n|0,Yw(t[582]|0,e,n)|0}function gr(e){e=e|0,Tn()}function C2(e){e=e|0}function sB(e,n){return e=e|0,n=n|0,0}function fB(e){return e=e|0,(tS(e+4|0)|0)==-1?(tf[t[(t[e>>2]|0)+8>>2]&127](e),e=1):e=0,e|0}function tS(e){e=e|0;var n=0;return n=t[e>>2]|0,t[e>>2]=n+-1,n+-1|0}function Zf(e){e=e|0,fB(e)|0&&cB(e)}function cB(e){e=e|0;var n=0;n=e+8|0,(t[n>>2]|0)!=0&&(tS(n)|0)!=-1||tf[t[(t[e>>2]|0)+16>>2]&127](e)}function Bt(e){e=e|0;var n=0;for(n=(e|0)==0?1:e;e=Dy(n)|0,!(e|0);){if(e=pB()|0,!e){e=0;break}mS[e&0]()}return e|0}function nS(e){return e=e|0,Bt(e)|0}function $e(e){e=e|0,wy(e)}function dB(e){e=e|0,(p[e+11>>0]|0)<0&&$e(t[e>>2]|0)}function pB(){var e=0;return e=t[2923]|0,t[2923]=e+0,e|0}function hB(){}function Ty(e,n,r,o){return e=e|0,n=n|0,r=r|0,o=o|0,o=n-o-(r>>>0>e>>>0|0)>>>0,Xe=o,e-r>>>0|0|0}function ZE(e,n,r,o){return e=e|0,n=n|0,r=r|0,o=o|0,r=e+r>>>0,Xe=n+o+(r>>>0>>0|0)>>>0,r|0|0}function x2(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0,h=0;if(s=e+r|0,n=n&255,(r|0)>=67){for(;e&3;)p[e>>0]=n,e=e+1|0;for(o=s&-4|0,a=o-64|0,h=n|n<<8|n<<16|n<<24;(e|0)<=(a|0);)t[e>>2]=h,t[e+4>>2]=h,t[e+8>>2]=h,t[e+12>>2]=h,t[e+16>>2]=h,t[e+20>>2]=h,t[e+24>>2]=h,t[e+28>>2]=h,t[e+32>>2]=h,t[e+36>>2]=h,t[e+40>>2]=h,t[e+44>>2]=h,t[e+48>>2]=h,t[e+52>>2]=h,t[e+56>>2]=h,t[e+60>>2]=h,e=e+64|0;for(;(e|0)<(o|0);)t[e>>2]=h,e=e+4|0}for(;(e|0)<(s|0);)p[e>>0]=n,e=e+1|0;return s-r|0}function rS(e,n,r){return e=e|0,n=n|0,r=r|0,(r|0)<32?(Xe=n<>>32-r,e<>>r,e>>>r|(n&(1<>>r-32|0)}function bn(e,n,r){e=e|0,n=n|0,r=r|0;var o=0,a=0,s=0;if((r|0)>=8192)return Dr(e|0,n|0,r|0)|0;if(s=e|0,a=e+r|0,(e&3)==(n&3)){for(;e&3;){if(!r)return s|0;p[e>>0]=p[n>>0]|0,e=e+1|0,n=n+1|0,r=r-1|0}for(r=a&-4|0,o=r-64|0;(e|0)<=(o|0);)t[e>>2]=t[n>>2],t[e+4>>2]=t[n+4>>2],t[e+8>>2]=t[n+8>>2],t[e+12>>2]=t[n+12>>2],t[e+16>>2]=t[n+16>>2],t[e+20>>2]=t[n+20>>2],t[e+24>>2]=t[n+24>>2],t[e+28>>2]=t[n+28>>2],t[e+32>>2]=t[n+32>>2],t[e+36>>2]=t[n+36>>2],t[e+40>>2]=t[n+40>>2],t[e+44>>2]=t[n+44>>2],t[e+48>>2]=t[n+48>>2],t[e+52>>2]=t[n+52>>2],t[e+56>>2]=t[n+56>>2],t[e+60>>2]=t[n+60>>2],e=e+64|0,n=n+64|0;for(;(e|0)<(r|0);)t[e>>2]=t[n>>2],e=e+4|0,n=n+4|0}else for(r=a-4|0;(e|0)<(r|0);)p[e>>0]=p[n>>0]|0,p[e+1>>0]=p[n+1>>0]|0,p[e+2>>0]=p[n+2>>0]|0,p[e+3>>0]=p[n+3>>0]|0,e=e+4|0,n=n+4|0;for(;(e|0)<(a|0);)p[e>>0]=p[n>>0]|0,e=e+1|0,n=n+1|0;return s|0}function iS(e){e=e|0;var n=0;return n=p[ye+(e&255)>>0]|0,(n|0)<8?n|0:(n=p[ye+(e>>8&255)>>0]|0,(n|0)<8?n+8|0:(n=p[ye+(e>>16&255)>>0]|0,(n|0)<8?n+16|0:(p[ye+(e>>>24)>>0]|0)+24|0))}function oS(e,n,r,o,a){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0;var s=0,h=0,E=0,D=0,k=0,R=0,F=0,H=0,xe=0,ce=0;if(R=e,D=n,k=D,h=r,H=o,E=H,!k)return s=(a|0)!=0,E?s?(t[a>>2]=e|0,t[a+4>>2]=n&0,H=0,a=0,Xe=H,a|0):(H=0,a=0,Xe=H,a|0):(s&&(t[a>>2]=(R>>>0)%(h>>>0),t[a+4>>2]=0),H=0,a=(R>>>0)/(h>>>0)>>>0,Xe=H,a|0);s=(E|0)==0;do if(h){if(!s){if(s=(Wn(E|0)|0)-(Wn(k|0)|0)|0,s>>>0<=31){F=s+1|0,E=31-s|0,n=s-31>>31,h=F,e=R>>>(F>>>0)&n|k<>>(F>>>0)&n,s=0,E=R<>2]=e|0,t[a+4>>2]=D|n&0,H=0,a=0,Xe=H,a|0):(H=0,a=0,Xe=H,a|0)}if(s=h-1|0,s&h|0){E=(Wn(h|0)|0)+33-(Wn(k|0)|0)|0,ce=64-E|0,F=32-E|0,D=F>>31,xe=E-32|0,n=xe>>31,h=E,e=F-1>>31&k>>>(xe>>>0)|(k<>>(E>>>0))&n,n=n&k>>>(E>>>0),s=R<>>(xe>>>0))&D|R<>31;break}return a|0&&(t[a>>2]=s&R,t[a+4>>2]=0),(h|0)==1?(xe=D|n&0,ce=e|0|0,Xe=xe,ce|0):(ce=iS(h|0)|0,xe=k>>>(ce>>>0)|0,ce=k<<32-ce|R>>>(ce>>>0)|0,Xe=xe,ce|0)}else{if(s)return a|0&&(t[a>>2]=(k>>>0)%(h>>>0),t[a+4>>2]=0),xe=0,ce=(k>>>0)/(h>>>0)>>>0,Xe=xe,ce|0;if(!R)return a|0&&(t[a>>2]=0,t[a+4>>2]=(k>>>0)%(E>>>0)),xe=0,ce=(k>>>0)/(E>>>0)>>>0,Xe=xe,ce|0;if(s=E-1|0,!(s&E))return a|0&&(t[a>>2]=e|0,t[a+4>>2]=s&k|n&0),xe=0,ce=k>>>((iS(E|0)|0)>>>0),Xe=xe,ce|0;if(s=(Wn(E|0)|0)-(Wn(k|0)|0)|0,s>>>0<=30){n=s+1|0,E=31-s|0,h=n,e=k<>>(n>>>0),n=k>>>(n>>>0),s=0,E=R<>2]=e|0,t[a+4>>2]=D|n&0,xe=0,ce=0,Xe=xe,ce|0):(xe=0,ce=0,Xe=xe,ce|0)}while(0);if(!h)k=E,D=0,E=0;else{F=r|0|0,R=H|o&0,k=ZE(F|0,R|0,-1,-1)|0,r=Xe,D=E,E=0;do o=D,D=s>>>31|D<<1,s=E|s<<1,o=e<<1|o>>>31|0,H=e>>>31|n<<1|0,Ty(k|0,r|0,o|0,H|0)|0,ce=Xe,xe=ce>>31|((ce|0)<0?-1:0)<<1,E=xe&1,e=Ty(o|0,H|0,xe&F|0,(((ce|0)<0?-1:0)>>31|((ce|0)<0?-1:0)<<1)&R|0)|0,n=Xe,h=h-1|0;while((h|0)!=0);k=D,D=0}return h=0,a|0&&(t[a>>2]=e,t[a+4>>2]=n),xe=(s|0)>>>31|(k|h)<<1|(h<<1|s>>>31)&0|D,ce=(s<<1|0>>>31)&-2|E,Xe=xe,ce|0}function $E(e,n,r,o){return e=e|0,n=n|0,r=r|0,o=o|0,oS(e,n,r,o,0)|0}function $f(e){e=e|0;var n=0,r=0;return r=e+15&-16|0,n=t[U>>2]|0,e=n+r|0,(r|0)>0&(e|0)<(n|0)|(e|0)<0?(Ln()|0,Pu(12),-1):(t[U>>2]=e,(e|0)>(sr()|0)&&(ir()|0)==0?(t[U>>2]=n,Pu(12),-1):n|0)}function ih(e,n,r){e=e|0,n=n|0,r=r|0;var o=0;if((n|0)<(e|0)&(e|0)<(n+r|0)){for(o=e,n=n+r|0,e=e+r|0;(r|0)>0;)e=e-1|0,n=n-1|0,r=r-1|0,p[e>>0]=p[n>>0]|0;e=o}else bn(e,n,r)|0;return e|0}function eD(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0;var a=0,s=0;return s=v,v=v+16|0,a=s|0,oS(e,n,r,o,a)|0,v=s,Xe=t[a+4>>2]|0,t[a>>2]|0|0}function uS(e){return e=e|0,(e&255)<<24|(e>>8&255)<<16|(e>>16&255)<<8|e>>>24|0}function vB(e,n,r,o,a,s){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0,lS[e&1](n|0,r|0,o|0,a|0,s|0)}function mB(e,n,r){e=e|0,n=n|0,r=w(r),aS[e&1](n|0,w(r))}function yB(e,n,r){e=e|0,n=n|0,r=+r,sS[e&31](n|0,+r)}function gB(e,n,r,o){return e=e|0,n=n|0,r=w(r),o=w(o),w(fS[e&0](n|0,w(r),w(o)))}function _B(e,n){e=e|0,n=n|0,tf[e&127](n|0)}function EB(e,n,r){e=e|0,n=n|0,r=r|0,nf[e&31](n|0,r|0)}function DB(e,n){return e=e|0,n=n|0,e1[e&31](n|0)|0}function wB(e,n,r,o,a){e=e|0,n=n|0,r=+r,o=+o,a=a|0,cS[e&1](n|0,+r,+o,a|0)}function SB(e,n,r,o){e=e|0,n=n|0,r=+r,o=+o,rU[e&1](n|0,+r,+o)}function TB(e,n,r,o){return e=e|0,n=n|0,r=r|0,o=o|0,Ry[e&7](n|0,r|0,o|0)|0}function CB(e,n,r,o){return e=e|0,n=n|0,r=r|0,o=o|0,+iU[e&1](n|0,r|0,o|0)}function xB(e,n){return e=e|0,n=n|0,+dS[e&15](n|0)}function RB(e,n,r){return e=e|0,n=n|0,r=+r,oU[e&1](n|0,+r)|0}function AB(e,n,r){return e=e|0,n=n|0,r=r|0,nD[e&15](n|0,r|0)|0}function kB(e,n,r,o,a,s){e=e|0,n=n|0,r=r|0,o=+o,a=+a,s=s|0,uU[e&1](n|0,r|0,+o,+a,s|0)}function OB(e,n,r,o,a,s,h){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0,h=h|0,lU[e&1](n|0,r|0,o|0,a|0,s|0,h|0)}function MB(e,n,r){return e=e|0,n=n|0,r=r|0,+pS[e&7](n|0,r|0)}function NB(e){return e=e|0,Ay[e&7]()|0}function FB(e,n,r,o,a,s){return e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0,hS[e&1](n|0,r|0,o|0,a|0,s|0)|0}function LB(e,n,r,o,a){e=e|0,n=n|0,r=r|0,o=o|0,a=+a,aU[e&1](n|0,r|0,o|0,+a)}function bB(e,n,r,o,a,s,h){e=e|0,n=n|0,r=r|0,o=w(o),a=a|0,s=w(s),h=h|0,vS[e&1](n|0,r|0,w(o),a|0,w(s),h|0)}function PB(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,lh[e&15](n|0,r|0,o|0)}function IB(e){e=e|0,mS[e&0]()}function BB(e,n,r,o){e=e|0,n=n|0,r=r|0,o=+o,yS[e&15](n|0,r|0,+o)}function UB(e,n,r){return e=e|0,n=+n,r=+r,sU[e&1](+n,+r)|0}function jB(e,n,r,o,a){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,rD[e&15](n|0,r|0,o|0,a|0)}function zB(e,n,r,o,a){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,Ct(0)}function qB(e,n){e=e|0,n=w(n),Ct(1)}function Ju(e,n){e=e|0,n=+n,Ct(2)}function HB(e,n,r){return e=e|0,n=w(n),r=w(r),Ct(3),lt}function En(e){e=e|0,Ct(4)}function oh(e,n){e=e|0,n=n|0,Ct(5)}function _l(e){return e=e|0,Ct(6),0}function WB(e,n,r,o){e=e|0,n=+n,r=+r,o=o|0,Ct(7)}function VB(e,n,r){e=e|0,n=+n,r=+r,Ct(8)}function GB(e,n,r){return e=e|0,n=n|0,r=r|0,Ct(9),0}function YB(e,n,r){return e=e|0,n=n|0,r=r|0,Ct(10),0}function $c(e){return e=e|0,Ct(11),0}function KB(e,n){return e=e|0,n=+n,Ct(12),0}function uh(e,n){return e=e|0,n=n|0,Ct(13),0}function XB(e,n,r,o,a){e=e|0,n=n|0,r=+r,o=+o,a=a|0,Ct(14)}function QB(e,n,r,o,a,s){e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,s=s|0,Ct(15)}function tD(e,n){return e=e|0,n=n|0,Ct(16),0}function JB(){return Ct(17),0}function ZB(e,n,r,o,a){return e=e|0,n=n|0,r=r|0,o=o|0,a=a|0,Ct(18),0}function $B(e,n,r,o){e=e|0,n=n|0,r=r|0,o=+o,Ct(19)}function eU(e,n,r,o,a,s){e=e|0,n=n|0,r=w(r),o=o|0,a=w(a),s=s|0,Ct(20)}function xy(e,n,r){e=e|0,n=n|0,r=r|0,Ct(21)}function tU(){Ct(22)}function R2(e,n,r){e=e|0,n=n|0,r=+r,Ct(23)}function nU(e,n){return e=+e,n=+n,Ct(24),0}function A2(e,n,r,o){e=e|0,n=n|0,r=r|0,o=o|0,Ct(25)}var lS=[zB,QF],aS=[qB,s0],sS=[Ju,ya,ga,bs,Ea,Bo,Af,$o,kf,Uo,Is,T1,Ec,Da,C1,es,x1,Of,Mf,Ju,Ju,Ju,Ju,Ju,Ju,Ju,Ju,Ju,Ju,Ju,Ju,Ju],fS=[HB],tf=[En,C2,qt,Xu,is,Ks,Hc,Au,CN,xN,RN,IF,BF,UF,lI,aI,sI,Se,xf,Za,eu,Ps,Tv,F1,Rd,zf,bd,Wv,h4,nm,sm,M4,pp,W4,$4,Bc,Yf,v_,D_,Wm,Km,W_,eE,cE,fy,vt,Ti,a0,Uk,tO,EO,BO,$O,EM,OM,FM,QM,$M,mN,kN,NN,XN,pF,Od,XL,Rb,qb,rP,CP,jP,JP,eI,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En,En],nf=[oh,ld,E1,_c,Eu,w1,ad,Bl,Du,Fs,Ls,$a,wa,ke,Ke,Nt,yn,Rr,Fn,Nf,Ev,Jg,hE,_E,qO,ZL,DF,Mw,oh,oh,oh,oh],e1=[_l,BI,Ns,m,K,ie,dt,ft,mt,Gn,ki,b0,ts,gv,vd,ku,rM,ZN,nb,ml,_l,_l,_l,_l,_l,_l,_l,_l,_l,_l,_l,_l],cS=[WB,Cv],rU=[VB,_N],Ry=[GB,Vw,UI,qI,im,Fm,Hk,lP],iU=[YB,t_],dS=[$c,D0,Le,Sr,Xg,xv,Rv,Qg,Av,md,$c,$c,$c,$c,$c,$c],oU=[KB,RM],nD=[uh,sB,_v,cl,zd,C4,sp,Rp,w_,Yn,Po,Gb,uh,uh,uh,uh],uU=[XB,Bv],lU=[QB,kP],pS=[tD,li,Zg,yd,gd,ru,tD,tD],Ay=[JB,_d,va,E0,IM,rN,PN,iI],hS=[ZB,Xa],aU=[$B,z_],vS=[eU,Yg],lh=[xy,C,f0,cr,ji,Pc,e2,G_,Gp,po,_L,Mb,WP,xy,xy,xy],mS=[tU],yS=[R2,D1,Il,S1,Io,R1,wu,y,F_,oO,SM,R2,R2,R2,R2,R2],sU=[nU,SN],rD=[A2,yp,hs,TO,dM,HM,sN,HN,gF,ab,vI,A2,A2,A2,A2,A2];return{_llvm_bswap_i32:uS,dynCall_idd:UB,dynCall_i:NB,_i64Subtract:Ty,___udivdi3:$E,dynCall_vif:mB,setThrew:nl,dynCall_viii:PB,_bitshift64Lshr:Cy,_bitshift64Shl:rS,dynCall_vi:_B,dynCall_viiddi:kB,dynCall_diii:CB,dynCall_iii:AB,_memset:x2,_sbrk:$f,_memcpy:bn,__GLOBAL__sub_I_Yoga_cpp:hi,dynCall_vii:EB,___uremdi3:eD,dynCall_vid:yB,stackAlloc:oo,_nbind_init:xI,getTempRet0:W,dynCall_di:xB,dynCall_iid:RB,setTempRet0:q0,_i64Add:ZE,dynCall_fiff:gB,dynCall_iiii:TB,_emscripten_get_global_libc:II,dynCall_viid:BB,dynCall_viiid:LB,dynCall_viififi:bB,dynCall_ii:DB,__GLOBAL__sub_I_Binding_cc:jL,dynCall_viiii:jB,dynCall_iiiiii:FB,stackSave:yu,dynCall_viiiii:vB,__GLOBAL__sub_I_nbind_cc:Ed,dynCall_vidd:SB,_free:wy,runPostSets:hB,dynCall_viiiiii:OB,establishStackSpace:e0,_memmove:ih,stackRestore:la,_malloc:Dy,__GLOBAL__sub_I_common_cc:uF,dynCall_viddi:wB,dynCall_dii:MB,dynCall_v:IB}}(Module.asmGlobalArg,Module.asmLibraryArg,buffer),_llvm_bswap_i32=Module._llvm_bswap_i32=asm._llvm_bswap_i32,getTempRet0=Module.getTempRet0=asm.getTempRet0,___udivdi3=Module.___udivdi3=asm.___udivdi3,setThrew=Module.setThrew=asm.setThrew,_bitshift64Lshr=Module._bitshift64Lshr=asm._bitshift64Lshr,_bitshift64Shl=Module._bitshift64Shl=asm._bitshift64Shl,_memset=Module._memset=asm._memset,_sbrk=Module._sbrk=asm._sbrk,_memcpy=Module._memcpy=asm._memcpy,stackAlloc=Module.stackAlloc=asm.stackAlloc,___uremdi3=Module.___uremdi3=asm.___uremdi3,_nbind_init=Module._nbind_init=asm._nbind_init,_i64Subtract=Module._i64Subtract=asm._i64Subtract,setTempRet0=Module.setTempRet0=asm.setTempRet0,_i64Add=Module._i64Add=asm._i64Add,_emscripten_get_global_libc=Module._emscripten_get_global_libc=asm._emscripten_get_global_libc,__GLOBAL__sub_I_Yoga_cpp=Module.__GLOBAL__sub_I_Yoga_cpp=asm.__GLOBAL__sub_I_Yoga_cpp,__GLOBAL__sub_I_Binding_cc=Module.__GLOBAL__sub_I_Binding_cc=asm.__GLOBAL__sub_I_Binding_cc,stackSave=Module.stackSave=asm.stackSave,__GLOBAL__sub_I_nbind_cc=Module.__GLOBAL__sub_I_nbind_cc=asm.__GLOBAL__sub_I_nbind_cc,_free=Module._free=asm._free,runPostSets=Module.runPostSets=asm.runPostSets,establishStackSpace=Module.establishStackSpace=asm.establishStackSpace,_memmove=Module._memmove=asm._memmove,stackRestore=Module.stackRestore=asm.stackRestore,_malloc=Module._malloc=asm._malloc,__GLOBAL__sub_I_common_cc=Module.__GLOBAL__sub_I_common_cc=asm.__GLOBAL__sub_I_common_cc,dynCall_viiiii=Module.dynCall_viiiii=asm.dynCall_viiiii,dynCall_vif=Module.dynCall_vif=asm.dynCall_vif,dynCall_vid=Module.dynCall_vid=asm.dynCall_vid,dynCall_fiff=Module.dynCall_fiff=asm.dynCall_fiff,dynCall_vi=Module.dynCall_vi=asm.dynCall_vi,dynCall_vii=Module.dynCall_vii=asm.dynCall_vii,dynCall_ii=Module.dynCall_ii=asm.dynCall_ii,dynCall_viddi=Module.dynCall_viddi=asm.dynCall_viddi,dynCall_vidd=Module.dynCall_vidd=asm.dynCall_vidd,dynCall_iiii=Module.dynCall_iiii=asm.dynCall_iiii,dynCall_diii=Module.dynCall_diii=asm.dynCall_diii,dynCall_di=Module.dynCall_di=asm.dynCall_di,dynCall_iid=Module.dynCall_iid=asm.dynCall_iid,dynCall_iii=Module.dynCall_iii=asm.dynCall_iii,dynCall_viiddi=Module.dynCall_viiddi=asm.dynCall_viiddi,dynCall_viiiiii=Module.dynCall_viiiiii=asm.dynCall_viiiiii,dynCall_dii=Module.dynCall_dii=asm.dynCall_dii,dynCall_i=Module.dynCall_i=asm.dynCall_i,dynCall_iiiiii=Module.dynCall_iiiiii=asm.dynCall_iiiiii,dynCall_viiid=Module.dynCall_viiid=asm.dynCall_viiid,dynCall_viififi=Module.dynCall_viififi=asm.dynCall_viififi,dynCall_viii=Module.dynCall_viii=asm.dynCall_viii,dynCall_v=Module.dynCall_v=asm.dynCall_v,dynCall_viid=Module.dynCall_viid=asm.dynCall_viid,dynCall_idd=Module.dynCall_idd=asm.dynCall_idd,dynCall_viiii=Module.dynCall_viiii=asm.dynCall_viiii;Runtime.stackAlloc=Module.stackAlloc,Runtime.stackSave=Module.stackSave,Runtime.stackRestore=Module.stackRestore,Runtime.establishStackSpace=Module.establishStackSpace,Runtime.setTempRet0=Module.setTempRet0,Runtime.getTempRet0=Module.getTempRet0,Module.asm=asm;function ExitStatus(u){this.name="ExitStatus",this.message="Program terminated with exit("+u+")",this.status=u}ExitStatus.prototype=new Error,ExitStatus.prototype.constructor=ExitStatus;var initialStackTop,preloadStartTime=null,calledMain=!1;dependenciesFulfilled=function u(){Module.calledRun||run(),Module.calledRun||(dependenciesFulfilled=u)},Module.callMain=Module.callMain=function u(l){l=l||[],ensureInitRuntime();var c=l.length+1;function p(){for(var A=0;A<4-1;A++)_.push(0)}var _=[allocate(intArrayFromString(Module.thisProgram),"i8",ALLOC_NORMAL)];p();for(var t=0;t0||(preRun(),runDependencies>0)||Module.calledRun)return;function l(){Module.calledRun||(Module.calledRun=!0,!ABORT&&(ensureInitRuntime(),preMain(),Module.onRuntimeInitialized&&Module.onRuntimeInitialized(),Module._main&&shouldRunNow&&Module.callMain(u),postRun()))}Module.setStatus?(Module.setStatus("Running..."),setTimeout(function(){setTimeout(function(){Module.setStatus("")},1),l()},1)):l()}Module.run=Module.run=run;function exit(u,l){l&&Module.noExitRuntime||(Module.noExitRuntime||(ABORT=!0,EXITSTATUS=u,STACKTOP=initialStackTop,exitRuntime(),Module.onExit&&Module.onExit(u)),ENVIRONMENT_IS_NODE&&process.exit(u),Module.quit(u,new ExitStatus(u)))}Module.exit=Module.exit=exit;var abortDecorators=[];function abort(u){Module.onAbort&&Module.onAbort(u),u!==void 0?(Module.print(u),Module.printErr(u),u=JSON.stringify(u)):u="",ABORT=!0,EXITSTATUS=1;var l=` +If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.`,c="abort("+u+") at "+stackTrace()+l;throw abortDecorators&&abortDecorators.forEach(function(p){c=p(c,u)}),c}if(Module.abort=Module.abort=abort,Module.preInit)for(typeof Module.preInit=="function"&&(Module.preInit=[Module.preInit]);Module.preInit.length>0;)Module.preInit.pop()();var shouldRunNow=!0;Module.noInitialRun&&(shouldRunNow=!1),run()})});var a1=re((xre,eR)=>{"use strict";var OX=Z9(),MX=$9(),y3=!1,g3=null;MX({},function(u,l){if(!y3){if(y3=!0,u)throw u;g3=l}});if(!y3)throw new Error("Failed to load the yoga module - it needed to be loaded synchronously, but didn't");eR.exports=OX(g3.bind,g3.lib)});var nR=re((Rre,tR)=>{"use strict";tR.exports=({onlyFirst:u=!1}={})=>{let l=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(l,u?void 0:"g")}});var _3=re((Are,rR)=>{"use strict";var NX=nR();rR.exports=u=>typeof u=="string"?u.replace(NX(),""):u});var D3=re((kre,E3)=>{"use strict";var iR=u=>Number.isNaN(u)?!1:u>=4352&&(u<=4447||u===9001||u===9002||11904<=u&&u<=12871&&u!==12351||12880<=u&&u<=19903||19968<=u&&u<=42182||43360<=u&&u<=43388||44032<=u&&u<=55203||63744<=u&&u<=64255||65040<=u&&u<=65049||65072<=u&&u<=65131||65281<=u&&u<=65376||65504<=u&&u<=65510||110592<=u&&u<=110593||127488<=u&&u<=127569||131072<=u&&u<=262141);E3.exports=iR;E3.exports.default=iR});var uR=re((Ore,oR)=>{"use strict";oR.exports=function(){return/\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB-\uDFFD])|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)\uFE0F|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620)\uFE0F|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF4\uD83C\uDDF2|\uD83C\uDDF6\uD83C\uDDE6|[#\*0-9]\uFE0F\u20E3|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC70\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD36\uDDB5\uDDB6\uDDBB\uDDD2-\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5\uDEEB\uDEEC\uDEF4-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g}});var hg=re((Mre,w3)=>{"use strict";var FX=_3(),LX=D3(),bX=uR(),lR=u=>{if(typeof u!="string"||u.length===0||(u=FX(u),u.length===0))return 0;u=u.replace(bX()," ");let l=0;for(let c=0;c=127&&p<=159||p>=768&&p<=879||(p>65535&&c++,l+=LX(p)?2:1)}return l};w3.exports=lR;w3.exports.default=lR});var T3=re((Nre,S3)=>{"use strict";var PX=hg(),aR=u=>{let l=0;for(let c of u.split(` +`))l=Math.max(l,PX(c));return l};S3.exports=aR;S3.exports.default=aR});var sR=re(Nh=>{"use strict";var IX=Nh&&Nh.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(Nh,"__esModule",{value:!0});var BX=IX(T3()),C3={};Nh.default=u=>{if(u.length===0)return{width:0,height:0};if(C3[u])return C3[u];let l=BX.default(u),c=u.split(` +`).length;return C3[u]={width:l,height:c},{width:l,height:c}}});var fR=re(Fh=>{"use strict";var UX=Fh&&Fh.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(Fh,"__esModule",{value:!0});var Yr=UX(a1()),jX=(u,l)=>{"position"in l&&u.setPositionType(l.position==="absolute"?Yr.default.POSITION_TYPE_ABSOLUTE:Yr.default.POSITION_TYPE_RELATIVE)},zX=(u,l)=>{"marginLeft"in l&&u.setMargin(Yr.default.EDGE_START,l.marginLeft||0),"marginRight"in l&&u.setMargin(Yr.default.EDGE_END,l.marginRight||0),"marginTop"in l&&u.setMargin(Yr.default.EDGE_TOP,l.marginTop||0),"marginBottom"in l&&u.setMargin(Yr.default.EDGE_BOTTOM,l.marginBottom||0)},qX=(u,l)=>{"paddingLeft"in l&&u.setPadding(Yr.default.EDGE_LEFT,l.paddingLeft||0),"paddingRight"in l&&u.setPadding(Yr.default.EDGE_RIGHT,l.paddingRight||0),"paddingTop"in l&&u.setPadding(Yr.default.EDGE_TOP,l.paddingTop||0),"paddingBottom"in l&&u.setPadding(Yr.default.EDGE_BOTTOM,l.paddingBottom||0)},HX=(u,l)=>{var c;"flexGrow"in l&&u.setFlexGrow((c=l.flexGrow)!==null&&c!==void 0?c:0),"flexShrink"in l&&u.setFlexShrink(typeof l.flexShrink=="number"?l.flexShrink:1),"flexDirection"in l&&(l.flexDirection==="row"&&u.setFlexDirection(Yr.default.FLEX_DIRECTION_ROW),l.flexDirection==="row-reverse"&&u.setFlexDirection(Yr.default.FLEX_DIRECTION_ROW_REVERSE),l.flexDirection==="column"&&u.setFlexDirection(Yr.default.FLEX_DIRECTION_COLUMN),l.flexDirection==="column-reverse"&&u.setFlexDirection(Yr.default.FLEX_DIRECTION_COLUMN_REVERSE)),"flexBasis"in l&&(typeof l.flexBasis=="number"?u.setFlexBasis(l.flexBasis):typeof l.flexBasis=="string"?u.setFlexBasisPercent(Number.parseInt(l.flexBasis,10)):u.setFlexBasis(NaN)),"alignItems"in l&&((l.alignItems==="stretch"||!l.alignItems)&&u.setAlignItems(Yr.default.ALIGN_STRETCH),l.alignItems==="flex-start"&&u.setAlignItems(Yr.default.ALIGN_FLEX_START),l.alignItems==="center"&&u.setAlignItems(Yr.default.ALIGN_CENTER),l.alignItems==="flex-end"&&u.setAlignItems(Yr.default.ALIGN_FLEX_END)),"alignSelf"in l&&((l.alignSelf==="auto"||!l.alignSelf)&&u.setAlignSelf(Yr.default.ALIGN_AUTO),l.alignSelf==="flex-start"&&u.setAlignSelf(Yr.default.ALIGN_FLEX_START),l.alignSelf==="center"&&u.setAlignSelf(Yr.default.ALIGN_CENTER),l.alignSelf==="flex-end"&&u.setAlignSelf(Yr.default.ALIGN_FLEX_END)),"justifyContent"in l&&((l.justifyContent==="flex-start"||!l.justifyContent)&&u.setJustifyContent(Yr.default.JUSTIFY_FLEX_START),l.justifyContent==="center"&&u.setJustifyContent(Yr.default.JUSTIFY_CENTER),l.justifyContent==="flex-end"&&u.setJustifyContent(Yr.default.JUSTIFY_FLEX_END),l.justifyContent==="space-between"&&u.setJustifyContent(Yr.default.JUSTIFY_SPACE_BETWEEN),l.justifyContent==="space-around"&&u.setJustifyContent(Yr.default.JUSTIFY_SPACE_AROUND))},WX=(u,l)=>{var c,p;"width"in l&&(typeof l.width=="number"?u.setWidth(l.width):typeof l.width=="string"?u.setWidthPercent(Number.parseInt(l.width,10)):u.setWidthAuto()),"height"in l&&(typeof l.height=="number"?u.setHeight(l.height):typeof l.height=="string"?u.setHeightPercent(Number.parseInt(l.height,10)):u.setHeightAuto()),"minWidth"in l&&(typeof l.minWidth=="string"?u.setMinWidthPercent(Number.parseInt(l.minWidth,10)):u.setMinWidth((c=l.minWidth)!==null&&c!==void 0?c:0)),"minHeight"in l&&(typeof l.minHeight=="string"?u.setMinHeightPercent(Number.parseInt(l.minHeight,10)):u.setMinHeight((p=l.minHeight)!==null&&p!==void 0?p:0))},VX=(u,l)=>{"display"in l&&u.setDisplay(l.display==="flex"?Yr.default.DISPLAY_FLEX:Yr.default.DISPLAY_NONE)},GX=(u,l)=>{if("borderStyle"in l){let c=typeof l.borderStyle=="string"?1:0;u.setBorder(Yr.default.EDGE_TOP,c),u.setBorder(Yr.default.EDGE_BOTTOM,c),u.setBorder(Yr.default.EDGE_LEFT,c),u.setBorder(Yr.default.EDGE_RIGHT,c)}};Fh.default=(u,l={})=>{jX(u,l),zX(u,l),qX(u,l),HX(u,l),WX(u,l),VX(u,l),GX(u,l)}});var dR=re((bre,cR)=>{"use strict";cR.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}});var x3=re((Pre,hR)=>{var Lh=dR(),pR={};for(let u of Object.keys(Lh))pR[Lh[u]]=u;var fn={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};hR.exports=fn;for(let u of Object.keys(fn)){if(!("channels"in fn[u]))throw new Error("missing channels property: "+u);if(!("labels"in fn[u]))throw new Error("missing channel labels property: "+u);if(fn[u].labels.length!==fn[u].channels)throw new Error("channel and label counts mismatch: "+u);let{channels:l,labels:c}=fn[u];delete fn[u].channels,delete fn[u].labels,Object.defineProperty(fn[u],"channels",{value:l}),Object.defineProperty(fn[u],"labels",{value:c})}fn.rgb.hsl=function(u){let l=u[0]/255,c=u[1]/255,p=u[2]/255,_=Math.min(l,c,p),t=Math.max(l,c,p),O=t-_,M,A;t===_?M=0:l===t?M=(c-p)/O:c===t?M=2+(p-l)/O:p===t&&(M=4+(l-c)/O),M=Math.min(M*60,360),M<0&&(M+=360);let T=(_+t)/2;return t===_?A=0:T<=.5?A=O/(t+_):A=O/(2-t-_),[M,A*100,T*100]};fn.rgb.hsv=function(u){let l,c,p,_,t,O=u[0]/255,M=u[1]/255,A=u[2]/255,T=Math.max(O,M,A),P=T-Math.min(O,M,A),U=function(z){return(T-z)/6/P+1/2};return P===0?(_=0,t=0):(t=P/T,l=U(O),c=U(M),p=U(A),O===T?_=p-c:M===T?_=1/3+l-p:A===T&&(_=2/3+c-l),_<0?_+=1:_>1&&(_-=1)),[_*360,t*100,T*100]};fn.rgb.hwb=function(u){let l=u[0],c=u[1],p=u[2],_=fn.rgb.hsl(u)[0],t=1/255*Math.min(l,Math.min(c,p));return p=1-1/255*Math.max(l,Math.max(c,p)),[_,t*100,p*100]};fn.rgb.cmyk=function(u){let l=u[0]/255,c=u[1]/255,p=u[2]/255,_=Math.min(1-l,1-c,1-p),t=(1-l-_)/(1-_)||0,O=(1-c-_)/(1-_)||0,M=(1-p-_)/(1-_)||0;return[t*100,O*100,M*100,_*100]};function YX(u,l){return(u[0]-l[0])**2+(u[1]-l[1])**2+(u[2]-l[2])**2}fn.rgb.keyword=function(u){let l=pR[u];if(l)return l;let c=1/0,p;for(let _ of Object.keys(Lh)){let t=Lh[_],O=YX(u,t);O.04045?((l+.055)/1.055)**2.4:l/12.92,c=c>.04045?((c+.055)/1.055)**2.4:c/12.92,p=p>.04045?((p+.055)/1.055)**2.4:p/12.92;let _=l*.4124+c*.3576+p*.1805,t=l*.2126+c*.7152+p*.0722,O=l*.0193+c*.1192+p*.9505;return[_*100,t*100,O*100]};fn.rgb.lab=function(u){let l=fn.rgb.xyz(u),c=l[0],p=l[1],_=l[2];c/=95.047,p/=100,_/=108.883,c=c>.008856?c**(1/3):7.787*c+16/116,p=p>.008856?p**(1/3):7.787*p+16/116,_=_>.008856?_**(1/3):7.787*_+16/116;let t=116*p-16,O=500*(c-p),M=200*(p-_);return[t,O,M]};fn.hsl.rgb=function(u){let l=u[0]/360,c=u[1]/100,p=u[2]/100,_,t,O;if(c===0)return O=p*255,[O,O,O];p<.5?_=p*(1+c):_=p+c-p*c;let M=2*p-_,A=[0,0,0];for(let T=0;T<3;T++)t=l+1/3*-(T-1),t<0&&t++,t>1&&t--,6*t<1?O=M+(_-M)*6*t:2*t<1?O=_:3*t<2?O=M+(_-M)*(2/3-t)*6:O=M,A[T]=O*255;return A};fn.hsl.hsv=function(u){let l=u[0],c=u[1]/100,p=u[2]/100,_=c,t=Math.max(p,.01);p*=2,c*=p<=1?p:2-p,_*=t<=1?t:2-t;let O=(p+c)/2,M=p===0?2*_/(t+_):2*c/(p+c);return[l,M*100,O*100]};fn.hsv.rgb=function(u){let l=u[0]/60,c=u[1]/100,p=u[2]/100,_=Math.floor(l)%6,t=l-Math.floor(l),O=255*p*(1-c),M=255*p*(1-c*t),A=255*p*(1-c*(1-t));switch(p*=255,_){case 0:return[p,A,O];case 1:return[M,p,O];case 2:return[O,p,A];case 3:return[O,M,p];case 4:return[A,O,p];case 5:return[p,O,M]}};fn.hsv.hsl=function(u){let l=u[0],c=u[1]/100,p=u[2]/100,_=Math.max(p,.01),t,O;O=(2-c)*p;let M=(2-c)*_;return t=c*_,t/=M<=1?M:2-M,t=t||0,O/=2,[l,t*100,O*100]};fn.hwb.rgb=function(u){let l=u[0]/360,c=u[1]/100,p=u[2]/100,_=c+p,t;_>1&&(c/=_,p/=_);let O=Math.floor(6*l),M=1-p;t=6*l-O,(O&1)!==0&&(t=1-t);let A=c+t*(M-c),T,P,U;switch(O){default:case 6:case 0:T=M,P=A,U=c;break;case 1:T=A,P=M,U=c;break;case 2:T=c,P=M,U=A;break;case 3:T=c,P=A,U=M;break;case 4:T=A,P=c,U=M;break;case 5:T=M,P=c,U=A;break}return[T*255,P*255,U*255]};fn.cmyk.rgb=function(u){let l=u[0]/100,c=u[1]/100,p=u[2]/100,_=u[3]/100,t=1-Math.min(1,l*(1-_)+_),O=1-Math.min(1,c*(1-_)+_),M=1-Math.min(1,p*(1-_)+_);return[t*255,O*255,M*255]};fn.xyz.rgb=function(u){let l=u[0]/100,c=u[1]/100,p=u[2]/100,_,t,O;return _=l*3.2406+c*-1.5372+p*-.4986,t=l*-.9689+c*1.8758+p*.0415,O=l*.0557+c*-.204+p*1.057,_=_>.0031308?1.055*_**(1/2.4)-.055:_*12.92,t=t>.0031308?1.055*t**(1/2.4)-.055:t*12.92,O=O>.0031308?1.055*O**(1/2.4)-.055:O*12.92,_=Math.min(Math.max(0,_),1),t=Math.min(Math.max(0,t),1),O=Math.min(Math.max(0,O),1),[_*255,t*255,O*255]};fn.xyz.lab=function(u){let l=u[0],c=u[1],p=u[2];l/=95.047,c/=100,p/=108.883,l=l>.008856?l**(1/3):7.787*l+16/116,c=c>.008856?c**(1/3):7.787*c+16/116,p=p>.008856?p**(1/3):7.787*p+16/116;let _=116*c-16,t=500*(l-c),O=200*(c-p);return[_,t,O]};fn.lab.xyz=function(u){let l=u[0],c=u[1],p=u[2],_,t,O;t=(l+16)/116,_=c/500+t,O=t-p/200;let M=t**3,A=_**3,T=O**3;return t=M>.008856?M:(t-16/116)/7.787,_=A>.008856?A:(_-16/116)/7.787,O=T>.008856?T:(O-16/116)/7.787,_*=95.047,t*=100,O*=108.883,[_,t,O]};fn.lab.lch=function(u){let l=u[0],c=u[1],p=u[2],_;_=Math.atan2(p,c)*360/2/Math.PI,_<0&&(_+=360);let O=Math.sqrt(c*c+p*p);return[l,O,_]};fn.lch.lab=function(u){let l=u[0],c=u[1],_=u[2]/360*2*Math.PI,t=c*Math.cos(_),O=c*Math.sin(_);return[l,t,O]};fn.rgb.ansi16=function(u,l=null){let[c,p,_]=u,t=l===null?fn.rgb.hsv(u)[2]:l;if(t=Math.round(t/50),t===0)return 30;let O=30+(Math.round(_/255)<<2|Math.round(p/255)<<1|Math.round(c/255));return t===2&&(O+=60),O};fn.hsv.ansi16=function(u){return fn.rgb.ansi16(fn.hsv.rgb(u),u[2])};fn.rgb.ansi256=function(u){let l=u[0],c=u[1],p=u[2];return l===c&&c===p?l<8?16:l>248?231:Math.round((l-8)/247*24)+232:16+36*Math.round(l/255*5)+6*Math.round(c/255*5)+Math.round(p/255*5)};fn.ansi16.rgb=function(u){let l=u%10;if(l===0||l===7)return u>50&&(l+=3.5),l=l/10.5*255,[l,l,l];let c=(~~(u>50)+1)*.5,p=(l&1)*c*255,_=(l>>1&1)*c*255,t=(l>>2&1)*c*255;return[p,_,t]};fn.ansi256.rgb=function(u){if(u>=232){let t=(u-232)*10+8;return[t,t,t]}u-=16;let l,c=Math.floor(u/36)/5*255,p=Math.floor((l=u%36)/6)/5*255,_=l%6/5*255;return[c,p,_]};fn.rgb.hex=function(u){let c=(((Math.round(u[0])&255)<<16)+((Math.round(u[1])&255)<<8)+(Math.round(u[2])&255)).toString(16).toUpperCase();return"000000".substring(c.length)+c};fn.hex.rgb=function(u){let l=u.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!l)return[0,0,0];let c=l[0];l[0].length===3&&(c=c.split("").map(M=>M+M).join(""));let p=parseInt(c,16),_=p>>16&255,t=p>>8&255,O=p&255;return[_,t,O]};fn.rgb.hcg=function(u){let l=u[0]/255,c=u[1]/255,p=u[2]/255,_=Math.max(Math.max(l,c),p),t=Math.min(Math.min(l,c),p),O=_-t,M,A;return O<1?M=t/(1-O):M=0,O<=0?A=0:_===l?A=(c-p)/O%6:_===c?A=2+(p-l)/O:A=4+(l-c)/O,A/=6,A%=1,[A*360,O*100,M*100]};fn.hsl.hcg=function(u){let l=u[1]/100,c=u[2]/100,p=c<.5?2*l*c:2*l*(1-c),_=0;return p<1&&(_=(c-.5*p)/(1-p)),[u[0],p*100,_*100]};fn.hsv.hcg=function(u){let l=u[1]/100,c=u[2]/100,p=l*c,_=0;return p<1&&(_=(c-p)/(1-p)),[u[0],p*100,_*100]};fn.hcg.rgb=function(u){let l=u[0]/360,c=u[1]/100,p=u[2]/100;if(c===0)return[p*255,p*255,p*255];let _=[0,0,0],t=l%1*6,O=t%1,M=1-O,A=0;switch(Math.floor(t)){case 0:_[0]=1,_[1]=O,_[2]=0;break;case 1:_[0]=M,_[1]=1,_[2]=0;break;case 2:_[0]=0,_[1]=1,_[2]=O;break;case 3:_[0]=0,_[1]=M,_[2]=1;break;case 4:_[0]=O,_[1]=0,_[2]=1;break;default:_[0]=1,_[1]=0,_[2]=M}return A=(1-c)*p,[(c*_[0]+A)*255,(c*_[1]+A)*255,(c*_[2]+A)*255]};fn.hcg.hsv=function(u){let l=u[1]/100,c=u[2]/100,p=l+c*(1-l),_=0;return p>0&&(_=l/p),[u[0],_*100,p*100]};fn.hcg.hsl=function(u){let l=u[1]/100,p=u[2]/100*(1-l)+.5*l,_=0;return p>0&&p<.5?_=l/(2*p):p>=.5&&p<1&&(_=l/(2*(1-p))),[u[0],_*100,p*100]};fn.hcg.hwb=function(u){let l=u[1]/100,c=u[2]/100,p=l+c*(1-l);return[u[0],(p-l)*100,(1-p)*100]};fn.hwb.hcg=function(u){let l=u[1]/100,p=1-u[2]/100,_=p-l,t=0;return _<1&&(t=(p-_)/(1-_)),[u[0],_*100,t*100]};fn.apple.rgb=function(u){return[u[0]/65535*255,u[1]/65535*255,u[2]/65535*255]};fn.rgb.apple=function(u){return[u[0]/255*65535,u[1]/255*65535,u[2]/255*65535]};fn.gray.rgb=function(u){return[u[0]/100*255,u[0]/100*255,u[0]/100*255]};fn.gray.hsl=function(u){return[0,0,u[0]]};fn.gray.hsv=fn.gray.hsl;fn.gray.hwb=function(u){return[0,100,u[0]]};fn.gray.cmyk=function(u){return[0,0,0,u[0]]};fn.gray.lab=function(u){return[u[0],0,0]};fn.gray.hex=function(u){let l=Math.round(u[0]/100*255)&255,p=((l<<16)+(l<<8)+l).toString(16).toUpperCase();return"000000".substring(p.length)+p};fn.rgb.gray=function(u){return[(u[0]+u[1]+u[2])/3/255*100]}});var mR=re((Ire,vR)=>{var vg=x3();function KX(){let u={},l=Object.keys(vg);for(let c=l.length,p=0;p{var R3=x3(),ZX=mR(),$2={},$X=Object.keys(R3);function eQ(u){let l=function(...c){let p=c[0];return p==null?p:(p.length>1&&(c=p),u(c))};return"conversion"in u&&(l.conversion=u.conversion),l}function tQ(u){let l=function(...c){let p=c[0];if(p==null)return p;p.length>1&&(c=p);let _=u(c);if(typeof _=="object")for(let t=_.length,O=0;O{$2[u]={},Object.defineProperty($2[u],"channels",{value:R3[u].channels}),Object.defineProperty($2[u],"labels",{value:R3[u].labels});let l=ZX(u);Object.keys(l).forEach(p=>{let _=l[p];$2[u][p]=tQ(_),$2[u][p].raw=eQ(_)})});yR.exports=$2});var yg=re((Ure,SR)=>{"use strict";var _R=(u,l)=>(...c)=>`\x1B[${u(...c)+l}m`,ER=(u,l)=>(...c)=>{let p=u(...c);return`\x1B[${38+l};5;${p}m`},DR=(u,l)=>(...c)=>{let p=u(...c);return`\x1B[${38+l};2;${p[0]};${p[1]};${p[2]}m`},mg=u=>u,wR=(u,l,c)=>[u,l,c],ed=(u,l,c)=>{Object.defineProperty(u,l,{get:()=>{let p=c();return Object.defineProperty(u,l,{value:p,enumerable:!0,configurable:!0}),p},enumerable:!0,configurable:!0})},A3,td=(u,l,c,p)=>{A3===void 0&&(A3=gR());let _=p?10:0,t={};for(let[O,M]of Object.entries(A3)){let A=O==="ansi16"?"ansi":O;O===l?t[A]=u(c,_):typeof M=="object"&&(t[A]=u(M[l],_))}return t};function nQ(){let u=new Map,l={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};l.color.gray=l.color.blackBright,l.bgColor.bgGray=l.bgColor.bgBlackBright,l.color.grey=l.color.blackBright,l.bgColor.bgGrey=l.bgColor.bgBlackBright;for(let[c,p]of Object.entries(l)){for(let[_,t]of Object.entries(p))l[_]={open:`\x1B[${t[0]}m`,close:`\x1B[${t[1]}m`},p[_]=l[_],u.set(t[0],t[1]);Object.defineProperty(l,c,{value:p,enumerable:!1})}return Object.defineProperty(l,"codes",{value:u,enumerable:!1}),l.color.close="\x1B[39m",l.bgColor.close="\x1B[49m",ed(l.color,"ansi",()=>td(_R,"ansi16",mg,!1)),ed(l.color,"ansi256",()=>td(ER,"ansi256",mg,!1)),ed(l.color,"ansi16m",()=>td(DR,"rgb",wR,!1)),ed(l.bgColor,"ansi",()=>td(_R,"ansi16",mg,!0)),ed(l.bgColor,"ansi256",()=>td(ER,"ansi256",mg,!0)),ed(l.bgColor,"ansi16m",()=>td(DR,"rgb",wR,!0)),l}Object.defineProperty(SR,"exports",{enumerable:!0,get:nQ})});var xR=re((jre,CR)=>{"use strict";var bh=hg(),rQ=_3(),iQ=yg(),O3=new Set(["\x1B","\x9B"]),oQ=39,TR=u=>`${O3.values().next().value}[${u}m`,uQ=u=>u.split(" ").map(l=>bh(l)),k3=(u,l,c)=>{let p=[...l],_=!1,t=bh(rQ(u[u.length-1]));for(let[O,M]of p.entries()){let A=bh(M);if(t+A<=c?u[u.length-1]+=M:(u.push(M),t=0),O3.has(M))_=!0;else if(_&&M==="m"){_=!1;continue}_||(t+=A,t===c&&O0&&u.length>1&&(u[u.length-2]+=u.pop())},lQ=u=>{let l=u.split(" "),c=l.length;for(;c>0&&!(bh(l[c-1])>0);)c--;return c===l.length?u:l.slice(0,c).join(" ")+l.slice(c).join("")},aQ=(u,l,c={})=>{if(c.trim!==!1&&u.trim()==="")return"";let p="",_="",t,O=uQ(u),M=[""];for(let[A,T]of u.split(" ").entries()){c.trim!==!1&&(M[M.length-1]=M[M.length-1].trimLeft());let P=bh(M[M.length-1]);if(A!==0&&(P>=l&&(c.wordWrap===!1||c.trim===!1)&&(M.push(""),P=0),(P>0||c.trim===!1)&&(M[M.length-1]+=" ",P++)),c.hard&&O[A]>l){let U=l-P,z=1+Math.floor((O[A]-U-1)/l);Math.floor((O[A]-1)/l)l&&P>0&&O[A]>0){if(c.wordWrap===!1&&Pl&&c.wordWrap===!1){k3(M,T,l);continue}M[M.length-1]+=T}c.trim!==!1&&(M=M.map(lQ)),p=M.join(` +`);for(let[A,T]of[...p].entries()){if(_+=T,O3.has(T)){let U=parseFloat(/\d[^m]*/.exec(p.slice(A,A+4)));t=U===oQ?null:U}let P=iQ.codes.get(Number(t));t&&P&&(p[A+1]===` +`?_+=TR(P):T===` +`&&(_+=TR(t)))}return _};CR.exports=(u,l,c)=>String(u).normalize().replace(/\r\n/g,` +`).split(` +`).map(p=>aQ(p,l,c)).join(` +`)});var kR=re((zre,AR)=>{"use strict";var RR="[\uD800-\uDBFF][\uDC00-\uDFFF]",sQ=u=>u&&u.exact?new RegExp(`^${RR}$`):new RegExp(RR,"g");AR.exports=sQ});var M3=re((qre,FR)=>{"use strict";var fQ=D3(),cQ=kR(),OR=yg(),NR=["\x1B","\x9B"],gg=u=>`${NR[0]}[${u}m`,MR=(u,l,c)=>{let p=[];u=[...u];for(let _ of u){let t=_;_.match(";")&&(_=_.split(";")[0][0]+"0");let O=OR.codes.get(parseInt(_,10));if(O){let M=u.indexOf(O.toString());M>=0?u.splice(M,1):p.push(gg(l?O:t))}else if(l){p.push(gg(0));break}else p.push(gg(t))}if(l&&(p=p.filter((_,t)=>p.indexOf(_)===t),c!==void 0)){let _=gg(OR.codes.get(parseInt(c,10)));p=p.reduce((t,O)=>O===_?[O,...t]:[...t,O],[])}return p.join("")};FR.exports=(u,l,c)=>{let p=[...u.normalize()],_=[];c=typeof c=="number"?c:p.length;let t=!1,O,M=0,A="";for(let[T,P]of p.entries()){let U=!1;if(NR.includes(P)){let z=/\d[^m]*/.exec(u.slice(T,T+18));O=z&&z.length>0?z[0]:void 0,Ml&&M<=c)A+=P;else if(M===l&&!t&&O!==void 0)A=MR(_);else if(M>=c){A+=MR(_,!0,O);break}}return A}});var bR=re((Hre,LR)=>{"use strict";var hc=M3(),dQ=hg();function _g(u,l,c){if(u.charAt(l)===" ")return l;for(let p=1;p<=3;p++)if(c){if(u.charAt(l+p)===" ")return l+p}else if(u.charAt(l-p)===" ")return l-p;return l}LR.exports=(u,l,c)=>{c={position:"end",preferTruncationOnSpace:!1,...c};let{position:p,space:_,preferTruncationOnSpace:t}=c,O="\u2026",M=1;if(typeof u!="string")throw new TypeError(`Expected \`input\` to be a string, got ${typeof u}`);if(typeof l!="number")throw new TypeError(`Expected \`columns\` to be a number, got ${typeof l}`);if(l<1)return"";if(l===1)return O;let A=dQ(u);if(A<=l)return u;if(p==="start"){if(t){let T=_g(u,A-l+1,!0);return O+hc(u,T,A).trim()}return _===!0&&(O+=" ",M=2),O+hc(u,A-l+M,A)}if(p==="middle"){_===!0&&(O=" "+O+" ",M=3);let T=Math.floor(l/2);if(t){let P=_g(u,T),U=_g(u,A-(l-T)+1,!0);return hc(u,0,P)+O+hc(u,U,A).trim()}return hc(u,0,T)+O+hc(u,A-(l-T)+M,A)}if(p==="end"){if(t){let T=_g(u,l-1);return hc(u,0,T)+O}return _===!0&&(O=" "+O,M=2),hc(u,0,l-M)+O}throw new Error(`Expected \`options.position\` to be either \`start\`, \`middle\` or \`end\`, got ${p}`)}});var F3=re(Ph=>{"use strict";var PR=Ph&&Ph.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(Ph,"__esModule",{value:!0});var pQ=PR(xR()),hQ=PR(bR()),N3={};Ph.default=(u,l,c)=>{let p=u+String(l)+String(c);if(N3[p])return N3[p];let _=u;if(c==="wrap"&&(_=pQ.default(u,l,{trim:!1,hard:!0})),c.startsWith("truncate")){let t="end";c==="truncate-middle"&&(t="middle"),c==="truncate-start"&&(t="start"),_=hQ.default(u,l,{position:t})}return N3[p]=_,_}});var b3=re(L3=>{"use strict";Object.defineProperty(L3,"__esModule",{value:!0});var IR=u=>{let l="";if(u.childNodes.length>0)for(let c of u.childNodes){let p="";c.nodeName==="#text"?p=c.nodeValue:((c.nodeName==="ink-text"||c.nodeName==="ink-virtual-text")&&(p=IR(c)),p.length>0&&typeof c.internal_transform=="function"&&(p=c.internal_transform(p))),l+=p}return l};L3.default=IR});var P3=re(Wi=>{"use strict";var Ih=Wi&&Wi.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(Wi,"__esModule",{value:!0});Wi.setTextNodeValue=Wi.createTextNode=Wi.setStyle=Wi.setAttribute=Wi.removeChildNode=Wi.insertBeforeNode=Wi.appendChildNode=Wi.createNode=Wi.TEXT_NAME=void 0;var vQ=Ih(a1()),BR=Ih(sR()),mQ=Ih(fR()),yQ=Ih(F3()),gQ=Ih(b3());Wi.TEXT_NAME="#text";Wi.createNode=u=>{var l;let c={nodeName:u,style:{},attributes:{},childNodes:[],parentNode:null,yogaNode:u==="ink-virtual-text"?void 0:vQ.default.Node.create()};return u==="ink-text"&&((l=c.yogaNode)===null||l===void 0||l.setMeasureFunc(_Q.bind(null,c))),c};Wi.appendChildNode=(u,l)=>{var c;l.parentNode&&Wi.removeChildNode(l.parentNode,l),l.parentNode=u,u.childNodes.push(l),l.yogaNode&&((c=u.yogaNode)===null||c===void 0||c.insertChild(l.yogaNode,u.yogaNode.getChildCount())),(u.nodeName==="ink-text"||u.nodeName==="ink-virtual-text")&&Eg(u)};Wi.insertBeforeNode=(u,l,c)=>{var p,_;l.parentNode&&Wi.removeChildNode(l.parentNode,l),l.parentNode=u;let t=u.childNodes.indexOf(c);if(t>=0){u.childNodes.splice(t,0,l),l.yogaNode&&((p=u.yogaNode)===null||p===void 0||p.insertChild(l.yogaNode,t));return}u.childNodes.push(l),l.yogaNode&&((_=u.yogaNode)===null||_===void 0||_.insertChild(l.yogaNode,u.yogaNode.getChildCount())),(u.nodeName==="ink-text"||u.nodeName==="ink-virtual-text")&&Eg(u)};Wi.removeChildNode=(u,l)=>{var c,p;l.yogaNode&&((p=(c=l.parentNode)===null||c===void 0?void 0:c.yogaNode)===null||p===void 0||p.removeChild(l.yogaNode)),l.parentNode=null;let _=u.childNodes.indexOf(l);_>=0&&u.childNodes.splice(_,1),(u.nodeName==="ink-text"||u.nodeName==="ink-virtual-text")&&Eg(u)};Wi.setAttribute=(u,l,c)=>{u.attributes[l]=c};Wi.setStyle=(u,l)=>{u.style=l,u.yogaNode&&mQ.default(u.yogaNode,l)};Wi.createTextNode=u=>{let l={nodeName:"#text",nodeValue:u,yogaNode:void 0,parentNode:null,style:{}};return Wi.setTextNodeValue(l,u),l};var _Q=function(u,l){var c,p;let _=u.nodeName==="#text"?u.nodeValue:gQ.default(u),t=BR.default(_);if(t.width<=l||t.width>=1&&l>0&&l<1)return t;let O=(p=(c=u.style)===null||c===void 0?void 0:c.textWrap)!==null&&p!==void 0?p:"wrap",M=yQ.default(_,l,O);return BR.default(M)},UR=u=>{var l;if(!(!u||!u.parentNode))return(l=u.yogaNode)!==null&&l!==void 0?l:UR(u.parentNode)},Eg=u=>{let l=UR(u);l==null||l.markDirty()};Wi.setTextNodeValue=(u,l)=>{typeof l!="string"&&(l=String(l)),u.nodeValue=l,Eg(u)}});var s1=re((Yre,jR)=>{"use strict";jR.exports={BINARY_TYPES:["nodebuffer","arraybuffer","fragments"],GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),EMPTY_BUFFER:Buffer.alloc(0),NOOP:()=>{}}});var Bh=re((Kre,I3)=>{"use strict";var{EMPTY_BUFFER:EQ}=s1();function zR(u,l){if(u.length===0)return EQ;if(u.length===1)return u[0];let c=Buffer.allocUnsafe(l),p=0;for(let _=0;_{"use strict";var VR=Symbol("kDone"),B3=Symbol("kRun"),U3=class{constructor(l){this[VR]=()=>{this.pending--,this[B3]()},this.concurrency=l||1/0,this.jobs=[],this.pending=0}add(l){this.jobs.push(l),this[B3]()}[B3](){if(this.pending!==this.concurrency&&this.jobs.length){let l=this.jobs.shift();this.pending++,l(this[VR])}}};GR.exports=U3});var zh=re((Qre,JR)=>{"use strict";var Uh=Kn("zlib"),KR=Bh(),DQ=YR(),{kStatusCode:XR,NOOP:wQ}=s1(),SQ=Buffer.from([0,0,255,255]),Sg=Symbol("permessage-deflate"),gf=Symbol("total-length"),jh=Symbol("callback"),vc=Symbol("buffers"),j3=Symbol("error"),wg,z3=class{constructor(l,c,p){if(this._maxPayload=p|0,this._options=l||{},this._threshold=this._options.threshold!==void 0?this._options.threshold:1024,this._isServer=!!c,this._deflate=null,this._inflate=null,this.params=null,!wg){let _=this._options.concurrencyLimit!==void 0?this._options.concurrencyLimit:10;wg=new DQ(_)}}static get extensionName(){return"permessage-deflate"}offer(){let l={};return this._options.serverNoContextTakeover&&(l.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(l.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(l.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?l.client_max_window_bits=this._options.clientMaxWindowBits:this._options.clientMaxWindowBits==null&&(l.client_max_window_bits=!0),l}accept(l){return l=this.normalizeParams(l),this.params=this._isServer?this.acceptAsServer(l):this.acceptAsClient(l),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){let l=this._deflate[jh];this._deflate.close(),this._deflate=null,l&&l(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(l){let c=this._options,p=l.find(_=>!(c.serverNoContextTakeover===!1&&_.server_no_context_takeover||_.server_max_window_bits&&(c.serverMaxWindowBits===!1||typeof c.serverMaxWindowBits=="number"&&c.serverMaxWindowBits>_.server_max_window_bits)||typeof c.clientMaxWindowBits=="number"&&!_.client_max_window_bits));if(!p)throw new Error("None of the extension offers can be accepted");return c.serverNoContextTakeover&&(p.server_no_context_takeover=!0),c.clientNoContextTakeover&&(p.client_no_context_takeover=!0),typeof c.serverMaxWindowBits=="number"&&(p.server_max_window_bits=c.serverMaxWindowBits),typeof c.clientMaxWindowBits=="number"?p.client_max_window_bits=c.clientMaxWindowBits:(p.client_max_window_bits===!0||c.clientMaxWindowBits===!1)&&delete p.client_max_window_bits,p}acceptAsClient(l){let c=l[0];if(this._options.clientNoContextTakeover===!1&&c.client_no_context_takeover)throw new Error('Unexpected parameter "client_no_context_takeover"');if(!c.client_max_window_bits)typeof this._options.clientMaxWindowBits=="number"&&(c.client_max_window_bits=this._options.clientMaxWindowBits);else if(this._options.clientMaxWindowBits===!1||typeof this._options.clientMaxWindowBits=="number"&&c.client_max_window_bits>this._options.clientMaxWindowBits)throw new Error('Unexpected or invalid parameter "client_max_window_bits"');return c}normalizeParams(l){return l.forEach(c=>{Object.keys(c).forEach(p=>{let _=c[p];if(_.length>1)throw new Error(`Parameter "${p}" must have only a single value`);if(_=_[0],p==="client_max_window_bits"){if(_!==!0){let t=+_;if(!Number.isInteger(t)||t<8||t>15)throw new TypeError(`Invalid value for parameter "${p}": ${_}`);_=t}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${p}": ${_}`)}else if(p==="server_max_window_bits"){let t=+_;if(!Number.isInteger(t)||t<8||t>15)throw new TypeError(`Invalid value for parameter "${p}": ${_}`);_=t}else if(p==="client_no_context_takeover"||p==="server_no_context_takeover"){if(_!==!0)throw new TypeError(`Invalid value for parameter "${p}": ${_}`)}else throw new Error(`Unknown parameter "${p}"`);c[p]=_})}),l}decompress(l,c,p){wg.add(_=>{this._decompress(l,c,(t,O)=>{_(),p(t,O)})})}compress(l,c,p){wg.add(_=>{this._compress(l,c,(t,O)=>{_(),p(t,O)})})}_decompress(l,c,p){let _=this._isServer?"client":"server";if(!this._inflate){let t=`${_}_max_window_bits`,O=typeof this.params[t]!="number"?Uh.Z_DEFAULT_WINDOWBITS:this.params[t];this._inflate=Uh.createInflateRaw({...this._options.zlibInflateOptions,windowBits:O}),this._inflate[Sg]=this,this._inflate[gf]=0,this._inflate[vc]=[],this._inflate.on("error",CQ),this._inflate.on("data",QR)}this._inflate[jh]=p,this._inflate.write(l),c&&this._inflate.write(SQ),this._inflate.flush(()=>{let t=this._inflate[j3];if(t){this._inflate.close(),this._inflate=null,p(t);return}let O=KR.concat(this._inflate[vc],this._inflate[gf]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[gf]=0,this._inflate[vc]=[],c&&this.params[`${_}_no_context_takeover`]&&this._inflate.reset()),p(null,O)})}_compress(l,c,p){let _=this._isServer?"server":"client";if(!this._deflate){let t=`${_}_max_window_bits`,O=typeof this.params[t]!="number"?Uh.Z_DEFAULT_WINDOWBITS:this.params[t];this._deflate=Uh.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:O}),this._deflate[gf]=0,this._deflate[vc]=[],this._deflate.on("error",wQ),this._deflate.on("data",TQ)}this._deflate[jh]=p,this._deflate.write(l),this._deflate.flush(Uh.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let t=KR.concat(this._deflate[vc],this._deflate[gf]);c&&(t=t.slice(0,t.length-4)),this._deflate[jh]=null,this._deflate[gf]=0,this._deflate[vc]=[],c&&this.params[`${_}_no_context_takeover`]&&this._deflate.reset(),p(null,t)})}};JR.exports=z3;function TQ(u){this[vc].push(u),this[gf]+=u.length}function QR(u){if(this[gf]+=u.length,this[Sg]._maxPayload<1||this[gf]<=this[Sg]._maxPayload){this[vc].push(u);return}this[j3]=new RangeError("Max payload size exceeded"),this[j3][XR]=1009,this.removeListener("data",QR),this.reset()}function CQ(u){this[Sg]._inflate=null,u[XR]=1007,this[jh](u)}});var H3=re((Jre,q3)=>{"use strict";function ZR(u){return u>=1e3&&u<=1014&&u!==1004&&u!==1005&&u!==1006||u>=3e3&&u<=4999}function $R(u){let l=u.length,c=0;for(;c=l||(u[c+1]&192)!==128||(u[c+2]&192)!==128||u[c]===224&&(u[c+1]&224)===128||u[c]===237&&(u[c+1]&224)===160)return!1;c+=3}else if((u[c]&248)===240){if(c+3>=l||(u[c+1]&192)!==128||(u[c+2]&192)!==128||(u[c+3]&192)!==128||u[c]===240&&(u[c+1]&240)===128||u[c]===244&&u[c+1]>143||u[c]>244)return!1;c+=4}else return!1;return!0}try{let u=Kn("utf-8-validate");typeof u=="object"&&(u=u.Validation.isValidUTF8),q3.exports={isValidStatusCode:ZR,isValidUTF8(l){return l.length<150?$R(l):u(l)}}}catch{q3.exports={isValidStatusCode:ZR,isValidUTF8:$R}}});var Y3=re((Zre,o7)=>{"use strict";var{Writable:xQ}=Kn("stream"),e7=zh(),{BINARY_TYPES:RQ,EMPTY_BUFFER:AQ,kStatusCode:kQ,kWebSocket:OQ}=s1(),{concat:W3,toArrayBuffer:MQ,unmask:NQ}=Bh(),{isValidStatusCode:FQ,isValidUTF8:t7}=H3(),qh=0,n7=1,r7=2,i7=3,V3=4,LQ=5,G3=class extends xQ{constructor(l,c,p,_){super(),this._binaryType=l||RQ[0],this[OQ]=void 0,this._extensions=c||{},this._isServer=!!p,this._maxPayload=_|0,this._bufferedBytes=0,this._buffers=[],this._compressed=!1,this._payloadLength=0,this._mask=void 0,this._fragmented=0,this._masked=!1,this._fin=!1,this._opcode=0,this._totalPayloadLength=0,this._messageLength=0,this._fragments=[],this._state=qh,this._loop=!1}_write(l,c,p){if(this._opcode===8&&this._state==qh)return p();this._bufferedBytes+=l.length,this._buffers.push(l),this.startLoop(p)}consume(l){if(this._bufferedBytes-=l,l===this._buffers[0].length)return this._buffers.shift();if(l=p.length?c.set(this._buffers.shift(),_):(c.set(new Uint8Array(p.buffer,p.byteOffset,l),_),this._buffers[0]=p.slice(l)),l-=p.length}while(l>0);return c}startLoop(l){let c;this._loop=!0;do switch(this._state){case qh:c=this.getInfo();break;case n7:c=this.getPayloadLength16();break;case r7:c=this.getPayloadLength64();break;case i7:this.getMask();break;case V3:c=this.getData(l);break;default:this._loop=!1;return}while(this._loop);l(c)}getInfo(){if(this._bufferedBytes<2){this._loop=!1;return}let l=this.consume(2);if((l[0]&48)!==0)return this._loop=!1,eo(RangeError,"RSV2 and RSV3 must be clear",!0,1002);let c=(l[0]&64)===64;if(c&&!this._extensions[e7.extensionName])return this._loop=!1,eo(RangeError,"RSV1 must be clear",!0,1002);if(this._fin=(l[0]&128)===128,this._opcode=l[0]&15,this._payloadLength=l[1]&127,this._opcode===0){if(c)return this._loop=!1,eo(RangeError,"RSV1 must be clear",!0,1002);if(!this._fragmented)return this._loop=!1,eo(RangeError,"invalid opcode 0",!0,1002);this._opcode=this._fragmented}else if(this._opcode===1||this._opcode===2){if(this._fragmented)return this._loop=!1,eo(RangeError,`invalid opcode ${this._opcode}`,!0,1002);this._compressed=c}else if(this._opcode>7&&this._opcode<11){if(!this._fin)return this._loop=!1,eo(RangeError,"FIN must be set",!0,1002);if(c)return this._loop=!1,eo(RangeError,"RSV1 must be clear",!0,1002);if(this._payloadLength>125)return this._loop=!1,eo(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002)}else return this._loop=!1,eo(RangeError,`invalid opcode ${this._opcode}`,!0,1002);if(!this._fin&&!this._fragmented&&(this._fragmented=this._opcode),this._masked=(l[1]&128)===128,this._isServer){if(!this._masked)return this._loop=!1,eo(RangeError,"MASK must be set",!0,1002)}else if(this._masked)return this._loop=!1,eo(RangeError,"MASK must be clear",!0,1002);if(this._payloadLength===126)this._state=n7;else if(this._payloadLength===127)this._state=r7;else return this.haveLength()}getPayloadLength16(){if(this._bufferedBytes<2){this._loop=!1;return}return this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength()}getPayloadLength64(){if(this._bufferedBytes<8){this._loop=!1;return}let l=this.consume(8),c=l.readUInt32BE(0);return c>Math.pow(2,53-32)-1?(this._loop=!1,eo(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009)):(this._payloadLength=c*Math.pow(2,32)+l.readUInt32BE(4),this.haveLength())}haveLength(){if(this._payloadLength&&this._opcode<8&&(this._totalPayloadLength+=this._payloadLength,this._totalPayloadLength>this._maxPayload&&this._maxPayload>0))return this._loop=!1,eo(RangeError,"Max payload size exceeded",!1,1009);this._masked?this._state=i7:this._state=V3}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=V3}getData(l){let c=AQ;if(this._payloadLength){if(this._bufferedBytes7)return this.controlMessage(c);if(this._compressed){this._state=LQ,this.decompress(c,l);return}return c.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(c)),this.dataMessage()}decompress(l,c){this._extensions[e7.extensionName].decompress(l,this._fin,(_,t)=>{if(_)return c(_);if(t.length){if(this._messageLength+=t.length,this._messageLength>this._maxPayload&&this._maxPayload>0)return c(eo(RangeError,"Max payload size exceeded",!1,1009));this._fragments.push(t)}let O=this.dataMessage();if(O)return c(O);this.startLoop(c)})}dataMessage(){if(this._fin){let l=this._messageLength,c=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._fragments=[],this._opcode===2){let p;this._binaryType==="nodebuffer"?p=W3(c,l):this._binaryType==="arraybuffer"?p=MQ(W3(c,l)):p=c,this.emit("message",p)}else{let p=W3(c,l);if(!t7(p))return this._loop=!1,eo(Error,"invalid UTF-8 sequence",!0,1007);this.emit("message",p.toString())}}this._state=qh}controlMessage(l){if(this._opcode===8)if(this._loop=!1,l.length===0)this.emit("conclude",1005,""),this.end();else{if(l.length===1)return eo(RangeError,"invalid payload length 1",!0,1002);{let c=l.readUInt16BE(0);if(!FQ(c))return eo(RangeError,`invalid status code ${c}`,!0,1002);let p=l.slice(2);if(!t7(p))return eo(Error,"invalid UTF-8 sequence",!0,1007);this.emit("conclude",c,p.toString()),this.end()}}else this._opcode===9?this.emit("ping",l):this.emit("pong",l);this._state=qh}};o7.exports=G3;function eo(u,l,c,p){let _=new u(c?`Invalid WebSocket frame: ${l}`:l);return Error.captureStackTrace(_,eo),_[kQ]=p,_}});var K3=re(($re,a7)=>{"use strict";var{randomFillSync:bQ}=Kn("crypto"),u7=zh(),{EMPTY_BUFFER:PQ}=s1(),{isValidStatusCode:IQ}=H3(),{mask:l7,toBuffer:_f}=Bh(),f1=Buffer.alloc(4),ws=class{constructor(l,c){this._extensions=c||{},this._socket=l,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._deflating=!1,this._queue=[]}static frame(l,c){let p=c.mask&&c.readOnly,_=c.mask?6:2,t=l.length;l.length>=65536?(_+=8,t=127):l.length>125&&(_+=2,t=126);let O=Buffer.allocUnsafe(p?l.length+_:_);return O[0]=c.fin?c.opcode|128:c.opcode,c.rsv1&&(O[0]|=64),O[1]=t,t===126?O.writeUInt16BE(l.length,2):t===127&&(O.writeUInt32BE(0,2),O.writeUInt32BE(l.length,6)),c.mask?(bQ(f1,0,4),O[1]|=128,O[_-4]=f1[0],O[_-3]=f1[1],O[_-2]=f1[2],O[_-1]=f1[3],p?(l7(l,f1,O,_,l.length),[O]):(l7(l,f1,l,0,l.length),[O,l])):[O,l]}close(l,c,p,_){let t;if(l===void 0)t=PQ;else{if(typeof l!="number"||!IQ(l))throw new TypeError("First argument must be a valid error code number");if(c===void 0||c==="")t=Buffer.allocUnsafe(2),t.writeUInt16BE(l,0);else{let O=Buffer.byteLength(c);if(O>123)throw new RangeError("The message must not be greater than 123 bytes");t=Buffer.allocUnsafe(2+O),t.writeUInt16BE(l,0),t.write(c,2)}}this._deflating?this.enqueue([this.doClose,t,p,_]):this.doClose(t,p,_)}doClose(l,c,p){this.sendFrame(ws.frame(l,{fin:!0,rsv1:!1,opcode:8,mask:c,readOnly:!1}),p)}ping(l,c,p){let _=_f(l);if(_.length>125)throw new RangeError("The data size must not be greater than 125 bytes");this._deflating?this.enqueue([this.doPing,_,c,_f.readOnly,p]):this.doPing(_,c,_f.readOnly,p)}doPing(l,c,p,_){this.sendFrame(ws.frame(l,{fin:!0,rsv1:!1,opcode:9,mask:c,readOnly:p}),_)}pong(l,c,p){let _=_f(l);if(_.length>125)throw new RangeError("The data size must not be greater than 125 bytes");this._deflating?this.enqueue([this.doPong,_,c,_f.readOnly,p]):this.doPong(_,c,_f.readOnly,p)}doPong(l,c,p,_){this.sendFrame(ws.frame(l,{fin:!0,rsv1:!1,opcode:10,mask:c,readOnly:p}),_)}send(l,c,p){let _=_f(l),t=this._extensions[u7.extensionName],O=c.binary?2:1,M=c.compress;if(this._firstFragment?(this._firstFragment=!1,M&&t&&(M=_.length>=t._threshold),this._compress=M):(M=!1,O=0),c.fin&&(this._firstFragment=!0),t){let A={fin:c.fin,rsv1:M,opcode:O,mask:c.mask,readOnly:_f.readOnly};this._deflating?this.enqueue([this.dispatch,_,this._compress,A,p]):this.dispatch(_,this._compress,A,p)}else this.sendFrame(ws.frame(_,{fin:c.fin,rsv1:!1,opcode:O,mask:c.mask,readOnly:_f.readOnly}),p)}dispatch(l,c,p,_){if(!c){this.sendFrame(ws.frame(l,p),_);return}let t=this._extensions[u7.extensionName];this._bufferedBytes+=l.length,this._deflating=!0,t.compress(l,p.fin,(O,M)=>{if(this._socket.destroyed){let A=new Error("The socket was closed while data was being compressed");typeof _=="function"&&_(A);for(let T=0;T{"use strict";var nd=class{constructor(l,c){this.target=c,this.type=l}},X3=class extends nd{constructor(l,c){super("message",c),this.data=l}},Q3=class extends nd{constructor(l,c,p){super("close",p),this.wasClean=p._closeFrameReceived&&p._closeFrameSent,this.reason=c,this.code=l}},J3=class extends nd{constructor(l){super("open",l)}},Z3=class extends nd{constructor(l,c){super("error",c),this.message=l.message,this.error=l}},BQ={addEventListener(u,l,c){if(typeof l!="function")return;function p(A){l.call(this,new X3(A,this))}function _(A,T){l.call(this,new Q3(A,T,this))}function t(A){l.call(this,new Z3(A,this))}function O(){l.call(this,new J3(this))}let M=c&&c.once?"once":"on";u==="message"?(p._listener=l,this[M](u,p)):u==="close"?(_._listener=l,this[M](u,_)):u==="error"?(t._listener=l,this[M](u,t)):u==="open"?(O._listener=l,this[M](u,O)):this[M](u,l)},removeEventListener(u,l){let c=this.listeners(u);for(let p=0;p{"use strict";var Hh=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0];function Ss(u,l,c){u[l]===void 0?u[l]=[c]:u[l].push(c)}function UQ(u){let l=Object.create(null);if(u===void 0||u==="")return l;let c=Object.create(null),p=!1,_=!1,t=!1,O,M,A=-1,T=-1,P=0;for(;P{let c=u[l];return Array.isArray(c)||(c=[c]),c.map(p=>[l].concat(Object.keys(p).map(_=>{let t=p[_];return Array.isArray(t)||(t=[t]),t.map(O=>O===!0?_:`${_}=${O}`).join("; ")})).join("; ")).join(", ")}).join(", ")}c7.exports={format:jQ,parse:UQ}});var i8=re((nie,D7)=>{"use strict";var zQ=Kn("events"),qQ=Kn("https"),HQ=Kn("http"),h7=Kn("net"),WQ=Kn("tls"),{randomBytes:VQ,createHash:GQ}=Kn("crypto"),{URL:e8}=Kn("url"),mc=zh(),YQ=Y3(),KQ=K3(),{BINARY_TYPES:d7,EMPTY_BUFFER:t8,GUID:XQ,kStatusCode:QQ,kWebSocket:$u,NOOP:v7}=s1(),{addEventListener:JQ,removeEventListener:ZQ}=f7(),{format:$Q,parse:eJ}=$3(),{toBuffer:tJ}=Bh(),m7=["CONNECTING","OPEN","CLOSING","CLOSED"],n8=[8,13],nJ=30*1e3,Hr=class extends zQ{constructor(l,c,p){super(),this._binaryType=d7[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage="",this._closeTimer=null,this._extensions={},this._protocol="",this._readyState=Hr.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,l!==null?(this._bufferedAmount=0,this._isServer=!1,this._redirects=0,Array.isArray(c)?c=c.join(", "):typeof c=="object"&&c!==null&&(p=c,c=void 0),y7(this,l,c,p)):this._isServer=!0}get binaryType(){return this._binaryType}set binaryType(l){!d7.includes(l)||(this._binaryType=l,this._receiver&&(this._receiver._binaryType=l))}get bufferedAmount(){return this._socket?this._socket._writableState.length+this._sender._bufferedBytes:this._bufferedAmount}get extensions(){return Object.keys(this._extensions).join()}get protocol(){return this._protocol}get readyState(){return this._readyState}get url(){return this._url}setSocket(l,c,p){let _=new YQ(this.binaryType,this._extensions,this._isServer,p);this._sender=new KQ(l,this._extensions),this._receiver=_,this._socket=l,_[$u]=this,l[$u]=this,_.on("conclude",oJ),_.on("drain",uJ),_.on("error",lJ),_.on("message",aJ),_.on("ping",sJ),_.on("pong",fJ),l.setTimeout(0),l.setNoDelay(),c.length>0&&l.unshift(c),l.on("close",g7),l.on("data",Tg),l.on("end",_7),l.on("error",E7),this._readyState=Hr.OPEN,this.emit("open")}emitClose(){if(!this._socket){this._readyState=Hr.CLOSED,this.emit("close",this._closeCode,this._closeMessage);return}this._extensions[mc.extensionName]&&this._extensions[mc.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=Hr.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(l,c){if(this.readyState!==Hr.CLOSED){if(this.readyState===Hr.CONNECTING){let p="WebSocket was closed before the connection was established";return Ef(this,this._req,p)}if(this.readyState===Hr.CLOSING){this._closeFrameSent&&this._closeFrameReceived&&this._socket.end();return}this._readyState=Hr.CLOSING,this._sender.close(l,c,!this._isServer,p=>{p||(this._closeFrameSent=!0,this._closeFrameReceived&&this._socket.end())}),this._closeTimer=setTimeout(this._socket.destroy.bind(this._socket),nJ)}}ping(l,c,p){if(this.readyState===Hr.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof l=="function"?(p=l,l=c=void 0):typeof c=="function"&&(p=c,c=void 0),typeof l=="number"&&(l=l.toString()),this.readyState!==Hr.OPEN){r8(this,l,p);return}c===void 0&&(c=!this._isServer),this._sender.ping(l||t8,c,p)}pong(l,c,p){if(this.readyState===Hr.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof l=="function"?(p=l,l=c=void 0):typeof c=="function"&&(p=c,c=void 0),typeof l=="number"&&(l=l.toString()),this.readyState!==Hr.OPEN){r8(this,l,p);return}c===void 0&&(c=!this._isServer),this._sender.pong(l||t8,c,p)}send(l,c,p){if(this.readyState===Hr.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof c=="function"&&(p=c,c={}),typeof l=="number"&&(l=l.toString()),this.readyState!==Hr.OPEN){r8(this,l,p);return}let _={binary:typeof l!="string",mask:!this._isServer,compress:!0,fin:!0,...c};this._extensions[mc.extensionName]||(_.compress=!1),this._sender.send(l||t8,_,p)}terminate(){if(this.readyState!==Hr.CLOSED){if(this.readyState===Hr.CONNECTING){let l="WebSocket was closed before the connection was established";return Ef(this,this._req,l)}this._socket&&(this._readyState=Hr.CLOSING,this._socket.destroy())}}};m7.forEach((u,l)=>{let c={enumerable:!0,value:l};Object.defineProperty(Hr.prototype,u,c),Object.defineProperty(Hr,u,c)});["binaryType","bufferedAmount","extensions","protocol","readyState","url"].forEach(u=>{Object.defineProperty(Hr.prototype,u,{enumerable:!0})});["open","error","close","message"].forEach(u=>{Object.defineProperty(Hr.prototype,`on${u}`,{configurable:!0,enumerable:!0,get(){let l=this.listeners(u);for(let c=0;c{Ef(u,z,"Opening handshake has timed out")}),z.on("error",Q=>{z===null||z.aborted||(z=u._req=null,u._readyState=Hr.CLOSING,u.emit("error",Q),u.emitClose())}),z.on("response",Q=>{let v=Q.headers.location,de=Q.statusCode;if(v&&_.followRedirects&&de>=300&&de<400){if(++u._redirects>_.maxRedirects){Ef(u,z,"Maximum redirects exceeded");return}z.abort();let ye=new e8(v,l);y7(u,ye,c,p)}else u.emit("unexpected-response",z,Q)||Ef(u,z,`Unexpected server response: ${Q.statusCode}`)}),z.on("upgrade",(Q,v,de)=>{if(u.emit("upgrade",Q),u.readyState!==Hr.CONNECTING)return;z=u._req=null;let ye=GQ("sha1").update(T+XQ).digest("base64");if(Q.headers["sec-websocket-accept"]!==ye){Ef(u,v,"Invalid Sec-WebSocket-Accept header");return}let le=Q.headers["sec-websocket-protocol"],ae=(c||"").split(/, */),Me;if(!c&&le?Me="Server sent a subprotocol but none was requested":c&&!le?Me="Server sent no subprotocol":le&&!ae.includes(le)&&(Me="Server sent an invalid subprotocol"),Me){Ef(u,v,Me);return}if(le&&(u._protocol=le),U)try{let fe=eJ(Q.headers["sec-websocket-extensions"]);fe[mc.extensionName]&&(U.accept(fe[mc.extensionName]),u._extensions[mc.extensionName]=U)}catch{Ef(u,v,"Invalid Sec-WebSocket-Extensions header");return}u.setSocket(v,de,_.maxPayload)})}function rJ(u){return u.path=u.socketPath,h7.connect(u)}function iJ(u){return u.path=void 0,!u.servername&&u.servername!==""&&(u.servername=h7.isIP(u.host)?"":u.host),WQ.connect(u)}function Ef(u,l,c){u._readyState=Hr.CLOSING;let p=new Error(c);Error.captureStackTrace(p,Ef),l.setHeader?(l.abort(),l.socket&&!l.socket.destroyed&&l.socket.destroy(),l.once("abort",u.emitClose.bind(u)),u.emit("error",p)):(l.destroy(p),l.once("error",u.emit.bind(u,"error")),l.once("close",u.emitClose.bind(u)))}function r8(u,l,c){if(l){let p=tJ(l).length;u._socket?u._sender._bufferedBytes+=p:u._bufferedAmount+=p}if(c){let p=new Error(`WebSocket is not open: readyState ${u.readyState} (${m7[u.readyState]})`);c(p)}}function oJ(u,l){let c=this[$u];c._socket.removeListener("data",Tg),c._socket.resume(),c._closeFrameReceived=!0,c._closeMessage=l,c._closeCode=u,u===1005?c.close():c.close(u,l)}function uJ(){this[$u]._socket.resume()}function lJ(u){let l=this[$u];l._socket.removeListener("data",Tg),l._readyState=Hr.CLOSING,l._closeCode=u[QQ],l.emit("error",u),l._socket.destroy()}function p7(){this[$u].emitClose()}function aJ(u){this[$u].emit("message",u)}function sJ(u){let l=this[$u];l.pong(u,!l._isServer,v7),l.emit("ping",u)}function fJ(u){this[$u].emit("pong",u)}function g7(){let u=this[$u];this.removeListener("close",g7),this.removeListener("end",_7),u._readyState=Hr.CLOSING,u._socket.read(),u._receiver.end(),this.removeListener("data",Tg),this[$u]=void 0,clearTimeout(u._closeTimer),u._receiver._writableState.finished||u._receiver._writableState.errorEmitted?u.emitClose():(u._receiver.on("error",p7),u._receiver.on("finish",p7))}function Tg(u){this[$u]._receiver.write(u)||this.pause()}function _7(){let u=this[$u];u._readyState=Hr.CLOSING,u._receiver.end(),this.end()}function E7(){let u=this[$u];this.removeListener("error",E7),this.on("error",v7),u&&(u._readyState=Hr.CLOSING,this.destroy())}});var C7=re((rie,T7)=>{"use strict";var{Duplex:cJ}=Kn("stream");function w7(u){u.emit("close")}function dJ(){!this.destroyed&&this._writableState.finished&&this.destroy()}function S7(u){this.removeListener("error",S7),this.destroy(),this.listenerCount("error")===0&&this.emit("error",u)}function pJ(u,l){let c=!0;function p(){c&&u._socket.resume()}u.readyState===u.CONNECTING?u.once("open",function(){u._receiver.removeAllListeners("drain"),u._receiver.on("drain",p)}):(u._receiver.removeAllListeners("drain"),u._receiver.on("drain",p));let _=new cJ({...l,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return u.on("message",function(O){_.push(O)||(c=!1,u._socket.pause())}),u.once("error",function(O){_.destroyed||_.destroy(O)}),u.once("close",function(){_.destroyed||_.push(null)}),_._destroy=function(t,O){if(u.readyState===u.CLOSED){O(t),process.nextTick(w7,_);return}let M=!1;u.once("error",function(T){M=!0,O(T)}),u.once("close",function(){M||O(t),process.nextTick(w7,_)}),u.terminate()},_._final=function(t){if(u.readyState===u.CONNECTING){u.once("open",function(){_._final(t)});return}u._socket!==null&&(u._socket._writableState.finished?(t(),_._readableState.endEmitted&&_.destroy()):(u._socket.once("finish",function(){t()}),u.close()))},_._read=function(){u.readyState===u.OPEN&&!c&&(c=!0,u._receiver._writableState.needDrain||u._socket.resume())},_._write=function(t,O,M){if(u.readyState===u.CONNECTING){u.once("open",function(){_._write(t,O,M)});return}u.send(t,M)},_.on("end",dJ),_.on("error",S7),_}T7.exports=pJ});var R7=re((iie,x7)=>{"use strict";var hJ=Kn("events"),{createHash:vJ}=Kn("crypto"),{createServer:mJ,STATUS_CODES:o8}=Kn("http"),c1=zh(),yJ=i8(),{format:gJ,parse:_J}=$3(),{GUID:EJ,kWebSocket:DJ}=s1(),wJ=/^[+/0-9A-Za-z]{22}==$/,u8=class extends hJ{constructor(l,c){if(super(),l={maxPayload:100*1024*1024,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,...l},l.port==null&&!l.server&&!l.noServer)throw new TypeError('One of the "port", "server", or "noServer" options must be specified');if(l.port!=null?(this._server=mJ((p,_)=>{let t=o8[426];_.writeHead(426,{"Content-Length":t.length,"Content-Type":"text/plain"}),_.end(t)}),this._server.listen(l.port,l.host,l.backlog,c)):l.server&&(this._server=l.server),this._server){let p=this.emit.bind(this,"connection");this._removeListeners=SJ(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(_,t,O)=>{this.handleUpgrade(_,t,O,p)}})}l.perMessageDeflate===!0&&(l.perMessageDeflate={}),l.clientTracking&&(this.clients=new Set),this.options=l}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(l){if(l&&this.once("close",l),this.clients)for(let p of this.clients)p.terminate();let c=this._server;if(c&&(this._removeListeners(),this._removeListeners=this._server=null,this.options.port!=null)){c.close(()=>this.emit("close"));return}process.nextTick(TJ,this)}shouldHandle(l){if(this.options.path){let c=l.url.indexOf("?");if((c!==-1?l.url.slice(0,c):l.url)!==this.options.path)return!1}return!0}handleUpgrade(l,c,p,_){c.on("error",l8);let t=l.headers["sec-websocket-key"]!==void 0?l.headers["sec-websocket-key"].trim():!1,O=+l.headers["sec-websocket-version"],M={};if(l.method!=="GET"||l.headers.upgrade.toLowerCase()!=="websocket"||!t||!wJ.test(t)||O!==8&&O!==13||!this.shouldHandle(l))return Cg(c,400);if(this.options.perMessageDeflate){let A=new c1(this.options.perMessageDeflate,!0,this.options.maxPayload);try{let T=_J(l.headers["sec-websocket-extensions"]);T[c1.extensionName]&&(A.accept(T[c1.extensionName]),M[c1.extensionName]=A)}catch{return Cg(c,400)}}if(this.options.verifyClient){let A={origin:l.headers[`${O===8?"sec-websocket-origin":"origin"}`],secure:!!(l.socket.authorized||l.socket.encrypted),req:l};if(this.options.verifyClient.length===2){this.options.verifyClient(A,(T,P,U,z)=>{if(!T)return Cg(c,P||401,U,z);this.completeUpgrade(t,M,l,c,p,_)});return}if(!this.options.verifyClient(A))return Cg(c,401)}this.completeUpgrade(t,M,l,c,p,_)}completeUpgrade(l,c,p,_,t,O){if(!_.readable||!_.writable)return _.destroy();if(_[DJ])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");let A=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${vJ("sha1").update(l+EJ).digest("base64")}`],T=new yJ(null),P=p.headers["sec-websocket-protocol"];if(P&&(P=P.split(",").map(CJ),this.options.handleProtocols?P=this.options.handleProtocols(P,p):P=P[0],P&&(A.push(`Sec-WebSocket-Protocol: ${P}`),T._protocol=P)),c[c1.extensionName]){let U=c[c1.extensionName].params,z=gJ({[c1.extensionName]:[U]});A.push(`Sec-WebSocket-Extensions: ${z}`),T._extensions=c}this.emit("headers",A,p),_.write(A.concat(`\r +`).join(`\r +`)),_.removeListener("error",l8),T.setSocket(_,t,this.options.maxPayload),this.clients&&(this.clients.add(T),T.on("close",()=>this.clients.delete(T))),O(T,p)}};x7.exports=u8;function SJ(u,l){for(let c of Object.keys(l))u.on(c,l[c]);return function(){for(let p of Object.keys(l))u.removeListener(p,l[p])}}function TJ(u){u.emit("close")}function l8(){this.destroy()}function Cg(u,l,c,p){u.writable&&(c=c||o8[l],p={Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(c),...p},u.write(`HTTP/1.1 ${l} ${o8[l]}\r +`+Object.keys(p).map(_=>`${_}: ${p[_]}`).join(`\r +`)+`\r +\r +`+c)),u.removeListener("error",l8),u.destroy()}function CJ(u){return u.trim()}});var k7=re((oie,A7)=>{"use strict";var Wh=i8();Wh.createWebSocketStream=C7();Wh.Server=R7();Wh.Receiver=Y3();Wh.Sender=K3();A7.exports=Wh});var O7=re(xg=>{"use strict";var xJ=xg&&xg.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(xg,"__esModule",{value:!0});var RJ=xJ(k7()),Vh=global;Vh.WebSocket||(Vh.WebSocket=RJ.default);Vh.window||(Vh.window=global);Vh.window.__REACT_DEVTOOLS_COMPONENT_FILTERS__=[{type:1,value:7,isEnabled:!0},{type:2,value:"InternalApp",isEnabled:!0,isValid:!0},{type:2,value:"InternalAppContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStdoutContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStderrContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStdinContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalFocusContext",isEnabled:!0,isValid:!0}]});var M7=re((Rg,a8)=>{(function(u,l){typeof Rg=="object"&&typeof a8=="object"?a8.exports=l():typeof define=="function"&&define.amd?define([],l):typeof Rg=="object"?Rg.ReactDevToolsBackend=l():u.ReactDevToolsBackend=l()})(window,function(){return function(u){var l={};function c(p){if(l[p])return l[p].exports;var _=l[p]={i:p,l:!1,exports:{}};return u[p].call(_.exports,_,_.exports,c),_.l=!0,_.exports}return c.m=u,c.c=l,c.d=function(p,_,t){c.o(p,_)||Object.defineProperty(p,_,{enumerable:!0,get:t})},c.r=function(p){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(p,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(p,"__esModule",{value:!0})},c.t=function(p,_){if(1&_&&(p=c(p)),8&_||4&_&&typeof p=="object"&&p&&p.__esModule)return p;var t=Object.create(null);if(c.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:p}),2&_&&typeof p!="string")for(var O in p)c.d(t,O,function(M){return p[M]}.bind(null,O));return t},c.n=function(p){var _=p&&p.__esModule?function(){return p.default}:function(){return p};return c.d(_,"a",_),_},c.o=function(p,_){return Object.prototype.hasOwnProperty.call(p,_)},c.p="",c(c.s=20)}([function(u,l,c){"use strict";u.exports=c(12)},function(u,l,c){"use strict";var p=Object.getOwnPropertySymbols,_=Object.prototype.hasOwnProperty,t=Object.prototype.propertyIsEnumerable;function O(M){if(M==null)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(M)}u.exports=function(){try{if(!Object.assign)return!1;var M=new String("abc");if(M[5]="de",Object.getOwnPropertyNames(M)[0]==="5")return!1;for(var A={},T=0;T<10;T++)A["_"+String.fromCharCode(T)]=T;if(Object.getOwnPropertyNames(A).map(function(U){return A[U]}).join("")!=="0123456789")return!1;var P={};return"abcdefghijklmnopqrst".split("").forEach(function(U){P[U]=U}),Object.keys(Object.assign({},P)).join("")==="abcdefghijklmnopqrst"}catch{return!1}}()?Object.assign:function(M,A){for(var T,P,U=O(M),z=1;z"u"?"undefined":_(self))=="object"&&self&&self.Object===Object&&self,z=P||U||Function("return this")(),Q=Object.prototype.toString,v=Math.max,de=Math.min,ye=function(){return z.Date.now()};function le(pe,Z,Ae){var Fe,He,ot,st,qe,Xe,Ie=0,kt=!1,Kt=!1,Ye=!0;if(typeof pe!="function")throw new TypeError("Expected a function");function V(ct){var Lt=Fe,Xt=He;return Fe=He=void 0,Ie=ct,st=pe.apply(Xt,Lt)}function oe(ct){return Ie=ct,qe=setTimeout(ee,Z),kt?V(ct):st}function ve(ct){var Lt=ct-Xe;return Xe===void 0||Lt>=Z||Lt<0||Kt&&ct-Ie>=ot}function ee(){var ct=ye();if(ve(ct))return Oe(ct);qe=setTimeout(ee,function(Lt){var Xt=Z-(Lt-Xe);return Kt?de(Xt,ot-(Lt-Ie)):Xt}(ct))}function Oe(ct){return qe=void 0,Ye&&Fe?V(ct):(Fe=He=void 0,st)}function et(){var ct=ye(),Lt=ve(ct);if(Fe=arguments,He=this,Xe=ct,Lt){if(qe===void 0)return oe(Xe);if(Kt)return qe=setTimeout(ee,Z),V(Xe)}return qe===void 0&&(qe=setTimeout(ee,Z)),st}return Z=fe(Z)||0,ae(Ae)&&(kt=!!Ae.leading,ot=(Kt="maxWait"in Ae)?v(fe(Ae.maxWait)||0,Z):ot,Ye="trailing"in Ae?!!Ae.trailing:Ye),et.cancel=function(){qe!==void 0&&clearTimeout(qe),Ie=0,Fe=Xe=He=qe=void 0},et.flush=function(){return qe===void 0?st:Oe(ye())},et}function ae(pe){var Z=_(pe);return!!pe&&(Z=="object"||Z=="function")}function Me(pe){return _(pe)=="symbol"||function(Z){return!!Z&&_(Z)=="object"}(pe)&&Q.call(pe)=="[object Symbol]"}function fe(pe){if(typeof pe=="number")return pe;if(Me(pe))return NaN;if(ae(pe)){var Z=typeof pe.valueOf=="function"?pe.valueOf():pe;pe=ae(Z)?Z+"":Z}if(typeof pe!="string")return pe===0?pe:+pe;pe=pe.replace(t,"");var Ae=M.test(pe);return Ae||A.test(pe)?T(pe.slice(2),Ae?2:8):O.test(pe)?NaN:+pe}u.exports=function(pe,Z,Ae){var Fe=!0,He=!0;if(typeof pe!="function")throw new TypeError("Expected a function");return ae(Ae)&&(Fe="leading"in Ae?!!Ae.leading:Fe,He="trailing"in Ae?!!Ae.trailing:He),le(pe,Z,{leading:Fe,maxWait:Z,trailing:He})}}).call(this,c(4))},function(u,l,c){(function(p){function _(V){return(_=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(oe){return typeof oe}:function(oe){return oe&&typeof Symbol=="function"&&oe.constructor===Symbol&&oe!==Symbol.prototype?"symbol":typeof oe})(V)}var t;l=u.exports=v,t=(p===void 0?"undefined":_(p))==="object"&&p.env&&p.env.NODE_DEBUG&&/\bsemver\b/i.test(p.env.NODE_DEBUG)?function(){var V=Array.prototype.slice.call(arguments,0);V.unshift("SEMVER"),console.log.apply(console,V)}:function(){},l.SEMVER_SPEC_VERSION="2.0.0";var O=Number.MAX_SAFE_INTEGER||9007199254740991,M=l.re=[],A=l.src=[],T=l.tokens={},P=0;function U(V){T[V]=P++}U("NUMERICIDENTIFIER"),A[T.NUMERICIDENTIFIER]="0|[1-9]\\d*",U("NUMERICIDENTIFIERLOOSE"),A[T.NUMERICIDENTIFIERLOOSE]="[0-9]+",U("NONNUMERICIDENTIFIER"),A[T.NONNUMERICIDENTIFIER]="\\d*[a-zA-Z-][a-zA-Z0-9-]*",U("MAINVERSION"),A[T.MAINVERSION]="("+A[T.NUMERICIDENTIFIER]+")\\.("+A[T.NUMERICIDENTIFIER]+")\\.("+A[T.NUMERICIDENTIFIER]+")",U("MAINVERSIONLOOSE"),A[T.MAINVERSIONLOOSE]="("+A[T.NUMERICIDENTIFIERLOOSE]+")\\.("+A[T.NUMERICIDENTIFIERLOOSE]+")\\.("+A[T.NUMERICIDENTIFIERLOOSE]+")",U("PRERELEASEIDENTIFIER"),A[T.PRERELEASEIDENTIFIER]="(?:"+A[T.NUMERICIDENTIFIER]+"|"+A[T.NONNUMERICIDENTIFIER]+")",U("PRERELEASEIDENTIFIERLOOSE"),A[T.PRERELEASEIDENTIFIERLOOSE]="(?:"+A[T.NUMERICIDENTIFIERLOOSE]+"|"+A[T.NONNUMERICIDENTIFIER]+")",U("PRERELEASE"),A[T.PRERELEASE]="(?:-("+A[T.PRERELEASEIDENTIFIER]+"(?:\\."+A[T.PRERELEASEIDENTIFIER]+")*))",U("PRERELEASELOOSE"),A[T.PRERELEASELOOSE]="(?:-?("+A[T.PRERELEASEIDENTIFIERLOOSE]+"(?:\\."+A[T.PRERELEASEIDENTIFIERLOOSE]+")*))",U("BUILDIDENTIFIER"),A[T.BUILDIDENTIFIER]="[0-9A-Za-z-]+",U("BUILD"),A[T.BUILD]="(?:\\+("+A[T.BUILDIDENTIFIER]+"(?:\\."+A[T.BUILDIDENTIFIER]+")*))",U("FULL"),U("FULLPLAIN"),A[T.FULLPLAIN]="v?"+A[T.MAINVERSION]+A[T.PRERELEASE]+"?"+A[T.BUILD]+"?",A[T.FULL]="^"+A[T.FULLPLAIN]+"$",U("LOOSEPLAIN"),A[T.LOOSEPLAIN]="[v=\\s]*"+A[T.MAINVERSIONLOOSE]+A[T.PRERELEASELOOSE]+"?"+A[T.BUILD]+"?",U("LOOSE"),A[T.LOOSE]="^"+A[T.LOOSEPLAIN]+"$",U("GTLT"),A[T.GTLT]="((?:<|>)?=?)",U("XRANGEIDENTIFIERLOOSE"),A[T.XRANGEIDENTIFIERLOOSE]=A[T.NUMERICIDENTIFIERLOOSE]+"|x|X|\\*",U("XRANGEIDENTIFIER"),A[T.XRANGEIDENTIFIER]=A[T.NUMERICIDENTIFIER]+"|x|X|\\*",U("XRANGEPLAIN"),A[T.XRANGEPLAIN]="[v=\\s]*("+A[T.XRANGEIDENTIFIER]+")(?:\\.("+A[T.XRANGEIDENTIFIER]+")(?:\\.("+A[T.XRANGEIDENTIFIER]+")(?:"+A[T.PRERELEASE]+")?"+A[T.BUILD]+"?)?)?",U("XRANGEPLAINLOOSE"),A[T.XRANGEPLAINLOOSE]="[v=\\s]*("+A[T.XRANGEIDENTIFIERLOOSE]+")(?:\\.("+A[T.XRANGEIDENTIFIERLOOSE]+")(?:\\.("+A[T.XRANGEIDENTIFIERLOOSE]+")(?:"+A[T.PRERELEASELOOSE]+")?"+A[T.BUILD]+"?)?)?",U("XRANGE"),A[T.XRANGE]="^"+A[T.GTLT]+"\\s*"+A[T.XRANGEPLAIN]+"$",U("XRANGELOOSE"),A[T.XRANGELOOSE]="^"+A[T.GTLT]+"\\s*"+A[T.XRANGEPLAINLOOSE]+"$",U("COERCE"),A[T.COERCE]="(^|[^\\d])(\\d{1,16})(?:\\.(\\d{1,16}))?(?:\\.(\\d{1,16}))?(?:$|[^\\d])",U("COERCERTL"),M[T.COERCERTL]=new RegExp(A[T.COERCE],"g"),U("LONETILDE"),A[T.LONETILDE]="(?:~>?)",U("TILDETRIM"),A[T.TILDETRIM]="(\\s*)"+A[T.LONETILDE]+"\\s+",M[T.TILDETRIM]=new RegExp(A[T.TILDETRIM],"g"),U("TILDE"),A[T.TILDE]="^"+A[T.LONETILDE]+A[T.XRANGEPLAIN]+"$",U("TILDELOOSE"),A[T.TILDELOOSE]="^"+A[T.LONETILDE]+A[T.XRANGEPLAINLOOSE]+"$",U("LONECARET"),A[T.LONECARET]="(?:\\^)",U("CARETTRIM"),A[T.CARETTRIM]="(\\s*)"+A[T.LONECARET]+"\\s+",M[T.CARETTRIM]=new RegExp(A[T.CARETTRIM],"g"),U("CARET"),A[T.CARET]="^"+A[T.LONECARET]+A[T.XRANGEPLAIN]+"$",U("CARETLOOSE"),A[T.CARETLOOSE]="^"+A[T.LONECARET]+A[T.XRANGEPLAINLOOSE]+"$",U("COMPARATORLOOSE"),A[T.COMPARATORLOOSE]="^"+A[T.GTLT]+"\\s*("+A[T.LOOSEPLAIN]+")$|^$",U("COMPARATOR"),A[T.COMPARATOR]="^"+A[T.GTLT]+"\\s*("+A[T.FULLPLAIN]+")$|^$",U("COMPARATORTRIM"),A[T.COMPARATORTRIM]="(\\s*)"+A[T.GTLT]+"\\s*("+A[T.LOOSEPLAIN]+"|"+A[T.XRANGEPLAIN]+")",M[T.COMPARATORTRIM]=new RegExp(A[T.COMPARATORTRIM],"g"),U("HYPHENRANGE"),A[T.HYPHENRANGE]="^\\s*("+A[T.XRANGEPLAIN]+")\\s+-\\s+("+A[T.XRANGEPLAIN]+")\\s*$",U("HYPHENRANGELOOSE"),A[T.HYPHENRANGELOOSE]="^\\s*("+A[T.XRANGEPLAINLOOSE]+")\\s+-\\s+("+A[T.XRANGEPLAINLOOSE]+")\\s*$",U("STAR"),A[T.STAR]="(<|>)?=?\\s*\\*";for(var z=0;z256||!(oe.loose?M[T.LOOSE]:M[T.FULL]).test(V))return null;try{return new v(V,oe)}catch{return null}}function v(V,oe){if(oe&&_(oe)==="object"||(oe={loose:!!oe,includePrerelease:!1}),V instanceof v){if(V.loose===oe.loose)return V;V=V.version}else if(typeof V!="string")throw new TypeError("Invalid Version: "+V);if(V.length>256)throw new TypeError("version is longer than 256 characters");if(!(this instanceof v))return new v(V,oe);t("SemVer",V,oe),this.options=oe,this.loose=!!oe.loose;var ve=V.trim().match(oe.loose?M[T.LOOSE]:M[T.FULL]);if(!ve)throw new TypeError("Invalid Version: "+V);if(this.raw=V,this.major=+ve[1],this.minor=+ve[2],this.patch=+ve[3],this.major>O||this.major<0)throw new TypeError("Invalid major version");if(this.minor>O||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>O||this.patch<0)throw new TypeError("Invalid patch version");ve[4]?this.prerelease=ve[4].split(".").map(function(ee){if(/^[0-9]+$/.test(ee)){var Oe=+ee;if(Oe>=0&&Oe=0;)typeof this.prerelease[ve]=="number"&&(this.prerelease[ve]++,ve=-2);ve===-1&&this.prerelease.push(0)}oe&&(this.prerelease[0]===oe?isNaN(this.prerelease[1])&&(this.prerelease=[oe,0]):this.prerelease=[oe,0]);break;default:throw new Error("invalid increment argument: "+V)}return this.format(),this.raw=this.version,this},l.inc=function(V,oe,ve,ee){typeof ve=="string"&&(ee=ve,ve=void 0);try{return new v(V,ve).inc(oe,ee).version}catch{return null}},l.diff=function(V,oe){if(fe(V,oe))return null;var ve=Q(V),ee=Q(oe),Oe="";if(ve.prerelease.length||ee.prerelease.length){Oe="pre";var et="prerelease"}for(var ct in ve)if((ct==="major"||ct==="minor"||ct==="patch")&&ve[ct]!==ee[ct])return Oe+ct;return et},l.compareIdentifiers=ye;var de=/^[0-9]+$/;function ye(V,oe){var ve=de.test(V),ee=de.test(oe);return ve&&ee&&(V=+V,oe=+oe),V===oe?0:ve&&!ee?-1:ee&&!ve?1:V0}function Me(V,oe,ve){return le(V,oe,ve)<0}function fe(V,oe,ve){return le(V,oe,ve)===0}function pe(V,oe,ve){return le(V,oe,ve)!==0}function Z(V,oe,ve){return le(V,oe,ve)>=0}function Ae(V,oe,ve){return le(V,oe,ve)<=0}function Fe(V,oe,ve,ee){switch(oe){case"===":return _(V)==="object"&&(V=V.version),_(ve)==="object"&&(ve=ve.version),V===ve;case"!==":return _(V)==="object"&&(V=V.version),_(ve)==="object"&&(ve=ve.version),V!==ve;case"":case"=":case"==":return fe(V,ve,ee);case"!=":return pe(V,ve,ee);case">":return ae(V,ve,ee);case">=":return Z(V,ve,ee);case"<":return Me(V,ve,ee);case"<=":return Ae(V,ve,ee);default:throw new TypeError("Invalid operator: "+oe)}}function He(V,oe){if(oe&&_(oe)==="object"||(oe={loose:!!oe,includePrerelease:!1}),V instanceof He){if(V.loose===!!oe.loose)return V;V=V.value}if(!(this instanceof He))return new He(V,oe);t("comparator",V,oe),this.options=oe,this.loose=!!oe.loose,this.parse(V),this.semver===ot?this.value="":this.value=this.operator+this.semver.version,t("comp",this)}l.rcompareIdentifiers=function(V,oe){return ye(oe,V)},l.major=function(V,oe){return new v(V,oe).major},l.minor=function(V,oe){return new v(V,oe).minor},l.patch=function(V,oe){return new v(V,oe).patch},l.compare=le,l.compareLoose=function(V,oe){return le(V,oe,!0)},l.compareBuild=function(V,oe,ve){var ee=new v(V,ve),Oe=new v(oe,ve);return ee.compare(Oe)||ee.compareBuild(Oe)},l.rcompare=function(V,oe,ve){return le(oe,V,ve)},l.sort=function(V,oe){return V.sort(function(ve,ee){return l.compareBuild(ve,ee,oe)})},l.rsort=function(V,oe){return V.sort(function(ve,ee){return l.compareBuild(ee,ve,oe)})},l.gt=ae,l.lt=Me,l.eq=fe,l.neq=pe,l.gte=Z,l.lte=Ae,l.cmp=Fe,l.Comparator=He;var ot={};function st(V,oe){if(oe&&_(oe)==="object"||(oe={loose:!!oe,includePrerelease:!1}),V instanceof st)return V.loose===!!oe.loose&&V.includePrerelease===!!oe.includePrerelease?V:new st(V.raw,oe);if(V instanceof He)return new st(V.value,oe);if(!(this instanceof st))return new st(V,oe);if(this.options=oe,this.loose=!!oe.loose,this.includePrerelease=!!oe.includePrerelease,this.raw=V,this.set=V.split(/\s*\|\|\s*/).map(function(ve){return this.parseRange(ve.trim())},this).filter(function(ve){return ve.length}),!this.set.length)throw new TypeError("Invalid SemVer Range: "+V);this.format()}function qe(V,oe){for(var ve=!0,ee=V.slice(),Oe=ee.pop();ve&&ee.length;)ve=ee.every(function(et){return Oe.intersects(et,oe)}),Oe=ee.pop();return ve}function Xe(V){return!V||V.toLowerCase()==="x"||V==="*"}function Ie(V,oe,ve,ee,Oe,et,ct,Lt,Xt,pn,Nn,Wt,Ot){return((oe=Xe(ve)?"":Xe(ee)?">="+ve+".0.0":Xe(Oe)?">="+ve+"."+ee+".0":">="+oe)+" "+(Lt=Xe(Xt)?"":Xe(pn)?"<"+(+Xt+1)+".0.0":Xe(Nn)?"<"+Xt+"."+(+pn+1)+".0":Wt?"<="+Xt+"."+pn+"."+Nn+"-"+Wt:"<="+Lt)).trim()}function kt(V,oe,ve){for(var ee=0;ee0){var Oe=V[ee].semver;if(Oe.major===oe.major&&Oe.minor===oe.minor&&Oe.patch===oe.patch)return!0}return!1}return!0}function Kt(V,oe,ve){try{oe=new st(oe,ve)}catch{return!1}return oe.test(V)}function Ye(V,oe,ve,ee){var Oe,et,ct,Lt,Xt;switch(V=new v(V,ee),oe=new st(oe,ee),ve){case">":Oe=ae,et=Ae,ct=Me,Lt=">",Xt=">=";break;case"<":Oe=Me,et=Z,ct=ae,Lt="<",Xt="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(Kt(V,oe,ee))return!1;for(var pn=0;pn=0.0.0")),Wt=Wt||Wn,Ot=Ot||Wn,Oe(Wn.semver,Wt.semver,ee)?Wt=Wn:ct(Wn.semver,Ot.semver,ee)&&(Ot=Wn)}),Wt.operator===Lt||Wt.operator===Xt||(!Ot.operator||Ot.operator===Lt)&&et(V,Ot.semver)||Ot.operator===Xt&&ct(V,Ot.semver))return!1}return!0}He.prototype.parse=function(V){var oe=this.options.loose?M[T.COMPARATORLOOSE]:M[T.COMPARATOR],ve=V.match(oe);if(!ve)throw new TypeError("Invalid comparator: "+V);this.operator=ve[1]!==void 0?ve[1]:"",this.operator==="="&&(this.operator=""),ve[2]?this.semver=new v(ve[2],this.options.loose):this.semver=ot},He.prototype.toString=function(){return this.value},He.prototype.test=function(V){if(t("Comparator.test",V,this.options.loose),this.semver===ot||V===ot)return!0;if(typeof V=="string")try{V=new v(V,this.options)}catch{return!1}return Fe(V,this.operator,this.semver,this.options)},He.prototype.intersects=function(V,oe){if(!(V instanceof He))throw new TypeError("a Comparator is required");var ve;if(oe&&_(oe)==="object"||(oe={loose:!!oe,includePrerelease:!1}),this.operator==="")return this.value===""||(ve=new st(V.value,oe),Kt(this.value,ve,oe));if(V.operator==="")return V.value===""||(ve=new st(this.value,oe),Kt(V.semver,ve,oe));var ee=!(this.operator!==">="&&this.operator!==">"||V.operator!==">="&&V.operator!==">"),Oe=!(this.operator!=="<="&&this.operator!=="<"||V.operator!=="<="&&V.operator!=="<"),et=this.semver.version===V.semver.version,ct=!(this.operator!==">="&&this.operator!=="<="||V.operator!==">="&&V.operator!=="<="),Lt=Fe(this.semver,"<",V.semver,oe)&&(this.operator===">="||this.operator===">")&&(V.operator==="<="||V.operator==="<"),Xt=Fe(this.semver,">",V.semver,oe)&&(this.operator==="<="||this.operator==="<")&&(V.operator===">="||V.operator===">");return ee||Oe||et&&ct||Lt||Xt},l.Range=st,st.prototype.format=function(){return this.range=this.set.map(function(V){return V.join(" ").trim()}).join("||").trim(),this.range},st.prototype.toString=function(){return this.range},st.prototype.parseRange=function(V){var oe=this.options.loose;V=V.trim();var ve=oe?M[T.HYPHENRANGELOOSE]:M[T.HYPHENRANGE];V=V.replace(ve,Ie),t("hyphen replace",V),V=V.replace(M[T.COMPARATORTRIM],"$1$2$3"),t("comparator trim",V,M[T.COMPARATORTRIM]),V=(V=(V=V.replace(M[T.TILDETRIM],"$1~")).replace(M[T.CARETTRIM],"$1^")).split(/\s+/).join(" ");var ee=oe?M[T.COMPARATORLOOSE]:M[T.COMPARATOR],Oe=V.split(" ").map(function(et){return function(ct,Lt){return t("comp",ct,Lt),ct=function(Xt,pn){return Xt.trim().split(/\s+/).map(function(Nn){return function(Wt,Ot){t("caret",Wt,Ot);var Wn=Ot.loose?M[T.CARETLOOSE]:M[T.CARET];return Wt.replace(Wn,function(w,Ct,wn,ir,sr){var Ln;return t("caret",Wt,w,Ct,wn,ir,sr),Xe(Ct)?Ln="":Xe(wn)?Ln=">="+Ct+".0.0 <"+(+Ct+1)+".0.0":Xe(ir)?Ln=Ct==="0"?">="+Ct+"."+wn+".0 <"+Ct+"."+(+wn+1)+".0":">="+Ct+"."+wn+".0 <"+(+Ct+1)+".0.0":sr?(t("replaceCaret pr",sr),Ln=Ct==="0"?wn==="0"?">="+Ct+"."+wn+"."+ir+"-"+sr+" <"+Ct+"."+wn+"."+(+ir+1):">="+Ct+"."+wn+"."+ir+"-"+sr+" <"+Ct+"."+(+wn+1)+".0":">="+Ct+"."+wn+"."+ir+"-"+sr+" <"+(+Ct+1)+".0.0"):(t("no pr"),Ln=Ct==="0"?wn==="0"?">="+Ct+"."+wn+"."+ir+" <"+Ct+"."+wn+"."+(+ir+1):">="+Ct+"."+wn+"."+ir+" <"+Ct+"."+(+wn+1)+".0":">="+Ct+"."+wn+"."+ir+" <"+(+Ct+1)+".0.0"),t("caret return",Ln),Ln})}(Nn,pn)}).join(" ")}(ct,Lt),t("caret",ct),ct=function(Xt,pn){return Xt.trim().split(/\s+/).map(function(Nn){return function(Wt,Ot){var Wn=Ot.loose?M[T.TILDELOOSE]:M[T.TILDE];return Wt.replace(Wn,function(w,Ct,wn,ir,sr){var Ln;return t("tilde",Wt,w,Ct,wn,ir,sr),Xe(Ct)?Ln="":Xe(wn)?Ln=">="+Ct+".0.0 <"+(+Ct+1)+".0.0":Xe(ir)?Ln=">="+Ct+"."+wn+".0 <"+Ct+"."+(+wn+1)+".0":sr?(t("replaceTilde pr",sr),Ln=">="+Ct+"."+wn+"."+ir+"-"+sr+" <"+Ct+"."+(+wn+1)+".0"):Ln=">="+Ct+"."+wn+"."+ir+" <"+Ct+"."+(+wn+1)+".0",t("tilde return",Ln),Ln})}(Nn,pn)}).join(" ")}(ct,Lt),t("tildes",ct),ct=function(Xt,pn){return t("replaceXRanges",Xt,pn),Xt.split(/\s+/).map(function(Nn){return function(Wt,Ot){Wt=Wt.trim();var Wn=Ot.loose?M[T.XRANGELOOSE]:M[T.XRANGE];return Wt.replace(Wn,function(w,Ct,wn,ir,sr,Ln){t("xRange",Wt,w,Ct,wn,ir,sr,Ln);var Er=Xe(wn),zt=Er||Xe(ir),p0=zt||Xe(sr),B0=p0;return Ct==="="&&B0&&(Ct=""),Ln=Ot.includePrerelease?"-0":"",Er?w=Ct===">"||Ct==="<"?"<0.0.0-0":"*":Ct&&B0?(zt&&(ir=0),sr=0,Ct===">"?(Ct=">=",zt?(wn=+wn+1,ir=0,sr=0):(ir=+ir+1,sr=0)):Ct==="<="&&(Ct="<",zt?wn=+wn+1:ir=+ir+1),w=Ct+wn+"."+ir+"."+sr+Ln):zt?w=">="+wn+".0.0"+Ln+" <"+(+wn+1)+".0.0"+Ln:p0&&(w=">="+wn+"."+ir+".0"+Ln+" <"+wn+"."+(+ir+1)+".0"+Ln),t("xRange return",w),w})}(Nn,pn)}).join(" ")}(ct,Lt),t("xrange",ct),ct=function(Xt,pn){return t("replaceStars",Xt,pn),Xt.trim().replace(M[T.STAR],"")}(ct,Lt),t("stars",ct),ct}(et,this.options)},this).join(" ").split(/\s+/);return this.options.loose&&(Oe=Oe.filter(function(et){return!!et.match(ee)})),Oe=Oe.map(function(et){return new He(et,this.options)},this)},st.prototype.intersects=function(V,oe){if(!(V instanceof st))throw new TypeError("a Range is required");return this.set.some(function(ve){return qe(ve,oe)&&V.set.some(function(ee){return qe(ee,oe)&&ve.every(function(Oe){return ee.every(function(et){return Oe.intersects(et,oe)})})})})},l.toComparators=function(V,oe){return new st(V,oe).set.map(function(ve){return ve.map(function(ee){return ee.value}).join(" ").trim().split(" ")})},st.prototype.test=function(V){if(!V)return!1;if(typeof V=="string")try{V=new v(V,this.options)}catch{return!1}for(var oe=0;oe":et.prerelease.length===0?et.patch++:et.prerelease.push(0),et.raw=et.format();case"":case">=":ve&&!ae(ve,et)||(ve=et);break;case"<":case"<=":break;default:throw new Error("Unexpected operation: "+Oe.operator)}});return ve&&V.test(ve)?ve:null},l.validRange=function(V,oe){try{return new st(V,oe).range||"*"}catch{return null}},l.ltr=function(V,oe,ve){return Ye(V,oe,"<",ve)},l.gtr=function(V,oe,ve){return Ye(V,oe,">",ve)},l.outside=Ye,l.prerelease=function(V,oe){var ve=Q(V,oe);return ve&&ve.prerelease.length?ve.prerelease:null},l.intersects=function(V,oe,ve){return V=new st(V,ve),oe=new st(oe,ve),V.intersects(oe)},l.coerce=function(V,oe){if(V instanceof v)return V;if(typeof V=="number"&&(V=String(V)),typeof V!="string")return null;var ve=null;if((oe=oe||{}).rtl){for(var ee;(ee=M[T.COERCERTL].exec(V))&&(!ve||ve.index+ve[0].length!==V.length);)ve&&ee.index+ee[0].length===ve.index+ve[0].length||(ve=ee),M[T.COERCERTL].lastIndex=ee.index+ee[1].length+ee[2].length;M[T.COERCERTL].lastIndex=-1}else ve=V.match(M[T.COERCE]);return ve===null?null:Q(ve[2]+"."+(ve[3]||"0")+"."+(ve[4]||"0"),oe)}}).call(this,c(5))},function(u,l){function c(_){return(c=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(t){return typeof t}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(_)}var p;p=function(){return this}();try{p=p||new Function("return this")()}catch{(typeof window>"u"?"undefined":c(window))==="object"&&(p=window)}u.exports=p},function(u,l){var c,p,_=u.exports={};function t(){throw new Error("setTimeout has not been defined")}function O(){throw new Error("clearTimeout has not been defined")}function M(ye){if(c===setTimeout)return setTimeout(ye,0);if((c===t||!c)&&setTimeout)return c=setTimeout,setTimeout(ye,0);try{return c(ye,0)}catch{try{return c.call(null,ye,0)}catch{return c.call(this,ye,0)}}}(function(){try{c=typeof setTimeout=="function"?setTimeout:t}catch{c=t}try{p=typeof clearTimeout=="function"?clearTimeout:O}catch{p=O}})();var A,T=[],P=!1,U=-1;function z(){P&&A&&(P=!1,A.length?T=A.concat(T):U=-1,T.length&&Q())}function Q(){if(!P){var ye=M(z);P=!0;for(var le=T.length;le;){for(A=T,T=[];++U1)for(var ae=1;aethis[O])return pe(this,this[v].get(qe)),!1;var Ye=this[v].get(qe).value;return this[U]&&(this[z]||this[U](qe,Ye.value)),Ye.now=kt,Ye.maxAge=Ie,Ye.value=Xe,this[M]+=Kt-Ye.length,Ye.length=Kt,this.get(qe),fe(this),!0}var V=new Z(qe,Xe,Kt,kt,Ie);return V.length>this[O]?(this[U]&&this[U](qe,Xe),!1):(this[M]+=V.length,this[Q].unshift(V),this[v].set(qe,this[Q].head),fe(this),!0)}},{key:"has",value:function(qe){if(!this[v].has(qe))return!1;var Xe=this[v].get(qe).value;return!Me(this,Xe)}},{key:"get",value:function(qe){return ae(this,qe,!0)}},{key:"peek",value:function(qe){return ae(this,qe,!1)}},{key:"pop",value:function(){var qe=this[Q].tail;return qe?(pe(this,qe),qe.value):null}},{key:"del",value:function(qe){pe(this,this[v].get(qe))}},{key:"load",value:function(qe){this.reset();for(var Xe=Date.now(),Ie=qe.length-1;Ie>=0;Ie--){var kt=qe[Ie],Kt=kt.e||0;if(Kt===0)this.set(kt.k,kt.v);else{var Ye=Kt-Xe;Ye>0&&this.set(kt.k,kt.v,Ye)}}}},{key:"prune",value:function(){var qe=this;this[v].forEach(function(Xe,Ie){return ae(qe,Ie,!1)})}},{key:"max",set:function(qe){if(typeof qe!="number"||qe<0)throw new TypeError("max must be a non-negative number");this[O]=qe||1/0,fe(this)},get:function(){return this[O]}},{key:"allowStale",set:function(qe){this[T]=!!qe},get:function(){return this[T]}},{key:"maxAge",set:function(qe){if(typeof qe!="number")throw new TypeError("maxAge must be a non-negative number");this[P]=qe,fe(this)},get:function(){return this[P]}},{key:"lengthCalculator",set:function(qe){var Xe=this;typeof qe!="function"&&(qe=ye),qe!==this[A]&&(this[A]=qe,this[M]=0,this[Q].forEach(function(Ie){Ie.length=Xe[A](Ie.value,Ie.key),Xe[M]+=Ie.length})),fe(this)},get:function(){return this[A]}},{key:"length",get:function(){return this[M]}},{key:"itemCount",get:function(){return this[Q].length}}])&&_(He.prototype,ot),st&&_(He,st),Fe}(),ae=function(Fe,He,ot){var st=Fe[v].get(He);if(st){var qe=st.value;if(Me(Fe,qe)){if(pe(Fe,st),!Fe[T])return}else ot&&(Fe[de]&&(st.value.now=Date.now()),Fe[Q].unshiftNode(st));return qe.value}},Me=function(Fe,He){if(!He||!He.maxAge&&!Fe[P])return!1;var ot=Date.now()-He.now;return He.maxAge?ot>He.maxAge:Fe[P]&&ot>Fe[P]},fe=function(Fe){if(Fe[M]>Fe[O])for(var He=Fe[Q].tail;Fe[M]>Fe[O]&&He!==null;){var ot=He.prev;pe(Fe,He),He=ot}},pe=function(Fe,He){if(He){var ot=He.value;Fe[U]&&Fe[U](ot.key,ot.value),Fe[M]-=ot.length,Fe[v].delete(ot.key),Fe[Q].removeNode(He)}},Z=function Fe(He,ot,st,qe,Xe){p(this,Fe),this.key=He,this.value=ot,this.length=st,this.now=qe,this.maxAge=Xe||0},Ae=function(Fe,He,ot,st){var qe=ot.value;Me(Fe,qe)&&(pe(Fe,ot),Fe[T]||(qe=void 0)),qe&&He.call(st,qe.value,qe.key,Fe)};u.exports=le},function(u,l,c){(function(p){function _(t){return(_=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(O){return typeof O}:function(O){return O&&typeof Symbol=="function"&&O.constructor===Symbol&&O!==Symbol.prototype?"symbol":typeof O})(t)}u.exports=function(){if(typeof document>"u"||!document.addEventListener)return null;var t,O,M,A={};return A.copy=function(){var T=!1,P=null,U=!1;function z(){T=!1,P=null,U&&window.getSelection().removeAllRanges(),U=!1}return document.addEventListener("copy",function(Q){if(T){for(var v in P)Q.clipboardData.setData(v,P[v]);Q.preventDefault()}}),function(Q){return new Promise(function(v,de){T=!0,typeof Q=="string"?P={"text/plain":Q}:Q instanceof Node?P={"text/html":new XMLSerializer().serializeToString(Q)}:Q instanceof Object?P=Q:de("Invalid data type. Must be string, DOM node, or an object mapping MIME types to strings."),function ye(le){try{if(document.execCommand("copy"))z(),v();else{if(le)throw z(),new Error("Unable to copy. Perhaps it's not available in your browser?");(function(){var ae=document.getSelection();if(!document.queryCommandEnabled("copy")&&ae.isCollapsed){var Me=document.createRange();Me.selectNodeContents(document.body),ae.removeAllRanges(),ae.addRange(Me),U=!0}})(),ye(!0)}}catch(ae){z(),de(ae)}}(!1)})}}(),A.paste=(M=!1,document.addEventListener("paste",function(T){if(M){M=!1,T.preventDefault();var P=t;t=null,P(T.clipboardData.getData(O))}}),function(T){return new Promise(function(P,U){M=!0,t=P,O=T||"text/plain";try{document.execCommand("paste")||(M=!1,U(new Error("Unable to paste. Pasting only works in Internet Explorer at the moment.")))}catch(z){M=!1,U(new Error(z))}})}),typeof ClipboardEvent>"u"&&window.clipboardData!==void 0&&window.clipboardData.setData!==void 0&&(function(T){function P(fe,pe){return function(){fe.apply(pe,arguments)}}function U(fe){if(_(this)!="object")throw new TypeError("Promises must be constructed via new");if(typeof fe!="function")throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],le(fe,P(Q,this),P(v,this))}function z(fe){var pe=this;return this._state===null?void this._deferreds.push(fe):void ae(function(){var Z=pe._state?fe.onFulfilled:fe.onRejected;if(Z!==null){var Ae;try{Ae=Z(pe._value)}catch(Fe){return void fe.reject(Fe)}fe.resolve(Ae)}else(pe._state?fe.resolve:fe.reject)(pe._value)})}function Q(fe){try{if(fe===this)throw new TypeError("A promise cannot be resolved with itself.");if(fe&&(_(fe)=="object"||typeof fe=="function")){var pe=fe.then;if(typeof pe=="function")return void le(P(pe,fe),P(Q,this),P(v,this))}this._state=!0,this._value=fe,de.call(this)}catch(Z){v.call(this,Z)}}function v(fe){this._state=!1,this._value=fe,de.call(this)}function de(){for(var fe=0,pe=this._deferreds.length;pe>fe;fe++)z.call(this,this._deferreds[fe]);this._deferreds=null}function ye(fe,pe,Z,Ae){this.onFulfilled=typeof fe=="function"?fe:null,this.onRejected=typeof pe=="function"?pe:null,this.resolve=Z,this.reject=Ae}function le(fe,pe,Z){var Ae=!1;try{fe(function(Fe){Ae||(Ae=!0,pe(Fe))},function(Fe){Ae||(Ae=!0,Z(Fe))})}catch(Fe){if(Ae)return;Ae=!0,Z(Fe)}}var ae=U.immediateFn||typeof p=="function"&&p||function(fe){setTimeout(fe,1)},Me=Array.isArray||function(fe){return Object.prototype.toString.call(fe)==="[object Array]"};U.prototype.catch=function(fe){return this.then(null,fe)},U.prototype.then=function(fe,pe){var Z=this;return new U(function(Ae,Fe){z.call(Z,new ye(fe,pe,Ae,Fe))})},U.all=function(){var fe=Array.prototype.slice.call(arguments.length===1&&Me(arguments[0])?arguments[0]:arguments);return new U(function(pe,Z){function Ae(ot,st){try{if(st&&(_(st)=="object"||typeof st=="function")){var qe=st.then;if(typeof qe=="function")return void qe.call(st,function(Xe){Ae(ot,Xe)},Z)}fe[ot]=st,--Fe==0&&pe(fe)}catch(Xe){Z(Xe)}}if(fe.length===0)return pe([]);for(var Fe=fe.length,He=0;HeAe;Ae++)fe[Ae].then(pe,Z)})},u.exports?u.exports=U:T.Promise||(T.Promise=U)}(this),A.copy=function(T){return new Promise(function(P,U){if(typeof T!="string"&&!("text/plain"in T))throw new Error("You must provide a text/plain type.");var z=typeof T=="string"?T:T["text/plain"];window.clipboardData.setData("Text",z)?P():U(new Error("Copying was rejected."))})},A.paste=function(){return new Promise(function(T,P){var U=window.clipboardData.getData("Text");U?T(U):P(new Error("Pasting was rejected."))})}),A}()}).call(this,c(13).setImmediate)},function(u,l,c){"use strict";u.exports=c(15)},function(u,l,c){"use strict";c.r(l),l.default=`:root { + /** + * IMPORTANT: When new theme variables are added below\u2013 also add them to SettingsContext updateThemeVariables() + */ + + /* Light theme */ + --light-color-attribute-name: #ef6632; + --light-color-attribute-name-not-editable: #23272f; + --light-color-attribute-name-inverted: rgba(255, 255, 255, 0.7); + --light-color-attribute-value: #1a1aa6; + --light-color-attribute-value-inverted: #ffffff; + --light-color-attribute-editable-value: #1a1aa6; + --light-color-background: #ffffff; + --light-color-background-hover: rgba(0, 136, 250, 0.1); + --light-color-background-inactive: #e5e5e5; + --light-color-background-invalid: #fff0f0; + --light-color-background-selected: #0088fa; + --light-color-button-background: #ffffff; + --light-color-button-background-focus: #ededed; + --light-color-button: #5f6673; + --light-color-button-disabled: #cfd1d5; + --light-color-button-active: #0088fa; + --light-color-button-focus: #23272f; + --light-color-button-hover: #23272f; + --light-color-border: #eeeeee; + --light-color-commit-did-not-render-fill: #cfd1d5; + --light-color-commit-did-not-render-fill-text: #000000; + --light-color-commit-did-not-render-pattern: #cfd1d5; + --light-color-commit-did-not-render-pattern-text: #333333; + --light-color-commit-gradient-0: #37afa9; + --light-color-commit-gradient-1: #63b19e; + --light-color-commit-gradient-2: #80b393; + --light-color-commit-gradient-3: #97b488; + --light-color-commit-gradient-4: #abb67d; + --light-color-commit-gradient-5: #beb771; + --light-color-commit-gradient-6: #cfb965; + --light-color-commit-gradient-7: #dfba57; + --light-color-commit-gradient-8: #efbb49; + --light-color-commit-gradient-9: #febc38; + --light-color-commit-gradient-text: #000000; + --light-color-component-name: #6a51b2; + --light-color-component-name-inverted: #ffffff; + --light-color-component-badge-background: rgba(0, 0, 0, 0.1); + --light-color-component-badge-background-inverted: rgba(255, 255, 255, 0.25); + --light-color-component-badge-count: #777d88; + --light-color-component-badge-count-inverted: rgba(255, 255, 255, 0.7); + --light-color-context-background: rgba(0,0,0,.9); + --light-color-context-background-hover: rgba(255, 255, 255, 0.1); + --light-color-context-background-selected: #178fb9; + --light-color-context-border: #3d424a; + --light-color-context-text: #ffffff; + --light-color-context-text-selected: #ffffff; + --light-color-dim: #777d88; + --light-color-dimmer: #cfd1d5; + --light-color-dimmest: #eff0f1; + --light-color-error-background: hsl(0, 100%, 97%); + --light-color-error-border: hsl(0, 100%, 92%); + --light-color-error-text: #ff0000; + --light-color-expand-collapse-toggle: #777d88; + --light-color-link: #0000ff; + --light-color-modal-background: rgba(255, 255, 255, 0.75); + --light-color-record-active: #fc3a4b; + --light-color-record-hover: #3578e5; + --light-color-record-inactive: #0088fa; + --light-color-scroll-thumb: #c2c2c2; + --light-color-scroll-track: #fafafa; + --light-color-search-match: yellow; + --light-color-search-match-current: #f7923b; + --light-color-selected-tree-highlight-active: rgba(0, 136, 250, 0.1); + --light-color-selected-tree-highlight-inactive: rgba(0, 0, 0, 0.05); + --light-color-shadow: rgba(0, 0, 0, 0.25); + --light-color-tab-selected-border: #0088fa; + --light-color-text: #000000; + --light-color-text-invalid: #ff0000; + --light-color-text-selected: #ffffff; + --light-color-toggle-background-invalid: #fc3a4b; + --light-color-toggle-background-on: #0088fa; + --light-color-toggle-background-off: #cfd1d5; + --light-color-toggle-text: #ffffff; + --light-color-tooltip-background: rgba(0, 0, 0, 0.9); + --light-color-tooltip-text: #ffffff; + + /* Dark theme */ + --dark-color-attribute-name: #9d87d2; + --dark-color-attribute-name-not-editable: #ededed; + --dark-color-attribute-name-inverted: #282828; + --dark-color-attribute-value: #cedae0; + --dark-color-attribute-value-inverted: #ffffff; + --dark-color-attribute-editable-value: yellow; + --dark-color-background: #282c34; + --dark-color-background-hover: rgba(255, 255, 255, 0.1); + --dark-color-background-inactive: #3d424a; + --dark-color-background-invalid: #5c0000; + --dark-color-background-selected: #178fb9; + --dark-color-button-background: #282c34; + --dark-color-button-background-focus: #3d424a; + --dark-color-button: #afb3b9; + --dark-color-button-active: #61dafb; + --dark-color-button-disabled: #4f5766; + --dark-color-button-focus: #a2e9fc; + --dark-color-button-hover: #ededed; + --dark-color-border: #3d424a; + --dark-color-commit-did-not-render-fill: #777d88; + --dark-color-commit-did-not-render-fill-text: #000000; + --dark-color-commit-did-not-render-pattern: #666c77; + --dark-color-commit-did-not-render-pattern-text: #ffffff; + --dark-color-commit-gradient-0: #37afa9; + --dark-color-commit-gradient-1: #63b19e; + --dark-color-commit-gradient-2: #80b393; + --dark-color-commit-gradient-3: #97b488; + --dark-color-commit-gradient-4: #abb67d; + --dark-color-commit-gradient-5: #beb771; + --dark-color-commit-gradient-6: #cfb965; + --dark-color-commit-gradient-7: #dfba57; + --dark-color-commit-gradient-8: #efbb49; + --dark-color-commit-gradient-9: #febc38; + --dark-color-commit-gradient-text: #000000; + --dark-color-component-name: #61dafb; + --dark-color-component-name-inverted: #282828; + --dark-color-component-badge-background: rgba(255, 255, 255, 0.25); + --dark-color-component-badge-background-inverted: rgba(0, 0, 0, 0.25); + --dark-color-component-badge-count: #8f949d; + --dark-color-component-badge-count-inverted: rgba(255, 255, 255, 0.7); + --dark-color-context-background: rgba(255,255,255,.9); + --dark-color-context-background-hover: rgba(0, 136, 250, 0.1); + --dark-color-context-background-selected: #0088fa; + --dark-color-context-border: #eeeeee; + --dark-color-context-text: #000000; + --dark-color-context-text-selected: #ffffff; + --dark-color-dim: #8f949d; + --dark-color-dimmer: #777d88; + --dark-color-dimmest: #4f5766; + --dark-color-error-background: #200; + --dark-color-error-border: #900; + --dark-color-error-text: #f55; + --dark-color-expand-collapse-toggle: #8f949d; + --dark-color-link: #61dafb; + --dark-color-modal-background: rgba(0, 0, 0, 0.75); + --dark-color-record-active: #fc3a4b; + --dark-color-record-hover: #a2e9fc; + --dark-color-record-inactive: #61dafb; + --dark-color-scroll-thumb: #afb3b9; + --dark-color-scroll-track: #313640; + --dark-color-search-match: yellow; + --dark-color-search-match-current: #f7923b; + --dark-color-selected-tree-highlight-active: rgba(23, 143, 185, 0.15); + --dark-color-selected-tree-highlight-inactive: rgba(255, 255, 255, 0.05); + --dark-color-shadow: rgba(0, 0, 0, 0.5); + --dark-color-tab-selected-border: #178fb9; + --dark-color-text: #ffffff; + --dark-color-text-invalid: #ff8080; + --dark-color-text-selected: #ffffff; + --dark-color-toggle-background-invalid: #fc3a4b; + --dark-color-toggle-background-on: #178fb9; + --dark-color-toggle-background-off: #777d88; + --dark-color-toggle-text: #ffffff; + --dark-color-tooltip-background: rgba(255, 255, 255, 0.9); + --dark-color-tooltip-text: #000000; + + /* Font smoothing */ + --light-font-smoothing: auto; + --dark-font-smoothing: antialiased; + --font-smoothing: auto; + + /* Compact density */ + --compact-font-size-monospace-small: 9px; + --compact-font-size-monospace-normal: 11px; + --compact-font-size-monospace-large: 15px; + --compact-font-size-sans-small: 10px; + --compact-font-size-sans-normal: 12px; + --compact-font-size-sans-large: 14px; + --compact-line-height-data: 18px; + --compact-root-font-size: 16px; + + /* Comfortable density */ + --comfortable-font-size-monospace-small: 10px; + --comfortable-font-size-monospace-normal: 13px; + --comfortable-font-size-monospace-large: 17px; + --comfortable-font-size-sans-small: 12px; + --comfortable-font-size-sans-normal: 14px; + --comfortable-font-size-sans-large: 16px; + --comfortable-line-height-data: 22px; + --comfortable-root-font-size: 20px; + + /* GitHub.com system fonts */ + --font-family-monospace: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, + Courier, monospace; + --font-family-sans: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, + Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + + /* Constant values shared between JS and CSS */ + --interaction-commit-size: 10px; + --interaction-label-width: 200px; +} +`},function(u,l,c){"use strict";function p(A){var T=this;if(T instanceof p||(T=new p),T.tail=null,T.head=null,T.length=0,A&&typeof A.forEach=="function")A.forEach(function(z){T.push(z)});else if(arguments.length>0)for(var P=0,U=arguments.length;P1)P=T;else{if(!this.head)throw new TypeError("Reduce of empty list with no initial value");U=this.head.next,P=this.head.value}for(var z=0;U!==null;z++)P=A(P,U.value,z),U=U.next;return P},p.prototype.reduceReverse=function(A,T){var P,U=this.tail;if(arguments.length>1)P=T;else{if(!this.tail)throw new TypeError("Reduce of empty list with no initial value");U=this.tail.prev,P=this.tail.value}for(var z=this.length-1;U!==null;z--)P=A(P,U.value,z),U=U.prev;return P},p.prototype.toArray=function(){for(var A=new Array(this.length),T=0,P=this.head;P!==null;T++)A[T]=P.value,P=P.next;return A},p.prototype.toArrayReverse=function(){for(var A=new Array(this.length),T=0,P=this.tail;P!==null;T++)A[T]=P.value,P=P.prev;return A},p.prototype.slice=function(A,T){(T=T||this.length)<0&&(T+=this.length),(A=A||0)<0&&(A+=this.length);var P=new p;if(Tthis.length&&(T=this.length);for(var U=0,z=this.head;z!==null&&Uthis.length&&(T=this.length);for(var U=this.length,z=this.tail;z!==null&&U>T;U--)z=z.prev;for(;z!==null&&U>A;U--,z=z.prev)P.push(z.value);return P},p.prototype.splice=function(A,T){A>this.length&&(A=this.length-1),A<0&&(A=this.length+A);for(var P=0,U=this.head;U!==null&&P=0&&(M._idleTimeoutId=setTimeout(function(){M._onTimeout&&M._onTimeout()},A))},c(14),l.setImmediate=typeof self<"u"&&self.setImmediate||p!==void 0&&p.setImmediate||this&&this.setImmediate,l.clearImmediate=typeof self<"u"&&self.clearImmediate||p!==void 0&&p.clearImmediate||this&&this.clearImmediate}).call(this,c(4))},function(u,l,c){(function(p,_){(function(t,O){"use strict";if(!t.setImmediate){var M,A,T,P,U,z=1,Q={},v=!1,de=t.document,ye=Object.getPrototypeOf&&Object.getPrototypeOf(t);ye=ye&&ye.setTimeout?ye:t,{}.toString.call(t.process)==="[object process]"?M=function(Me){_.nextTick(function(){ae(Me)})}:function(){if(t.postMessage&&!t.importScripts){var Me=!0,fe=t.onmessage;return t.onmessage=function(){Me=!1},t.postMessage("","*"),t.onmessage=fe,Me}}()?(P="setImmediate$"+Math.random()+"$",U=function(Me){Me.source===t&&typeof Me.data=="string"&&Me.data.indexOf(P)===0&&ae(+Me.data.slice(P.length))},t.addEventListener?t.addEventListener("message",U,!1):t.attachEvent("onmessage",U),M=function(Me){t.postMessage(P+Me,"*")}):t.MessageChannel?((T=new MessageChannel).port1.onmessage=function(Me){ae(Me.data)},M=function(Me){T.port2.postMessage(Me)}):de&&"onreadystatechange"in de.createElement("script")?(A=de.documentElement,M=function(Me){var fe=de.createElement("script");fe.onreadystatechange=function(){ae(Me),fe.onreadystatechange=null,A.removeChild(fe),fe=null},A.appendChild(fe)}):M=function(Me){setTimeout(ae,0,Me)},ye.setImmediate=function(Me){typeof Me!="function"&&(Me=new Function(""+Me));for(var fe=new Array(arguments.length-1),pe=0;pe"u"?p===void 0?this:p:self)}).call(this,c(4),c(5))},function(u,l,c){"use strict";function p(Z){return(p=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(Ae){return typeof Ae}:function(Ae){return Ae&&typeof Symbol=="function"&&Ae.constructor===Symbol&&Ae!==Symbol.prototype?"symbol":typeof Ae})(Z)}var _=c(1),t=c(16),O=c(18).__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,M=60128;if(typeof Symbol=="function"&&Symbol.for){var A=Symbol.for;M=A("react.opaque.id")}var T=[],P=null,U=null;function z(){if(P===null){var Z=new Map;try{de.useContext({_currentValue:null}),de.useState(null),de.useReducer(function(ot){return ot},null),de.useRef(null),de.useLayoutEffect(function(){}),de.useEffect(function(){}),de.useImperativeHandle(void 0,function(){return null}),de.useDebugValue(null),de.useCallback(function(){}),de.useMemo(function(){return null})}finally{var Ae=T;T=[]}for(var Fe=0;Feoe;oe++)if((V=le(Ye,kt,oe))!==-1){ye=oe,kt=V;break e}kt=-1}}e:{if(Ye=Kt,(V=z().get(Ie.primitive))!==void 0){for(oe=0;oekt-Ye?null:Kt.slice(Ye,kt-1))!==null){if(kt=0,He!==null){for(;ktkt;He--)ot=qe.pop()}for(He=Kt.length-kt-1;1<=He;He--)kt=[],ot.push({id:null,isStateEditable:!1,name:Me(Kt[He-1].functionName),value:void 0,subHooks:kt}),qe.push(ot),ot=kt;He=Kt}kt=(Kt=Ie.primitive)==="Context"||Kt==="DebugValue"?null:st++,ot.push({id:kt,isStateEditable:Kt==="Reducer"||Kt==="State",name:Kt,value:Ie.value,subHooks:[]})}return function ve(ee,Oe){for(var et=[],ct=0;ct-1&&(Q=Q.replace(/eval code/g,"eval").replace(/(\(eval at [^()]*)|(\),.*$)/g,""));var v=Q.replace(/^\s+/,"").replace(/\(eval code/g,"("),de=v.match(/ (\((.+):(\d+):(\d+)\)$)/),ye=(v=de?v.replace(de[0],""):v).split(/\s+/).slice(1),le=this.extractLocation(de?de[1]:ye.pop()),ae=ye.join(" ")||void 0,Me=["eval",""].indexOf(le[0])>-1?void 0:le[0];return new A({functionName:ae,fileName:Me,lineNumber:le[1],columnNumber:le[2],source:Q})},this)},parseFFOrSafari:function(z){return z.stack.split(` +`).filter(function(Q){return!Q.match(U)},this).map(function(Q){if(Q.indexOf(" > eval")>-1&&(Q=Q.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,":$1")),Q.indexOf("@")===-1&&Q.indexOf(":")===-1)return new A({functionName:Q});var v=/((.*".+"[^@]*)?[^@]*)(?:@)/,de=Q.match(v),ye=de&&de[1]?de[1]:void 0,le=this.extractLocation(Q.replace(v,""));return new A({functionName:ye,fileName:le[0],lineNumber:le[1],columnNumber:le[2],source:Q})},this)},parseOpera:function(z){return!z.stacktrace||z.message.indexOf(` +`)>-1&&z.message.split(` +`).length>z.stacktrace.split(` +`).length?this.parseOpera9(z):z.stack?this.parseOpera11(z):this.parseOpera10(z)},parseOpera9:function(z){for(var Q=/Line (\d+).*script (?:in )?(\S+)/i,v=z.message.split(` +`),de=[],ye=2,le=v.length;ye/,"$2").replace(/\([^)]*\)/g,"")||void 0;le.match(/\(([^)]*)\)/)&&(v=le.replace(/^[^(]+\(([^)]*)\)$/,"$1"));var Me=v===void 0||v==="[arguments not available]"?void 0:v.split(",");return new A({functionName:ae,args:Me,fileName:ye[0],lineNumber:ye[1],columnNumber:ye[2],source:Q})},this)}}})=="function"?p.apply(l,_):p)===void 0||(u.exports=t)})()},function(u,l,c){var p,_,t;(function(O,M){"use strict";_=[],(t=typeof(p=function(){function A(ae){return ae.charAt(0).toUpperCase()+ae.substring(1)}function T(ae){return function(){return this[ae]}}var P=["isConstructor","isEval","isNative","isToplevel"],U=["columnNumber","lineNumber"],z=["fileName","functionName","source"],Q=P.concat(U,z,["args"]);function v(ae){if(ae)for(var Me=0;Me1?ge-1:0),De=1;De=0&&ge.splice(G,1)}}}])&&p(B.prototype,q),Y&&p(B,Y),b}(),t=c(2),O=c.n(t);try{var M=c(9).default,A=function(b){var B=new RegExp("".concat(b,": ([0-9]+)")),q=M.match(B);return parseInt(q[1],10)};A("comfortable-line-height-data"),A("compact-line-height-data")}catch{}function T(b){try{return sessionStorage.getItem(b)}catch{return null}}function P(b){try{sessionStorage.removeItem(b)}catch{}}function U(b,B){try{return sessionStorage.setItem(b,B)}catch{}}var z=function(b,B){return b===B},Q=c(1),v=c.n(Q);function de(b){return b.ownerDocument?b.ownerDocument.defaultView:null}function ye(b){var B=de(b);return B?B.frameElement:null}function le(b){var B=fe(b);return ae([b.getBoundingClientRect(),{top:B.borderTop,left:B.borderLeft,bottom:B.borderBottom,right:B.borderRight,width:0,height:0}])}function ae(b){return b.reduce(function(B,q){return B==null?q:{top:B.top+q.top,left:B.left+q.left,width:B.width,height:B.height,bottom:B.bottom+q.bottom,right:B.right+q.right}})}function Me(b,B){var q=ye(b);if(q&&q!==B){for(var Y=[b.getBoundingClientRect()],_e=q,se=!1;_e;){var ge=le(_e);if(Y.push(ge),_e=ye(_e),se)break;_e&&de(_e)===B&&(se=!0)}return ae(Y)}return b.getBoundingClientRect()}function fe(b){var B=window.getComputedStyle(b);return{borderLeft:parseInt(B.borderLeftWidth,10),borderRight:parseInt(B.borderRightWidth,10),borderTop:parseInt(B.borderTopWidth,10),borderBottom:parseInt(B.borderBottomWidth,10),marginLeft:parseInt(B.marginLeft,10),marginRight:parseInt(B.marginRight,10),marginTop:parseInt(B.marginTop,10),marginBottom:parseInt(B.marginBottom,10),paddingLeft:parseInt(B.paddingLeft,10),paddingRight:parseInt(B.paddingRight,10),paddingTop:parseInt(B.paddingTop,10),paddingBottom:parseInt(B.paddingBottom,10)}}function pe(b,B){var q;if(typeof Symbol>"u"||b[Symbol.iterator]==null){if(Array.isArray(b)||(q=function(De,je){if(!!De){if(typeof De=="string")return Z(De,je);var nt=Object.prototype.toString.call(De).slice(8,-1);if(nt==="Object"&&De.constructor&&(nt=De.constructor.name),nt==="Map"||nt==="Set")return Array.from(De);if(nt==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(nt))return Z(De,je)}}(b))||B&&b&&typeof b.length=="number"){q&&(b=q);var Y=0,_e=function(){};return{s:_e,n:function(){return Y>=b.length?{done:!0}:{done:!1,value:b[Y++]}},e:function(De){throw De},f:_e}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var se,ge=!0,G=!1;return{s:function(){q=b[Symbol.iterator]()},n:function(){var De=q.next();return ge=De.done,De},e:function(De){G=!0,se=De},f:function(){try{ge||q.return==null||q.return()}finally{if(G)throw se}}}}function Z(b,B){(B==null||B>b.length)&&(B=b.length);for(var q=0,Y=new Array(B);qge.left+ge.width&&(ne=ge.left+ge.width-nt-5),{style:{top:De+="px",left:ne+="px"}}}(B,q,{width:Y.width,height:Y.height});v()(this.tip.style,_e.style)}}]),b}(),qe=function(){function b(){Ae(this,b);var B=window.__REACT_DEVTOOLS_TARGET_WINDOW__||window;this.window=B;var q=window.__REACT_DEVTOOLS_TARGET_WINDOW__||window;this.tipBoundsWindow=q;var Y=B.document;this.container=Y.createElement("div"),this.container.style.zIndex="10000000",this.tip=new st(Y,this.container),this.rects=[],Y.body.appendChild(this.container)}return He(b,[{key:"remove",value:function(){this.tip.remove(),this.rects.forEach(function(B){B.remove()}),this.rects.length=0,this.container.parentNode&&this.container.parentNode.removeChild(this.container)}},{key:"inspect",value:function(B,q){for(var Y=this,_e=B.filter(function(ut){return ut.nodeType===Node.ELEMENT_NODE});this.rects.length>_e.length;)this.rects.pop().remove();if(_e.length!==0){for(;this.rects.length<_e.length;)this.rects.push(new ot(this.window.document,this.container));var se={top:Number.POSITIVE_INFINITY,right:Number.NEGATIVE_INFINITY,bottom:Number.NEGATIVE_INFINITY,left:Number.POSITIVE_INFINITY};if(_e.forEach(function(ut,ht){var wt=Me(ut,Y.window),Vt=fe(ut);se.top=Math.min(se.top,wt.top-Vt.marginTop),se.right=Math.max(se.right,wt.left+wt.width+Vt.marginRight),se.bottom=Math.max(se.bottom,wt.top+wt.height+Vt.marginBottom),se.left=Math.min(se.left,wt.left-Vt.marginLeft),Y.rects[ht].update(wt,Vt)}),!q){q=_e[0].nodeName.toLowerCase();var ge=_e[0],G=ge.ownerDocument.defaultView.__REACT_DEVTOOLS_GLOBAL_HOOK__;if(G!=null&&G.rendererInterfaces!=null){var De,je=null,nt=pe(G.rendererInterfaces.values());try{for(nt.s();!(De=nt.n()).done;){var ne=De.value,Ne=ne.getFiberIDForNative(ge,!0);if(Ne!==null){je=ne.getDisplayNameForFiberID(Ne,!0);break}}}catch(ut){nt.e(ut)}finally{nt.f()}je&&(q+=" (in "+je+")")}}this.tip.updateText(q,se.right-se.left,se.bottom-se.top);var Je=Me(this.tipBoundsWindow.document.documentElement,this.window);this.tip.updatePosition({top:se.top,left:se.left,height:se.bottom-se.top,width:se.right-se.left},{top:Je.top+this.tipBoundsWindow.scrollY,left:Je.left+this.tipBoundsWindow.scrollX,height:this.tipBoundsWindow.innerHeight,width:this.tipBoundsWindow.innerWidth})}}}]),b}();function Xe(b,B,q){v()(q.style,{borderTopWidth:b[B+"Top"]+"px",borderLeftWidth:b[B+"Left"]+"px",borderRightWidth:b[B+"Right"]+"px",borderBottomWidth:b[B+"Bottom"]+"px",borderStyle:"solid"})}var Ie={background:"rgba(120, 170, 210, 0.7)",padding:"rgba(77, 200, 0, 0.3)",margin:"rgba(255, 155, 0, 0.3)",border:"rgba(255, 200, 50, 0.3)"},kt=null,Kt=null;function Ye(){kt=null,Kt!==null&&(Kt.remove(),Kt=null)}function V(b,B,q){window.document!=null&&(kt!==null&&clearTimeout(kt),b!=null&&(Kt===null&&(Kt=new qe),Kt.inspect(b,B),q&&(kt=setTimeout(Ye,2e3))))}var oe=new Set;function ve(b,B){function q(ne){ne&&typeof ne.addEventListener=="function"&&(ne.addEventListener("click",se,!0),ne.addEventListener("mousedown",ge,!0),ne.addEventListener("mouseover",ge,!0),ne.addEventListener("mouseup",ge,!0),ne.addEventListener("pointerdown",G,!0),ne.addEventListener("pointerover",De,!0),ne.addEventListener("pointerup",je,!0))}function Y(){Ye(),_e(window),oe.forEach(function(ne){try{_e(ne.contentWindow)}catch{}}),oe=new Set}function _e(ne){ne&&typeof ne.removeEventListener=="function"&&(ne.removeEventListener("click",se,!0),ne.removeEventListener("mousedown",ge,!0),ne.removeEventListener("mouseover",ge,!0),ne.removeEventListener("mouseup",ge,!0),ne.removeEventListener("pointerdown",G,!0),ne.removeEventListener("pointerover",De,!0),ne.removeEventListener("pointerup",je,!0))}function se(ne){ne.preventDefault(),ne.stopPropagation(),Y(),b.send("stopInspectingNative",!0)}function ge(ne){ne.preventDefault(),ne.stopPropagation()}function G(ne){ne.preventDefault(),ne.stopPropagation(),nt(ne.target)}function De(ne){ne.preventDefault(),ne.stopPropagation();var Ne=ne.target;if(Ne.tagName==="IFRAME"){var Je=Ne;try{oe.has(Je)||(q(Je.contentWindow),oe.add(Je))}catch{}}V([Ne],null,!1),nt(Ne)}function je(ne){ne.preventDefault(),ne.stopPropagation()}b.addListener("clearNativeElementHighlight",function(){Ye()}),b.addListener("highlightNativeElement",function(ne){var Ne=ne.displayName,Je=ne.hideAfterTimeout,ut=ne.id,ht=ne.openNativeElementsPanel,wt=ne.rendererID,Vt=ne.scrollIntoView,bt=B.rendererInterfaces[wt];bt==null&&console.warn('Invalid renderer id "'.concat(wt,'" for element "').concat(ut,'"'));var Pt=null;if(bt!=null&&(Pt=bt.findNativeNodesForFiberID(ut)),Pt!=null&&Pt[0]!=null){var ln=Pt[0];Vt&&typeof ln.scrollIntoView=="function"&&ln.scrollIntoView({block:"nearest",inline:"nearest"}),V(Pt,Ne,Je),ht&&(window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0=ln,b.send("syncSelectionToNativeElementsPanel"))}else Ye()}),b.addListener("shutdown",Y),b.addListener("startInspectingNative",function(){q(window)}),b.addListener("stopInspectingNative",Y);var nt=O()(function(ne){var Ne=arguments.length>1&&arguments[1]!==void 0?arguments[1]:z,Je=void 0,ut=[],ht=void 0,wt=!1,Vt=function(Pt,ln){return Ne(Pt,ut[ln])},bt=function(){for(var Pt=arguments.length,ln=Array(Pt),jn=0;jn"u"?"undefined":ct(performance))==="object"&&typeof performance.now=="function"?function(){return performance.now()}:function(){return Date.now()},Xt=new Map,pn=null,Nn=!1,Wt=null;function Ot(b){(Nn=b)||(Xt.clear(),pn!==null&&(cancelAnimationFrame(pn),pn=null),Wt!==null&&(clearTimeout(Wt),Wt=null),Oe!==null&&(Oe.parentNode!=null&&Oe.parentNode.removeChild(Oe),Oe=null))}function Wn(b){Nn&&(b.forEach(function(B){var q=Xt.get(B),Y=Lt(),_e=q!=null?q.lastMeasuredAt:0,se=q!=null?q.rect:null;(se===null||_e+2505&&arguments[5]!==void 0?arguments[5]:0,G=Co(b);switch(G){case"html_element":return B.push(Y),{inspectable:!1,preview_short:Wr(b,!1),preview_long:Wr(b,!0),name:b.tagName,type:G};case"function":return B.push(Y),{inspectable:!1,preview_short:Wr(b,!1),preview_long:Wr(b,!0),name:typeof b.name!="function"&&b.name?b.name:"function",type:G};case"string":return b.length<=500?b:b.slice(0,500)+"...";case"bigint":case"symbol":return B.push(Y),{inspectable:!1,preview_short:Wr(b,!1),preview_long:Wr(b,!0),name:b.toString(),type:G};case"react_element":return B.push(Y),{inspectable:!1,preview_short:Wr(b,!1),preview_long:Wr(b,!0),name:U0(b)||"Unknown",type:G};case"array_buffer":case"data_view":return B.push(Y),{inspectable:!1,preview_short:Wr(b,!1),preview_long:Wr(b,!0),name:G==="data_view"?"DataView":"ArrayBuffer",size:b.byteLength,type:G};case"array":return se=_e(Y),ge>=2&&!se?B0(G,!0,b,B,Y):b.map(function(nt,ne){return Do(nt,B,q,Y.concat([ne]),_e,se?1:ge+1)});case"html_all_collection":case"typed_array":case"iterator":if(se=_e(Y),ge>=2&&!se)return B0(G,!0,b,B,Y);var De={unserializable:!0,type:G,readonly:!0,size:G==="typed_array"?b.length:void 0,preview_short:Wr(b,!1),preview_long:Wr(b,!0),name:b.constructor&&b.constructor.name!=="Object"?b.constructor.name:""};return zt(b[Symbol.iterator])&&Array.from(b).forEach(function(nt,ne){return De[ne]=Do(nt,B,q,Y.concat([ne]),_e,se?1:ge+1)}),q.push(Y),De;case"opaque_iterator":return B.push(Y),{inspectable:!1,preview_short:Wr(b,!1),preview_long:Wr(b,!0),name:b[Symbol.toStringTag],type:G};case"date":case"regexp":return B.push(Y),{inspectable:!1,preview_short:Wr(b,!1),preview_long:Wr(b,!0),name:b.toString(),type:G};case"object":if(se=_e(Y),ge>=2&&!se)return B0(G,!0,b,B,Y);var je={};return Ai(b).forEach(function(nt){var ne=nt.toString();je[ne]=Do(b[nt],B,q,Y.concat([ne]),_e,se?1:ge+1)}),je;case"infinity":case"nan":case"undefined":return B.push(Y),{type:G};default:return b}}function wl(b){return(wl=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(B){return typeof B}:function(B){return B&&typeof Symbol=="function"&&B.constructor===Symbol&&B!==Symbol.prototype?"symbol":typeof B})(b)}function Sl(b){return function(B){if(Array.isArray(B))return Tl(B)}(b)||function(B){if(typeof Symbol<"u"&&Symbol.iterator in Object(B))return Array.from(B)}(b)||function(B,q){if(!!B){if(typeof B=="string")return Tl(B,q);var Y=Object.prototype.toString.call(B).slice(8,-1);if(Y==="Object"&&B.constructor&&(Y=B.constructor.name),Y==="Map"||Y==="Set")return Array.from(B);if(Y==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(Y))return Tl(B,q)}}(b)||function(){throw new TypeError(`Invalid attempt to spread non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function Tl(b,B){(B==null||B>b.length)&&(B=b.length);for(var q=0,Y=new Array(B);qB.toString()?1:B.toString()>b.toString()?-1:0}function Ai(b){for(var B=[],q=b,Y=function(){var _e=[].concat(Sl(Object.keys(q)),Sl(Object.getOwnPropertySymbols(q))),se=Object.getOwnPropertyDescriptors(q);_e.forEach(function(ge){se[ge].enumerable&&B.push(ge)}),q=Object.getPrototypeOf(q)};q!=null;)Y();return B}function br(b){var B=arguments.length>1&&arguments[1]!==void 0?arguments[1]:"Anonymous",q=ua.get(b);if(q!=null)return q;var Y=B;return typeof b.displayName=="string"?Y=b.displayName:typeof b.name=="string"&&b.name!==""&&(Y=b.name),ua.set(b,Y),Y}var Xn=0;function Fu(){return++Xn}function wo(b){var B=Rt.get(b);if(B!==void 0)return B;for(var q=new Array(b.length),Y=0;Y1&&arguments[1]!==void 0?arguments[1]:50;return b.length>B?b.substr(0,B)+"\u2026":b}function Wr(b,B){if(b!=null&&hasOwnProperty.call(b,p0.type))return B?b[p0.preview_long]:b[p0.preview_short];switch(Co(b)){case"html_element":return"<".concat(xi(b.tagName.toLowerCase())," />");case"function":return xi("\u0192 ".concat(typeof b.name=="function"?"":b.name,"() {}"));case"string":return'"'.concat(b,'"');case"bigint":return xi(b.toString()+"n");case"regexp":case"symbol":return xi(b.toString());case"react_element":return"<".concat(xi(U0(b)||"Unknown")," />");case"array_buffer":return"ArrayBuffer(".concat(b.byteLength,")");case"data_view":return"DataView(".concat(b.buffer.byteLength,")");case"array":if(B){for(var q="",Y=0;Y0&&(q+=", "),!((q+=Wr(b[Y],!1)).length>50));Y++);return"[".concat(xi(q),"]")}var _e=hasOwnProperty.call(b,p0.size)?b[p0.size]:b.length;return"Array(".concat(_e,")");case"typed_array":var se="".concat(b.constructor.name,"(").concat(b.length,")");if(B){for(var ge="",G=0;G0&&(ge+=", "),!((ge+=b[G]).length>50));G++);return"".concat(se," [").concat(xi(ge),"]")}return se;case"iterator":var De=b.constructor.name;if(B){for(var je=Array.from(b),nt="",ne=0;ne0&&(nt+=", "),Array.isArray(Ne)){var Je=Wr(Ne[0],!0),ut=Wr(Ne[1],!1);nt+="".concat(Je," => ").concat(ut)}else nt+=Wr(Ne,!1);if(nt.length>50)break}return"".concat(De,"(").concat(b.size,") {").concat(xi(nt),"}")}return"".concat(De,"(").concat(b.size,")");case"opaque_iterator":return b[Symbol.toStringTag];case"date":return b.toString();case"object":if(B){for(var ht=Ai(b).sort(Kr),wt="",Vt=0;Vt0&&(wt+=", "),(wt+="".concat(bt.toString(),": ").concat(Wr(b[bt],!1))).length>50)break}return"{".concat(xi(wt),"}")}return"{\u2026}";case"boolean":case"number":case"infinity":case"nan":case"null":case"undefined":return b;default:try{return xi(""+b)}catch{return"unserializable"}}}var Cl=c(7);function Lu(b){return(Lu=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(B){return typeof B}:function(B){return B&&typeof Symbol=="function"&&B.constructor===Symbol&&B!==Symbol.prototype?"symbol":typeof B})(b)}function F0(b,B){var q=Object.keys(b);if(Object.getOwnPropertySymbols){var Y=Object.getOwnPropertySymbols(b);B&&(Y=Y.filter(function(_e){return Object.getOwnPropertyDescriptor(b,_e).enumerable})),q.push.apply(q,Y)}return q}function S0(b){for(var B=1;B2&&arguments[2]!==void 0?arguments[2]:[];if(b!==null){var Y=[],_e=[],se=Do(b,Y,_e,q,B);return{data:se,cleaned:Y,unserializable:_e}}return null}function j0(b){var B,q,Y=(B=b,q=new Set,JSON.stringify(B,function(ge,G){if(Lu(G)==="object"&&G!==null){if(q.has(G))return;q.add(G)}return typeof G=="bigint"?G.toString()+"n":G})),_e=Y===void 0?"undefined":Y,se=window.__REACT_DEVTOOLS_GLOBAL_HOOK__.clipboardCopyText;typeof se=="function"?se(_e).catch(function(ge){}):Object(Cl.copy)(_e)}function Ir(b,B){var q=arguments.length>2&&arguments[2]!==void 0?arguments[2]:0,Y=B[q],_e=Array.isArray(b)?b.slice():S0({},b);return q+1===B.length?Array.isArray(_e)?_e.splice(Y,1):delete _e[Y]:_e[Y]=Ir(b[Y],B,q+1),_e}function Ft(b,B,q){var Y=arguments.length>3&&arguments[3]!==void 0?arguments[3]:0,_e=B[Y],se=Array.isArray(b)?b.slice():S0({},b);if(Y+1===B.length){var ge=q[Y];se[ge]=se[_e],Array.isArray(se)?se.splice(_e,1):delete se[_e]}else se[_e]=Ft(b[_e],B,q,Y+1);return se}function hn(b,B,q){var Y=arguments.length>3&&arguments[3]!==void 0?arguments[3]:0;if(Y>=B.length)return q;var _e=B[Y],se=Array.isArray(b)?b.slice():S0({},b);return se[_e]=hn(b[_e],B,q,Y+1),se}var Br=c(8);function Tr(b,B){var q=Object.keys(b);if(Object.getOwnPropertySymbols){var Y=Object.getOwnPropertySymbols(b);B&&(Y=Y.filter(function(_e){return Object.getOwnPropertyDescriptor(b,_e).enumerable})),q.push.apply(q,Y)}return q}function xt(b){for(var B=1;B"u"||!(Symbol.iterator in Object(q)))){var _e=[],se=!0,ge=!1,G=void 0;try{for(var De,je=q[Symbol.iterator]();!(se=(De=je.next()).done)&&(_e.push(De.value),!Y||_e.length!==Y);se=!0);}catch(nt){ge=!0,G=nt}finally{try{se||je.return==null||je.return()}finally{if(ge)throw G}}return _e}}(b,B)||bu(b,B)||function(){throw new TypeError(`Invalid attempt to destructure non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function ti(b,B){var q;if(typeof Symbol>"u"||b[Symbol.iterator]==null){if(Array.isArray(b)||(q=bu(b))||B&&b&&typeof b.length=="number"){q&&(b=q);var Y=0,_e=function(){};return{s:_e,n:function(){return Y>=b.length?{done:!0}:{done:!1,value:b[Y++]}},e:function(De){throw De},f:_e}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var se,ge=!0,G=!1;return{s:function(){q=b[Symbol.iterator]()},n:function(){var De=q.next();return ge=De.done,De},e:function(De){G=!0,se=De},f:function(){try{ge||q.return==null||q.return()}finally{if(G)throw se}}}}function bu(b,B){if(b){if(typeof b=="string")return Ko(b,B);var q=Object.prototype.toString.call(b).slice(8,-1);return q==="Object"&&b.constructor&&(q=b.constructor.name),q==="Map"||q==="Set"?Array.from(b):q==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(q)?Ko(b,B):void 0}}function Ko(b,B){(B==null||B>b.length)&&(B=b.length);for(var q=0,Y=new Array(B);q"u"?"undefined":Dr(performance))==="object"&&typeof performance.now=="function"?function(){return performance.now()}:function(){return Date.now()};function xo(b){var B=null;function q(bt){var Pt=Dr(bt)==="object"&&bt!==null?bt.$$typeof:bt;return Dr(Pt)==="symbol"?Pt.toString():Pt}var Y=B=Object(Ct.gte)(b,"17.0.0-alpha")?{Block:22,ClassComponent:1,ContextConsumer:9,ContextProvider:10,CoroutineComponent:-1,CoroutineHandlerPhase:-1,DehydratedSuspenseComponent:18,ForwardRef:11,Fragment:7,FunctionComponent:0,HostComponent:5,HostPortal:4,HostRoot:3,HostText:6,IncompleteClassComponent:17,IndeterminateComponent:2,LazyComponent:16,MemoComponent:14,Mode:8,OffscreenComponent:23,Profiler:12,SimpleMemoComponent:15,SuspenseComponent:13,SuspenseListComponent:19,YieldComponent:-1}:Object(Ct.gte)(b,"16.6.0-beta.0")?{Block:22,ClassComponent:1,ContextConsumer:9,ContextProvider:10,CoroutineComponent:-1,CoroutineHandlerPhase:-1,DehydratedSuspenseComponent:18,ForwardRef:11,Fragment:7,FunctionComponent:0,HostComponent:5,HostPortal:4,HostRoot:3,HostText:6,IncompleteClassComponent:17,IndeterminateComponent:2,LazyComponent:16,MemoComponent:14,Mode:8,OffscreenComponent:-1,Profiler:12,SimpleMemoComponent:15,SuspenseComponent:13,SuspenseListComponent:19,YieldComponent:-1}:Object(Ct.gte)(b,"16.4.3-alpha")?{Block:-1,ClassComponent:2,ContextConsumer:11,ContextProvider:12,CoroutineComponent:-1,CoroutineHandlerPhase:-1,DehydratedSuspenseComponent:-1,ForwardRef:13,Fragment:9,FunctionComponent:0,HostComponent:7,HostPortal:6,HostRoot:5,HostText:8,IncompleteClassComponent:-1,IndeterminateComponent:4,LazyComponent:-1,MemoComponent:-1,Mode:10,OffscreenComponent:-1,Profiler:15,SimpleMemoComponent:-1,SuspenseComponent:16,SuspenseListComponent:-1,YieldComponent:-1}:{Block:-1,ClassComponent:2,ContextConsumer:12,ContextProvider:13,CoroutineComponent:7,CoroutineHandlerPhase:8,DehydratedSuspenseComponent:-1,ForwardRef:14,Fragment:10,FunctionComponent:1,HostComponent:5,HostPortal:4,HostRoot:3,HostText:6,IncompleteClassComponent:-1,IndeterminateComponent:0,LazyComponent:-1,MemoComponent:-1,Mode:11,OffscreenComponent:-1,Profiler:15,SimpleMemoComponent:-1,SuspenseComponent:16,SuspenseListComponent:-1,YieldComponent:9},_e=Y.ClassComponent,se=Y.IncompleteClassComponent,ge=Y.FunctionComponent,G=Y.IndeterminateComponent,De=Y.ForwardRef,je=Y.HostRoot,nt=Y.HostComponent,ne=Y.HostPortal,Ne=Y.HostText,Je=Y.Fragment,ut=Y.MemoComponent,ht=Y.SimpleMemoComponent,wt=Y.SuspenseComponent,Vt=Y.SuspenseListComponent;return{getDisplayNameForFiber:function(bt){var Pt=bt.type,ln=bt.tag,jn=Pt;Dr(Pt)==="object"&&Pt!==null&&(jn=function Jn(nn){switch(q(nn)){case 60115:case"Symbol(react.memo)":return Jn(nn.type);case 60112:case"Symbol(react.forward_ref)":return nn.render;default:return nn}}(Pt));var xn=null;switch(ln){case _e:case se:return br(jn);case ge:case G:return br(jn);case De:return Pt&&Pt.displayName||br(jn,"Anonymous");case je:return null;case nt:return Pt;case ne:case Ne:case Je:return null;case ut:case ht:return br(jn,"Anonymous");case wt:return"Suspense";case Vt:return"SuspenseList";default:switch(q(Pt)){case 60111:case"Symbol(react.concurrent_mode)":case"Symbol(react.async_mode)":return null;case 60109:case"Symbol(react.provider)":return xn=bt.type._context||bt.type.context,"".concat(xn.displayName||"Context",".Provider");case 60110:case"Symbol(react.context)":return xn=bt.type._context||bt.type,"".concat(xn.displayName||"Context",".Consumer");case 60108:case"Symbol(react.strict_mode)":return null;case 60114:case"Symbol(react.profiler)":return"Profiler(".concat(bt.memoizedProps.id,")");case 60119:case"Symbol(react.scope)":return"Scope";default:return null}}},getTypeSymbol:q,ReactPriorityLevels:{ImmediatePriority:99,UserBlockingPriority:98,NormalPriority:97,LowPriority:96,IdlePriority:95,NoPriority:90},ReactTypeOfWork:B,ReactTypeOfSideEffect:{NoFlags:0,PerformedWork:1,Placement:2}}}function xl(b,B,q,Y){var _e=xo(q.version),se=_e.getDisplayNameForFiber,ge=_e.getTypeSymbol,G=_e.ReactPriorityLevels,De=_e.ReactTypeOfWork,je=_e.ReactTypeOfSideEffect,nt=je.NoFlags,ne=je.PerformedWork,Ne=je.Placement,Je=De.FunctionComponent,ut=De.ClassComponent,ht=De.ContextConsumer,wt=De.DehydratedSuspenseComponent,Vt=De.Fragment,bt=De.ForwardRef,Pt=De.HostRoot,ln=De.HostPortal,jn=De.HostComponent,xn=De.HostText,Jn=De.IncompleteClassComponent,nn=De.IndeterminateComponent,$n=De.MemoComponent,y0=De.OffscreenComponent,nr=De.SimpleMemoComponent,Ge=De.SuspenseComponent,at=De.SuspenseListComponent,ze=G.ImmediatePriority,yt=G.UserBlockingPriority,It=G.NormalPriority,Gt=G.LowPriority,An=G.IdlePriority,Vn=G.NoPriority,gi=q.overrideHookState,i0=q.overrideHookStateDeletePath,W0=q.overrideHookStateRenamePath,V0=q.overrideProps,Gi=q.overridePropsDeletePath,Yi=q.overridePropsRenamePath,gu=q.setSuspenseHandler,Ml=q.scheduleUpdate,Cf=typeof gu=="function"&&typeof Ml=="function";oo(q);var ju=window.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__!==!1,As=window.__REACT_DEVTOOLS_BREAK_ON_CONSOLE_ERRORS__===!0;(ju||As)&&la({appendComponentStack:ju,breakOnConsoleErrors:As});var Oo=new Set,ol=new Set,Nl=new Set,Mo=!1,Fl=new Set;function ul(te){Nl.clear(),Oo.clear(),ol.clear(),te.forEach(function(J){if(J.isEnabled)switch(J.type){case 2:J.isValid&&J.value!==""&&Oo.add(new RegExp(J.value,"i"));break;case 1:Nl.add(J.value);break;case 3:J.isValid&&J.value!==""&&ol.add(new RegExp(J.value,"i"));break;case 4:Oo.add(new RegExp("\\("));break;default:console.warn('Invalid component filter type "'.concat(J.type,'"'))}})}function o0(te){var J=te._debugSource,Te=te.tag,Ee=te.type;switch(Te){case wt:return!0;case ln:case xn:case Vt:case y0:return!0;case Pt:return!1;default:switch(ge(Ee)){case 60111:case"Symbol(react.concurrent_mode)":case"Symbol(react.async_mode)":case 60108:case"Symbol(react.strict_mode)":return!0}}var Qe=Ki(te);if(Nl.has(Qe))return!0;if(Oo.size>0){var rt=se(te);if(rt!=null){var Mt,vn=ti(Oo);try{for(vn.s();!(Mt=vn.n()).done;)if(Mt.value.test(rt))return!0}catch(kn){vn.e(kn)}finally{vn.f()}}}if(J!=null&&ol.size>0){var Jt,Qt=J.fileName,Zt=ti(ol);try{for(Zt.s();!(Jt=Zt.n()).done;)if(Jt.value.test(Qt))return!0}catch(kn){Zt.e(kn)}finally{Zt.f()}}return!1}function Ki(te){var J=te.type;switch(te.tag){case ut:case Jn:return 1;case Je:case nn:return 5;case bt:return 6;case Pt:return 11;case jn:return 7;case ln:case xn:case Vt:return 9;case $n:case nr:return 8;case Ge:return 12;case at:return 13;default:switch(ge(J)){case 60111:case"Symbol(react.concurrent_mode)":case"Symbol(react.async_mode)":return 9;case 60109:case"Symbol(react.provider)":return 2;case 60110:case"Symbol(react.context)":return 2;case 60108:case"Symbol(react.strict_mode)":return 9;case 60114:case"Symbol(react.profiler)":return 10;default:return 9}}}function kr(te){if(No.has(te))return te;var J=te.alternate;return J!=null&&No.has(J)?J:(No.add(te),te)}window.__REACT_DEVTOOLS_COMPONENT_FILTERS__!=null?ul(window.__REACT_DEVTOOLS_COMPONENT_FILTERS__):ul([{type:1,value:7,isEnabled:!0}]);var zu=new Map,Xo=new Map,No=new Set,fa=new Map,qu=new Map,Xi=-1;function pi(te){if(!zu.has(te)){var J=Fu();zu.set(te,J),Xo.set(J,te)}return zu.get(te)}function Fo(te){switch(Ki(te)){case 1:if(K0!==null){var J=pi(kr(te)),Te=Or(te);Te!==null&&K0.set(J,Te)}}}var Qr={};function Or(te){switch(Ki(te)){case 1:var J=te.stateNode,Te=Qr,Ee=Qr;return J!=null&&(J.constructor&&J.constructor.contextType!=null?Ee=J.context:(Te=J.context)&&Object.keys(Te).length===0&&(Te=Qr)),[Te,Ee];default:return null}}function ks(te){switch(Ki(te)){case 1:if(K0!==null){var J=pi(kr(te)),Te=K0.has(J)?K0.get(J):null,Ee=Or(te);if(Te==null||Ee==null)return null;var Qe=z0(Te,2),rt=Qe[0],Mt=Qe[1],vn=z0(Ee,2),Jt=vn[0],Qt=vn[1];if(Jt!==Qr)return G0(rt,Jt);if(Qt!==Qr)return Mt!==Qt}}return null}function Os(te,J){if(te==null||J==null)return!1;if(J.hasOwnProperty("baseState")&&J.hasOwnProperty("memoizedState")&&J.hasOwnProperty("next")&&J.hasOwnProperty("queue"))for(;J!==null;){if(J.memoizedState!==te.memoizedState)return!0;J=J.next,te=te.next}return!1}function G0(te,J){if(te==null||J==null||J.hasOwnProperty("baseState")&&J.hasOwnProperty("memoizedState")&&J.hasOwnProperty("next")&&J.hasOwnProperty("queue"))return null;var Te,Ee=[],Qe=ti(new Set([].concat(di(Object.keys(te)),di(Object.keys(J)))));try{for(Qe.s();!(Te=Qe.n()).done;){var rt=Te.value;te[rt]!==J[rt]&&Ee.push(rt)}}catch(Mt){Qe.e(Mt)}finally{Qe.f()}return Ee}function Ll(te,J){switch(J.tag){case ut:case Je:case ht:case $n:case nr:return(ro(J)&ne)===ne;default:return te.memoizedProps!==J.memoizedProps||te.memoizedState!==J.memoizedState||te.ref!==J.ref}}var Qo=[],Jo=[],Zo=[],Y0=[],ur=new Map,R0=0,lo=null;function zr(te){Qo.push(te)}function Ui(te){if(Qo.length!==0||Jo.length!==0||Zo.length!==0||lo!==null||k0){var J=Jo.length+Zo.length+(lo===null?0:1),Te=new Array(3+R0+(J>0?2+J:0)+Qo.length),Ee=0;if(Te[Ee++]=B,Te[Ee++]=Xi,Te[Ee++]=R0,ur.forEach(function(vn,Jt){Te[Ee++]=Jt.length;for(var Qt=wo(Jt),Zt=0;Zt0){Te[Ee++]=2,Te[Ee++]=J;for(var Qe=Jo.length-1;Qe>=0;Qe--)Te[Ee++]=Jo[Qe];for(var rt=0;rt0?te.forEach(function(J){b.emit("operations",J)}):(er!==null&&(Di=!0),b.getFiberRoots(B).forEach(function(J){l0(Xi=pi(kr(J.current)),J.current),k0&&J.memoizedInteractions!=null&&(ll={changeDescriptions:pa?new Map:null,durations:[],commitTime:Pu()-bo,interactions:Array.from(J.memoizedInteractions).map(function(Te){return xt(xt({},Te),{},{timestamp:Te.timestamp-bo})}),maxActualDuration:0,priorityLevel:null}),wr(J.current,null,!1,!1),Ui(),Xi=-1}))},getBestMatchForTrackedPath:function(){if(er===null||X0===null)return null;for(var te=X0;te!==null&&o0(te);)te=te.return;return te===null?null:{id:pi(kr(te)),isFullMatch:Ei===er.length-1}},getDisplayNameForFiberID:function(te){var J=Xo.get(te);return J!=null?se(J):null},getFiberIDForNative:function(te){var J=arguments.length>1&&arguments[1]!==void 0&&arguments[1],Te=q.findFiberByHostInstance(te);if(Te!=null){if(J)for(;Te!==null&&o0(Te);)Te=Te.return;return pi(kr(Te))}return null},getInstanceAndStyle:function(te){var J=null,Te=null,Ee=A0(te);return Ee!==null&&(J=Ee.stateNode,Ee.memoizedProps!==null&&(Te=Ee.memoizedProps.style)),{instance:J,style:Te}},getOwnersList:function(te){var J=A0(te);if(J==null)return null;var Te=J._debugOwner,Ee=[{displayName:se(J)||"Anonymous",id:te,type:Ki(J)}];if(Te)for(var Qe=Te;Qe!==null;)Ee.unshift({displayName:se(Qe)||"Anonymous",id:pi(kr(Qe)),type:Ki(Qe)}),Qe=Qe._debugOwner||null;return Ee},getPathForElement:function(te){var J=Xo.get(te);if(J==null)return null;for(var Te=[];J!==null;)Te.push(M0(J)),J=J.return;return Te.reverse(),Te},getProfilingData:function(){var te=[];if(al===null)throw Error("getProfilingData() called before any profiling data was recorded");return al.forEach(function(J,Te){var Ee=[],Qe=[],rt=new Map,Mt=new Map,vn=Hu!==null&&Hu.get(Te)||"Unknown";co!=null&&co.forEach(function(Jt,Qt){Lo!=null&&Lo.get(Qt)===Te&&Qe.push([Qt,Jt])}),J.forEach(function(Jt,Qt){var Zt=Jt.changeDescriptions,kn=Jt.durations,Et=Jt.interactions,oi=Jt.maxActualDuration,lr=Jt.priorityLevel,zn=Jt.commitTime,Mr=[];Et.forEach(function(xr){rt.has(xr.id)||rt.set(xr.id,xr),Mr.push(xr.id);var hi=Mt.get(xr.id);hi!=null?hi.push(Qt):Mt.set(xr.id,[Qt])});for(var qr=[],Cr=[],ui=0;ui1?fr.set(Zt,kn-1):fr.delete(Zt),O0.delete(Jt)}(Xi),_i(Te,!1))}else l0(Xi,Te),wr(Te,null,!1,!1);if(k0&&Qe){var vn=al.get(Xi);vn!=null?vn.push(ll):al.set(Xi,[ll])}Ui(),Mo&&b.emit("traceUpdates",Fl),Xi=-1},handleCommitFiberUnmount:function(te){_i(te,!1)},inspectElement:function(te,J){if(Ji(te)){if(J!=null){fo(J);var Te=null;return J[0]==="hooks"&&(Te="hooks"),{id:te,type:"hydrated-path",path:J,value:Pr(h0(ri,J),ii(null,Te),J)}}return{id:te,type:"no-change"}}if(bl=!1,ri!==null&&ri.id===te||(so={}),(ri=da(te))===null)return{id:te,type:"not-found"};J!=null&&fo(J),function(Qe){var rt=Qe.hooks,Mt=Qe.id,vn=Qe.props,Jt=Xo.get(Mt);if(Jt!=null){var Qt=Jt.elementType,Zt=Jt.stateNode,kn=Jt.tag,Et=Jt.type;switch(kn){case ut:case Jn:case nn:Y.$r=Zt;break;case Je:Y.$r={hooks:rt,props:vn,type:Et};break;case bt:Y.$r={props:vn,type:Et.render};break;case $n:case nr:Y.$r={props:vn,type:Qt!=null&&Qt.type!=null?Qt.type:Et};break;default:Y.$r=null}}else console.warn('Could not find Fiber with id "'.concat(Mt,'"'))}(ri);var Ee=xt({},ri);return Ee.context=Pr(Ee.context,ii("context",null)),Ee.hooks=Pr(Ee.hooks,ii("hooks","hooks")),Ee.props=Pr(Ee.props,ii("props",null)),Ee.state=Pr(Ee.state,ii("state",null)),{id:te,type:"full-data",value:Ee}},logElementToConsole:function(te){var J=Ji(te)?ri:da(te);if(J!==null){var Te=typeof console.groupCollapsed=="function";Te&&console.groupCollapsed("[Click to expand] %c<".concat(J.displayName||"Component"," />"),"color: var(--dom-tag-name-color); font-weight: normal;"),J.props!==null&&console.log("Props:",J.props),J.state!==null&&console.log("State:",J.state),J.hooks!==null&&console.log("Hooks:",J.hooks);var Ee=_u(te);Ee!==null&&console.log("Nodes:",Ee),J.source!==null&&console.log("Location:",J.source),(window.chrome||/firefox/i.test(navigator.userAgent))&&console.log("Right-click any value to save it as a global variable for further inspection."),Te&&console.groupEnd()}else console.warn('Could not find Fiber with id "'.concat(te,'"'))},prepareViewAttributeSource:function(te,J){Ji(te)&&(window.$attribute=h0(ri,J))},prepareViewElementSource:function(te){var J=Xo.get(te);if(J!=null){var Te=J.elementType,Ee=J.tag,Qe=J.type;switch(Ee){case ut:case Jn:case nn:case Je:Y.$type=Qe;break;case bt:Y.$type=Qe.render;break;case $n:case nr:Y.$type=Te!=null&&Te.type!=null?Te.type:Qe;break;default:Y.$type=null}}else console.warn('Could not find Fiber with id "'.concat(te,'"'))},overrideSuspense:function(te,J){if(typeof gu!="function"||typeof Ml!="function")throw new Error("Expected overrideSuspense() to not get called for earlier React versions.");J?(L0.add(te),L0.size===1&&gu(Qa)):(L0.delete(te),L0.size===0&&gu(Ms));var Te=Xo.get(te);Te!=null&&Ml(Te)},overrideValueAtPath:function(te,J,Te,Ee,Qe){var rt=A0(J);if(rt!==null){var Mt=rt.stateNode;switch(te){case"context":switch(Ee=Ee.slice(1),rt.tag){case ut:Ee.length===0?Mt.context=Qe:To(Mt.context,Ee,Qe),Mt.forceUpdate()}break;case"hooks":typeof gi=="function"&&gi(rt,Te,Ee,Qe);break;case"props":switch(rt.tag){case ut:rt.pendingProps=hn(Mt.props,Ee,Qe),Mt.forceUpdate();break;default:typeof V0=="function"&&V0(rt,Ee,Qe)}break;case"state":switch(rt.tag){case ut:To(Mt.state,Ee,Qe),Mt.forceUpdate()}}}},renamePath:function(te,J,Te,Ee,Qe){var rt=A0(J);if(rt!==null){var Mt=rt.stateNode;switch(te){case"context":switch(Ee=Ee.slice(1),Qe=Qe.slice(1),rt.tag){case ut:Ee.length===0||hr(Mt.context,Ee,Qe),Mt.forceUpdate()}break;case"hooks":typeof W0=="function"&&W0(rt,Te,Ee,Qe);break;case"props":Mt===null?typeof Yi=="function"&&Yi(rt,Ee,Qe):(rt.pendingProps=Ft(Mt.props,Ee,Qe),Mt.forceUpdate());break;case"state":hr(Mt.state,Ee,Qe),Mt.forceUpdate()}}},renderer:q,setTraceUpdatesEnabled:function(te){Mo=te},setTrackedPath:Vr,startProfiling:ha,stopProfiling:function(){k0=!1,pa=!1},storeAsGlobal:function(te,J,Te){if(Ji(te)){var Ee=h0(ri,J),Qe="$reactTemp".concat(Te);window[Qe]=Ee,console.log(Qe),console.log(Ee)}},updateComponentFilters:function(te){if(k0)throw Error("Cannot modify filter preferences while profiling");b.getFiberRoots(B).forEach(function(J){Xi=pi(kr(J.current)),Qi(J.current),_i(J.current,!1),Xi=-1}),ul(te),fr.clear(),b.getFiberRoots(B).forEach(function(J){l0(Xi=pi(kr(J.current)),J.current),wr(J.current,null,!1,!1),Ui(J),Xi=-1})}}}var Tn;function tl(b){return(tl=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(B){return typeof B}:function(B){return B&&typeof Symbol=="function"&&B.constructor===Symbol&&B!==Symbol.prototype?"symbol":typeof B})(b)}function io(b,B,q){if(Tn===void 0)try{throw Error()}catch(_e){var Y=_e.stack.trim().match(/\n( *(at )?)/);Tn=Y&&Y[1]||""}return` +`+Tn+b}var Ro=!1;function mu(b,B,q){if(!b||Ro)return"";var Y,_e=Error.prepareStackTrace;Error.prepareStackTrace=void 0,Ro=!0;var se=q.current;q.current=null;try{if(B){var ge=function(){throw Error()};if(Object.defineProperty(ge.prototype,"props",{set:function(){throw Error()}}),(typeof Reflect>"u"?"undefined":tl(Reflect))==="object"&&Reflect.construct){try{Reflect.construct(ge,[])}catch(Ne){Y=Ne}Reflect.construct(b,[],ge)}else{try{ge.call()}catch(Ne){Y=Ne}b.call(ge.prototype)}}else{try{throw Error()}catch(Ne){Y=Ne}b()}}catch(Ne){if(Ne&&Y&&typeof Ne.stack=="string"){for(var G=Ne.stack.split(` +`),De=Y.stack.split(` +`),je=G.length-1,nt=De.length-1;je>=1&&nt>=0&&G[je]!==De[nt];)nt--;for(;je>=1&&nt>=0;je--,nt--)if(G[je]!==De[nt]){if(je!==1||nt!==1)do if(je--,--nt<0||G[je]!==De[nt])return` +`+G[je].replace(" at new "," at ");while(je>=1&&nt>=0);break}}}finally{Ro=!1,Error.prepareStackTrace=_e,q.current=se}var ne=b?b.displayName||b.name:"";return ne?io(ne):""}function Ao(b,B,q,Y){return mu(b,!1,Y)}function it(b,B,q){var Y=b.HostComponent,_e=b.LazyComponent,se=b.SuspenseComponent,ge=b.SuspenseListComponent,G=b.FunctionComponent,De=b.IndeterminateComponent,je=b.SimpleMemoComponent,nt=b.ForwardRef,ne=b.Block,Ne=b.ClassComponent;switch(B.tag){case Y:return io(B.type);case _e:return io("Lazy");case se:return io("Suspense");case ge:return io("SuspenseList");case G:case De:case je:return Ao(B.type,0,0,q);case nt:return Ao(B.type.render,0,0,q);case ne:return Ao(B.type._render,0,0,q);case Ne:return function(Je,ut,ht,wt){return mu(Je,!0,wt)}(B.type,0,0,q);default:return""}}function Dt(b,B,q){try{var Y="",_e=B;do Y+=it(b,_e,q),_e=_e.return;while(_e);return Y}catch(se){return` +Error generating stack: `+se.message+` +`+se.stack}}function mn(b,B){var q;if(typeof Symbol>"u"||b[Symbol.iterator]==null){if(Array.isArray(b)||(q=function(De,je){if(!!De){if(typeof De=="string")return vr(De,je);var nt=Object.prototype.toString.call(De).slice(8,-1);if(nt==="Object"&&De.constructor&&(nt=De.constructor.name),nt==="Map"||nt==="Set")return Array.from(De);if(nt==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(nt))return vr(De,je)}}(b))||B&&b&&typeof b.length=="number"){q&&(b=q);var Y=0,_e=function(){};return{s:_e,n:function(){return Y>=b.length?{done:!0}:{done:!1,value:b[Y++]}},e:function(De){throw De},f:_e}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var se,ge=!0,G=!1;return{s:function(){q=b[Symbol.iterator]()},n:function(){var De=q.next();return ge=De.done,De},e:function(De){G=!0,se=De},f:function(){try{ge||q.return==null||q.return()}finally{if(G)throw se}}}}function vr(b,B){(B==null||B>b.length)&&(B=b.length);for(var q=0,Y=new Array(B);q0?je[je.length-1]:null,Ne=ne!==null&&(mr.test(ne)||bi.test(ne));if(!Ne){var Je,ut=mn(v0.values());try{for(ut.s();!(Je=ut.n()).done;){var ht=Je.value,wt=ht.currentDispatcherRef,Vt=ht.getCurrentFiber,bt=ht.workTagMap,Pt=Vt();if(Pt!=null){var ln=Dt(bt,Pt,wt);ln!==""&&je.push(ln);break}}}catch(jn){ut.e(jn)}finally{ut.f()}}}catch{}se.apply(void 0,je)};ge.__REACT_DEVTOOLS_ORIGINAL_METHOD__=se,Xr[_e]=ge}catch{}})}}function e0(b){return(e0=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(B){return typeof B}:function(B){return B&&typeof Symbol=="function"&&B.constructor===Symbol&&B!==Symbol.prototype?"symbol":typeof B})(b)}function nl(b,B){for(var q=0;q"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch{return!1}}();return function(){var q,Y=we(b);if(B){var _e=we(this).constructor;q=Reflect.construct(Y,arguments,_e)}else q=Y.apply(this,arguments);return he(this,q)}}function he(b,B){return!B||e0(B)!=="object"&&typeof B!="function"?Se(b):B}function Se(b){if(b===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return b}function we(b){return(we=Object.setPrototypeOf?Object.getPrototypeOf:function(B){return B.__proto__||Object.getPrototypeOf(B)})(b)}function tt(b,B,q){return B in b?Object.defineProperty(b,B,{value:q,enumerable:!0,configurable:!0,writable:!0}):b[B]=q,b}var Cn=function(b){(function(ge,G){if(typeof G!="function"&&G!==null)throw new TypeError("Super expression must either be null or a function");ge.prototype=Object.create(G&&G.prototype,{constructor:{value:ge,writable:!0,configurable:!0}}),G&&q0(ge,G)})(se,b);var B,q,Y,_e=W(se);function se(ge){var G;(function(ne,Ne){if(!(ne instanceof Ne))throw new TypeError("Cannot call a class as a function")})(this,se),tt(Se(G=_e.call(this)),"_isProfiling",!1),tt(Se(G),"_recordChangeDescriptions",!1),tt(Se(G),"_rendererInterfaces",{}),tt(Se(G),"_persistedSelection",null),tt(Se(G),"_persistedSelectionMatch",null),tt(Se(G),"_traceUpdatesEnabled",!1),tt(Se(G),"copyElementPath",function(ne){var Ne=ne.id,Je=ne.path,ut=ne.rendererID,ht=G._rendererInterfaces[ut];ht==null?console.warn('Invalid renderer id "'.concat(ut,'" for element "').concat(Ne,'"')):ht.copyElementPath(Ne,Je)}),tt(Se(G),"deletePath",function(ne){var Ne=ne.hookID,Je=ne.id,ut=ne.path,ht=ne.rendererID,wt=ne.type,Vt=G._rendererInterfaces[ht];Vt==null?console.warn('Invalid renderer id "'.concat(ht,'" for element "').concat(Je,'"')):Vt.deletePath(wt,Je,Ne,ut)}),tt(Se(G),"getProfilingData",function(ne){var Ne=ne.rendererID,Je=G._rendererInterfaces[Ne];Je==null&&console.warn('Invalid renderer id "'.concat(Ne,'"')),G._bridge.send("profilingData",Je.getProfilingData())}),tt(Se(G),"getProfilingStatus",function(){G._bridge.send("profilingStatus",G._isProfiling)}),tt(Se(G),"getOwnersList",function(ne){var Ne=ne.id,Je=ne.rendererID,ut=G._rendererInterfaces[Je];if(ut==null)console.warn('Invalid renderer id "'.concat(Je,'" for element "').concat(Ne,'"'));else{var ht=ut.getOwnersList(Ne);G._bridge.send("ownersList",{id:Ne,owners:ht})}}),tt(Se(G),"inspectElement",function(ne){var Ne=ne.id,Je=ne.path,ut=ne.rendererID,ht=G._rendererInterfaces[ut];ht==null?console.warn('Invalid renderer id "'.concat(ut,'" for element "').concat(Ne,'"')):(G._bridge.send("inspectedElement",ht.inspectElement(Ne,Je)),G._persistedSelectionMatch!==null&&G._persistedSelectionMatch.id===Ne||(G._persistedSelection=null,G._persistedSelectionMatch=null,ht.setTrackedPath(null),G._throttledPersistSelection(ut,Ne)))}),tt(Se(G),"logElementToConsole",function(ne){var Ne=ne.id,Je=ne.rendererID,ut=G._rendererInterfaces[Je];ut==null?console.warn('Invalid renderer id "'.concat(Je,'" for element "').concat(Ne,'"')):ut.logElementToConsole(Ne)}),tt(Se(G),"overrideSuspense",function(ne){var Ne=ne.id,Je=ne.rendererID,ut=ne.forceFallback,ht=G._rendererInterfaces[Je];ht==null?console.warn('Invalid renderer id "'.concat(Je,'" for element "').concat(Ne,'"')):ht.overrideSuspense(Ne,ut)}),tt(Se(G),"overrideValueAtPath",function(ne){var Ne=ne.hookID,Je=ne.id,ut=ne.path,ht=ne.rendererID,wt=ne.type,Vt=ne.value,bt=G._rendererInterfaces[ht];bt==null?console.warn('Invalid renderer id "'.concat(ht,'" for element "').concat(Je,'"')):bt.overrideValueAtPath(wt,Je,Ne,ut,Vt)}),tt(Se(G),"overrideContext",function(ne){var Ne=ne.id,Je=ne.path,ut=ne.rendererID,ht=ne.wasForwarded,wt=ne.value;ht||G.overrideValueAtPath({id:Ne,path:Je,rendererID:ut,type:"context",value:wt})}),tt(Se(G),"overrideHookState",function(ne){var Ne=ne.id,Je=(ne.hookID,ne.path),ut=ne.rendererID,ht=ne.wasForwarded,wt=ne.value;ht||G.overrideValueAtPath({id:Ne,path:Je,rendererID:ut,type:"hooks",value:wt})}),tt(Se(G),"overrideProps",function(ne){var Ne=ne.id,Je=ne.path,ut=ne.rendererID,ht=ne.wasForwarded,wt=ne.value;ht||G.overrideValueAtPath({id:Ne,path:Je,rendererID:ut,type:"props",value:wt})}),tt(Se(G),"overrideState",function(ne){var Ne=ne.id,Je=ne.path,ut=ne.rendererID,ht=ne.wasForwarded,wt=ne.value;ht||G.overrideValueAtPath({id:Ne,path:Je,rendererID:ut,type:"state",value:wt})}),tt(Se(G),"reloadAndProfile",function(ne){U("React::DevTools::reloadAndProfile","true"),U("React::DevTools::recordChangeDescriptions",ne?"true":"false"),G._bridge.send("reloadAppForProfiling")}),tt(Se(G),"renamePath",function(ne){var Ne=ne.hookID,Je=ne.id,ut=ne.newPath,ht=ne.oldPath,wt=ne.rendererID,Vt=ne.type,bt=G._rendererInterfaces[wt];bt==null?console.warn('Invalid renderer id "'.concat(wt,'" for element "').concat(Je,'"')):bt.renamePath(Vt,Je,Ne,ht,ut)}),tt(Se(G),"setTraceUpdatesEnabled",function(ne){for(var Ne in G._traceUpdatesEnabled=ne,Ot(ne),G._rendererInterfaces)G._rendererInterfaces[Ne].setTraceUpdatesEnabled(ne)}),tt(Se(G),"syncSelectionFromNativeElementsPanel",function(){var ne=window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0;ne!=null&&G.selectNode(ne)}),tt(Se(G),"shutdown",function(){G.emit("shutdown")}),tt(Se(G),"startProfiling",function(ne){for(var Ne in G._recordChangeDescriptions=ne,G._isProfiling=!0,G._rendererInterfaces)G._rendererInterfaces[Ne].startProfiling(ne);G._bridge.send("profilingStatus",G._isProfiling)}),tt(Se(G),"stopProfiling",function(){for(var ne in G._isProfiling=!1,G._recordChangeDescriptions=!1,G._rendererInterfaces)G._rendererInterfaces[ne].stopProfiling();G._bridge.send("profilingStatus",G._isProfiling)}),tt(Se(G),"storeAsGlobal",function(ne){var Ne=ne.count,Je=ne.id,ut=ne.path,ht=ne.rendererID,wt=G._rendererInterfaces[ht];wt==null?console.warn('Invalid renderer id "'.concat(ht,'" for element "').concat(Je,'"')):wt.storeAsGlobal(Je,ut,Ne)}),tt(Se(G),"updateConsolePatchSettings",function(ne){var Ne=ne.appendComponentStack,Je=ne.breakOnConsoleErrors;Ne||Je?la({appendComponentStack:Ne,breakOnConsoleErrors:Je}):lt!==null&&(lt(),lt=null)}),tt(Se(G),"updateComponentFilters",function(ne){for(var Ne in G._rendererInterfaces)G._rendererInterfaces[Ne].updateComponentFilters(ne)}),tt(Se(G),"viewAttributeSource",function(ne){var Ne=ne.id,Je=ne.path,ut=ne.rendererID,ht=G._rendererInterfaces[ut];ht==null?console.warn('Invalid renderer id "'.concat(ut,'" for element "').concat(Ne,'"')):ht.prepareViewAttributeSource(Ne,Je)}),tt(Se(G),"viewElementSource",function(ne){var Ne=ne.id,Je=ne.rendererID,ut=G._rendererInterfaces[Je];ut==null?console.warn('Invalid renderer id "'.concat(Je,'" for element "').concat(Ne,'"')):ut.prepareViewElementSource(Ne)}),tt(Se(G),"onTraceUpdates",function(ne){G.emit("traceUpdates",ne)}),tt(Se(G),"onHookOperations",function(ne){if(G._bridge.send("operations",ne),G._persistedSelection!==null){var Ne=ne[0];if(G._persistedSelection.rendererID===Ne){var Je=G._rendererInterfaces[Ne];if(Je==null)console.warn('Invalid renderer id "'.concat(Ne,'"'));else{var ut=G._persistedSelectionMatch,ht=Je.getBestMatchForTrackedPath();G._persistedSelectionMatch=ht;var wt=ut!==null?ut.id:null,Vt=ht!==null?ht.id:null;wt!==Vt&&Vt!==null&&G._bridge.send("selectFiber",Vt),ht!==null&&ht.isFullMatch&&(G._persistedSelection=null,G._persistedSelectionMatch=null,Je.setTrackedPath(null))}}}}),tt(Se(G),"_throttledPersistSelection",O()(function(ne,Ne){var Je=G._rendererInterfaces[ne],ut=Je!=null?Je.getPathForElement(Ne):null;ut!==null?U("React::DevTools::lastSelection",JSON.stringify({rendererID:ne,path:ut})):P("React::DevTools::lastSelection")},1e3)),T("React::DevTools::reloadAndProfile")==="true"&&(G._recordChangeDescriptions=T("React::DevTools::recordChangeDescriptions")==="true",G._isProfiling=!0,P("React::DevTools::recordChangeDescriptions"),P("React::DevTools::reloadAndProfile"));var De=T("React::DevTools::lastSelection");De!=null&&(G._persistedSelection=JSON.parse(De)),G._bridge=ge,ge.addListener("copyElementPath",G.copyElementPath),ge.addListener("deletePath",G.deletePath),ge.addListener("getProfilingData",G.getProfilingData),ge.addListener("getProfilingStatus",G.getProfilingStatus),ge.addListener("getOwnersList",G.getOwnersList),ge.addListener("inspectElement",G.inspectElement),ge.addListener("logElementToConsole",G.logElementToConsole),ge.addListener("overrideSuspense",G.overrideSuspense),ge.addListener("overrideValueAtPath",G.overrideValueAtPath),ge.addListener("reloadAndProfile",G.reloadAndProfile),ge.addListener("renamePath",G.renamePath),ge.addListener("setTraceUpdatesEnabled",G.setTraceUpdatesEnabled),ge.addListener("startProfiling",G.startProfiling),ge.addListener("stopProfiling",G.stopProfiling),ge.addListener("storeAsGlobal",G.storeAsGlobal),ge.addListener("syncSelectionFromNativeElementsPanel",G.syncSelectionFromNativeElementsPanel),ge.addListener("shutdown",G.shutdown),ge.addListener("updateConsolePatchSettings",G.updateConsolePatchSettings),ge.addListener("updateComponentFilters",G.updateComponentFilters),ge.addListener("viewAttributeSource",G.viewAttributeSource),ge.addListener("viewElementSource",G.viewElementSource),ge.addListener("overrideContext",G.overrideContext),ge.addListener("overrideHookState",G.overrideHookState),ge.addListener("overrideProps",G.overrideProps),ge.addListener("overrideState",G.overrideState),G._isProfiling&&ge.send("profilingStatus",!0);var je,nt=!1;try{localStorage.getItem("test"),nt=!0}catch{}return ge.send("isBackendStorageAPISupported",nt),ve(ge,Se(G)),je=Se(G),je.addListener("traceUpdates",Wn),G}return B=se,(q=[{key:"getInstanceAndStyle",value:function(ge){var G=ge.id,De=ge.rendererID,je=this._rendererInterfaces[De];return je==null?(console.warn('Invalid renderer id "'.concat(De,'"')),null):je.getInstanceAndStyle(G)}},{key:"getIDForNode",value:function(ge){for(var G in this._rendererInterfaces){var De=this._rendererInterfaces[G];try{var je=De.getFiberIDForNative(ge,!0);if(je!==null)return je}catch{}}return null}},{key:"selectNode",value:function(ge){var G=this.getIDForNode(ge);G!==null&&this._bridge.send("selectFiber",G)}},{key:"setRendererInterface",value:function(ge,G){this._rendererInterfaces[ge]=G,this._isProfiling&&G.startProfiling(this._recordChangeDescriptions),G.setTraceUpdatesEnabled(this._traceUpdatesEnabled);var De=this._persistedSelection;De!==null&&De.rendererID===ge&&G.setTrackedPath(De.path)}},{key:"onUnsupportedRenderer",value:function(ge){this._bridge.send("unsupportedRendererVersion",ge)}},{key:"rendererInterfaces",get:function(){return this._rendererInterfaces}}])&&nl(B.prototype,q),Y&&nl(B,Y),se}(_);function cn(b){return(cn=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(B){return typeof B}:function(B){return B&&typeof Symbol=="function"&&B.constructor===Symbol&&B!==Symbol.prototype?"symbol":typeof B})(b)}function In(b){return function(B){if(Array.isArray(B))return Ur(B)}(b)||function(B){if(typeof Symbol<"u"&&Symbol.iterator in Object(B))return Array.from(B)}(b)||function(B,q){if(!!B){if(typeof B=="string")return Ur(B,q);var Y=Object.prototype.toString.call(B).slice(8,-1);if(Y==="Object"&&B.constructor&&(Y=B.constructor.name),Y==="Map"||Y==="Set")return Array.from(B);if(Y==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(Y))return Ur(B,q)}}(b)||function(){throw new TypeError(`Invalid attempt to spread non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function Ur(b,B){(B==null||B>b.length)&&(B=b.length);for(var q=0,Y=new Array(B);q"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch{return!1}}();return function(){var q,Y=ko(b);if(B){var _e=ko(this).constructor;q=Reflect.construct(Y,arguments,_e)}else q=Y.apply(this,arguments);return Ii(this,q)}}function Ii(b,B){return!B||cn(B)!=="object"&&typeof B!="function"?jr(b):B}function jr(b){if(b===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return b}function ko(b){return(ko=Object.setPrototypeOf?Object.getPrototypeOf:function(B){return B.__proto__||Object.getPrototypeOf(B)})(b)}function Bi(b,B,q){return B in b?Object.defineProperty(b,B,{value:q,enumerable:!0,configurable:!0,writable:!0}):b[B]=q,b}var uo=function(b){(function(ge,G){if(typeof G!="function"&&G!==null)throw new TypeError("Super expression must either be null or a function");ge.prototype=Object.create(G&&G.prototype,{constructor:{value:ge,writable:!0,configurable:!0}}),G&&t0(ge,G)})(se,b);var B,q,Y,_e=n0(se);function se(ge){var G;return function(De,je){if(!(De instanceof je))throw new TypeError("Cannot call a class as a function")}(this,se),Bi(jr(G=_e.call(this)),"_isShutdown",!1),Bi(jr(G),"_messageQueue",[]),Bi(jr(G),"_timeoutID",null),Bi(jr(G),"_wallUnlisten",null),Bi(jr(G),"_flush",function(){if(G._timeoutID!==null&&(clearTimeout(G._timeoutID),G._timeoutID=null),G._messageQueue.length){for(var De=0;De1?G-1:0),je=1;je0?ne[ne.length-1]:0),ne.push(It),G.set(ze,je(yt._topLevelWrapper));try{var Gt=Ge.apply(this,at);return ne.pop(),Gt}catch(Vn){throw ne=[],Vn}finally{if(ne.length===0){var An=G.get(ze);if(An===void 0)throw new Error("Expected to find root ID.");jn(An)}}},performUpdateIfNecessary:function(Ge,at){var ze=at[0];if(C0(ze)===9)return Ge.apply(this,at);var yt=je(ze);ne.push(yt);var It=Sn(ze);try{var Gt=Ge.apply(this,at),An=Sn(ze);return nt(It,An)||ut(ze,yt,An),ne.pop(),Gt}catch(gi){throw ne=[],gi}finally{if(ne.length===0){var Vn=G.get(ze);if(Vn===void 0)throw new Error("Expected to find root ID.");jn(Vn)}}},receiveComponent:function(Ge,at){var ze=at[0];if(C0(ze)===9)return Ge.apply(this,at);var yt=je(ze);ne.push(yt);var It=Sn(ze);try{var Gt=Ge.apply(this,at),An=Sn(ze);return nt(It,An)||ut(ze,yt,An),ne.pop(),Gt}catch(gi){throw ne=[],gi}finally{if(ne.length===0){var Vn=G.get(ze);if(Vn===void 0)throw new Error("Expected to find root ID.");jn(Vn)}}},unmountComponent:function(Ge,at){var ze=at[0];if(C0(ze)===9)return Ge.apply(this,at);var yt=je(ze);ne.push(yt);try{var It=Ge.apply(this,at);return ne.pop(),function(An,Vn){bt.push(Vn),se.delete(Vn)}(0,yt),It}catch(An){throw ne=[],An}finally{if(ne.length===0){var Gt=G.get(ze);if(Gt===void 0)throw new Error("Expected to find root ID.");jn(Gt)}}}}));var wt=[],Vt=new Map,bt=[],Pt=0,ln=null;function jn(Ge){if(wt.length!==0||bt.length!==0||ln!==null){var at=bt.length+(ln===null?0:1),ze=new Array(3+Pt+(at>0?2+at:0)+wt.length),yt=0;if(ze[yt++]=B,ze[yt++]=Ge,ze[yt++]=Pt,Vt.forEach(function(An,Vn){ze[yt++]=Vn.length;for(var gi=wo(Vn),i0=0;i00){ze[yt++]=2,ze[yt++]=at;for(var It=0;It"),"color: var(--dom-tag-name-color); font-weight: normal;"),at.props!==null&&console.log("Props:",at.props),at.state!==null&&console.log("State:",at.state),at.context!==null&&console.log("Context:",at.context);var yt=_e(Ge);yt!==null&&console.log("Node:",yt),(window.chrome||/firefox/i.test(navigator.userAgent))&&console.log("Right-click any value to save it as a global variable for further inspection."),ze&&console.groupEnd()}else console.warn('Could not find element with id "'.concat(Ge,'"'))},overrideSuspense:function(){throw new Error("overrideSuspense not supported by this renderer")},overrideValueAtPath:function(Ge,at,ze,yt,It){var Gt=se.get(at);if(Gt!=null){var An=Gt._instance;if(An!=null)switch(Ge){case"context":To(An.context,yt,It),m0(An);break;case"hooks":throw new Error("Hooks not supported by this renderer");case"props":var Vn=Gt._currentElement;Gt._currentElement=H0(H0({},Vn),{},{props:hn(Vn.props,yt,It)}),m0(An);break;case"state":To(An.state,yt,It),m0(An)}}},renamePath:function(Ge,at,ze,yt,It){var Gt=se.get(at);if(Gt!=null){var An=Gt._instance;if(An!=null)switch(Ge){case"context":hr(An.context,yt,It),m0(An);break;case"hooks":throw new Error("Hooks not supported by this renderer");case"props":var Vn=Gt._currentElement;Gt._currentElement=H0(H0({},Vn),{},{props:Ft(Vn.props,yt,It)}),m0(An);break;case"state":hr(An.state,yt,It),m0(An)}}},prepareViewAttributeSource:function(Ge,at){var ze=nr(Ge);ze!==null&&(window.$attribute=h0(ze,at))},prepareViewElementSource:function(Ge){var at=se.get(Ge);if(at!=null){var ze=at._currentElement;ze!=null?Y.$type=ze.type:console.warn('Could not find element with id "'.concat(Ge,'"'))}else console.warn('Could not find instance with id "'.concat(Ge,'"'))},renderer:q,setTraceUpdatesEnabled:function(Ge){},setTrackedPath:function(Ge){},startProfiling:function(){},stopProfiling:function(){},storeAsGlobal:function(Ge,at,ze){var yt=nr(Ge);if(yt!==null){var It=h0(yt,at),Gt="$reactTemp".concat(ze);window[Gt]=It,console.log(Gt),console.log(It)}},updateComponentFilters:function(Ge){}}}function il(b,B){var q=!1,Y={bottom:0,left:0,right:0,top:0},_e=B[b];if(_e!=null){for(var se=0,ge=Object.keys(Y);se0?"development":"production";var wt=Function.prototype.toString;if(ht.Mount&&ht.Mount._renderNewRootComponent){var Vt=wt.call(ht.Mount._renderNewRootComponent);return Vt.indexOf("function")!==0?"production":Vt.indexOf("storedMeasure")!==-1?"development":Vt.indexOf("should be a pure function")!==-1?Vt.indexOf("NODE_ENV")!==-1||Vt.indexOf("development")!==-1||Vt.indexOf("true")!==-1?"development":Vt.indexOf("nextElement")!==-1||Vt.indexOf("nextComponent")!==-1?"unminified":"development":Vt.indexOf("nextElement")!==-1||Vt.indexOf("nextComponent")!==-1?"unminified":"outdated"}}catch{}return"production"}(De);try{var ne=window.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__!==!1,Ne=window.__REACT_DEVTOOLS_BREAK_ON_CONSOLE_ERRORS__===!0;(ne||Ne)&&(oo(De),la({appendComponentStack:ne,breakOnConsoleErrors:Ne}))}catch{}var Je=b.__REACT_DEVTOOLS_ATTACH__;if(typeof Je=="function"){var ut=Je(G,je,De,b);G.rendererInterfaces.set(je,ut)}return G.emit("renderer",{id:je,renderer:De,reactBuildType:nt}),je},on:function(De,je){se[De]||(se[De]=[]),se[De].push(je)},off:function(De,je){if(se[De]){var nt=se[De].indexOf(je);nt!==-1&&se[De].splice(nt,1),se[De].length||delete se[De]}},sub:function(De,je){return G.on(De,je),function(){return G.off(De,je)}},supportsFiber:!0,checkDCE:function(De){try{Function.prototype.toString.call(De).indexOf("^_^")>-1&&(q=!0,setTimeout(function(){throw new Error("React is running in production mode, but dead code elimination has not been applied. Read how to correctly configure React for production: https://reactjs.org/link/perf-use-production-build")}))}catch{}},onCommitFiberUnmount:function(De,je){var nt=_e.get(De);nt!=null&&nt.handleCommitFiberUnmount(je)},onCommitFiberRoot:function(De,je,nt){var ne=G.getFiberRoots(De),Ne=je.current,Je=ne.has(je),ut=Ne.memoizedState==null||Ne.memoizedState.element==null;Je||ut?Je&&ut&&ne.delete(je):ne.add(je);var ht=_e.get(De);ht!=null&&ht.handleCommitFiberRoot(je,nt)}};Object.defineProperty(b,"__REACT_DEVTOOLS_GLOBAL_HOOK__",{configurable:!1,enumerable:!1,get:function(){return G}})})(window);var x0=window.__REACT_DEVTOOLS_GLOBAL_HOOK__,Ol=[{type:1,value:7,isEnabled:!0}];function Uu(b){if(x0!=null){var B=b||{},q=B.host,Y=q===void 0?"localhost":q,_e=B.nativeStyleEditorValidAttributes,se=B.useHttps,ge=se!==void 0&&se,G=B.port,De=G===void 0?8097:G,je=B.websocket,nt=B.resolveRNStyle,ne=nt===void 0?null:nt,Ne=B.isAppActive,Je=ge?"wss":"ws",ut=null;if((Ne===void 0?function(){return!0}:Ne)()){var ht=null,wt=[],Vt=Je+"://"+Y+":"+De,bt=je||new window.WebSocket(Vt);bt.onclose=function(){ht!==null&&ht.emit("shutdown"),Pt()},bt.onerror=function(){Pt()},bt.onmessage=function(ln){var jn;try{if(typeof ln.data!="string")throw Error();jn=JSON.parse(ln.data)}catch{return void console.error("[React DevTools] Failed to parse JSON: "+ln.data)}wt.forEach(function(xn){try{xn(jn)}catch(Jn){throw console.log("[React DevTools] Error calling listener",jn),console.log("error:",Jn),Jn}})},bt.onopen=function(){(ht=new uo({listen:function(nn){return wt.push(nn),function(){var $n=wt.indexOf(nn);$n>=0&&wt.splice($n,1)}},send:function(nn,$n,y0){bt.readyState===bt.OPEN?bt.send(JSON.stringify({event:nn,payload:$n})):(ht!==null&&ht.shutdown(),Pt())}})).addListener("inspectElement",function(nn){var $n=nn.id,y0=nn.rendererID,nr=ln.rendererInterfaces[y0];if(nr!=null){var Ge=nr.findNativeNodesForFiberID($n);Ge!=null&&Ge[0]!=null&&ln.emit("showNativeHighlight",Ge[0])}}),ht.addListener("updateComponentFilters",function(nn){Ol=nn}),window.__REACT_DEVTOOLS_COMPONENT_FILTERS__==null&&ht.send("overrideComponentFilters",Ol);var ln=new Cn(ht);if(ln.addListener("shutdown",function(){x0.emit("shutdown")}),function(nn,$n,y0){if(nn==null)return function(){};var nr=[nn.sub("renderer-attached",function(ze){var yt=ze.id,It=(ze.renderer,ze.rendererInterface);$n.setRendererInterface(yt,It),It.flushInitialOperations()}),nn.sub("unsupported-renderer-version",function(ze){$n.onUnsupportedRenderer(ze)}),nn.sub("operations",$n.onHookOperations),nn.sub("traceUpdates",$n.onTraceUpdates)],Ge=function(ze,yt){var It=nn.rendererInterfaces.get(ze);It==null&&(typeof yt.findFiberByHostInstance=="function"?It=xl(nn,ze,yt,y0):yt.ComponentTree&&(It=Tf(nn,ze,yt,y0)),It!=null&&nn.rendererInterfaces.set(ze,It)),It!=null?nn.emit("renderer-attached",{id:ze,renderer:yt,rendererInterface:It}):nn.emit("unsupported-renderer-version",ze)};nn.renderers.forEach(function(ze,yt){Ge(yt,ze)}),nr.push(nn.sub("renderer",function(ze){var yt=ze.id,It=ze.renderer;Ge(yt,It)})),nn.emit("react-devtools",$n),nn.reactDevtoolsAgent=$n;var at=function(){nr.forEach(function(ze){return ze()}),nn.rendererInterfaces.forEach(function(ze){ze.cleanup()}),nn.reactDevtoolsAgent=null};$n.addListener("shutdown",at),nr.push(function(){$n.removeListener("shutdown",at)})}(x0,ln,window),ne!=null||x0.resolveRNStyle!=null)sa(ht,ln,ne||x0.resolveRNStyle,_e||x0.nativeStyleEditorValidAttributes||null);else{var jn,xn,Jn=function(){ht!==null&&sa(ht,ln,jn,xn)};x0.hasOwnProperty("resolveRNStyle")||Object.defineProperty(x0,"resolveRNStyle",{enumerable:!1,get:function(){return jn},set:function(nn){jn=nn,Jn()}}),x0.hasOwnProperty("nativeStyleEditorValidAttributes")||Object.defineProperty(x0,"nativeStyleEditorValidAttributes",{enumerable:!1,get:function(){return xn},set:function(nn){xn=nn,Jn()}})}}}else Pt()}function Pt(){ut===null&&(ut=setTimeout(function(){return Uu(b)},2e3))}}}])})});var F7=re(N7=>{"use strict";Object.defineProperty(N7,"__esModule",{value:!0});O7();var AJ=M7();AJ.connectToDevTools()});var B7=re(Gh=>{"use strict";var I7=Gh&&Gh.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(Gh,"__esModule",{value:!0});var L7=dg(),kJ=I7(G9()),b7=I7(a1()),vu=P3();process.env.DEV==="true"&&F7();var P7=u=>{u==null||u.unsetMeasureFunc(),u==null||u.freeRecursive()};Gh.default=kJ.default({schedulePassiveEffects:L7.unstable_scheduleCallback,cancelPassiveEffects:L7.unstable_cancelCallback,now:Date.now,getRootHostContext:()=>({isInsideText:!1}),prepareForCommit:()=>{},resetAfterCommit:u=>{if(u.isStaticDirty){u.isStaticDirty=!1,typeof u.onImmediateRender=="function"&&u.onImmediateRender();return}typeof u.onRender=="function"&&u.onRender()},getChildHostContext:(u,l)=>{let c=u.isInsideText,p=l==="ink-text"||l==="ink-virtual-text";return c===p?u:{isInsideText:p}},shouldSetTextContent:()=>!1,createInstance:(u,l,c,p)=>{if(p.isInsideText&&u==="ink-box")throw new Error(" can\u2019t be nested inside component");let _=u==="ink-text"&&p.isInsideText?"ink-virtual-text":u,t=vu.createNode(_);for(let[O,M]of Object.entries(l))O!=="children"&&(O==="style"?vu.setStyle(t,M):O==="internal_transform"?t.internal_transform=M:O==="internal_static"?t.internal_static=!0:vu.setAttribute(t,O,M));return t},createTextInstance:(u,l,c)=>{if(!c.isInsideText)throw new Error(`Text string "${u}" must be rendered inside component`);return vu.createTextNode(u)},resetTextContent:()=>{},hideTextInstance:u=>{vu.setTextNodeValue(u,"")},unhideTextInstance:(u,l)=>{vu.setTextNodeValue(u,l)},getPublicInstance:u=>u,hideInstance:u=>{var l;(l=u.yogaNode)===null||l===void 0||l.setDisplay(b7.default.DISPLAY_NONE)},unhideInstance:u=>{var l;(l=u.yogaNode)===null||l===void 0||l.setDisplay(b7.default.DISPLAY_FLEX)},appendInitialChild:vu.appendChildNode,appendChild:vu.appendChildNode,insertBefore:vu.insertBeforeNode,finalizeInitialChildren:(u,l,c,p)=>(u.internal_static&&(p.isStaticDirty=!0,p.staticNode=u),!1),supportsMutation:!0,appendChildToContainer:vu.appendChildNode,insertInContainerBefore:vu.insertBeforeNode,removeChildFromContainer:(u,l)=>{vu.removeChildNode(u,l),P7(l.yogaNode)},prepareUpdate:(u,l,c,p,_)=>{u.internal_static&&(_.isStaticDirty=!0);let t={},O=Object.keys(p);for(let M of O)if(p[M]!==c[M]){if(M==="style"&&typeof p.style=="object"&&typeof c.style=="object"){let T=p.style,P=c.style,U=Object.keys(T);for(let z of U){if(z==="borderStyle"||z==="borderColor"){if(typeof t.style!="object"){let Q={};t.style=Q}t.style.borderStyle=T.borderStyle,t.style.borderColor=T.borderColor}if(T[z]!==P[z]){if(typeof t.style!="object"){let Q={};t.style=Q}t.style[z]=T[z]}}continue}t[M]=p[M]}return t},commitUpdate:(u,l)=>{for(let[c,p]of Object.entries(l))c!=="children"&&(c==="style"?vu.setStyle(u,p):c==="internal_transform"?u.internal_transform=p:c==="internal_static"?u.internal_static=!0:vu.setAttribute(u,c,p))},commitTextUpdate:(u,l,c)=>{vu.setTextNodeValue(u,c)},removeChild:(u,l)=>{vu.removeChildNode(u,l),P7(l.yogaNode)}})});var j7=re((sie,U7)=>{"use strict";U7.exports=(u,l=1,c)=>{if(c={indent:" ",includeEmptyLines:!1,...c},typeof u!="string")throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof u}\``);if(typeof l!="number")throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof l}\``);if(typeof c.indent!="string")throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof c.indent}\``);if(l===0)return u;let p=c.includeEmptyLines?/^/gm:/^(?!\s*$)/gm;return u.replace(p,c.indent.repeat(l))}});var z7=re(Yh=>{"use strict";var OJ=Yh&&Yh.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(Yh,"__esModule",{value:!0});var Ag=OJ(a1());Yh.default=u=>u.getComputedWidth()-u.getComputedPadding(Ag.default.EDGE_LEFT)-u.getComputedPadding(Ag.default.EDGE_RIGHT)-u.getComputedBorder(Ag.default.EDGE_LEFT)-u.getComputedBorder(Ag.default.EDGE_RIGHT)});var q7=re((cie,MJ)=>{MJ.exports={single:{topLeft:"\u250C",topRight:"\u2510",bottomRight:"\u2518",bottomLeft:"\u2514",vertical:"\u2502",horizontal:"\u2500"},double:{topLeft:"\u2554",topRight:"\u2557",bottomRight:"\u255D",bottomLeft:"\u255A",vertical:"\u2551",horizontal:"\u2550"},round:{topLeft:"\u256D",topRight:"\u256E",bottomRight:"\u256F",bottomLeft:"\u2570",vertical:"\u2502",horizontal:"\u2500"},bold:{topLeft:"\u250F",topRight:"\u2513",bottomRight:"\u251B",bottomLeft:"\u2517",vertical:"\u2503",horizontal:"\u2501"},singleDouble:{topLeft:"\u2553",topRight:"\u2556",bottomRight:"\u255C",bottomLeft:"\u2559",vertical:"\u2551",horizontal:"\u2500"},doubleSingle:{topLeft:"\u2552",topRight:"\u2555",bottomRight:"\u255B",bottomLeft:"\u2558",vertical:"\u2502",horizontal:"\u2550"},classic:{topLeft:"+",topRight:"+",bottomRight:"+",bottomLeft:"+",vertical:"|",horizontal:"-"}}});var W7=re((die,s8)=>{"use strict";var H7=q7();s8.exports=H7;s8.exports.default=H7});var G7=re((pie,V7)=>{"use strict";V7.exports=(u,l=process.argv)=>{let c=u.startsWith("-")?"":u.length===1?"-":"--",p=l.indexOf(c+u),_=l.indexOf("--");return p!==-1&&(_===-1||p<_)}});var X7=re((hie,K7)=>{"use strict";var NJ=Kn("os"),Y7=Kn("tty"),oa=G7(),{env:to}=process,yc;oa("no-color")||oa("no-colors")||oa("color=false")||oa("color=never")?yc=0:(oa("color")||oa("colors")||oa("color=true")||oa("color=always"))&&(yc=1);"FORCE_COLOR"in to&&(to.FORCE_COLOR==="true"?yc=1:to.FORCE_COLOR==="false"?yc=0:yc=to.FORCE_COLOR.length===0?1:Math.min(parseInt(to.FORCE_COLOR,10),3));function f8(u){return u===0?!1:{level:u,hasBasic:!0,has256:u>=2,has16m:u>=3}}function c8(u,l){if(yc===0)return 0;if(oa("color=16m")||oa("color=full")||oa("color=truecolor"))return 3;if(oa("color=256"))return 2;if(u&&!l&&yc===void 0)return 0;let c=yc||0;if(to.TERM==="dumb")return c;if(process.platform==="win32"){let p=NJ.release().split(".");return Number(p[0])>=10&&Number(p[2])>=10586?Number(p[2])>=14931?3:2:1}if("CI"in to)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI"].some(p=>p in to)||to.CI_NAME==="codeship"?1:c;if("TEAMCITY_VERSION"in to)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(to.TEAMCITY_VERSION)?1:0;if("GITHUB_ACTIONS"in to)return 1;if(to.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in to){let p=parseInt((to.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(to.TERM_PROGRAM){case"iTerm.app":return p>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(to.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(to.TERM)||"COLORTERM"in to?1:c}function FJ(u){let l=c8(u,u&&u.isTTY);return f8(l)}K7.exports={supportsColor:FJ,stdout:f8(c8(!0,Y7.isatty(1))),stderr:f8(c8(!0,Y7.isatty(2)))}});var J7=re((vie,Q7)=>{"use strict";var LJ=(u,l,c)=>{let p=u.indexOf(l);if(p===-1)return u;let _=l.length,t=0,O="";do O+=u.substr(t,p-t)+l+c,t=p+_,p=u.indexOf(l,t);while(p!==-1);return O+=u.substr(t),O},bJ=(u,l,c,p)=>{let _=0,t="";do{let O=u[p-1]==="\r";t+=u.substr(_,(O?p-1:p)-_)+l+(O?`\r +`:` +`)+c,_=p+1,p=u.indexOf(` +`,_)}while(p!==-1);return t+=u.substr(_),t};Q7.exports={stringReplaceAll:LJ,stringEncaseCRLFWithFirstIndex:bJ}});var nA=re((mie,tA)=>{"use strict";var PJ=/(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi,Z7=/(?:^|\.)(\w+)(?:\(([^)]*)\))?/g,IJ=/^(['"])((?:\\.|(?!\1)[^\\])*)\1$/,BJ=/\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi,UJ=new Map([["n",` +`],["r","\r"],["t"," "],["b","\b"],["f","\f"],["v","\v"],["0","\0"],["\\","\\"],["e","\x1B"],["a","\x07"]]);function eA(u){let l=u[0]==="u",c=u[1]==="{";return l&&!c&&u.length===5||u[0]==="x"&&u.length===3?String.fromCharCode(parseInt(u.slice(1),16)):l&&c?String.fromCodePoint(parseInt(u.slice(2,-1),16)):UJ.get(u)||u}function jJ(u,l){let c=[],p=l.trim().split(/\s*,\s*/g),_;for(let t of p){let O=Number(t);if(!Number.isNaN(O))c.push(O);else if(_=t.match(IJ))c.push(_[2].replace(BJ,(M,A,T)=>A?eA(A):T));else throw new Error(`Invalid Chalk template style argument: ${t} (in style '${u}')`)}return c}function zJ(u){Z7.lastIndex=0;let l=[],c;for(;(c=Z7.exec(u))!==null;){let p=c[1];if(c[2]){let _=jJ(p,c[2]);l.push([p].concat(_))}else l.push([p])}return l}function $7(u,l){let c={};for(let _ of l)for(let t of _.styles)c[t[0]]=_.inverse?null:t.slice(1);let p=u;for(let[_,t]of Object.entries(c))if(!!Array.isArray(t)){if(!(_ in p))throw new Error(`Unknown Chalk style: ${_}`);p=t.length>0?p[_](...t):p[_]}return p}tA.exports=(u,l)=>{let c=[],p=[],_=[];if(l.replace(PJ,(t,O,M,A,T,P)=>{if(O)_.push(eA(O));else if(A){let U=_.join("");_=[],p.push(c.length===0?U:$7(u,c)(U)),c.push({inverse:M,styles:zJ(A)})}else if(T){if(c.length===0)throw new Error("Found extraneous } in Chalk template literal");p.push($7(u,c)(_.join(""))),_=[],c.pop()}else _.push(P)}),p.push(_.join("")),c.length>0){let t=`Chalk template literal is missing ${c.length} closing bracket${c.length===1?"":"s"} (\`}\`)`;throw new Error(t)}return p.join("")}});var y8=re((yie,aA)=>{"use strict";var Kh=yg(),{stdout:p8,stderr:h8}=X7(),{stringReplaceAll:qJ,stringEncaseCRLFWithFirstIndex:HJ}=J7(),{isArray:kg}=Array,iA=["ansi","ansi","ansi256","ansi16m"],rd=Object.create(null),WJ=(u,l={})=>{if(l.level&&!(Number.isInteger(l.level)&&l.level>=0&&l.level<=3))throw new Error("The `level` option should be an integer from 0 to 3");let c=p8?p8.level:0;u.level=l.level===void 0?c:l.level},v8=class{constructor(l){return oA(l)}},oA=u=>{let l={};return WJ(l,u),l.template=(...c)=>lA(l.template,...c),Object.setPrototypeOf(l,Og.prototype),Object.setPrototypeOf(l.template,l),l.template.constructor=()=>{throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.")},l.template.Instance=v8,l.template};function Og(u){return oA(u)}for(let[u,l]of Object.entries(Kh))rd[u]={get(){let c=Mg(this,m8(l.open,l.close,this._styler),this._isEmpty);return Object.defineProperty(this,u,{value:c}),c}};rd.visible={get(){let u=Mg(this,this._styler,!0);return Object.defineProperty(this,"visible",{value:u}),u}};var uA=["rgb","hex","keyword","hsl","hsv","hwb","ansi","ansi256"];for(let u of uA)rd[u]={get(){let{level:l}=this;return function(...c){let p=m8(Kh.color[iA[l]][u](...c),Kh.color.close,this._styler);return Mg(this,p,this._isEmpty)}}};for(let u of uA){let l="bg"+u[0].toUpperCase()+u.slice(1);rd[l]={get(){let{level:c}=this;return function(...p){let _=m8(Kh.bgColor[iA[c]][u](...p),Kh.bgColor.close,this._styler);return Mg(this,_,this._isEmpty)}}}}var VJ=Object.defineProperties(()=>{},{...rd,level:{enumerable:!0,get(){return this._generator.level},set(u){this._generator.level=u}}}),m8=(u,l,c)=>{let p,_;return c===void 0?(p=u,_=l):(p=c.openAll+u,_=l+c.closeAll),{open:u,close:l,openAll:p,closeAll:_,parent:c}},Mg=(u,l,c)=>{let p=(..._)=>kg(_[0])&&kg(_[0].raw)?rA(p,lA(p,..._)):rA(p,_.length===1?""+_[0]:_.join(" "));return Object.setPrototypeOf(p,VJ),p._generator=u,p._styler=l,p._isEmpty=c,p},rA=(u,l)=>{if(u.level<=0||!l)return u._isEmpty?"":l;let c=u._styler;if(c===void 0)return l;let{openAll:p,closeAll:_}=c;if(l.indexOf("\x1B")!==-1)for(;c!==void 0;)l=qJ(l,c.close,c.open),c=c.parent;let t=l.indexOf(` +`);return t!==-1&&(l=HJ(l,_,p,t)),p+l+_},d8,lA=(u,...l)=>{let[c]=l;if(!kg(c)||!kg(c.raw))return l.join(" ");let p=l.slice(1),_=[c.raw[0]];for(let t=1;t{"use strict";var GJ=Qh&&Qh.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(Qh,"__esModule",{value:!0});var Xh=GJ(y8()),YJ=/^(rgb|hsl|hsv|hwb)\(\s?(\d+),\s?(\d+),\s?(\d+)\s?\)$/,KJ=/^(ansi|ansi256)\(\s?(\d+)\s?\)$/,Fg=(u,l)=>l==="foreground"?u:"bg"+u[0].toUpperCase()+u.slice(1);Qh.default=(u,l,c)=>{if(!l)return u;if(l in Xh.default){let _=Fg(l,c);return Xh.default[_](u)}if(l.startsWith("#")){let _=Fg("hex",c);return Xh.default[_](l)(u)}if(l.startsWith("ansi")){let _=KJ.exec(l);if(!_)return u;let t=Fg(_[1],c),O=Number(_[2]);return Xh.default[t](O)(u)}if(l.startsWith("rgb")||l.startsWith("hsl")||l.startsWith("hsv")||l.startsWith("hwb")){let _=YJ.exec(l);if(!_)return u;let t=Fg(_[1],c),O=Number(_[2]),M=Number(_[3]),A=Number(_[4]);return Xh.default[t](O,M,A)(u)}return u}});var fA=re(Jh=>{"use strict";var sA=Jh&&Jh.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(Jh,"__esModule",{value:!0});var XJ=sA(W7()),_8=sA(g8());Jh.default=(u,l,c,p)=>{if(typeof c.style.borderStyle=="string"){let _=c.yogaNode.getComputedWidth(),t=c.yogaNode.getComputedHeight(),O=c.style.borderColor,M=XJ.default[c.style.borderStyle],A=_8.default(M.topLeft+M.horizontal.repeat(_-2)+M.topRight,O,"foreground"),T=(_8.default(M.vertical,O,"foreground")+` +`).repeat(t-2),P=_8.default(M.bottomLeft+M.horizontal.repeat(_-2)+M.bottomRight,O,"foreground");p.write(u,l,A,{transformers:[]}),p.write(u,l+1,T,{transformers:[]}),p.write(u+_-1,l+1,T,{transformers:[]}),p.write(u,l+t-1,P,{transformers:[]})}}});var dA=re(Zh=>{"use strict";var d1=Zh&&Zh.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(Zh,"__esModule",{value:!0});var QJ=d1(a1()),JJ=d1(T3()),ZJ=d1(j7()),$J=d1(F3()),eZ=d1(z7()),tZ=d1(b3()),nZ=d1(fA()),rZ=(u,l)=>{var c;let p=(c=u.childNodes[0])===null||c===void 0?void 0:c.yogaNode;if(p){let _=p.getComputedLeft(),t=p.getComputedTop();l=` +`.repeat(t)+ZJ.default(l,_)}return l},cA=(u,l,c)=>{var p;let{offsetX:_=0,offsetY:t=0,transformers:O=[],skipStaticElements:M}=c;if(M&&u.internal_static)return;let{yogaNode:A}=u;if(A){if(A.getDisplay()===QJ.default.DISPLAY_NONE)return;let T=_+A.getComputedLeft(),P=t+A.getComputedTop(),U=O;if(typeof u.internal_transform=="function"&&(U=[u.internal_transform,...O]),u.nodeName==="ink-text"){let z=tZ.default(u);if(z.length>0){let Q=JJ.default(z),v=eZ.default(A);if(Q>v){let de=(p=u.style.textWrap)!==null&&p!==void 0?p:"wrap";z=$J.default(z,v,de)}z=rZ(u,z),l.write(T,P,z,{transformers:U})}return}if(u.nodeName==="ink-box"&&nZ.default(T,P,u,l),u.nodeName==="ink-root"||u.nodeName==="ink-box")for(let z of u.childNodes)cA(z,l,{offsetX:T,offsetY:P,transformers:U,skipStaticElements:M})}};Zh.default=cA});var hA=re((Die,pA)=>{"use strict";pA.exports=u=>{u=Object.assign({onlyFirst:!1},u);let l=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(l,u.onlyFirst?void 0:"g")}});var mA=re((wie,E8)=>{"use strict";var iZ=hA(),vA=u=>typeof u=="string"?u.replace(iZ(),""):u;E8.exports=vA;E8.exports.default=vA});var _A=re((Sie,gA)=>{"use strict";var yA="[\uD800-\uDBFF][\uDC00-\uDFFF]";gA.exports=u=>u&&u.exact?new RegExp(`^${yA}$`):new RegExp(yA,"g")});var DA=re((Tie,D8)=>{"use strict";var oZ=mA(),uZ=_A(),EA=u=>oZ(u).replace(uZ()," ").length;D8.exports=EA;D8.exports.default=EA});var TA=re($h=>{"use strict";var SA=$h&&$h.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty($h,"__esModule",{value:!0});var wA=SA(M3()),lZ=SA(DA()),w8=class{constructor(l){this.writes=[];let{width:c,height:p}=l;this.width=c,this.height=p}write(l,c,p,_){let{transformers:t}=_;!p||this.writes.push({x:l,y:c,text:p,transformers:t})}get(){let l=[];for(let p=0;pp.trimRight()).join(` +`),height:l.length}}};$h.default=w8});var RA=re(ev=>{"use strict";var S8=ev&&ev.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(ev,"__esModule",{value:!0});var aZ=S8(a1()),CA=S8(dA()),xA=S8(TA());ev.default=(u,l)=>{var c;if(u.yogaNode.setWidth(l),u.yogaNode){u.yogaNode.calculateLayout(void 0,void 0,aZ.default.DIRECTION_LTR);let p=new xA.default({width:u.yogaNode.getComputedWidth(),height:u.yogaNode.getComputedHeight()});CA.default(u,p,{skipStaticElements:!0});let _;!((c=u.staticNode)===null||c===void 0)&&c.yogaNode&&(_=new xA.default({width:u.staticNode.yogaNode.getComputedWidth(),height:u.staticNode.yogaNode.getComputedHeight()}),CA.default(u.staticNode,_,{skipStaticElements:!1}));let{output:t,height:O}=p.get();return{output:t,outputHeight:O,staticOutput:_?`${_.get().output} +`:""}}return{output:"",outputHeight:0,staticOutput:""}}});var MA=re((Rie,OA)=>{"use strict";var AA=Kn("stream"),kA=["assert","count","countReset","debug","dir","dirxml","error","group","groupCollapsed","groupEnd","info","log","table","time","timeEnd","timeLog","trace","warn"],T8={},sZ=u=>{let l=new AA.PassThrough,c=new AA.PassThrough;l.write=_=>u("stdout",_),c.write=_=>u("stderr",_);let p=new console.Console(l,c);for(let _ of kA)T8[_]=console[_],console[_]=p[_];return()=>{for(let _ of kA)console[_]=T8[_];T8={}}};OA.exports=sZ});var x8=re(C8=>{"use strict";Object.defineProperty(C8,"__esModule",{value:!0});C8.default=new WeakMap});var A8=re(R8=>{"use strict";Object.defineProperty(R8,"__esModule",{value:!0});var fZ=fi(),NA=fZ.createContext({exit:()=>{}});NA.displayName="InternalAppContext";R8.default=NA});var O8=re(k8=>{"use strict";Object.defineProperty(k8,"__esModule",{value:!0});var cZ=fi(),FA=cZ.createContext({stdin:void 0,setRawMode:()=>{},isRawModeSupported:!1,internal_exitOnCtrlC:!0});FA.displayName="InternalStdinContext";k8.default=FA});var N8=re(M8=>{"use strict";Object.defineProperty(M8,"__esModule",{value:!0});var dZ=fi(),LA=dZ.createContext({stdout:void 0,write:()=>{}});LA.displayName="InternalStdoutContext";M8.default=LA});var L8=re(F8=>{"use strict";Object.defineProperty(F8,"__esModule",{value:!0});var pZ=fi(),bA=pZ.createContext({stderr:void 0,write:()=>{}});bA.displayName="InternalStderrContext";F8.default=bA});var Lg=re(b8=>{"use strict";Object.defineProperty(b8,"__esModule",{value:!0});var hZ=fi(),PA=hZ.createContext({activeId:void 0,add:()=>{},remove:()=>{},activate:()=>{},deactivate:()=>{},enableFocus:()=>{},disableFocus:()=>{},focusNext:()=>{},focusPrevious:()=>{}});PA.displayName="InternalFocusContext";b8.default=PA});var BA=re((Lie,IA)=>{"use strict";var vZ=/[|\\{}()[\]^$+*?.-]/g;IA.exports=u=>{if(typeof u!="string")throw new TypeError("Expected a string");return u.replace(vZ,"\\$&")}});var qA=re((bie,zA)=>{"use strict";var mZ=BA(),jA=[].concat(Kn("module").builtinModules,"bootstrap_node","node").map(u=>new RegExp(`(?:\\(${u}\\.js:\\d+:\\d+\\)$|^\\s*at ${u}\\.js:\\d+:\\d+$)`));jA.push(/\(internal\/[^:]+:\d+:\d+\)$/,/\s*at internal\/[^:]+:\d+:\d+$/,/\/\.node-spawn-wrap-\w+-\w+\/node:\d+:\d+\)?$/);var tv=class{constructor(l){l={ignoredPackages:[],...l},"internals"in l||(l.internals=tv.nodeInternals()),"cwd"in l||(l.cwd=process.cwd()),this._cwd=l.cwd.replace(/\\/g,"/"),this._internals=[].concat(l.internals,yZ(l.ignoredPackages)),this._wrapCallSite=l.wrapCallSite||!1}static nodeInternals(){return[...jA]}clean(l,c=0){c=" ".repeat(c),Array.isArray(l)||(l=l.split(` +`)),!/^\s*at /.test(l[0])&&/^\s*at /.test(l[1])&&(l=l.slice(1));let p=!1,_=null,t=[];return l.forEach(O=>{if(O=O.replace(/\\/g,"/"),this._internals.some(A=>A.test(O)))return;let M=/^\s*at /.test(O);p?O=O.trimEnd().replace(/^(\s+)at /,"$1"):(O=O.trim(),M&&(O=O.slice(3))),O=O.replace(`${this._cwd}/`,""),O&&(M?(_&&(t.push(_),_=null),t.push(O)):(p=!0,_=O))}),t.map(O=>`${c}${O} +`).join("")}captureString(l,c=this.captureString){typeof l=="function"&&(c=l,l=1/0);let{stackTraceLimit:p}=Error;l&&(Error.stackTraceLimit=l);let _={};Error.captureStackTrace(_,c);let{stack:t}=_;return Error.stackTraceLimit=p,this.clean(t)}capture(l,c=this.capture){typeof l=="function"&&(c=l,l=1/0);let{prepareStackTrace:p,stackTraceLimit:_}=Error;Error.prepareStackTrace=(M,A)=>this._wrapCallSite?A.map(this._wrapCallSite):A,l&&(Error.stackTraceLimit=l);let t={};Error.captureStackTrace(t,c);let{stack:O}=t;return Object.assign(Error,{prepareStackTrace:p,stackTraceLimit:_}),O}at(l=this.at){let[c]=this.capture(1,l);if(!c)return{};let p={line:c.getLineNumber(),column:c.getColumnNumber()};UA(p,c.getFileName(),this._cwd),c.isConstructor()&&(p.constructor=!0),c.isEval()&&(p.evalOrigin=c.getEvalOrigin()),c.isNative()&&(p.native=!0);let _;try{_=c.getTypeName()}catch{}_&&_!=="Object"&&_!=="[object Object]"&&(p.type=_);let t=c.getFunctionName();t&&(p.function=t);let O=c.getMethodName();return O&&t!==O&&(p.method=O),p}parseLine(l){let c=l&&l.match(gZ);if(!c)return null;let p=c[1]==="new",_=c[2],t=c[3],O=c[4],M=Number(c[5]),A=Number(c[6]),T=c[7],P=c[8],U=c[9],z=c[10]==="native",Q=c[11]===")",v,de={};if(P&&(de.line=Number(P)),U&&(de.column=Number(U)),Q&&T){let ye=0;for(let le=T.length-1;le>0;le--)if(T.charAt(le)===")")ye++;else if(T.charAt(le)==="("&&T.charAt(le-1)===" "&&(ye--,ye===-1&&T.charAt(le-1)===" ")){let ae=T.slice(0,le-1);T=T.slice(le+1),_+=` (${ae}`;break}}if(_){let ye=_.match(_Z);ye&&(_=ye[1],v=ye[2])}return UA(de,T,this._cwd),p&&(de.constructor=!0),t&&(de.evalOrigin=t,de.evalLine=M,de.evalColumn=A,de.evalFile=O&&O.replace(/\\/g,"/")),z&&(de.native=!0),_&&(de.function=_),v&&_!==v&&(de.method=v),de}};function UA(u,l,c){l&&(l=l.replace(/\\/g,"/"),l.startsWith(`${c}/`)&&(l=l.slice(c.length+1)),u.file=l)}function yZ(u){if(u.length===0)return[];let l=u.map(c=>mZ(c));return new RegExp(`[/\\\\]node_modules[/\\\\](?:${l.join("|")})[/\\\\][^:]+:\\d+:\\d+`)}var gZ=new RegExp("^(?:\\s*at )?(?:(new) )?(?:(.*?) \\()?(?:eval at ([^ ]+) \\((.+?):(\\d+):(\\d+)\\), )?(?:(.+?):(\\d+):(\\d+)|(native))(\\)?)$"),_Z=/^(.*?) \[as (.*?)\]$/;zA.exports=tv});var WA=re((Pie,HA)=>{"use strict";HA.exports=(u,l)=>u.replace(/^\t+/gm,c=>" ".repeat(c.length*(l||2)))});var GA=re((Iie,VA)=>{"use strict";var EZ=WA(),DZ=(u,l)=>{let c=[],p=u-l,_=u+l;for(let t=p;t<=_;t++)c.push(t);return c};VA.exports=(u,l,c)=>{if(typeof u!="string")throw new TypeError("Source code is missing.");if(!l||l<1)throw new TypeError("Line number must start from `1`.");if(u=EZ(u).split(/\r?\n/),!(l>u.length))return c={around:3,...c},DZ(l,c.around).filter(p=>u[p-1]!==void 0).map(p=>({line:p,value:u[p-1]}))}});var bg=re(ja=>{"use strict";var wZ=ja&&ja.__createBinding||(Object.create?function(u,l,c,p){p===void 0&&(p=c),Object.defineProperty(u,p,{enumerable:!0,get:function(){return l[c]}})}:function(u,l,c,p){p===void 0&&(p=c),u[p]=l[c]}),SZ=ja&&ja.__setModuleDefault||(Object.create?function(u,l){Object.defineProperty(u,"default",{enumerable:!0,value:l})}:function(u,l){u.default=l}),TZ=ja&&ja.__importStar||function(u){if(u&&u.__esModule)return u;var l={};if(u!=null)for(var c in u)c!=="default"&&Object.hasOwnProperty.call(u,c)&&wZ(l,u,c);return SZ(l,u),l},CZ=ja&&ja.__rest||function(u,l){var c={};for(var p in u)Object.prototype.hasOwnProperty.call(u,p)&&l.indexOf(p)<0&&(c[p]=u[p]);if(u!=null&&typeof Object.getOwnPropertySymbols=="function")for(var _=0,p=Object.getOwnPropertySymbols(u);_{var{children:c}=u,p=CZ(u,["children"]);let _=Object.assign(Object.assign({},p),{marginLeft:p.marginLeft||p.marginX||p.margin||0,marginRight:p.marginRight||p.marginX||p.margin||0,marginTop:p.marginTop||p.marginY||p.margin||0,marginBottom:p.marginBottom||p.marginY||p.margin||0,paddingLeft:p.paddingLeft||p.paddingX||p.padding||0,paddingRight:p.paddingRight||p.paddingX||p.padding||0,paddingTop:p.paddingTop||p.paddingY||p.padding||0,paddingBottom:p.paddingBottom||p.paddingY||p.padding||0});return YA.default.createElement("ink-box",{ref:l,style:_},c)});P8.displayName="Box";P8.defaultProps={flexDirection:"row",flexGrow:0,flexShrink:1};ja.default=P8});var U8=re(nv=>{"use strict";var I8=nv&&nv.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(nv,"__esModule",{value:!0});var xZ=I8(fi()),id=I8(y8()),KA=I8(g8()),B8=({color:u,backgroundColor:l,dimColor:c,bold:p,italic:_,underline:t,strikethrough:O,inverse:M,wrap:A,children:T})=>{if(T==null)return null;let P=U=>(c&&(U=id.default.dim(U)),u&&(U=KA.default(U,u,"foreground")),l&&(U=KA.default(U,l,"background")),p&&(U=id.default.bold(U)),_&&(U=id.default.italic(U)),t&&(U=id.default.underline(U)),O&&(U=id.default.strikethrough(U)),M&&(U=id.default.inverse(U)),U);return xZ.default.createElement("ink-text",{style:{flexGrow:0,flexShrink:1,flexDirection:"row",textWrap:A},internal_transform:P},T)};B8.displayName="Text";B8.defaultProps={dimColor:!1,bold:!1,italic:!1,underline:!1,strikethrough:!1,wrap:"wrap"};nv.default=B8});var ZA=re(za=>{"use strict";var RZ=za&&za.__createBinding||(Object.create?function(u,l,c,p){p===void 0&&(p=c),Object.defineProperty(u,p,{enumerable:!0,get:function(){return l[c]}})}:function(u,l,c,p){p===void 0&&(p=c),u[p]=l[c]}),AZ=za&&za.__setModuleDefault||(Object.create?function(u,l){Object.defineProperty(u,"default",{enumerable:!0,value:l})}:function(u,l){u.default=l}),kZ=za&&za.__importStar||function(u){if(u&&u.__esModule)return u;var l={};if(u!=null)for(var c in u)c!=="default"&&Object.hasOwnProperty.call(u,c)&&RZ(l,u,c);return AZ(l,u),l},rv=za&&za.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(za,"__esModule",{value:!0});var XA=kZ(Kn("fs")),no=rv(fi()),QA=rv(qA()),OZ=rv(GA()),Df=rv(bg()),Ts=rv(U8()),JA=new QA.default({cwd:process.cwd(),internals:QA.default.nodeInternals()}),MZ=({error:u})=>{let l=u.stack?u.stack.split(` +`).slice(1):void 0,c=l?JA.parseLine(l[0]):void 0,p,_=0;if((c==null?void 0:c.file)&&(c==null?void 0:c.line)&&XA.existsSync(c.file)){let t=XA.readFileSync(c.file,"utf8");if(p=OZ.default(t,c.line),p)for(let{line:O}of p)_=Math.max(_,String(O).length)}return no.default.createElement(Df.default,{flexDirection:"column",padding:1},no.default.createElement(Df.default,null,no.default.createElement(Ts.default,{backgroundColor:"red",color:"white"}," ","ERROR"," "),no.default.createElement(Ts.default,null," ",u.message)),c&&no.default.createElement(Df.default,{marginTop:1},no.default.createElement(Ts.default,{dimColor:!0},c.file,":",c.line,":",c.column)),c&&p&&no.default.createElement(Df.default,{marginTop:1,flexDirection:"column"},p.map(({line:t,value:O})=>no.default.createElement(Df.default,{key:t},no.default.createElement(Df.default,{width:_+1},no.default.createElement(Ts.default,{dimColor:t!==c.line,backgroundColor:t===c.line?"red":void 0,color:t===c.line?"white":void 0},String(t).padStart(_," "),":")),no.default.createElement(Ts.default,{key:t,backgroundColor:t===c.line?"red":void 0,color:t===c.line?"white":void 0}," "+O)))),u.stack&&no.default.createElement(Df.default,{marginTop:1,flexDirection:"column"},u.stack.split(` +`).slice(1).map(t=>{let O=JA.parseLine(t);return O?no.default.createElement(Df.default,{key:t},no.default.createElement(Ts.default,{dimColor:!0},"- "),no.default.createElement(Ts.default,{dimColor:!0,bold:!0},O.function),no.default.createElement(Ts.default,{dimColor:!0,color:"gray"}," ","(",O.file,":",O.line,":",O.column,")")):no.default.createElement(Df.default,{key:t},no.default.createElement(Ts.default,{dimColor:!0},"- "),no.default.createElement(Ts.default,{dimColor:!0,bold:!0},t))})))};za.default=MZ});var ek=re(qa=>{"use strict";var NZ=qa&&qa.__createBinding||(Object.create?function(u,l,c,p){p===void 0&&(p=c),Object.defineProperty(u,p,{enumerable:!0,get:function(){return l[c]}})}:function(u,l,c,p){p===void 0&&(p=c),u[p]=l[c]}),FZ=qa&&qa.__setModuleDefault||(Object.create?function(u,l){Object.defineProperty(u,"default",{enumerable:!0,value:l})}:function(u,l){u.default=l}),LZ=qa&&qa.__importStar||function(u){if(u&&u.__esModule)return u;var l={};if(u!=null)for(var c in u)c!=="default"&&Object.hasOwnProperty.call(u,c)&&NZ(l,u,c);return FZ(l,u),l},h1=qa&&qa.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(qa,"__esModule",{value:!0});var p1=LZ(fi()),$A=h1(t3()),bZ=h1(A8()),PZ=h1(O8()),IZ=h1(N8()),BZ=h1(L8()),UZ=h1(Lg()),jZ=h1(ZA()),zZ=" ",qZ="\x1B[Z",HZ="\x1B",Pg=class extends p1.PureComponent{constructor(){super(...arguments),this.state={isFocusEnabled:!0,activeFocusId:void 0,focusables:[],error:void 0},this.rawModeEnabledCount=0,this.handleSetRawMode=l=>{let{stdin:c}=this.props;if(!this.isRawModeSupported())throw c===process.stdin?new Error(`Raw mode is not supported on the current process.stdin, which Ink uses as input stream by default. +Read about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`):new Error(`Raw mode is not supported on the stdin provided to Ink. +Read about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`);if(c.setEncoding("utf8"),l){this.rawModeEnabledCount===0&&(c.addListener("data",this.handleInput),c.resume(),c.setRawMode(!0)),this.rawModeEnabledCount++;return}--this.rawModeEnabledCount===0&&(c.setRawMode(!1),c.removeListener("data",this.handleInput),c.pause())},this.handleInput=l=>{l===""&&this.props.exitOnCtrlC&&this.handleExit(),l===HZ&&this.state.activeFocusId&&this.setState({activeFocusId:void 0}),this.state.isFocusEnabled&&this.state.focusables.length>0&&(l===zZ&&this.focusNext(),l===qZ&&this.focusPrevious())},this.handleExit=l=>{this.isRawModeSupported()&&this.handleSetRawMode(!1),this.props.onExit(l)},this.enableFocus=()=>{this.setState({isFocusEnabled:!0})},this.disableFocus=()=>{this.setState({isFocusEnabled:!1})},this.focusNext=()=>{this.setState(l=>{let c=l.focusables[0].id;return{activeFocusId:this.findNextFocusable(l)||c}})},this.focusPrevious=()=>{this.setState(l=>{let c=l.focusables[l.focusables.length-1].id;return{activeFocusId:this.findPreviousFocusable(l)||c}})},this.addFocusable=(l,{autoFocus:c})=>{this.setState(p=>{let _=p.activeFocusId;return!_&&c&&(_=l),{activeFocusId:_,focusables:[...p.focusables,{id:l,isActive:!0}]}})},this.removeFocusable=l=>{this.setState(c=>({activeFocusId:c.activeFocusId===l?void 0:c.activeFocusId,focusables:c.focusables.filter(p=>p.id!==l)}))},this.activateFocusable=l=>{this.setState(c=>({focusables:c.focusables.map(p=>p.id!==l?p:{id:l,isActive:!0})}))},this.deactivateFocusable=l=>{this.setState(c=>({activeFocusId:c.activeFocusId===l?void 0:c.activeFocusId,focusables:c.focusables.map(p=>p.id!==l?p:{id:l,isActive:!1})}))},this.findNextFocusable=l=>{let c=l.focusables.findIndex(p=>p.id===l.activeFocusId);for(let p=c+1;p{let c=l.focusables.findIndex(p=>p.id===l.activeFocusId);for(let p=c-1;p>=0;p--)if(l.focusables[p].isActive)return l.focusables[p].id}}static getDerivedStateFromError(l){return{error:l}}isRawModeSupported(){return this.props.stdin.isTTY}render(){return p1.default.createElement(bZ.default.Provider,{value:{exit:this.handleExit}},p1.default.createElement(PZ.default.Provider,{value:{stdin:this.props.stdin,setRawMode:this.handleSetRawMode,isRawModeSupported:this.isRawModeSupported(),internal_exitOnCtrlC:this.props.exitOnCtrlC}},p1.default.createElement(IZ.default.Provider,{value:{stdout:this.props.stdout,write:this.props.writeToStdout}},p1.default.createElement(BZ.default.Provider,{value:{stderr:this.props.stderr,write:this.props.writeToStderr}},p1.default.createElement(UZ.default.Provider,{value:{activeId:this.state.activeFocusId,add:this.addFocusable,remove:this.removeFocusable,activate:this.activateFocusable,deactivate:this.deactivateFocusable,enableFocus:this.enableFocus,disableFocus:this.disableFocus,focusNext:this.focusNext,focusPrevious:this.focusPrevious}},this.state.error?p1.default.createElement(jZ.default,{error:this.state.error}):this.props.children)))))}componentDidMount(){$A.default.hide(this.props.stdout)}componentWillUnmount(){$A.default.show(this.props.stdout),this.isRawModeSupported()&&this.handleSetRawMode(!1)}componentDidCatch(l){this.handleExit(l)}};qa.default=Pg;Pg.displayName="InternalApp"});var rk=re(Ha=>{"use strict";var WZ=Ha&&Ha.__createBinding||(Object.create?function(u,l,c,p){p===void 0&&(p=c),Object.defineProperty(u,p,{enumerable:!0,get:function(){return l[c]}})}:function(u,l,c,p){p===void 0&&(p=c),u[p]=l[c]}),VZ=Ha&&Ha.__setModuleDefault||(Object.create?function(u,l){Object.defineProperty(u,"default",{enumerable:!0,value:l})}:function(u,l){u.default=l}),GZ=Ha&&Ha.__importStar||function(u){if(u&&u.__esModule)return u;var l={};if(u!=null)for(var c in u)c!=="default"&&Object.hasOwnProperty.call(u,c)&&WZ(l,u,c);return VZ(l,u),l},Wa=Ha&&Ha.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(Ha,"__esModule",{value:!0});var YZ=Wa(fi()),tk=a9(),KZ=Wa(T9()),XZ=Wa(QD()),QZ=Wa(O9()),JZ=Wa(N9()),Ig=Wa(B7()),ZZ=Wa(RA()),$Z=Wa(e3()),e$=Wa(MA()),t$=GZ(P3()),n$=Wa(x8()),r$=Wa(ek()),od=process.env.CI==="false"?!1:QZ.default,nk=()=>{},j8=class{constructor(l){this.resolveExitPromise=()=>{},this.rejectExitPromise=()=>{},this.unsubscribeExit=()=>{},this.onRender=()=>{if(this.isUnmounted)return;let{output:c,outputHeight:p,staticOutput:_}=ZZ.default(this.rootNode,this.options.stdout.columns||80),t=_&&_!==` +`;if(this.options.debug){t&&(this.fullStaticOutput+=_),this.options.stdout.write(this.fullStaticOutput+c);return}if(od){t&&this.options.stdout.write(_),this.lastOutput=c;return}if(t&&(this.fullStaticOutput+=_),p>=this.options.stdout.rows){this.options.stdout.write(XZ.default.clearTerminal+this.fullStaticOutput+c),this.lastOutput=c;return}t&&(this.log.clear(),this.options.stdout.write(_),this.log(c)),!t&&c!==this.lastOutput&&this.throttledLog(c),this.lastOutput=c},JZ.default(this),this.options=l,this.rootNode=t$.createNode("ink-root"),this.rootNode.onRender=l.debug?this.onRender:tk(this.onRender,32,{leading:!0,trailing:!0}),this.rootNode.onImmediateRender=this.onRender,this.log=KZ.default.create(l.stdout),this.throttledLog=l.debug?this.log:tk(this.log,void 0,{leading:!0,trailing:!0}),this.isUnmounted=!1,this.lastOutput="",this.fullStaticOutput="",this.container=Ig.default.createContainer(this.rootNode,!1,!1),this.unsubscribeExit=$Z.default(this.unmount,{alwaysLast:!1}),process.env.DEV==="true"&&Ig.default.injectIntoDevTools({bundleType:0,version:"16.13.1",rendererPackageName:"ink"}),l.patchConsole&&this.patchConsole(),od||(l.stdout.on("resize",this.onRender),this.unsubscribeResize=()=>{l.stdout.off("resize",this.onRender)})}render(l){let c=YZ.default.createElement(r$.default,{stdin:this.options.stdin,stdout:this.options.stdout,stderr:this.options.stderr,writeToStdout:this.writeToStdout,writeToStderr:this.writeToStderr,exitOnCtrlC:this.options.exitOnCtrlC,onExit:this.unmount},l);Ig.default.updateContainer(c,this.container,null,nk)}writeToStdout(l){if(!this.isUnmounted){if(this.options.debug){this.options.stdout.write(l+this.fullStaticOutput+this.lastOutput);return}if(od){this.options.stdout.write(l);return}this.log.clear(),this.options.stdout.write(l),this.log(this.lastOutput)}}writeToStderr(l){if(!this.isUnmounted){if(this.options.debug){this.options.stderr.write(l),this.options.stdout.write(this.fullStaticOutput+this.lastOutput);return}if(od){this.options.stderr.write(l);return}this.log.clear(),this.options.stderr.write(l),this.log(this.lastOutput)}}unmount(l){this.isUnmounted||(this.onRender(),this.unsubscribeExit(),typeof this.restoreConsole=="function"&&this.restoreConsole(),typeof this.unsubscribeResize=="function"&&this.unsubscribeResize(),od?this.options.stdout.write(this.lastOutput+` +`):this.options.debug||this.log.done(),this.isUnmounted=!0,Ig.default.updateContainer(null,this.container,null,nk),n$.default.delete(this.options.stdout),l instanceof Error?this.rejectExitPromise(l):this.resolveExitPromise())}waitUntilExit(){return this.exitPromise||(this.exitPromise=new Promise((l,c)=>{this.resolveExitPromise=l,this.rejectExitPromise=c})),this.exitPromise}clear(){!od&&!this.options.debug&&this.log.clear()}patchConsole(){this.options.debug||(this.restoreConsole=e$.default((l,c)=>{l==="stdout"&&this.writeToStdout(c),l==="stderr"&&(c.startsWith("The above error occurred")||this.writeToStderr(c))}))}};Ha.default=j8});var ok=re(iv=>{"use strict";var ik=iv&&iv.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(iv,"__esModule",{value:!0});var i$=ik(rk()),Bg=ik(x8()),o$=Kn("stream"),u$=(u,l)=>{let c=Object.assign({stdout:process.stdout,stdin:process.stdin,stderr:process.stderr,debug:!1,exitOnCtrlC:!0,patchConsole:!0},l$(l)),p=a$(c.stdout,()=>new i$.default(c));return p.render(u),{rerender:p.render,unmount:()=>p.unmount(),waitUntilExit:p.waitUntilExit,cleanup:()=>Bg.default.delete(c.stdout),clear:p.clear}};iv.default=u$;var l$=(u={})=>u instanceof o$.Stream?{stdout:u,stdin:process.stdin}:u,a$=(u,l)=>{let c;return Bg.default.has(u)?c=Bg.default.get(u):(c=l(),Bg.default.set(u,c)),c}});var lk=re(wf=>{"use strict";var s$=wf&&wf.__createBinding||(Object.create?function(u,l,c,p){p===void 0&&(p=c),Object.defineProperty(u,p,{enumerable:!0,get:function(){return l[c]}})}:function(u,l,c,p){p===void 0&&(p=c),u[p]=l[c]}),f$=wf&&wf.__setModuleDefault||(Object.create?function(u,l){Object.defineProperty(u,"default",{enumerable:!0,value:l})}:function(u,l){u.default=l}),c$=wf&&wf.__importStar||function(u){if(u&&u.__esModule)return u;var l={};if(u!=null)for(var c in u)c!=="default"&&Object.hasOwnProperty.call(u,c)&&s$(l,u,c);return f$(l,u),l};Object.defineProperty(wf,"__esModule",{value:!0});var ov=c$(fi()),uk=u=>{let{items:l,children:c,style:p}=u,[_,t]=ov.useState(0),O=ov.useMemo(()=>l.slice(_),[l,_]);ov.useLayoutEffect(()=>{t(l.length)},[l.length]);let M=O.map((T,P)=>c(T,_+P)),A=ov.useMemo(()=>Object.assign({position:"absolute",flexDirection:"column"},p),[p]);return ov.default.createElement("ink-box",{internal_static:!0,style:A},M)};uk.displayName="Static";wf.default=uk});var sk=re(uv=>{"use strict";var d$=uv&&uv.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(uv,"__esModule",{value:!0});var p$=d$(fi()),ak=({children:u,transform:l})=>u==null?null:p$.default.createElement("ink-text",{style:{flexGrow:0,flexShrink:1,flexDirection:"row"},internal_transform:l},u);ak.displayName="Transform";uv.default=ak});var ck=re(lv=>{"use strict";var h$=lv&&lv.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(lv,"__esModule",{value:!0});var v$=h$(fi()),fk=({count:u=1})=>v$.default.createElement("ink-text",null,` +`.repeat(u));fk.displayName="Newline";lv.default=fk});var hk=re(av=>{"use strict";var dk=av&&av.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(av,"__esModule",{value:!0});var m$=dk(fi()),y$=dk(bg()),pk=()=>m$.default.createElement(y$.default,{flexGrow:1});pk.displayName="Spacer";av.default=pk});var Ug=re(sv=>{"use strict";var g$=sv&&sv.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(sv,"__esModule",{value:!0});var _$=fi(),E$=g$(O8()),D$=()=>_$.useContext(E$.default);sv.default=D$});var mk=re(fv=>{"use strict";var w$=fv&&fv.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(fv,"__esModule",{value:!0});var vk=fi(),S$=w$(Ug()),T$=(u,l={})=>{let{stdin:c,setRawMode:p,internal_exitOnCtrlC:_}=S$.default();vk.useEffect(()=>{if(l.isActive!==!1)return p(!0),()=>{p(!1)}},[l.isActive,p]),vk.useEffect(()=>{if(l.isActive===!1)return;let t=O=>{let M=String(O),A={upArrow:M==="\x1B[A",downArrow:M==="\x1B[B",leftArrow:M==="\x1B[D",rightArrow:M==="\x1B[C",pageDown:M==="\x1B[6~",pageUp:M==="\x1B[5~",return:M==="\r",escape:M==="\x1B",ctrl:!1,shift:!1,tab:M===" "||M==="\x1B[Z",backspace:M==="\b",delete:M==="\x7F"||M==="\x1B[3~",meta:!1};M<=""&&!A.return&&(M=String.fromCharCode(M.charCodeAt(0)+"a".charCodeAt(0)-1),A.ctrl=!0),M.startsWith("\x1B")&&(M=M.slice(1),A.meta=!0);let T=M>="A"&&M<="Z",P=M>="\u0410"&&M<="\u042F";M.length===1&&(T||P)&&(A.shift=!0),A.tab&&M==="[Z"&&(A.shift=!0),(A.tab||A.backspace||A.delete)&&(M=""),(!(M==="c"&&A.ctrl)||!_)&&u(M,A)};return c==null||c.on("data",t),()=>{c==null||c.off("data",t)}},[l.isActive,c,_,u])};fv.default=T$});var yk=re(cv=>{"use strict";var C$=cv&&cv.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(cv,"__esModule",{value:!0});var x$=fi(),R$=C$(A8()),A$=()=>x$.useContext(R$.default);cv.default=A$});var gk=re(dv=>{"use strict";var k$=dv&&dv.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(dv,"__esModule",{value:!0});var O$=fi(),M$=k$(N8()),N$=()=>O$.useContext(M$.default);dv.default=N$});var _k=re(pv=>{"use strict";var F$=pv&&pv.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(pv,"__esModule",{value:!0});var L$=fi(),b$=F$(L8()),P$=()=>L$.useContext(b$.default);pv.default=P$});var Dk=re(vv=>{"use strict";var Ek=vv&&vv.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(vv,"__esModule",{value:!0});var hv=fi(),I$=Ek(Lg()),B$=Ek(Ug()),U$=({isActive:u=!0,autoFocus:l=!1}={})=>{let{isRawModeSupported:c,setRawMode:p}=B$.default(),{activeId:_,add:t,remove:O,activate:M,deactivate:A}=hv.useContext(I$.default),T=hv.useMemo(()=>Math.random().toString().slice(2,7),[]);return hv.useEffect(()=>(t(T,{autoFocus:l}),()=>{O(T)}),[T,l]),hv.useEffect(()=>{u?M(T):A(T)},[u,T]),hv.useEffect(()=>{if(!(!c||!u))return p(!0),()=>{p(!1)}},[u]),{isFocused:Boolean(T)&&_===T}};vv.default=U$});var wk=re(mv=>{"use strict";var j$=mv&&mv.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(mv,"__esModule",{value:!0});var z$=fi(),q$=j$(Lg()),H$=()=>{let u=z$.useContext(q$.default);return{enableFocus:u.enableFocus,disableFocus:u.disableFocus,focusNext:u.focusNext,focusPrevious:u.focusPrevious}};mv.default=H$});var Sk=re(z8=>{"use strict";Object.defineProperty(z8,"__esModule",{value:!0});z8.default=u=>{var l,c,p,_;return{width:(c=(l=u.yogaNode)===null||l===void 0?void 0:l.getComputedWidth())!==null&&c!==void 0?c:0,height:(_=(p=u.yogaNode)===null||p===void 0?void 0:p.getComputedHeight())!==null&&_!==void 0?_:0}}});var v1=re(Yo=>{"use strict";Object.defineProperty(Yo,"__esModule",{value:!0});var W$=ok();Object.defineProperty(Yo,"render",{enumerable:!0,get:function(){return W$.default}});var V$=bg();Object.defineProperty(Yo,"Box",{enumerable:!0,get:function(){return V$.default}});var G$=U8();Object.defineProperty(Yo,"Text",{enumerable:!0,get:function(){return G$.default}});var Y$=lk();Object.defineProperty(Yo,"Static",{enumerable:!0,get:function(){return Y$.default}});var K$=sk();Object.defineProperty(Yo,"Transform",{enumerable:!0,get:function(){return K$.default}});var X$=ck();Object.defineProperty(Yo,"Newline",{enumerable:!0,get:function(){return X$.default}});var Q$=hk();Object.defineProperty(Yo,"Spacer",{enumerable:!0,get:function(){return Q$.default}});var J$=mk();Object.defineProperty(Yo,"useInput",{enumerable:!0,get:function(){return J$.default}});var Z$=yk();Object.defineProperty(Yo,"useApp",{enumerable:!0,get:function(){return Z$.default}});var $$=Ug();Object.defineProperty(Yo,"useStdin",{enumerable:!0,get:function(){return $$.default}});var eee=gk();Object.defineProperty(Yo,"useStdout",{enumerable:!0,get:function(){return eee.default}});var tee=_k();Object.defineProperty(Yo,"useStderr",{enumerable:!0,get:function(){return tee.default}});var nee=Dk();Object.defineProperty(Yo,"useFocus",{enumerable:!0,get:function(){return nee.default}});var ree=wk();Object.defineProperty(Yo,"useFocusManager",{enumerable:!0,get:function(){return ree.default}});var iee=Sk();Object.defineProperty(Yo,"measureElement",{enumerable:!0,get:function(){return iee.default}})});var aee={};gS(aee,{default:()=>lee,versionUtils:()=>H2});var W8=Kn("@yarnpkg/core");var Vy=Kn("@yarnpkg/cli"),W2=Kn("@yarnpkg/core"),Gy=Kn("@yarnpkg/core"),dc=Kn("clipanion");var H2={};gS(H2,{Decision:()=>z2,applyPrerelease:()=>x5,applyReleases:()=>bD,applyStrategy:()=>Wy,clearVersionFiles:()=>ND,fetchBase:()=>wK,fetchChangedFiles:()=>TK,fetchRoot:()=>SK,getUndecidedDependentWorkspaces:()=>_h,getUndecidedWorkspaces:()=>Hy,openVersionFile:()=>q2,requireMoreDecisions:()=>xK,resolveVersionFiles:()=>gh,suggestStrategy:()=>LD,updateVersionFiles:()=>FD,validateReleaseDecision:()=>j2});var Zr=Kn("@yarnpkg/core"),Hi=Kn("@yarnpkg/fslib"),mf=Kn("@yarnpkg/parsers"),r1=Kn("@yarnpkg/plugin-git"),U2=Kn("clipanion"),C5=pu(T5()),Es=pu(Kn("semver")),wK=r1.gitUtils.fetchBase,SK=r1.gitUtils.fetchRoot,TK=r1.gitUtils.fetchChangedFiles,CK=/^(>=|[~^]|)(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/,z2=(O=>(O.UNDECIDED="undecided",O.DECLINE="decline",O.MAJOR="major",O.MINOR="minor",O.PATCH="patch",O.PRERELEASE="prerelease",O))(z2||{});function j2(u){let l=Es.default.valid(u);return l||Zr.miscUtils.validateEnum((0,C5.default)(z2,"UNDECIDED"),u)}async function gh(u,{prerelease:l=null}={}){var t;let c=new Map,p=u.configuration.get("deferredVersionFolder");if(!Hi.xfs.existsSync(p))return c;let _=await Hi.xfs.readdirPromise(p);for(let O of _){if(!O.endsWith(".yml"))continue;let M=Hi.ppath.join(p,O),A=await Hi.xfs.readFilePromise(M,"utf8"),T=(0,mf.parseSyml)(A);for(let[P,U]of Object.entries(T.releases||{})){if(U==="decline")continue;let z=Zr.structUtils.parseIdent(P),Q=u.tryWorkspaceByIdent(z);if(Q===null)throw new Error(`Assertion failed: Expected a release definition file to only reference existing workspaces (${Hi.ppath.basename(M)} references ${P})`);if(Q.manifest.version===null)throw new Error(`Assertion failed: Expected the workspace to have a version (${Zr.structUtils.prettyLocator(u.configuration,Q.anchoredLocator)})`);let v=(t=Q.manifest.raw.stableVersion)!=null?t:Q.manifest.version,de=c.get(Q),ye=Wy(v,j2(U));if(ye===null)throw new Error(`Assertion failed: Expected ${v} to support being bumped via strategy ${U}`);let le=typeof de<"u"?Es.default.gt(ye,de)?ye:de:ye;c.set(Q,le)}}return l&&(c=new Map([...c].map(([O,M])=>[O,x5(M,{current:O.manifest.version,prerelease:l})]))),c}async function ND(u){let l=u.configuration.get("deferredVersionFolder");!Hi.xfs.existsSync(l)||await Hi.xfs.removePromise(l)}async function FD(u,l){let c=new Set(l),p=u.configuration.get("deferredVersionFolder");if(!Hi.xfs.existsSync(p))return;let _=await Hi.xfs.readdirPromise(p);for(let t of _){if(!t.endsWith(".yml"))continue;let O=Hi.ppath.join(p,t),M=await Hi.xfs.readFilePromise(O,"utf8"),A=(0,mf.parseSyml)(M),T=A==null?void 0:A.releases;if(!!T){for(let P of Object.keys(T)){let U=Zr.structUtils.parseIdent(P),z=u.tryWorkspaceByIdent(U);(z===null||c.has(z))&&delete A.releases[P]}Object.keys(A.releases).length>0?await Hi.xfs.changeFilePromise(O,(0,mf.stringifySyml)(new mf.stringifySyml.PreserveOrdering(A))):await Hi.xfs.unlinkPromise(O)}}}async function q2(u,{allowEmpty:l=!1}={}){let c=u.configuration;if(c.projectCwd===null)throw new U2.UsageError("This command can only be run from within a Yarn project");let p=await r1.gitUtils.fetchRoot(c.projectCwd),_=p!==null?await r1.gitUtils.fetchBase(p,{baseRefs:c.get("changesetBaseRefs")}):null,t=p!==null?await r1.gitUtils.fetchChangedFiles(p,{base:_.hash,project:u}):[],O=c.get("deferredVersionFolder"),M=t.filter(Q=>Hi.ppath.contains(O,Q)!==null);if(M.length>1)throw new U2.UsageError(`Your current branch contains multiple versioning files; this isn't supported: +- ${M.map(Q=>Hi.npath.fromPortablePath(Q)).join(` +- `)}`);let A=new Set(Zr.miscUtils.mapAndFilter(t,Q=>{let v=u.tryWorkspaceByFilePath(Q);return v===null?Zr.miscUtils.mapAndFilter.skip:v}));if(M.length===0&&A.size===0&&!l)return null;let T=M.length===1?M[0]:Hi.ppath.join(O,`${Zr.hashUtils.makeHash(Math.random().toString()).slice(0,8)}.yml`),P=Hi.xfs.existsSync(T)?await Hi.xfs.readFilePromise(T,"utf8"):"{}",U=(0,mf.parseSyml)(P),z=new Map;for(let Q of U.declined||[]){let v=Zr.structUtils.parseIdent(Q),de=u.getWorkspaceByIdent(v);z.set(de,"decline")}for(let[Q,v]of Object.entries(U.releases||{})){let de=Zr.structUtils.parseIdent(Q),ye=u.getWorkspaceByIdent(de);z.set(ye,j2(v))}return{project:u,root:p,baseHash:_!==null?_.hash:null,baseTitle:_!==null?_.title:null,changedFiles:new Set(t),changedWorkspaces:A,releaseRoots:new Set([...A].filter(Q=>Q.manifest.version!==null)),releases:z,async saveAll(){let Q={},v=[],de=[];for(let ye of u.workspaces){if(ye.manifest.version===null)continue;let le=Zr.structUtils.stringifyIdent(ye.locator),ae=z.get(ye);ae==="decline"?v.push(le):typeof ae<"u"?Q[le]=j2(ae):A.has(ye)&&de.push(le)}await Hi.xfs.mkdirPromise(Hi.ppath.dirname(T),{recursive:!0}),await Hi.xfs.changeFilePromise(T,(0,mf.stringifySyml)(new mf.stringifySyml.PreserveOrdering({releases:Object.keys(Q).length>0?Q:void 0,declined:v.length>0?v:void 0,undecided:de.length>0?de:void 0})))}}}function xK(u){return Hy(u).size>0||_h(u).length>0}function Hy(u){let l=new Set;for(let c of u.changedWorkspaces)c.manifest.version!==null&&(u.releases.has(c)||l.add(c));return l}function _h(u,{include:l=new Set}={}){let c=[],p=new Map(Zr.miscUtils.mapAndFilter([...u.releases],([t,O])=>O==="decline"?Zr.miscUtils.mapAndFilter.skip:[t.anchoredLocator.locatorHash,t])),_=new Map(Zr.miscUtils.mapAndFilter([...u.releases],([t,O])=>O!=="decline"?Zr.miscUtils.mapAndFilter.skip:[t.anchoredLocator.locatorHash,t]));for(let t of u.project.workspaces)if(!(!l.has(t)&&(_.has(t.anchoredLocator.locatorHash)||p.has(t.anchoredLocator.locatorHash)))&&t.manifest.version!==null)for(let O of Zr.Manifest.hardDependencies)for(let M of t.manifest.getForScope(O).values()){let A=u.project.tryWorkspaceByDescriptor(M);A!==null&&p.has(A.anchoredLocator.locatorHash)&&c.push([t,A])}return c}function LD(u,l){let c=Es.default.clean(l);for(let p of Object.values(z2))if(p!=="undecided"&&p!=="decline"&&Es.default.inc(u,p)===c)return p;return null}function Wy(u,l){if(Es.default.valid(l))return l;if(u===null)throw new U2.UsageError(`Cannot apply the release strategy "${l}" unless the workspace already has a valid version`);if(!Es.default.valid(u))throw new U2.UsageError(`Cannot apply the release strategy "${l}" on a non-semver version (${u})`);let c=Es.default.inc(u,l);if(c===null)throw new U2.UsageError(`Cannot apply the release strategy "${l}" on the specified version (${u})`);return c}function bD(u,l,{report:c}){let p=new Map;for(let _ of u.workspaces)for(let t of Zr.Manifest.allDependencies)for(let O of _.manifest[t].values()){let M=u.tryWorkspaceByDescriptor(O);if(M===null||!l.has(M))continue;Zr.miscUtils.getArrayWithDefault(p,M).push([_,t,O.identHash])}for(let[_,t]of l){let O=_.manifest.version;_.manifest.version=t,Es.default.prerelease(t)===null?delete _.manifest.raw.stableVersion:_.manifest.raw.stableVersion||(_.manifest.raw.stableVersion=O);let M=_.manifest.name!==null?Zr.structUtils.stringifyIdent(_.manifest.name):null;c.reportInfo(Zr.MessageName.UNNAMED,`${Zr.structUtils.prettyLocator(u.configuration,_.anchoredLocator)}: Bumped to ${t}`),c.reportJson({cwd:Hi.npath.fromPortablePath(_.cwd),ident:M,oldVersion:O,newVersion:t});let A=p.get(_);if(!(typeof A>"u"))for(let[T,P,U]of A){let z=T.manifest[P].get(U);if(typeof z>"u")throw new Error("Assertion failed: The dependency should have existed");let Q=z.range,v=!1;if(Q.startsWith(Zr.WorkspaceResolver.protocol)&&(Q=Q.slice(Zr.WorkspaceResolver.protocol.length),v=!0,Q===_.relativeCwd))continue;let de=Q.match(CK);if(!de){c.reportWarning(Zr.MessageName.UNNAMED,`Couldn't auto-upgrade range ${Q} (in ${Zr.structUtils.prettyLocator(u.configuration,T.anchoredLocator)})`);continue}let ye=`${de[1]}${t}`;v&&(ye=`${Zr.WorkspaceResolver.protocol}${ye}`);let le=Zr.structUtils.makeDescriptor(z,ye);T.manifest[P].set(U,le)}}}var RK=new Map([["%n",{extract:u=>u.length>=1?[u[0],u.slice(1)]:null,generate:(u=0)=>`${u+1}`}]]);function x5(u,{current:l,prerelease:c}){let p=new Es.default.SemVer(l),_=p.prerelease.slice(),t=[];p.prerelease=[],p.format()!==u&&(_.length=0);let O=!0,M=c.split(/\./g);for(let A of M){let T=RK.get(A);if(typeof T>"u")t.push(A),_[0]===A?_.shift():O=!1;else{let P=O?T.extract(_):null;P!==null&&typeof P[0]=="number"?(t.push(T.generate(P[0])),_=P[1]):(t.push(T.generate()),O=!1)}}return p.prerelease&&(p.prerelease=[]),`${u}-${t.join(".")}`}var i1=class extends Vy.BaseCommand{constructor(){super(...arguments);this.all=dc.Option.Boolean("--all",!1,{description:"Apply the deferred version changes on all workspaces"});this.dryRun=dc.Option.Boolean("--dry-run",!1,{description:"Print the versions without actually generating the package archive"});this.prerelease=dc.Option.String("--prerelease",{description:"Add a prerelease identifier to new versions",tolerateBoolean:!0});this.recursive=dc.Option.Boolean("-R,--recursive",{description:"Release the transitive workspaces as well"});this.json=dc.Option.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}async execute(){let c=await W2.Configuration.find(this.context.cwd,this.context.plugins),{project:p,workspace:_}=await Gy.Project.find(c,this.context.cwd),t=await W2.Cache.find(c);if(!_)throw new Vy.WorkspaceRequiredError(p.cwd,this.context.cwd);return await p.restoreInstallState({restoreResolutions:!1}),(await Gy.StreamReport.start({configuration:c,json:this.json,stdout:this.context.stdout},async M=>{let A=this.prerelease?typeof this.prerelease!="boolean"?this.prerelease:"rc.%n":null,T=await gh(p,{prerelease:A}),P=new Map;if(this.all)P=T;else{let U=this.recursive?_.getRecursiveWorkspaceDependencies():[_];for(let z of U){let Q=T.get(z);typeof Q<"u"&&P.set(z,Q)}}if(P.size===0){let U=T.size>0?" Did you want to add --all?":"";M.reportWarning(W2.MessageName.UNNAMED,`The current workspace doesn't seem to require a version bump.${U}`);return}bD(p,P,{report:M}),this.dryRun||(A||(this.all?await ND(p):await FD(p,[...P.keys()])),M.reportSeparator(),await p.install({cache:t,report:M}))})).exitCode()}};i1.paths=[["version","apply"]],i1.usage=dc.Command.Usage({category:"Release-related commands",description:"apply all the deferred version bumps at once",details:` + This command will apply the deferred version changes and remove their definitions from the repository. + + Note that if \`--prerelease\` is set, the given prerelease identifier (by default \`rc.%d\`) will be used on all new versions and the version definitions will be kept as-is. + + By default only the current workspace will be bumped, but you can configure this behavior by using one of: + + - \`--recursive\` to also apply the version bump on its dependencies + - \`--all\` to apply the version bump on all packages in the repository + + Note that this command will also update the \`workspace:\` references across all your local workspaces, thus ensuring that they keep referring to the same workspaces even after the version bump. + `,examples:[["Apply the version change to the local workspace","yarn version apply"],["Apply the version change to all the workspaces in the local workspace","yarn version apply --all"]]});var yv=Kn("@yarnpkg/cli"),Vi=Kn("@yarnpkg/core"),Va=Kn("@yarnpkg/fslib");var Tk=pu(v1()),m1=pu(fi()),Ck=(0,m1.memo)(({active:u})=>{let l=(0,m1.useMemo)(()=>u?"\u25C9":"\u25EF",[u]),c=(0,m1.useMemo)(()=>u?"green":"yellow",[u]);return m1.default.createElement(Tk.Text,{color:c},l)});var gc=pu(v1()),el=pu(fi());var xk=pu(v1()),jg=pu(fi());function ud({active:u},l,c){let{stdin:p}=(0,xk.useStdin)(),_=(0,jg.useCallback)((t,O)=>l(t,O),c);(0,jg.useEffect)(()=>{if(!(!u||!p))return p.on("keypress",_),()=>{p.off("keypress",_)}},[u,_,p])}var Rk=function({active:u},l,c){ud({active:u},(p,_)=>{_.name==="tab"&&(_.shift?l("before"):l("after"))},c)};var zg=function(u,l,{active:c,minus:p,plus:_,set:t,loop:O=!0}){ud({active:c},(M,A)=>{let T=l.indexOf(u);switch(A.name){case p:{let P=T-1;if(O){t(l[(l.length+P)%l.length]);return}if(P<0)return;t(l[P])}break;case _:{let P=T+1;if(O){t(l[P%l.length]);return}if(P>=l.length)return;t(l[P])}break}},[l,u,_,t,O])};var q8=({active:u=!0,children:l=[],radius:c=10,size:p=1,loop:_=!0,onFocusRequest:t,willReachEnd:O})=>{let M=ye=>{if(ye.key===null)throw new Error("Expected all children to have a key");return ye.key},A=el.default.Children.map(l,ye=>M(ye)),T=A[0],[P,U]=(0,el.useState)(T),z=A.indexOf(P);(0,el.useEffect)(()=>{A.includes(P)||U(T)},[l]),(0,el.useEffect)(()=>{O&&z>=A.length-2&&O()},[z]),Rk({active:u&&!!t},ye=>{t==null||t(ye)},[t]),zg(P,A,{active:u,minus:"up",plus:"down",set:U,loop:_});let Q=z-c,v=z+c;v>A.length&&(Q-=v-A.length,v=A.length),Q<0&&(v+=-Q,Q=0),v>=A.length&&(v=A.length-1);let de=[];for(let ye=Q;ye<=v;++ye){let le=A[ye],ae=u&&le===P;de.push(el.default.createElement(gc.Box,{key:le,height:p},el.default.createElement(gc.Box,{marginLeft:1,marginRight:1},el.default.createElement(gc.Text,null,ae?el.default.createElement(gc.Text,{color:"cyan",bold:!0},">"):" ")),el.default.createElement(gc.Box,null,el.default.cloneElement(l[ye],{active:ae}))))}return el.default.createElement(gc.Box,{flexDirection:"column",width:"100%"},de)};var qg=pu(v1()),H8=pu(fi());var Ak=pu(v1()),Sf=pu(fi()),kk=Kn("readline"),oee=Sf.default.createContext(null),Ok=({children:u})=>{let{stdin:l,setRawMode:c}=(0,Ak.useStdin)();(0,Sf.useEffect)(()=>{c&&c(!0),l&&(0,kk.emitKeypressEvents)(l)},[l,c]);let[p,_]=(0,Sf.useState)(new Map),t=(0,Sf.useMemo)(()=>({getAll:()=>p,get:O=>p.get(O),set:(O,M)=>_(new Map([...p,[O,M]]))}),[p,_]);return Sf.default.createElement(oee.Provider,{value:t,children:u})};async function Mk(u,l,{stdin:c,stdout:p,stderr:_}={}){let t,O=A=>{let{exit:T}=(0,qg.useApp)();ud({active:!0},(P,U)=>{U.name==="return"&&(t=A,T())},[T,A])},{waitUntilExit:M}=(0,qg.render)(H8.default.createElement(Ok,null,H8.default.createElement(u,{...l,useSubmit:O})),{stdin:c,stdout:p,stderr:_});return await M(),t}var g1=Kn("clipanion"),qn=pu(v1()),$t=pu(fi()),Hg=pu(Kn("semver"));var y1=class extends yv.BaseCommand{constructor(){super(...arguments);this.interactive=g1.Option.Boolean("-i,--interactive",{description:"Open an interactive interface used to set version bumps"})}async execute(){return this.interactive?await this.executeInteractive():await this.executeStandard()}async executeInteractive(){let c=await Vi.Configuration.find(this.context.cwd,this.context.plugins),{project:p,workspace:_}=await Vi.Project.find(c,this.context.cwd);if(!_)throw new yv.WorkspaceRequiredError(p.cwd,this.context.cwd);await p.restoreInstallState();let t=await q2(p);if(t===null||t.releaseRoots.size===0)return 0;if(t.root===null)throw new g1.UsageError("This command can only be run on Git repositories");let O=()=>$t.default.createElement(qn.Box,{flexDirection:"row",paddingBottom:1},$t.default.createElement(qn.Box,{flexDirection:"column",width:60},$t.default.createElement(qn.Box,null,$t.default.createElement(qn.Text,null,"Press ",$t.default.createElement(qn.Text,{bold:!0,color:"cyanBright"},""),"/",$t.default.createElement(qn.Text,{bold:!0,color:"cyanBright"},"")," to select workspaces.")),$t.default.createElement(qn.Box,null,$t.default.createElement(qn.Text,null,"Press ",$t.default.createElement(qn.Text,{bold:!0,color:"cyanBright"},""),"/",$t.default.createElement(qn.Text,{bold:!0,color:"cyanBright"},"")," to select release strategies."))),$t.default.createElement(qn.Box,{flexDirection:"column"},$t.default.createElement(qn.Box,{marginLeft:1},$t.default.createElement(qn.Text,null,"Press ",$t.default.createElement(qn.Text,{bold:!0,color:"cyanBright"},"")," to save.")),$t.default.createElement(qn.Box,{marginLeft:1},$t.default.createElement(qn.Text,null,"Press ",$t.default.createElement(qn.Text,{bold:!0,color:"cyanBright"},"")," to abort.")))),M=({workspace:Q,active:v,decision:de,setDecision:ye})=>{var fe;let le=(fe=Q.manifest.raw.stableVersion)!=null?fe:Q.manifest.version;if(le===null)throw new Error(`Assertion failed: The version should have been set (${Vi.structUtils.prettyLocator(c,Q.anchoredLocator)})`);if(Hg.default.prerelease(le)!==null)throw new Error(`Assertion failed: Prerelease identifiers shouldn't be found (${le})`);let ae=["undecided","decline","patch","minor","major"];zg(de,ae,{active:v,minus:"left",plus:"right",set:ye});let Me=de==="undecided"?$t.default.createElement(qn.Text,{color:"yellow"},le):de==="decline"?$t.default.createElement(qn.Text,{color:"green"},le):$t.default.createElement(qn.Text,null,$t.default.createElement(qn.Text,{color:"magenta"},le)," \u2192 ",$t.default.createElement(qn.Text,{color:"green"},Hg.default.valid(de)?de:Hg.default.inc(le,de)));return $t.default.createElement(qn.Box,{flexDirection:"column"},$t.default.createElement(qn.Box,null,$t.default.createElement(qn.Text,null,Vi.structUtils.prettyLocator(c,Q.anchoredLocator)," - ",Me)),$t.default.createElement(qn.Box,null,ae.map(pe=>$t.default.createElement(qn.Box,{key:pe,paddingLeft:2},$t.default.createElement(qn.Text,null,$t.default.createElement(Ck,{active:pe===de})," ",pe)))))},A=Q=>{let v=new Set(t.releaseRoots),de=new Map([...Q].filter(([ye])=>v.has(ye)));for(;;){let ye=_h({project:t.project,releases:de}),le=!1;if(ye.length>0){for(let[ae]of ye)if(!v.has(ae)){v.add(ae),le=!0;let Me=Q.get(ae);typeof Me<"u"&&de.set(ae,Me)}}if(!le)break}return{relevantWorkspaces:v,relevantReleases:de}},T=()=>{let[Q,v]=(0,$t.useState)(()=>new Map(t.releases)),de=(0,$t.useCallback)((ye,le)=>{let ae=new Map(Q);le!=="undecided"?ae.set(ye,le):ae.delete(ye);let{relevantReleases:Me}=A(ae);v(Me)},[Q,v]);return[Q,de]},P=({workspaces:Q,releases:v})=>{let de=[];de.push(`${Q.size} total`);let ye=0,le=0;for(let ae of Q){let Me=v.get(ae);typeof Me>"u"?le+=1:Me!=="decline"&&(ye+=1)}return de.push(`${ye} release${ye===1?"":"s"}`),de.push(`${le} remaining`),$t.default.createElement(qn.Text,{color:"yellow"},de.join(", "))},z=await Mk(({useSubmit:Q})=>{let[v,de]=T();Q(v);let{relevantWorkspaces:ye}=A(v),le=new Set([...ye].filter(pe=>!t.releaseRoots.has(pe))),[ae,Me]=(0,$t.useState)(0),fe=(0,$t.useCallback)(pe=>{switch(pe){case"before":Me(ae-1);break;case"after":Me(ae+1);break}},[ae,Me]);return $t.default.createElement(qn.Box,{flexDirection:"column"},$t.default.createElement(O,null),$t.default.createElement(qn.Box,null,$t.default.createElement(qn.Text,{wrap:"wrap"},"The following files have been modified in your local checkout.")),$t.default.createElement(qn.Box,{flexDirection:"column",marginTop:1,paddingLeft:2},[...t.changedFiles].map(pe=>$t.default.createElement(qn.Box,{key:pe},$t.default.createElement(qn.Text,null,$t.default.createElement(qn.Text,{color:"grey"},Va.npath.fromPortablePath(t.root)),Va.npath.sep,Va.npath.relative(Va.npath.fromPortablePath(t.root),Va.npath.fromPortablePath(pe)))))),t.releaseRoots.size>0&&$t.default.createElement($t.default.Fragment,null,$t.default.createElement(qn.Box,{marginTop:1},$t.default.createElement(qn.Text,{wrap:"wrap"},"Because of those files having been modified, the following workspaces may need to be released again (note that private workspaces are also shown here, because even though they won't be published, releasing them will allow us to flag their dependents for potential re-release):")),le.size>3?$t.default.createElement(qn.Box,{marginTop:1},$t.default.createElement(P,{workspaces:t.releaseRoots,releases:v})):null,$t.default.createElement(qn.Box,{marginTop:1,flexDirection:"column"},$t.default.createElement(q8,{active:ae%2===0,radius:1,size:2,onFocusRequest:fe},[...t.releaseRoots].map(pe=>$t.default.createElement(M,{key:pe.cwd,workspace:pe,decision:v.get(pe)||"undecided",setDecision:Z=>de(pe,Z)}))))),le.size>0?$t.default.createElement($t.default.Fragment,null,$t.default.createElement(qn.Box,{marginTop:1},$t.default.createElement(qn.Text,{wrap:"wrap"},"The following workspaces depend on other workspaces that have been marked for release, and thus may need to be released as well:")),$t.default.createElement(qn.Box,null,$t.default.createElement(qn.Text,null,"(Press ",$t.default.createElement(qn.Text,{bold:!0,color:"cyanBright"},"")," to move the focus between the workspace groups.)")),le.size>5?$t.default.createElement(qn.Box,{marginTop:1},$t.default.createElement(P,{workspaces:le,releases:v})):null,$t.default.createElement(qn.Box,{marginTop:1,flexDirection:"column"},$t.default.createElement(q8,{active:ae%2===1,radius:2,size:2,onFocusRequest:fe},[...le].map(pe=>$t.default.createElement(M,{key:pe.cwd,workspace:pe,decision:v.get(pe)||"undecided",setDecision:Z=>de(pe,Z)}))))):null)},{versionFile:t},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof z>"u")return 1;t.releases.clear();for(let[Q,v]of z)t.releases.set(Q,v);await t.saveAll()}async executeStandard(){let c=await Vi.Configuration.find(this.context.cwd,this.context.plugins),{project:p,workspace:_}=await Vi.Project.find(c,this.context.cwd);if(!_)throw new yv.WorkspaceRequiredError(p.cwd,this.context.cwd);return await p.restoreInstallState(),(await Vi.StreamReport.start({configuration:c,stdout:this.context.stdout},async O=>{let M=await q2(p);if(M===null||M.releaseRoots.size===0)return;if(M.root===null)throw new g1.UsageError("This command can only be run on Git repositories");if(O.reportInfo(Vi.MessageName.UNNAMED,`Your PR was started right after ${Vi.formatUtils.pretty(c,M.baseHash.slice(0,7),"yellow")} ${Vi.formatUtils.pretty(c,M.baseTitle,"magenta")}`),M.changedFiles.size>0){O.reportInfo(Vi.MessageName.UNNAMED,"You have changed the following files since then:"),O.reportSeparator();for(let z of M.changedFiles)O.reportInfo(null,`${Vi.formatUtils.pretty(c,Va.npath.fromPortablePath(M.root),"gray")}${Va.npath.sep}${Va.npath.relative(Va.npath.fromPortablePath(M.root),Va.npath.fromPortablePath(z))}`)}let A=!1,T=!1,P=Hy(M);if(P.size>0){A||O.reportSeparator();for(let z of P)O.reportError(Vi.MessageName.UNNAMED,`${Vi.structUtils.prettyLocator(c,z.anchoredLocator)} has been modified but doesn't have a release strategy attached`);A=!0}let U=_h(M);for(let[z,Q]of U)T||O.reportSeparator(),O.reportError(Vi.MessageName.UNNAMED,`${Vi.structUtils.prettyLocator(c,z.anchoredLocator)} doesn't have a release strategy attached, but depends on ${Vi.structUtils.prettyWorkspace(c,Q)} which is planned for release.`),T=!0;(A||T)&&(O.reportSeparator(),O.reportInfo(Vi.MessageName.UNNAMED,"This command detected that at least some workspaces have received modifications without explicit instructions as to how they had to be released (if needed)."),O.reportInfo(Vi.MessageName.UNNAMED,"To correct these errors, run `yarn version check --interactive` then follow the instructions."))})).exitCode()}};y1.paths=[["version","check"]],y1.usage=g1.Command.Usage({category:"Release-related commands",description:"check that all the relevant packages have been bumped",details:"\n **Warning:** This command currently requires Git.\n\n This command will check that all the packages covered by the files listed in argument have been properly bumped or declined to bump.\n\n In the case of a bump, the check will also cover transitive packages - meaning that should `Foo` be bumped, a package `Bar` depending on `Foo` will require a decision as to whether `Bar` will need to be bumped. This check doesn't cross packages that have declined to bump.\n\n In case no arguments are passed to the function, the list of modified files will be generated by comparing the HEAD against `master`.\n ",examples:[["Check whether the modified packages need a bump","yarn version check"]]});var Vg=Kn("@yarnpkg/cli"),Gg=Kn("@yarnpkg/core"),Cs=Kn("clipanion"),Wg=pu(Kn("semver"));var _1=class extends Vg.BaseCommand{constructor(){super(...arguments);this.deferred=Cs.Option.Boolean("-d,--deferred",{description:"Prepare the version to be bumped during the next release cycle"});this.immediate=Cs.Option.Boolean("-i,--immediate",{description:"Bump the version immediately"});this.strategy=Cs.Option.String()}async execute(){let c=await Gg.Configuration.find(this.context.cwd,this.context.plugins),{project:p,workspace:_}=await Gg.Project.find(c,this.context.cwd);if(!_)throw new Vg.WorkspaceRequiredError(p.cwd,this.context.cwd);let t=c.get("preferDeferredVersions");this.deferred&&(t=!0),this.immediate&&(t=!1);let O=Wg.default.valid(this.strategy),M=this.strategy==="decline",A;if(O)if(_.manifest.version!==null){let P=LD(_.manifest.version,this.strategy);P!==null?A=P:A=this.strategy}else A=this.strategy;else{let P=_.manifest.version;if(!M){if(P===null)throw new Cs.UsageError("Can't bump the version if there wasn't a version to begin with - use 0.0.0 as initial version then run the command again.");if(typeof P!="string"||!Wg.default.valid(P))throw new Cs.UsageError(`Can't bump the version (${P}) if it's not valid semver`)}A=j2(this.strategy)}if(!t){let U=(await gh(p)).get(_);if(typeof U<"u"&&A!=="decline"){let z=Wy(_.manifest.version,A);if(Wg.default.lt(z,U))throw new Cs.UsageError(`Can't bump the version to one that would be lower than the current deferred one (${U})`)}}let T=await q2(p,{allowEmpty:!0});return T.releases.set(_,A),await T.saveAll(),t?0:await this.cli.run(["version","apply"])}};_1.paths=[["version"]],_1.usage=Cs.Command.Usage({category:"Release-related commands",description:"apply a new version to the current package",details:"\n This command will bump the version number for the given package, following the specified strategy:\n\n - If `major`, the first number from the semver range will be increased (`X.0.0`).\n - If `minor`, the second number from the semver range will be increased (`0.X.0`).\n - If `patch`, the third number from the semver range will be increased (`0.0.X`).\n - If prefixed by `pre` (`premajor`, ...), a `-0` suffix will be set (`0.0.0-0`).\n - If `prerelease`, the suffix will be increased (`0.0.0-X`); the third number from the semver range will also be increased if there was no suffix in the previous version.\n - If `decline`, the nonce will be increased for `yarn version check` to pass without version bump.\n - If a valid semver range, it will be used as new version.\n - If unspecified, Yarn will ask you for guidance.\n\n For more information about the `--deferred` flag, consult our documentation (https://yarnpkg.com/features/release-workflow#deferred-versioning).\n ",examples:[["Immediately bump the version to the next major","yarn version major"],["Prepare the version to be bumped to the next major","yarn version major --deferred"]]});var uee={configuration:{deferredVersionFolder:{description:"Folder where are stored the versioning files",type:W8.SettingsType.ABSOLUTE_PATH,default:"./.yarn/versions"},preferDeferredVersions:{description:"If true, running `yarn version` will assume the `--deferred` flag unless `--immediate` is set",type:W8.SettingsType.BOOLEAN,default:!1}},commands:[i1,y1,_1]},lee=uee;return vU(aee);})(); +/* +object-assign +(c) Sindre Sorhus +@license MIT +*/ +/** @license React v0.0.0-experimental-51a3aa6af + * react-debug-tools.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.0.0-experimental-51a3aa6af + * react-is.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.0.0-experimental-51a3aa6af + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.18.0 + * scheduler-tracing.development.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.18.0 + * scheduler-tracing.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.18.0 + * scheduler.development.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.18.0 + * scheduler.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.24.0 + * react-reconciler.development.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.24.0 + * react-reconciler.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v16.13.1 + * react.development.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v16.13.1 + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +return plugin; +} +}; diff --git a/.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs b/.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs new file mode 100644 index 000000000..b9044a014 --- /dev/null +++ b/.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs @@ -0,0 +1,28 @@ +/* eslint-disable */ +//prettier-ignore +module.exports = { +name: "@yarnpkg/plugin-workspace-tools", +factory: function (require) { +var plugin=(()=>{var wr=Object.create,me=Object.defineProperty,Sr=Object.defineProperties,vr=Object.getOwnPropertyDescriptor,Hr=Object.getOwnPropertyDescriptors,$r=Object.getOwnPropertyNames,et=Object.getOwnPropertySymbols,kr=Object.getPrototypeOf,tt=Object.prototype.hasOwnProperty,Tr=Object.prototype.propertyIsEnumerable;var rt=(e,t,r)=>t in e?me(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,B=(e,t)=>{for(var r in t||(t={}))tt.call(t,r)&&rt(e,r,t[r]);if(et)for(var r of et(t))Tr.call(t,r)&&rt(e,r,t[r]);return e},Q=(e,t)=>Sr(e,Hr(t)),Lr=e=>me(e,"__esModule",{value:!0});var K=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Or=(e,t)=>{for(var r in t)me(e,r,{get:t[r],enumerable:!0})},Nr=(e,t,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of $r(t))!tt.call(e,n)&&n!=="default"&&me(e,n,{get:()=>t[n],enumerable:!(r=vr(t,n))||r.enumerable});return e},X=e=>Nr(Lr(me(e!=null?wr(kr(e)):{},"default",e&&e.__esModule&&"default"in e?{get:()=>e.default,enumerable:!0}:{value:e,enumerable:!0})),e);var $e=K(te=>{"use strict";te.isInteger=e=>typeof e=="number"?Number.isInteger(e):typeof e=="string"&&e.trim()!==""?Number.isInteger(Number(e)):!1;te.find=(e,t)=>e.nodes.find(r=>r.type===t);te.exceedsLimit=(e,t,r=1,n)=>n===!1||!te.isInteger(e)||!te.isInteger(t)?!1:(Number(t)-Number(e))/Number(r)>=n;te.escapeNode=(e,t=0,r)=>{let n=e.nodes[t];!n||(r&&n.type===r||n.type==="open"||n.type==="close")&&n.escaped!==!0&&(n.value="\\"+n.value,n.escaped=!0)};te.encloseBrace=e=>e.type!=="brace"?!1:e.commas>>0+e.ranges>>0==0?(e.invalid=!0,!0):!1;te.isInvalidBrace=e=>e.type!=="brace"?!1:e.invalid===!0||e.dollar?!0:e.commas>>0+e.ranges>>0==0||e.open!==!0||e.close!==!0?(e.invalid=!0,!0):!1;te.isOpenOrClose=e=>e.type==="open"||e.type==="close"?!0:e.open===!0||e.close===!0;te.reduce=e=>e.reduce((t,r)=>(r.type==="text"&&t.push(r.value),r.type==="range"&&(r.type="text"),t),[]);te.flatten=(...e)=>{let t=[],r=n=>{for(let s=0;s{"use strict";var it=$e();at.exports=(e,t={})=>{let r=(n,s={})=>{let a=t.escapeInvalid&&it.isInvalidBrace(s),i=n.invalid===!0&&t.escapeInvalid===!0,o="";if(n.value)return(a||i)&&it.isOpenOrClose(n)?"\\"+n.value:n.value;if(n.value)return n.value;if(n.nodes)for(let h of n.nodes)o+=r(h);return o};return r(e)}});var ct=K((os,ot)=>{"use strict";ot.exports=function(e){return typeof e=="number"?e-e==0:typeof e=="string"&&e.trim()!==""?Number.isFinite?Number.isFinite(+e):isFinite(+e):!1}});var At=K((cs,ut)=>{"use strict";var lt=ct(),pe=(e,t,r)=>{if(lt(e)===!1)throw new TypeError("toRegexRange: expected the first argument to be a number");if(t===void 0||e===t)return String(e);if(lt(t)===!1)throw new TypeError("toRegexRange: expected the second argument to be a number.");let n=B({relaxZeros:!0},r);typeof n.strictZeros=="boolean"&&(n.relaxZeros=n.strictZeros===!1);let s=String(n.relaxZeros),a=String(n.shorthand),i=String(n.capture),o=String(n.wrap),h=e+":"+t+"="+s+a+i+o;if(pe.cache.hasOwnProperty(h))return pe.cache[h].result;let g=Math.min(e,t),f=Math.max(e,t);if(Math.abs(g-f)===1){let R=e+"|"+t;return n.capture?`(${R})`:n.wrap===!1?R:`(?:${R})`}let A=ft(e)||ft(t),p={min:e,max:t,a:g,b:f},k=[],y=[];if(A&&(p.isPadded=A,p.maxLen=String(p.max).length),g<0){let R=f<0?Math.abs(f):1;y=pt(R,Math.abs(g),p,n),g=p.a=0}return f>=0&&(k=pt(g,f,p,n)),p.negatives=y,p.positives=k,p.result=Ir(y,k,n),n.capture===!0?p.result=`(${p.result})`:n.wrap!==!1&&k.length+y.length>1&&(p.result=`(?:${p.result})`),pe.cache[h]=p,p.result};function Ir(e,t,r){let n=Pe(e,t,"-",!1,r)||[],s=Pe(t,e,"",!1,r)||[],a=Pe(e,t,"-?",!0,r)||[];return n.concat(a).concat(s).join("|")}function Mr(e,t){let r=1,n=1,s=ht(e,r),a=new Set([t]);for(;e<=s&&s<=t;)a.add(s),r+=1,s=ht(e,r);for(s=dt(t+1,n)-1;e1&&o.count.pop(),o.count.push(f.count[0]),o.string=o.pattern+gt(o.count),i=g+1;continue}r.isPadded&&(A=Gr(g,r,n)),f.string=A+f.pattern+gt(f.count),a.push(f),i=g+1,o=f}return a}function Pe(e,t,r,n,s){let a=[];for(let i of e){let{string:o}=i;!n&&!mt(t,"string",o)&&a.push(r+o),n&&mt(t,"string",o)&&a.push(r+o)}return a}function Pr(e,t){let r=[];for(let n=0;nt?1:t>e?-1:0}function mt(e,t,r){return e.some(n=>n[t]===r)}function ht(e,t){return Number(String(e).slice(0,-t)+"9".repeat(t))}function dt(e,t){return e-e%Math.pow(10,t)}function gt(e){let[t=0,r=""]=e;return r||t>1?`{${t+(r?","+r:"")}}`:""}function Dr(e,t,r){return`[${e}${t-e==1?"":"-"}${t}]`}function ft(e){return/^-?(0+)\d/.test(e)}function Gr(e,t,r){if(!t.isPadded)return e;let n=Math.abs(t.maxLen-String(e).length),s=r.relaxZeros!==!1;switch(n){case 0:return"";case 1:return s?"0?":"0";case 2:return s?"0{0,2}":"00";default:return s?`0{0,${n}}`:`0{${n}}`}}pe.cache={};pe.clearCache=()=>pe.cache={};ut.exports=pe});var Ge=K((us,Rt)=>{"use strict";var qr=require("util"),yt=At(),bt=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),Kr=e=>t=>e===!0?Number(t):String(t),De=e=>typeof e=="number"||typeof e=="string"&&e!=="",Re=e=>Number.isInteger(+e),Ue=e=>{let t=`${e}`,r=-1;if(t[0]==="-"&&(t=t.slice(1)),t==="0")return!1;for(;t[++r]==="0";);return r>0},Wr=(e,t,r)=>typeof e=="string"||typeof t=="string"?!0:r.stringify===!0,jr=(e,t,r)=>{if(t>0){let n=e[0]==="-"?"-":"";n&&(e=e.slice(1)),e=n+e.padStart(n?t-1:t,"0")}return r===!1?String(e):e},_t=(e,t)=>{let r=e[0]==="-"?"-":"";for(r&&(e=e.slice(1),t--);e.length{e.negatives.sort((i,o)=>io?1:0),e.positives.sort((i,o)=>io?1:0);let r=t.capture?"":"?:",n="",s="",a;return e.positives.length&&(n=e.positives.join("|")),e.negatives.length&&(s=`-(${r}${e.negatives.join("|")})`),n&&s?a=`${n}|${s}`:a=n||s,t.wrap?`(${r}${a})`:a},Et=(e,t,r,n)=>{if(r)return yt(e,t,B({wrap:!1},n));let s=String.fromCharCode(e);if(e===t)return s;let a=String.fromCharCode(t);return`[${s}-${a}]`},xt=(e,t,r)=>{if(Array.isArray(e)){let n=r.wrap===!0,s=r.capture?"":"?:";return n?`(${s}${e.join("|")})`:e.join("|")}return yt(e,t,r)},Ct=(...e)=>new RangeError("Invalid range arguments: "+qr.inspect(...e)),wt=(e,t,r)=>{if(r.strictRanges===!0)throw Ct([e,t]);return[]},Qr=(e,t)=>{if(t.strictRanges===!0)throw new TypeError(`Expected step "${e}" to be a number`);return[]},Xr=(e,t,r=1,n={})=>{let s=Number(e),a=Number(t);if(!Number.isInteger(s)||!Number.isInteger(a)){if(n.strictRanges===!0)throw Ct([e,t]);return[]}s===0&&(s=0),a===0&&(a=0);let i=s>a,o=String(e),h=String(t),g=String(r);r=Math.max(Math.abs(r),1);let f=Ue(o)||Ue(h)||Ue(g),A=f?Math.max(o.length,h.length,g.length):0,p=f===!1&&Wr(e,t,n)===!1,k=n.transform||Kr(p);if(n.toRegex&&r===1)return Et(_t(e,A),_t(t,A),!0,n);let y={negatives:[],positives:[]},R=T=>y[T<0?"negatives":"positives"].push(Math.abs(T)),_=[],x=0;for(;i?s>=a:s<=a;)n.toRegex===!0&&r>1?R(s):_.push(jr(k(s,x),A,p)),s=i?s-r:s+r,x++;return n.toRegex===!0?r>1?Fr(y,n):xt(_,null,B({wrap:!1},n)):_},Zr=(e,t,r=1,n={})=>{if(!Re(e)&&e.length>1||!Re(t)&&t.length>1)return wt(e,t,n);let s=n.transform||(p=>String.fromCharCode(p)),a=`${e}`.charCodeAt(0),i=`${t}`.charCodeAt(0),o=a>i,h=Math.min(a,i),g=Math.max(a,i);if(n.toRegex&&r===1)return Et(h,g,!1,n);let f=[],A=0;for(;o?a>=i:a<=i;)f.push(s(a,A)),a=o?a-r:a+r,A++;return n.toRegex===!0?xt(f,null,{wrap:!1,options:n}):f},Te=(e,t,r,n={})=>{if(t==null&&De(e))return[e];if(!De(e)||!De(t))return wt(e,t,n);if(typeof r=="function")return Te(e,t,1,{transform:r});if(bt(r))return Te(e,t,0,r);let s=B({},n);return s.capture===!0&&(s.wrap=!0),r=r||s.step||1,Re(r)?Re(e)&&Re(t)?Xr(e,t,r,s):Zr(e,t,Math.max(Math.abs(r),1),s):r!=null&&!bt(r)?Qr(r,s):Te(e,t,1,r)};Rt.exports=Te});var Ht=K((ls,St)=>{"use strict";var Yr=Ge(),vt=$e(),zr=(e,t={})=>{let r=(n,s={})=>{let a=vt.isInvalidBrace(s),i=n.invalid===!0&&t.escapeInvalid===!0,o=a===!0||i===!0,h=t.escapeInvalid===!0?"\\":"",g="";if(n.isOpen===!0||n.isClose===!0)return h+n.value;if(n.type==="open")return o?h+n.value:"(";if(n.type==="close")return o?h+n.value:")";if(n.type==="comma")return n.prev.type==="comma"?"":o?n.value:"|";if(n.value)return n.value;if(n.nodes&&n.ranges>0){let f=vt.reduce(n.nodes),A=Yr(...f,Q(B({},t),{wrap:!1,toRegex:!0}));if(A.length!==0)return f.length>1&&A.length>1?`(${A})`:A}if(n.nodes)for(let f of n.nodes)g+=r(f,n);return g};return r(e)};St.exports=zr});var Tt=K((ps,$t)=>{"use strict";var Vr=Ge(),kt=ke(),he=$e(),fe=(e="",t="",r=!1)=>{let n=[];if(e=[].concat(e),t=[].concat(t),!t.length)return e;if(!e.length)return r?he.flatten(t).map(s=>`{${s}}`):t;for(let s of e)if(Array.isArray(s))for(let a of s)n.push(fe(a,t,r));else for(let a of t)r===!0&&typeof a=="string"&&(a=`{${a}}`),n.push(Array.isArray(a)?fe(s,a,r):s+a);return he.flatten(n)},Jr=(e,t={})=>{let r=t.rangeLimit===void 0?1e3:t.rangeLimit,n=(s,a={})=>{s.queue=[];let i=a,o=a.queue;for(;i.type!=="brace"&&i.type!=="root"&&i.parent;)i=i.parent,o=i.queue;if(s.invalid||s.dollar){o.push(fe(o.pop(),kt(s,t)));return}if(s.type==="brace"&&s.invalid!==!0&&s.nodes.length===2){o.push(fe(o.pop(),["{}"]));return}if(s.nodes&&s.ranges>0){let A=he.reduce(s.nodes);if(he.exceedsLimit(...A,t.step,r))throw new RangeError("expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.");let p=Vr(...A,t);p.length===0&&(p=kt(s,t)),o.push(fe(o.pop(),p)),s.nodes=[];return}let h=he.encloseBrace(s),g=s.queue,f=s;for(;f.type!=="brace"&&f.type!=="root"&&f.parent;)f=f.parent,g=f.queue;for(let A=0;A{"use strict";Lt.exports={MAX_LENGTH:1024*64,CHAR_0:"0",CHAR_9:"9",CHAR_UPPERCASE_A:"A",CHAR_LOWERCASE_A:"a",CHAR_UPPERCASE_Z:"Z",CHAR_LOWERCASE_Z:"z",CHAR_LEFT_PARENTHESES:"(",CHAR_RIGHT_PARENTHESES:")",CHAR_ASTERISK:"*",CHAR_AMPERSAND:"&",CHAR_AT:"@",CHAR_BACKSLASH:"\\",CHAR_BACKTICK:"`",CHAR_CARRIAGE_RETURN:"\r",CHAR_CIRCUMFLEX_ACCENT:"^",CHAR_COLON:":",CHAR_COMMA:",",CHAR_DOLLAR:"$",CHAR_DOT:".",CHAR_DOUBLE_QUOTE:'"',CHAR_EQUAL:"=",CHAR_EXCLAMATION_MARK:"!",CHAR_FORM_FEED:"\f",CHAR_FORWARD_SLASH:"/",CHAR_HASH:"#",CHAR_HYPHEN_MINUS:"-",CHAR_LEFT_ANGLE_BRACKET:"<",CHAR_LEFT_CURLY_BRACE:"{",CHAR_LEFT_SQUARE_BRACKET:"[",CHAR_LINE_FEED:` +`,CHAR_NO_BREAK_SPACE:"\xA0",CHAR_PERCENT:"%",CHAR_PLUS:"+",CHAR_QUESTION_MARK:"?",CHAR_RIGHT_ANGLE_BRACKET:">",CHAR_RIGHT_CURLY_BRACE:"}",CHAR_RIGHT_SQUARE_BRACKET:"]",CHAR_SEMICOLON:";",CHAR_SINGLE_QUOTE:"'",CHAR_SPACE:" ",CHAR_TAB:" ",CHAR_UNDERSCORE:"_",CHAR_VERTICAL_LINE:"|",CHAR_ZERO_WIDTH_NOBREAK_SPACE:"\uFEFF"}});var Pt=K((hs,Nt)=>{"use strict";var en=ke(),{MAX_LENGTH:It,CHAR_BACKSLASH:qe,CHAR_BACKTICK:tn,CHAR_COMMA:rn,CHAR_DOT:nn,CHAR_LEFT_PARENTHESES:sn,CHAR_RIGHT_PARENTHESES:an,CHAR_LEFT_CURLY_BRACE:on,CHAR_RIGHT_CURLY_BRACE:cn,CHAR_LEFT_SQUARE_BRACKET:Bt,CHAR_RIGHT_SQUARE_BRACKET:Mt,CHAR_DOUBLE_QUOTE:un,CHAR_SINGLE_QUOTE:ln,CHAR_NO_BREAK_SPACE:pn,CHAR_ZERO_WIDTH_NOBREAK_SPACE:fn}=Ot(),hn=(e,t={})=>{if(typeof e!="string")throw new TypeError("Expected a string");let r=t||{},n=typeof r.maxLength=="number"?Math.min(It,r.maxLength):It;if(e.length>n)throw new SyntaxError(`Input length (${e.length}), exceeds max characters (${n})`);let s={type:"root",input:e,nodes:[]},a=[s],i=s,o=s,h=0,g=e.length,f=0,A=0,p,k={},y=()=>e[f++],R=_=>{if(_.type==="text"&&o.type==="dot"&&(o.type="text"),o&&o.type==="text"&&_.type==="text"){o.value+=_.value;return}return i.nodes.push(_),_.parent=i,_.prev=o,o=_,_};for(R({type:"bos"});f0){if(i.ranges>0){i.ranges=0;let _=i.nodes.shift();i.nodes=[_,{type:"text",value:en(i)}]}R({type:"comma",value:p}),i.commas++;continue}if(p===nn&&A>0&&i.commas===0){let _=i.nodes;if(A===0||_.length===0){R({type:"text",value:p});continue}if(o.type==="dot"){if(i.range=[],o.value+=p,o.type="range",i.nodes.length!==3&&i.nodes.length!==5){i.invalid=!0,i.ranges=0,o.type="text";continue}i.ranges++,i.args=[];continue}if(o.type==="range"){_.pop();let x=_[_.length-1];x.value+=o.value+p,o=x,i.ranges--;continue}R({type:"dot",value:p});continue}R({type:"text",value:p})}do if(i=a.pop(),i.type!=="root"){i.nodes.forEach(T=>{T.nodes||(T.type==="open"&&(T.isOpen=!0),T.type==="close"&&(T.isClose=!0),T.nodes||(T.type="text"),T.invalid=!0)});let _=a[a.length-1],x=_.nodes.indexOf(i);_.nodes.splice(x,1,...i.nodes)}while(a.length>0);return R({type:"eos"}),s};Nt.exports=hn});var Gt=K((ds,Dt)=>{"use strict";var Ut=ke(),dn=Ht(),gn=Tt(),mn=Pt(),V=(e,t={})=>{let r=[];if(Array.isArray(e))for(let n of e){let s=V.create(n,t);Array.isArray(s)?r.push(...s):r.push(s)}else r=[].concat(V.create(e,t));return t&&t.expand===!0&&t.nodupes===!0&&(r=[...new Set(r)]),r};V.parse=(e,t={})=>mn(e,t);V.stringify=(e,t={})=>typeof e=="string"?Ut(V.parse(e,t),t):Ut(e,t);V.compile=(e,t={})=>(typeof e=="string"&&(e=V.parse(e,t)),dn(e,t));V.expand=(e,t={})=>{typeof e=="string"&&(e=V.parse(e,t));let r=gn(e,t);return t.noempty===!0&&(r=r.filter(Boolean)),t.nodupes===!0&&(r=[...new Set(r)]),r};V.create=(e,t={})=>e===""||e.length<3?[e]:t.expand!==!0?V.compile(e,t):V.expand(e,t);Dt.exports=V});var ye=K((gs,qt)=>{"use strict";var An=require("path"),ie="\\\\/",Kt=`[^${ie}]`,ce="\\.",Rn="\\+",yn="\\?",Le="\\/",bn="(?=.)",Wt="[^/]",Ke=`(?:${Le}|$)`,jt=`(?:^|${Le})`,We=`${ce}{1,2}${Ke}`,_n=`(?!${ce})`,En=`(?!${jt}${We})`,xn=`(?!${ce}{0,1}${Ke})`,Cn=`(?!${We})`,wn=`[^.${Le}]`,Sn=`${Wt}*?`,Ft={DOT_LITERAL:ce,PLUS_LITERAL:Rn,QMARK_LITERAL:yn,SLASH_LITERAL:Le,ONE_CHAR:bn,QMARK:Wt,END_ANCHOR:Ke,DOTS_SLASH:We,NO_DOT:_n,NO_DOTS:En,NO_DOT_SLASH:xn,NO_DOTS_SLASH:Cn,QMARK_NO_DOT:wn,STAR:Sn,START_ANCHOR:jt},vn=Q(B({},Ft),{SLASH_LITERAL:`[${ie}]`,QMARK:Kt,STAR:`${Kt}*?`,DOTS_SLASH:`${ce}{1,2}(?:[${ie}]|$)`,NO_DOT:`(?!${ce})`,NO_DOTS:`(?!(?:^|[${ie}])${ce}{1,2}(?:[${ie}]|$))`,NO_DOT_SLASH:`(?!${ce}{0,1}(?:[${ie}]|$))`,NO_DOTS_SLASH:`(?!${ce}{1,2}(?:[${ie}]|$))`,QMARK_NO_DOT:`[^.${ie}]`,START_ANCHOR:`(?:^|[${ie}])`,END_ANCHOR:`(?:[${ie}]|$)`}),Hn={alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\\x00-\\x7F",blank:" \\t",cntrl:"\\x00-\\x1F\\x7F",digit:"0-9",graph:"\\x21-\\x7E",lower:"a-z",print:"\\x20-\\x7E ",punct:"\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~",space:" \\t\\r\\n\\v\\f",upper:"A-Z",word:"A-Za-z0-9_",xdigit:"A-Fa-f0-9"};qt.exports={MAX_LENGTH:1024*64,POSIX_REGEX_SOURCE:Hn,REGEX_BACKSLASH:/\\(?![*+?^${}(|)[\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\].,$*+?^{}()|\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\?)((\W)(\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\[.*?[^\\]\]|\\(?=.))/g,REPLACEMENTS:{"***":"*","**/**":"**","**/**/**":"**"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,SEP:An.sep,extglobChars(e){return{"!":{type:"negate",open:"(?:(?!(?:",close:`))${e.STAR})`},"?":{type:"qmark",open:"(?:",close:")?"},"+":{type:"plus",open:"(?:",close:")+"},"*":{type:"star",open:"(?:",close:")*"},"@":{type:"at",open:"(?:",close:")"}}},globChars(e){return e===!0?vn:Ft}}});var be=K(Z=>{"use strict";var $n=require("path"),kn=process.platform==="win32",{REGEX_BACKSLASH:Tn,REGEX_REMOVE_BACKSLASH:Ln,REGEX_SPECIAL_CHARS:On,REGEX_SPECIAL_CHARS_GLOBAL:Nn}=ye();Z.isObject=e=>e!==null&&typeof e=="object"&&!Array.isArray(e);Z.hasRegexChars=e=>On.test(e);Z.isRegexChar=e=>e.length===1&&Z.hasRegexChars(e);Z.escapeRegex=e=>e.replace(Nn,"\\$1");Z.toPosixSlashes=e=>e.replace(Tn,"/");Z.removeBackslashes=e=>e.replace(Ln,t=>t==="\\"?"":t);Z.supportsLookbehinds=()=>{let e=process.version.slice(1).split(".").map(Number);return e.length===3&&e[0]>=9||e[0]===8&&e[1]>=10};Z.isWindows=e=>e&&typeof e.windows=="boolean"?e.windows:kn===!0||$n.sep==="\\";Z.escapeLast=(e,t,r)=>{let n=e.lastIndexOf(t,r);return n===-1?e:e[n-1]==="\\"?Z.escapeLast(e,t,n-1):`${e.slice(0,n)}\\${e.slice(n)}`};Z.removePrefix=(e,t={})=>{let r=e;return r.startsWith("./")&&(r=r.slice(2),t.prefix="./"),r};Z.wrapOutput=(e,t={},r={})=>{let n=r.contains?"":"^",s=r.contains?"":"$",a=`${n}(?:${e})${s}`;return t.negated===!0&&(a=`(?:^(?!${a}).*$)`),a}});var er=K((As,Qt)=>{"use strict";var Xt=be(),{CHAR_ASTERISK:je,CHAR_AT:In,CHAR_BACKWARD_SLASH:_e,CHAR_COMMA:Bn,CHAR_DOT:Fe,CHAR_EXCLAMATION_MARK:Qe,CHAR_FORWARD_SLASH:Zt,CHAR_LEFT_CURLY_BRACE:Xe,CHAR_LEFT_PARENTHESES:Ze,CHAR_LEFT_SQUARE_BRACKET:Mn,CHAR_PLUS:Pn,CHAR_QUESTION_MARK:Yt,CHAR_RIGHT_CURLY_BRACE:Dn,CHAR_RIGHT_PARENTHESES:zt,CHAR_RIGHT_SQUARE_BRACKET:Un}=ye(),Vt=e=>e===Zt||e===_e,Jt=e=>{e.isPrefix!==!0&&(e.depth=e.isGlobstar?Infinity:1)},Gn=(e,t)=>{let r=t||{},n=e.length-1,s=r.parts===!0||r.scanToEnd===!0,a=[],i=[],o=[],h=e,g=-1,f=0,A=0,p=!1,k=!1,y=!1,R=!1,_=!1,x=!1,T=!1,O=!1,W=!1,G=!1,ne=0,E,b,C={value:"",depth:0,isGlob:!1},M=()=>g>=n,l=()=>h.charCodeAt(g+1),H=()=>(E=b,h.charCodeAt(++g));for(;g0&&(j=h.slice(0,f),h=h.slice(f),A-=f),w&&y===!0&&A>0?(w=h.slice(0,A),c=h.slice(A)):y===!0?(w="",c=h):w=h,w&&w!==""&&w!=="/"&&w!==h&&Vt(w.charCodeAt(w.length-1))&&(w=w.slice(0,-1)),r.unescape===!0&&(c&&(c=Xt.removeBackslashes(c)),w&&T===!0&&(w=Xt.removeBackslashes(w)));let u={prefix:j,input:e,start:f,base:w,glob:c,isBrace:p,isBracket:k,isGlob:y,isExtglob:R,isGlobstar:_,negated:O,negatedExtglob:W};if(r.tokens===!0&&(u.maxDepth=0,Vt(b)||i.push(C),u.tokens=i),r.parts===!0||r.tokens===!0){let I;for(let $=0;${"use strict";var Oe=ye(),J=be(),{MAX_LENGTH:Ne,POSIX_REGEX_SOURCE:qn,REGEX_NON_SPECIAL_CHARS:Kn,REGEX_SPECIAL_CHARS_BACKREF:Wn,REPLACEMENTS:rr}=Oe,jn=(e,t)=>{if(typeof t.expandRange=="function")return t.expandRange(...e,t);e.sort();let r=`[${e.join("-")}]`;try{new RegExp(r)}catch(n){return e.map(s=>J.escapeRegex(s)).join("..")}return r},de=(e,t)=>`Missing ${e}: "${t}" - use "\\\\${t}" to match literal characters`,nr=(e,t)=>{if(typeof e!="string")throw new TypeError("Expected a string");e=rr[e]||e;let r=B({},t),n=typeof r.maxLength=="number"?Math.min(Ne,r.maxLength):Ne,s=e.length;if(s>n)throw new SyntaxError(`Input length: ${s}, exceeds maximum allowed length: ${n}`);let a={type:"bos",value:"",output:r.prepend||""},i=[a],o=r.capture?"":"?:",h=J.isWindows(t),g=Oe.globChars(h),f=Oe.extglobChars(g),{DOT_LITERAL:A,PLUS_LITERAL:p,SLASH_LITERAL:k,ONE_CHAR:y,DOTS_SLASH:R,NO_DOT:_,NO_DOT_SLASH:x,NO_DOTS_SLASH:T,QMARK:O,QMARK_NO_DOT:W,STAR:G,START_ANCHOR:ne}=g,E=m=>`(${o}(?:(?!${ne}${m.dot?R:A}).)*?)`,b=r.dot?"":_,C=r.dot?O:W,M=r.bash===!0?E(r):G;r.capture&&(M=`(${M})`),typeof r.noext=="boolean"&&(r.noextglob=r.noext);let l={input:e,index:-1,start:0,dot:r.dot===!0,consumed:"",output:"",prefix:"",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens:i};e=J.removePrefix(e,l),s=e.length;let H=[],w=[],j=[],c=a,u,I=()=>l.index===s-1,$=l.peek=(m=1)=>e[l.index+m],ee=l.advance=()=>e[++l.index]||"",se=()=>e.slice(l.index+1),z=(m="",L=0)=>{l.consumed+=m,l.index+=L},Ce=m=>{l.output+=m.output!=null?m.output:m.value,z(m.value)},xr=()=>{let m=1;for(;$()==="!"&&($(2)!=="("||$(3)==="?");)ee(),l.start++,m++;return m%2==0?!1:(l.negated=!0,l.start++,!0)},we=m=>{l[m]++,j.push(m)},ue=m=>{l[m]--,j.pop()},v=m=>{if(c.type==="globstar"){let L=l.braces>0&&(m.type==="comma"||m.type==="brace"),d=m.extglob===!0||H.length&&(m.type==="pipe"||m.type==="paren");m.type!=="slash"&&m.type!=="paren"&&!L&&!d&&(l.output=l.output.slice(0,-c.output.length),c.type="star",c.value="*",c.output=M,l.output+=c.output)}if(H.length&&m.type!=="paren"&&(H[H.length-1].inner+=m.value),(m.value||m.output)&&Ce(m),c&&c.type==="text"&&m.type==="text"){c.value+=m.value,c.output=(c.output||"")+m.value;return}m.prev=c,i.push(m),c=m},Se=(m,L)=>{let d=Q(B({},f[L]),{conditions:1,inner:""});d.prev=c,d.parens=l.parens,d.output=l.output;let S=(r.capture?"(":"")+d.open;we("parens"),v({type:m,value:L,output:l.output?"":y}),v({type:"paren",extglob:!0,value:ee(),output:S}),H.push(d)},Cr=m=>{let L=m.close+(r.capture?")":""),d;if(m.type==="negate"){let S=M;m.inner&&m.inner.length>1&&m.inner.includes("/")&&(S=E(r)),(S!==M||I()||/^\)+$/.test(se()))&&(L=m.close=`)$))${S}`),m.inner.includes("*")&&(d=se())&&/^\.[^\\/.]+$/.test(d)&&(L=m.close=`)${d})${S})`),m.prev.type==="bos"&&(l.negatedExtglob=!0)}v({type:"paren",extglob:!0,value:u,output:L}),ue("parens")};if(r.fastpaths!==!1&&!/(^[*!]|[/()[\]{}"])/.test(e)){let m=!1,L=e.replace(Wn,(d,S,P,F,q,Me)=>F==="\\"?(m=!0,d):F==="?"?S?S+F+(q?O.repeat(q.length):""):Me===0?C+(q?O.repeat(q.length):""):O.repeat(P.length):F==="."?A.repeat(P.length):F==="*"?S?S+F+(q?M:""):M:S?d:`\\${d}`);return m===!0&&(r.unescape===!0?L=L.replace(/\\/g,""):L=L.replace(/\\+/g,d=>d.length%2==0?"\\\\":d?"\\":"")),L===e&&r.contains===!0?(l.output=e,l):(l.output=J.wrapOutput(L,l,t),l)}for(;!I();){if(u=ee(),u==="\0")continue;if(u==="\\"){let d=$();if(d==="/"&&r.bash!==!0||d==="."||d===";")continue;if(!d){u+="\\",v({type:"text",value:u});continue}let S=/^\\+/.exec(se()),P=0;if(S&&S[0].length>2&&(P=S[0].length,l.index+=P,P%2!=0&&(u+="\\")),r.unescape===!0?u=ee():u+=ee(),l.brackets===0){v({type:"text",value:u});continue}}if(l.brackets>0&&(u!=="]"||c.value==="["||c.value==="[^")){if(r.posix!==!1&&u===":"){let d=c.value.slice(1);if(d.includes("[")&&(c.posix=!0,d.includes(":"))){let S=c.value.lastIndexOf("["),P=c.value.slice(0,S),F=c.value.slice(S+2),q=qn[F];if(q){c.value=P+q,l.backtrack=!0,ee(),!a.output&&i.indexOf(c)===1&&(a.output=y);continue}}}(u==="["&&$()!==":"||u==="-"&&$()==="]")&&(u=`\\${u}`),u==="]"&&(c.value==="["||c.value==="[^")&&(u=`\\${u}`),r.posix===!0&&u==="!"&&c.value==="["&&(u="^"),c.value+=u,Ce({value:u});continue}if(l.quotes===1&&u!=='"'){u=J.escapeRegex(u),c.value+=u,Ce({value:u});continue}if(u==='"'){l.quotes=l.quotes===1?0:1,r.keepQuotes===!0&&v({type:"text",value:u});continue}if(u==="("){we("parens"),v({type:"paren",value:u});continue}if(u===")"){if(l.parens===0&&r.strictBrackets===!0)throw new SyntaxError(de("opening","("));let d=H[H.length-1];if(d&&l.parens===d.parens+1){Cr(H.pop());continue}v({type:"paren",value:u,output:l.parens?")":"\\)"}),ue("parens");continue}if(u==="["){if(r.nobracket===!0||!se().includes("]")){if(r.nobracket!==!0&&r.strictBrackets===!0)throw new SyntaxError(de("closing","]"));u=`\\${u}`}else we("brackets");v({type:"bracket",value:u});continue}if(u==="]"){if(r.nobracket===!0||c&&c.type==="bracket"&&c.value.length===1){v({type:"text",value:u,output:`\\${u}`});continue}if(l.brackets===0){if(r.strictBrackets===!0)throw new SyntaxError(de("opening","["));v({type:"text",value:u,output:`\\${u}`});continue}ue("brackets");let d=c.value.slice(1);if(c.posix!==!0&&d[0]==="^"&&!d.includes("/")&&(u=`/${u}`),c.value+=u,Ce({value:u}),r.literalBrackets===!1||J.hasRegexChars(d))continue;let S=J.escapeRegex(c.value);if(l.output=l.output.slice(0,-c.value.length),r.literalBrackets===!0){l.output+=S,c.value=S;continue}c.value=`(${o}${S}|${c.value})`,l.output+=c.value;continue}if(u==="{"&&r.nobrace!==!0){we("braces");let d={type:"brace",value:u,output:"(",outputIndex:l.output.length,tokensIndex:l.tokens.length};w.push(d),v(d);continue}if(u==="}"){let d=w[w.length-1];if(r.nobrace===!0||!d){v({type:"text",value:u,output:u});continue}let S=")";if(d.dots===!0){let P=i.slice(),F=[];for(let q=P.length-1;q>=0&&(i.pop(),P[q].type!=="brace");q--)P[q].type!=="dots"&&F.unshift(P[q].value);S=jn(F,r),l.backtrack=!0}if(d.comma!==!0&&d.dots!==!0){let P=l.output.slice(0,d.outputIndex),F=l.tokens.slice(d.tokensIndex);d.value=d.output="\\{",u=S="\\}",l.output=P;for(let q of F)l.output+=q.output||q.value}v({type:"brace",value:u,output:S}),ue("braces"),w.pop();continue}if(u==="|"){H.length>0&&H[H.length-1].conditions++,v({type:"text",value:u});continue}if(u===","){let d=u,S=w[w.length-1];S&&j[j.length-1]==="braces"&&(S.comma=!0,d="|"),v({type:"comma",value:u,output:d});continue}if(u==="/"){if(c.type==="dot"&&l.index===l.start+1){l.start=l.index+1,l.consumed="",l.output="",i.pop(),c=a;continue}v({type:"slash",value:u,output:k});continue}if(u==="."){if(l.braces>0&&c.type==="dot"){c.value==="."&&(c.output=A);let d=w[w.length-1];c.type="dots",c.output+=u,c.value+=u,d.dots=!0;continue}if(l.braces+l.parens===0&&c.type!=="bos"&&c.type!=="slash"){v({type:"text",value:u,output:A});continue}v({type:"dot",value:u,output:A});continue}if(u==="?"){if(!(c&&c.value==="(")&&r.noextglob!==!0&&$()==="("&&$(2)!=="?"){Se("qmark",u);continue}if(c&&c.type==="paren"){let S=$(),P=u;if(S==="<"&&!J.supportsLookbehinds())throw new Error("Node.js v10 or higher is required for regex lookbehinds");(c.value==="("&&!/[!=<:]/.test(S)||S==="<"&&!/<([!=]|\w+>)/.test(se()))&&(P=`\\${u}`),v({type:"text",value:u,output:P});continue}if(r.dot!==!0&&(c.type==="slash"||c.type==="bos")){v({type:"qmark",value:u,output:W});continue}v({type:"qmark",value:u,output:O});continue}if(u==="!"){if(r.noextglob!==!0&&$()==="("&&($(2)!=="?"||!/[!=<:]/.test($(3)))){Se("negate",u);continue}if(r.nonegate!==!0&&l.index===0){xr();continue}}if(u==="+"){if(r.noextglob!==!0&&$()==="("&&$(2)!=="?"){Se("plus",u);continue}if(c&&c.value==="("||r.regex===!1){v({type:"plus",value:u,output:p});continue}if(c&&(c.type==="bracket"||c.type==="paren"||c.type==="brace")||l.parens>0){v({type:"plus",value:u});continue}v({type:"plus",value:p});continue}if(u==="@"){if(r.noextglob!==!0&&$()==="("&&$(2)!=="?"){v({type:"at",extglob:!0,value:u,output:""});continue}v({type:"text",value:u});continue}if(u!=="*"){(u==="$"||u==="^")&&(u=`\\${u}`);let d=Kn.exec(se());d&&(u+=d[0],l.index+=d[0].length),v({type:"text",value:u});continue}if(c&&(c.type==="globstar"||c.star===!0)){c.type="star",c.star=!0,c.value+=u,c.output=M,l.backtrack=!0,l.globstar=!0,z(u);continue}let m=se();if(r.noextglob!==!0&&/^\([^?]/.test(m)){Se("star",u);continue}if(c.type==="star"){if(r.noglobstar===!0){z(u);continue}let d=c.prev,S=d.prev,P=d.type==="slash"||d.type==="bos",F=S&&(S.type==="star"||S.type==="globstar");if(r.bash===!0&&(!P||m[0]&&m[0]!=="/")){v({type:"star",value:u,output:""});continue}let q=l.braces>0&&(d.type==="comma"||d.type==="brace"),Me=H.length&&(d.type==="pipe"||d.type==="paren");if(!P&&d.type!=="paren"&&!q&&!Me){v({type:"star",value:u,output:""});continue}for(;m.slice(0,3)==="/**";){let ve=e[l.index+4];if(ve&&ve!=="/")break;m=m.slice(3),z("/**",3)}if(d.type==="bos"&&I()){c.type="globstar",c.value+=u,c.output=E(r),l.output=c.output,l.globstar=!0,z(u);continue}if(d.type==="slash"&&d.prev.type!=="bos"&&!F&&I()){l.output=l.output.slice(0,-(d.output+c.output).length),d.output=`(?:${d.output}`,c.type="globstar",c.output=E(r)+(r.strictSlashes?")":"|$)"),c.value+=u,l.globstar=!0,l.output+=d.output+c.output,z(u);continue}if(d.type==="slash"&&d.prev.type!=="bos"&&m[0]==="/"){let ve=m[1]!==void 0?"|$":"";l.output=l.output.slice(0,-(d.output+c.output).length),d.output=`(?:${d.output}`,c.type="globstar",c.output=`${E(r)}${k}|${k}${ve})`,c.value+=u,l.output+=d.output+c.output,l.globstar=!0,z(u+ee()),v({type:"slash",value:"/",output:""});continue}if(d.type==="bos"&&m[0]==="/"){c.type="globstar",c.value+=u,c.output=`(?:^|${k}|${E(r)}${k})`,l.output=c.output,l.globstar=!0,z(u+ee()),v({type:"slash",value:"/",output:""});continue}l.output=l.output.slice(0,-c.output.length),c.type="globstar",c.output=E(r),c.value+=u,l.output+=c.output,l.globstar=!0,z(u);continue}let L={type:"star",value:u,output:M};if(r.bash===!0){L.output=".*?",(c.type==="bos"||c.type==="slash")&&(L.output=b+L.output),v(L);continue}if(c&&(c.type==="bracket"||c.type==="paren")&&r.regex===!0){L.output=u,v(L);continue}(l.index===l.start||c.type==="slash"||c.type==="dot")&&(c.type==="dot"?(l.output+=x,c.output+=x):r.dot===!0?(l.output+=T,c.output+=T):(l.output+=b,c.output+=b),$()!=="*"&&(l.output+=y,c.output+=y)),v(L)}for(;l.brackets>0;){if(r.strictBrackets===!0)throw new SyntaxError(de("closing","]"));l.output=J.escapeLast(l.output,"["),ue("brackets")}for(;l.parens>0;){if(r.strictBrackets===!0)throw new SyntaxError(de("closing",")"));l.output=J.escapeLast(l.output,"("),ue("parens")}for(;l.braces>0;){if(r.strictBrackets===!0)throw new SyntaxError(de("closing","}"));l.output=J.escapeLast(l.output,"{"),ue("braces")}if(r.strictSlashes!==!0&&(c.type==="star"||c.type==="bracket")&&v({type:"maybe_slash",value:"",output:`${k}?`}),l.backtrack===!0){l.output="";for(let m of l.tokens)l.output+=m.output!=null?m.output:m.value,m.suffix&&(l.output+=m.suffix)}return l};nr.fastpaths=(e,t)=>{let r=B({},t),n=typeof r.maxLength=="number"?Math.min(Ne,r.maxLength):Ne,s=e.length;if(s>n)throw new SyntaxError(`Input length: ${s}, exceeds maximum allowed length: ${n}`);e=rr[e]||e;let a=J.isWindows(t),{DOT_LITERAL:i,SLASH_LITERAL:o,ONE_CHAR:h,DOTS_SLASH:g,NO_DOT:f,NO_DOTS:A,NO_DOTS_SLASH:p,STAR:k,START_ANCHOR:y}=Oe.globChars(a),R=r.dot?A:f,_=r.dot?p:f,x=r.capture?"":"?:",T={negated:!1,prefix:""},O=r.bash===!0?".*?":k;r.capture&&(O=`(${O})`);let W=b=>b.noglobstar===!0?O:`(${x}(?:(?!${y}${b.dot?g:i}).)*?)`,G=b=>{switch(b){case"*":return`${R}${h}${O}`;case".*":return`${i}${h}${O}`;case"*.*":return`${R}${O}${i}${h}${O}`;case"*/*":return`${R}${O}${o}${h}${_}${O}`;case"**":return R+W(r);case"**/*":return`(?:${R}${W(r)}${o})?${_}${h}${O}`;case"**/*.*":return`(?:${R}${W(r)}${o})?${_}${O}${i}${h}${O}`;case"**/.*":return`(?:${R}${W(r)}${o})?${i}${h}${O}`;default:{let C=/^(.*?)\.(\w+)$/.exec(b);if(!C)return;let M=G(C[1]);return M?M+i+C[2]:void 0}}},ne=J.removePrefix(e,T),E=G(ne);return E&&r.strictSlashes!==!0&&(E+=`${o}?`),E};tr.exports=nr});var ir=K((ys,ar)=>{"use strict";var Fn=require("path"),Qn=er(),Ye=sr(),ze=be(),Xn=ye(),Zn=e=>e&&typeof e=="object"&&!Array.isArray(e),D=(e,t,r=!1)=>{if(Array.isArray(e)){let f=e.map(p=>D(p,t,r));return p=>{for(let k of f){let y=k(p);if(y)return y}return!1}}let n=Zn(e)&&e.tokens&&e.input;if(e===""||typeof e!="string"&&!n)throw new TypeError("Expected pattern to be a non-empty string");let s=t||{},a=ze.isWindows(t),i=n?D.compileRe(e,t):D.makeRe(e,t,!1,!0),o=i.state;delete i.state;let h=()=>!1;if(s.ignore){let f=Q(B({},t),{ignore:null,onMatch:null,onResult:null});h=D(s.ignore,f,r)}let g=(f,A=!1)=>{let{isMatch:p,match:k,output:y}=D.test(f,i,t,{glob:e,posix:a}),R={glob:e,state:o,regex:i,posix:a,input:f,output:y,match:k,isMatch:p};return typeof s.onResult=="function"&&s.onResult(R),p===!1?(R.isMatch=!1,A?R:!1):h(f)?(typeof s.onIgnore=="function"&&s.onIgnore(R),R.isMatch=!1,A?R:!1):(typeof s.onMatch=="function"&&s.onMatch(R),A?R:!0)};return r&&(g.state=o),g};D.test=(e,t,r,{glob:n,posix:s}={})=>{if(typeof e!="string")throw new TypeError("Expected input to be a string");if(e==="")return{isMatch:!1,output:""};let a=r||{},i=a.format||(s?ze.toPosixSlashes:null),o=e===n,h=o&&i?i(e):e;return o===!1&&(h=i?i(e):e,o=h===n),(o===!1||a.capture===!0)&&(a.matchBase===!0||a.basename===!0?o=D.matchBase(e,t,r,s):o=t.exec(h)),{isMatch:Boolean(o),match:o,output:h}};D.matchBase=(e,t,r,n=ze.isWindows(r))=>(t instanceof RegExp?t:D.makeRe(t,r)).test(Fn.basename(e));D.isMatch=(e,t,r)=>D(t,r)(e);D.parse=(e,t)=>Array.isArray(e)?e.map(r=>D.parse(r,t)):Ye(e,Q(B({},t),{fastpaths:!1}));D.scan=(e,t)=>Qn(e,t);D.compileRe=(e,t,r=!1,n=!1)=>{if(r===!0)return e.output;let s=t||{},a=s.contains?"":"^",i=s.contains?"":"$",o=`${a}(?:${e.output})${i}`;e&&e.negated===!0&&(o=`^(?!${o}).*$`);let h=D.toRegex(o,t);return n===!0&&(h.state=e),h};D.makeRe=(e,t={},r=!1,n=!1)=>{if(!e||typeof e!="string")throw new TypeError("Expected a non-empty string");let s={negated:!1,fastpaths:!0};return t.fastpaths!==!1&&(e[0]==="."||e[0]==="*")&&(s.output=Ye.fastpaths(e,t)),s.output||(s=Ye(e,t)),D.compileRe(s,t,r,n)};D.toRegex=(e,t)=>{try{let r=t||{};return new RegExp(e,r.flags||(r.nocase?"i":""))}catch(r){if(t&&t.debug===!0)throw r;return/$^/}};D.constants=Xn;ar.exports=D});var cr=K((bs,or)=>{"use strict";or.exports=ir()});var hr=K((_s,ur)=>{"use strict";var lr=require("util"),pr=Gt(),oe=cr(),Ve=be(),fr=e=>e===""||e==="./",N=(e,t,r)=>{t=[].concat(t),e=[].concat(e);let n=new Set,s=new Set,a=new Set,i=0,o=f=>{a.add(f.output),r&&r.onResult&&r.onResult(f)};for(let f=0;f!n.has(f));if(r&&g.length===0){if(r.failglob===!0)throw new Error(`No matches found for "${t.join(", ")}"`);if(r.nonull===!0||r.nullglob===!0)return r.unescape?t.map(f=>f.replace(/\\/g,"")):t}return g};N.match=N;N.matcher=(e,t)=>oe(e,t);N.isMatch=(e,t,r)=>oe(t,r)(e);N.any=N.isMatch;N.not=(e,t,r={})=>{t=[].concat(t).map(String);let n=new Set,s=[],a=o=>{r.onResult&&r.onResult(o),s.push(o.output)},i=N(e,t,Q(B({},r),{onResult:a}));for(let o of s)i.includes(o)||n.add(o);return[...n]};N.contains=(e,t,r)=>{if(typeof e!="string")throw new TypeError(`Expected a string: "${lr.inspect(e)}"`);if(Array.isArray(t))return t.some(n=>N.contains(e,n,r));if(typeof t=="string"){if(fr(e)||fr(t))return!1;if(e.includes(t)||e.startsWith("./")&&e.slice(2).includes(t))return!0}return N.isMatch(e,t,Q(B({},r),{contains:!0}))};N.matchKeys=(e,t,r)=>{if(!Ve.isObject(e))throw new TypeError("Expected the first argument to be an object");let n=N(Object.keys(e),t,r),s={};for(let a of n)s[a]=e[a];return s};N.some=(e,t,r)=>{let n=[].concat(e);for(let s of[].concat(t)){let a=oe(String(s),r);if(n.some(i=>a(i)))return!0}return!1};N.every=(e,t,r)=>{let n=[].concat(e);for(let s of[].concat(t)){let a=oe(String(s),r);if(!n.every(i=>a(i)))return!1}return!0};N.all=(e,t,r)=>{if(typeof e!="string")throw new TypeError(`Expected a string: "${lr.inspect(e)}"`);return[].concat(t).every(n=>oe(n,r)(e))};N.capture=(e,t,r)=>{let n=Ve.isWindows(r),a=oe.makeRe(String(e),Q(B({},r),{capture:!0})).exec(n?Ve.toPosixSlashes(t):t);if(a)return a.slice(1).map(i=>i===void 0?"":i)};N.makeRe=(...e)=>oe.makeRe(...e);N.scan=(...e)=>oe.scan(...e);N.parse=(e,t)=>{let r=[];for(let n of[].concat(e||[]))for(let s of pr(String(n),t))r.push(oe.parse(s,t));return r};N.braces=(e,t)=>{if(typeof e!="string")throw new TypeError("Expected a string");return t&&t.nobrace===!0||!/\{.*\}/.test(e)?[e]:pr(e,t)};N.braceExpand=(e,t)=>{if(typeof e!="string")throw new TypeError("Expected a string");return N.braces(e,Q(B({},t),{expand:!0}))};ur.exports=N});var gr=K((Es,dr)=>{"use strict";dr.exports=(e,...t)=>new Promise(r=>{r(e(...t))})});var Ar=K((xs,Je)=>{"use strict";var Yn=gr(),mr=e=>{if(e<1)throw new TypeError("Expected `concurrency` to be a number from 1 and up");let t=[],r=0,n=()=>{r--,t.length>0&&t.shift()()},s=(o,h,...g)=>{r++;let f=Yn(o,...g);h(f),f.then(n,n)},a=(o,h,...g)=>{rnew Promise(g=>a(o,g,...h));return Object.defineProperties(i,{activeCount:{get:()=>r},pendingCount:{get:()=>t.length}}),i};Je.exports=mr;Je.exports.default=mr});var Vn={};Or(Vn,{default:()=>es});var He=X(require("@yarnpkg/cli")),ae=X(require("@yarnpkg/core")),nt=X(require("@yarnpkg/core")),le=X(require("clipanion")),Ae=class extends He.BaseCommand{constructor(){super(...arguments);this.json=le.Option.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.production=le.Option.Boolean("--production",!1,{description:"Only install regular dependencies by omitting dev dependencies"});this.all=le.Option.Boolean("-A,--all",!1,{description:"Install the entire project"});this.workspaces=le.Option.Rest()}async execute(){let t=await ae.Configuration.find(this.context.cwd,this.context.plugins),{project:r,workspace:n}=await ae.Project.find(t,this.context.cwd),s=await ae.Cache.find(t);await r.restoreInstallState({restoreResolutions:!1});let a;if(this.all)a=new Set(r.workspaces);else if(this.workspaces.length===0){if(!n)throw new He.WorkspaceRequiredError(r.cwd,this.context.cwd);a=new Set([n])}else a=new Set(this.workspaces.map(o=>r.getWorkspaceByIdent(nt.structUtils.parseIdent(o))));for(let o of a)for(let h of this.production?["dependencies"]:ae.Manifest.hardDependencies)for(let g of o.manifest.getForScope(h).values()){let f=r.tryWorkspaceByDescriptor(g);f!==null&&a.add(f)}for(let o of r.workspaces)a.has(o)?this.production&&o.manifest.devDependencies.clear():(o.manifest.installConfig=o.manifest.installConfig||{},o.manifest.installConfig.selfReferences=!1,o.manifest.dependencies.clear(),o.manifest.devDependencies.clear(),o.manifest.peerDependencies.clear(),o.manifest.scripts.clear());return(await ae.StreamReport.start({configuration:t,json:this.json,stdout:this.context.stdout,includeLogs:!0},async o=>{await r.install({cache:s,report:o,persistProject:!1})})).exitCode()}};Ae.paths=[["workspaces","focus"]],Ae.usage=le.Command.Usage({category:"Workspace-related commands",description:"install a single workspace and its dependencies",details:"\n This command will run an install as if the specified workspaces (and all other workspaces they depend on) were the only ones in the project. If no workspaces are explicitly listed, the active one will be assumed.\n\n Note that this command is only very moderately useful when using zero-installs, since the cache will contain all the packages anyway - meaning that the only difference between a full install and a focused install would just be a few extra lines in the `.pnp.cjs` file, at the cost of introducing an extra complexity.\n\n If the `-A,--all` flag is set, the entire project will be installed. Combine with `--production` to replicate the old `yarn install --production`.\n "});var st=Ae;var Ie=X(require("@yarnpkg/cli")),ge=X(require("@yarnpkg/core")),Ee=X(require("@yarnpkg/core")),Y=X(require("@yarnpkg/core")),Rr=X(require("@yarnpkg/plugin-git")),U=X(require("clipanion")),Be=X(hr()),yr=X(require("os")),br=X(Ar()),re=X(require("typanion")),xe=class extends Ie.BaseCommand{constructor(){super(...arguments);this.recursive=U.Option.Boolean("-R,--recursive",!1,{description:"Find packages via dependencies/devDependencies instead of using the workspaces field"});this.from=U.Option.Array("--from",[],{description:"An array of glob pattern idents from which to base any recursion"});this.all=U.Option.Boolean("-A,--all",!1,{description:"Run the command on all workspaces of a project"});this.verbose=U.Option.Boolean("-v,--verbose",!1,{description:"Prefix each output line with the name of the originating workspace"});this.parallel=U.Option.Boolean("-p,--parallel",!1,{description:"Run the commands in parallel"});this.interlaced=U.Option.Boolean("-i,--interlaced",!1,{description:"Print the output of commands in real-time instead of buffering it"});this.jobs=U.Option.String("-j,--jobs",{description:"The maximum number of parallel tasks that the execution will be limited to; or `unlimited`",validator:re.isOneOf([re.isEnum(["unlimited"]),re.applyCascade(re.isNumber(),[re.isInteger(),re.isAtLeast(1)])])});this.topological=U.Option.Boolean("-t,--topological",!1,{description:"Run the command after all workspaces it depends on (regular) have finished"});this.topologicalDev=U.Option.Boolean("--topological-dev",!1,{description:"Run the command after all workspaces it depends on (regular + dev) have finished"});this.include=U.Option.Array("--include",[],{description:"An array of glob pattern idents; only matching workspaces will be traversed"});this.exclude=U.Option.Array("--exclude",[],{description:"An array of glob pattern idents; matching workspaces won't be traversed"});this.publicOnly=U.Option.Boolean("--no-private",{description:"Avoid running the command on private workspaces"});this.since=U.Option.String("--since",{description:"Only include workspaces that have been changed since the specified ref.",tolerateBoolean:!0});this.commandName=U.Option.String();this.args=U.Option.Proxy()}async execute(){let t=await ge.Configuration.find(this.context.cwd,this.context.plugins),{project:r,workspace:n}=await ge.Project.find(t,this.context.cwd);if(!this.all&&!n)throw new Ie.WorkspaceRequiredError(r.cwd,this.context.cwd);await r.restoreInstallState();let s=this.cli.process([this.commandName,...this.args]),a=s.path.length===1&&s.path[0]==="run"&&typeof s.scriptName!="undefined"?s.scriptName:null;if(s.path.length===0)throw new U.UsageError("Invalid subcommand name for iteration - use the 'run' keyword if you wish to execute a script");let i=this.all?r.topLevelWorkspace:n,o=this.since?Array.from(await Rr.gitUtils.fetchChangedWorkspaces({ref:this.since,project:r})):[i,...this.from.length>0?i.getRecursiveWorkspaceChildren():[]],h=E=>Be.default.isMatch(Y.structUtils.stringifyIdent(E.locator),this.from),g=this.from.length>0?o.filter(h):o,f=new Set([...g,...g.map(E=>[...this.recursive?this.since?E.getRecursiveWorkspaceDependents():E.getRecursiveWorkspaceDependencies():E.getRecursiveWorkspaceChildren()]).flat()]),A=[],p=!1;if(a==null?void 0:a.includes(":")){for(let E of r.workspaces)if(E.manifest.scripts.has(a)&&(p=!p,p===!1))break}for(let E of f)a&&!E.manifest.scripts.has(a)&&!p&&!(await ge.scriptUtils.getWorkspaceAccessibleBinaries(E)).has(a)||a===process.env.npm_lifecycle_event&&E.cwd===n.cwd||this.include.length>0&&!Be.default.isMatch(Y.structUtils.stringifyIdent(E.locator),this.include)||this.exclude.length>0&&Be.default.isMatch(Y.structUtils.stringifyIdent(E.locator),this.exclude)||this.publicOnly&&E.manifest.private===!0||A.push(E);let k=this.parallel?this.jobs==="unlimited"?Infinity:this.jobs||Math.max(1,(0,yr.cpus)().length/2):1,y=k===1?!1:this.parallel,R=y?this.interlaced:!0,_=(0,br.default)(k),x=new Map,T=new Set,O=0,W=null,G=!1,ne=await Ee.StreamReport.start({configuration:t,stdout:this.context.stdout},async E=>{let b=async(C,{commandIndex:M})=>{if(G)return-1;!y&&this.verbose&&M>1&&E.reportSeparator();let l=zn(C,{configuration:t,verbose:this.verbose,commandIndex:M}),[H,w]=_r(E,{prefix:l,interlaced:R}),[j,c]=_r(E,{prefix:l,interlaced:R});try{this.verbose&&E.reportInfo(null,`${l} Process started`);let u=Date.now(),I=await this.cli.run([this.commandName,...this.args],{cwd:C.cwd,stdout:H,stderr:j})||0;H.end(),j.end(),await w,await c;let $=Date.now();if(this.verbose){let ee=t.get("enableTimers")?`, completed in ${Y.formatUtils.pretty(t,$-u,Y.formatUtils.Type.DURATION)}`:"";E.reportInfo(null,`${l} Process exited (exit code ${I})${ee}`)}return I===130&&(G=!0,W=I),I}catch(u){throw H.end(),j.end(),await w,await c,u}};for(let C of A)x.set(C.anchoredLocator.locatorHash,C);for(;x.size>0&&!E.hasErrors();){let C=[];for(let[H,w]of x){if(T.has(w.anchoredDescriptor.descriptorHash))continue;let j=!0;if(this.topological||this.topologicalDev){let c=this.topologicalDev?new Map([...w.manifest.dependencies,...w.manifest.devDependencies]):w.manifest.dependencies;for(let u of c.values()){let I=r.tryWorkspaceByDescriptor(u);if(j=I===null||!x.has(I.anchoredLocator.locatorHash),!j)break}}if(!!j&&(T.add(w.anchoredDescriptor.descriptorHash),C.push(_(async()=>{let c=await b(w,{commandIndex:++O});return x.delete(H),T.delete(w.anchoredDescriptor.descriptorHash),c})),!y))break}if(C.length===0){let H=Array.from(x.values()).map(w=>Y.structUtils.prettyLocator(t,w.anchoredLocator)).join(", ");E.reportError(Ee.MessageName.CYCLIC_DEPENDENCIES,`Dependency cycle detected (${H})`);return}let l=(await Promise.all(C)).find(H=>H!==0);W===null&&(W=typeof l!="undefined"?1:W),(this.topological||this.topologicalDev)&&typeof l!="undefined"&&E.reportError(Ee.MessageName.UNNAMED,"The command failed for workspaces that are depended upon by other workspaces; can't satisfy the dependency graph")}});return W!==null?W:ne.exitCode()}};xe.paths=[["workspaces","foreach"]],xe.usage=U.Command.Usage({category:"Workspace-related commands",description:"run a command on all workspaces",details:"\n This command will run a given sub-command on current and all its descendant workspaces. Various flags can alter the exact behavior of the command:\n\n - If `-p,--parallel` is set, the commands will be ran in parallel; they'll by default be limited to a number of parallel tasks roughly equal to half your core number, but that can be overridden via `-j,--jobs`, or disabled by setting `-j unlimited`.\n\n - If `-p,--parallel` and `-i,--interlaced` are both set, Yarn will print the lines from the output as it receives them. If `-i,--interlaced` wasn't set, it would instead buffer the output from each process and print the resulting buffers only after their source processes have exited.\n\n - If `-t,--topological` is set, Yarn will only run the command after all workspaces that it depends on through the `dependencies` field have successfully finished executing. If `--topological-dev` is set, both the `dependencies` and `devDependencies` fields will be considered when figuring out the wait points.\n\n - If `-A,--all` is set, Yarn will run the command on all the workspaces of a project. By default yarn runs the command only on current and all its descendant workspaces.\n\n - If `-R,--recursive` is set, Yarn will find workspaces to run the command on by recursively evaluating `dependencies` and `devDependencies` fields, instead of looking at the `workspaces` fields.\n\n - If `--from` is set, Yarn will use the packages matching the 'from' glob as the starting point for any recursive search.\n\n - If `--since` is set, Yarn will only run the command on workspaces that have been modified since the specified ref. By default Yarn will use the refs specified by the `changesetBaseRefs` configuration option.\n\n - The command may apply to only some workspaces through the use of `--include` which acts as a whitelist. The `--exclude` flag will do the opposite and will be a list of packages that mustn't execute the script. Both flags accept glob patterns (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\n\n Adding the `-v,--verbose` flag will cause Yarn to print more information; in particular the name of the workspace that generated the output will be printed at the front of each line.\n\n If the command is `run` and the script being run does not exist the child workspace will be skipped without error.\n ",examples:[["Publish current and all descendant packages","yarn workspaces foreach npm publish --tolerate-republish"],["Run build script on current and all descendant packages","yarn workspaces foreach run build"],["Run build script on current and all descendant packages in parallel, building package dependencies first","yarn workspaces foreach -pt run build"],["Run build script on several packages and all their dependencies, building dependencies first","yarn workspaces foreach -ptR --from '{workspace-a,workspace-b}' run build"]]});var Er=xe;function _r(e,{prefix:t,interlaced:r}){let n=e.createStreamReporter(t),s=new Y.miscUtils.DefaultStream;s.pipe(n,{end:!1}),s.on("finish",()=>{n.end()});let a=new Promise(o=>{n.on("finish",()=>{o(s.active)})});if(r)return[s,a];let i=new Y.miscUtils.BufferStream;return i.pipe(s,{end:!1}),i.on("finish",()=>{s.end()}),[i,a]}function zn(e,{configuration:t,commandIndex:r,verbose:n}){if(!n)return null;let s=Y.structUtils.convertToIdent(e.locator),i=`[${Y.structUtils.stringifyIdent(s)}]:`,o=["#2E86AB","#A23B72","#F18F01","#C73E1D","#CCE2A3"],h=o[r%o.length];return Y.formatUtils.pretty(t,i,h)}var Jn={commands:[st,Er]},es=Jn;return Vn;})(); +/*! + * fill-range + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Licensed under the MIT License. + */ +/*! + * is-number + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Released under the MIT License. + */ +/*! + * to-regex-range + * + * Copyright (c) 2015-present, Jon Schlinkert. + * Released under the MIT License. + */ +return plugin; +} +}; diff --git a/.yarn/releases/yarn-3.7.0.cjs b/.yarn/releases/yarn-3.7.0.cjs new file mode 100755 index 000000000..d5174e5ac --- /dev/null +++ b/.yarn/releases/yarn-3.7.0.cjs @@ -0,0 +1,875 @@ +#!/usr/bin/env node +/* eslint-disable */ +//prettier-ignore +(()=>{var Tge=Object.create;var cS=Object.defineProperty;var Lge=Object.getOwnPropertyDescriptor;var Oge=Object.getOwnPropertyNames;var Mge=Object.getPrototypeOf,Kge=Object.prototype.hasOwnProperty;var J=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+r+'" is not supported')});var Uge=(r,e)=>()=>(r&&(e=r(r=0)),e);var I=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),ct=(r,e)=>{for(var t in e)cS(r,t,{get:e[t],enumerable:!0})},Hge=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Oge(e))!Kge.call(r,n)&&n!==t&&cS(r,n,{get:()=>e[n],enumerable:!(i=Lge(e,n))||i.enumerable});return r};var ve=(r,e,t)=>(t=r!=null?Tge(Mge(r)):{},Hge(e||!r||!r.__esModule?cS(t,"default",{value:r,enumerable:!0}):t,r));var DK=I((rZe,kK)=>{kK.exports=PK;PK.sync=Afe;var vK=J("fs");function afe(r,e){var t=e.pathExt!==void 0?e.pathExt:process.env.PATHEXT;if(!t||(t=t.split(";"),t.indexOf("")!==-1))return!0;for(var i=0;i{TK.exports=FK;FK.sync=lfe;var RK=J("fs");function FK(r,e,t){RK.stat(r,function(i,n){t(i,i?!1:NK(n,e))})}function lfe(r,e){return NK(RK.statSync(r),e)}function NK(r,e){return r.isFile()&&cfe(r,e)}function cfe(r,e){var t=r.mode,i=r.uid,n=r.gid,s=e.uid!==void 0?e.uid:process.getuid&&process.getuid(),o=e.gid!==void 0?e.gid:process.getgid&&process.getgid(),a=parseInt("100",8),l=parseInt("010",8),c=parseInt("001",8),u=a|l,g=t&c||t&l&&n===o||t&a&&i===s||t&u&&s===0;return g}});var MK=I((sZe,OK)=>{var nZe=J("fs"),cI;process.platform==="win32"||global.TESTING_WINDOWS?cI=DK():cI=LK();OK.exports=vS;vS.sync=ufe;function vS(r,e,t){if(typeof e=="function"&&(t=e,e={}),!t){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(i,n){vS(r,e||{},function(s,o){s?n(s):i(o)})})}cI(r,e||{},function(i,n){i&&(i.code==="EACCES"||e&&e.ignoreErrors)&&(i=null,n=!1),t(i,n)})}function ufe(r,e){try{return cI.sync(r,e||{})}catch(t){if(e&&e.ignoreErrors||t.code==="EACCES")return!1;throw t}}});var qK=I((oZe,jK)=>{var Dg=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",KK=J("path"),gfe=Dg?";":":",UK=MK(),HK=r=>Object.assign(new Error(`not found: ${r}`),{code:"ENOENT"}),GK=(r,e)=>{let t=e.colon||gfe,i=r.match(/\//)||Dg&&r.match(/\\/)?[""]:[...Dg?[process.cwd()]:[],...(e.path||process.env.PATH||"").split(t)],n=Dg?e.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",s=Dg?n.split(t):[""];return Dg&&r.indexOf(".")!==-1&&s[0]!==""&&s.unshift(""),{pathEnv:i,pathExt:s,pathExtExe:n}},YK=(r,e,t)=>{typeof e=="function"&&(t=e,e={}),e||(e={});let{pathEnv:i,pathExt:n,pathExtExe:s}=GK(r,e),o=[],a=c=>new Promise((u,g)=>{if(c===i.length)return e.all&&o.length?u(o):g(HK(r));let h=i[c],p=/^".*"$/.test(h)?h.slice(1,-1):h,d=KK.join(p,r),m=!p&&/^\.[\\\/]/.test(r)?r.slice(0,2)+d:d;u(l(m,c,0))}),l=(c,u,g)=>new Promise((h,p)=>{if(g===n.length)return h(a(u+1));let d=n[g];UK(c+d,{pathExt:s},(m,y)=>{if(!m&&y)if(e.all)o.push(c+d);else return h(c+d);return h(l(c,u,g+1))})});return t?a(0).then(c=>t(null,c),t):a(0)},ffe=(r,e)=>{e=e||{};let{pathEnv:t,pathExt:i,pathExtExe:n}=GK(r,e),s=[];for(let o=0;o{"use strict";var JK=(r={})=>{let e=r.env||process.env;return(r.platform||process.platform)!=="win32"?"PATH":Object.keys(e).reverse().find(i=>i.toUpperCase()==="PATH")||"Path"};xS.exports=JK;xS.exports.default=JK});var ZK=I((AZe,XK)=>{"use strict";var zK=J("path"),hfe=qK(),pfe=WK();function VK(r,e){let t=r.options.env||process.env,i=process.cwd(),n=r.options.cwd!=null,s=n&&process.chdir!==void 0&&!process.chdir.disabled;if(s)try{process.chdir(r.options.cwd)}catch{}let o;try{o=hfe.sync(r.command,{path:t[pfe({env:t})],pathExt:e?zK.delimiter:void 0})}catch{}finally{s&&process.chdir(i)}return o&&(o=zK.resolve(n?r.options.cwd:"",o)),o}function dfe(r){return VK(r)||VK(r,!0)}XK.exports=dfe});var _K=I((lZe,kS)=>{"use strict";var PS=/([()\][%!^"`<>&|;, *?])/g;function Cfe(r){return r=r.replace(PS,"^$1"),r}function mfe(r,e){return r=`${r}`,r=r.replace(/(\\*)"/g,'$1$1\\"'),r=r.replace(/(\\*)$/,"$1$1"),r=`"${r}"`,r=r.replace(PS,"^$1"),e&&(r=r.replace(PS,"^$1")),r}kS.exports.command=Cfe;kS.exports.argument=mfe});var eU=I((cZe,$K)=>{"use strict";$K.exports=/^#!(.*)/});var rU=I((uZe,tU)=>{"use strict";var Efe=eU();tU.exports=(r="")=>{let e=r.match(Efe);if(!e)return null;let[t,i]=e[0].replace(/#! ?/,"").split(" "),n=t.split("/").pop();return n==="env"?i:i?`${n} ${i}`:n}});var nU=I((gZe,iU)=>{"use strict";var DS=J("fs"),Ife=rU();function yfe(r){let t=Buffer.alloc(150),i;try{i=DS.openSync(r,"r"),DS.readSync(i,t,0,150,0),DS.closeSync(i)}catch{}return Ife(t.toString())}iU.exports=yfe});var AU=I((fZe,aU)=>{"use strict";var wfe=J("path"),sU=ZK(),oU=_K(),Bfe=nU(),Qfe=process.platform==="win32",bfe=/\.(?:com|exe)$/i,Sfe=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function vfe(r){r.file=sU(r);let e=r.file&&Bfe(r.file);return e?(r.args.unshift(r.file),r.command=e,sU(r)):r.file}function xfe(r){if(!Qfe)return r;let e=vfe(r),t=!bfe.test(e);if(r.options.forceShell||t){let i=Sfe.test(e);r.command=wfe.normalize(r.command),r.command=oU.command(r.command),r.args=r.args.map(s=>oU.argument(s,i));let n=[r.command].concat(r.args).join(" ");r.args=["/d","/s","/c",`"${n}"`],r.command=process.env.comspec||"cmd.exe",r.options.windowsVerbatimArguments=!0}return r}function Pfe(r,e,t){e&&!Array.isArray(e)&&(t=e,e=null),e=e?e.slice(0):[],t=Object.assign({},t);let i={command:r,args:e,options:t,file:void 0,original:{command:r,args:e}};return t.shell?i:xfe(i)}aU.exports=Pfe});var uU=I((hZe,cU)=>{"use strict";var RS=process.platform==="win32";function FS(r,e){return Object.assign(new Error(`${e} ${r.command} ENOENT`),{code:"ENOENT",errno:"ENOENT",syscall:`${e} ${r.command}`,path:r.command,spawnargs:r.args})}function kfe(r,e){if(!RS)return;let t=r.emit;r.emit=function(i,n){if(i==="exit"){let s=lU(n,e,"spawn");if(s)return t.call(r,"error",s)}return t.apply(r,arguments)}}function lU(r,e){return RS&&r===1&&!e.file?FS(e.original,"spawn"):null}function Dfe(r,e){return RS&&r===1&&!e.file?FS(e.original,"spawnSync"):null}cU.exports={hookChildProcess:kfe,verifyENOENT:lU,verifyENOENTSync:Dfe,notFoundError:FS}});var LS=I((pZe,Rg)=>{"use strict";var gU=J("child_process"),NS=AU(),TS=uU();function fU(r,e,t){let i=NS(r,e,t),n=gU.spawn(i.command,i.args,i.options);return TS.hookChildProcess(n,i),n}function Rfe(r,e,t){let i=NS(r,e,t),n=gU.spawnSync(i.command,i.args,i.options);return n.error=n.error||TS.verifyENOENTSync(n.status,i),n}Rg.exports=fU;Rg.exports.spawn=fU;Rg.exports.sync=Rfe;Rg.exports._parse=NS;Rg.exports._enoent=TS});var pU=I((dZe,hU)=>{"use strict";function Ffe(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function $l(r,e,t,i){this.message=r,this.expected=e,this.found=t,this.location=i,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,$l)}Ffe($l,Error);$l.buildMessage=function(r,e){var t={literal:function(c){return'"'+n(c.text)+'"'},class:function(c){var u="",g;for(g=0;g0){for(g=1,h=1;g>",re=Ke(">>",!1),de=">&",Ze=Ke(">&",!1),vt=">",mt=Ke(">",!1),Tr="<<<",ei=Ke("<<<",!1),ci="<&",gr=Ke("<&",!1),ui="<",ti=Ke("<",!1),Ms=function(C){return{type:"argument",segments:[].concat(...C)}},fr=function(C){return C},Ei="$'",ts=Ke("$'",!1),ua="'",CA=Ke("'",!1),gg=function(C){return[{type:"text",text:C}]},rs='""',mA=Ke('""',!1),ga=function(){return{type:"text",text:""}},Bp='"',EA=Ke('"',!1),IA=function(C){return C},Ir=function(C){return{type:"arithmetic",arithmetic:C,quoted:!0}},Nl=function(C){return{type:"shell",shell:C,quoted:!0}},fg=function(C){return{type:"variable",...C,quoted:!0}},Io=function(C){return{type:"text",text:C}},hg=function(C){return{type:"arithmetic",arithmetic:C,quoted:!1}},Qp=function(C){return{type:"shell",shell:C,quoted:!1}},bp=function(C){return{type:"variable",...C,quoted:!1}},br=function(C){return{type:"glob",pattern:C}},ne=/^[^']/,yo=Ve(["'"],!0,!1),Fn=function(C){return C.join("")},pg=/^[^$"]/,yt=Ve(["$",'"'],!0,!1),Tl=`\\ +`,Nn=Ke(`\\ +`,!1),is=function(){return""},ns="\\",ut=Ke("\\",!1),wo=/^[\\$"`]/,At=Ve(["\\","$",'"',"`"],!1,!1),An=function(C){return C},b="\\a",Ft=Ke("\\a",!1),dg=function(){return"a"},Ll="\\b",Sp=Ke("\\b",!1),vp=function(){return"\b"},xp=/^[Ee]/,Pp=Ve(["E","e"],!1,!1),kp=function(){return"\x1B"},G="\\f",Et=Ke("\\f",!1),yA=function(){return"\f"},Wi="\\n",Ol=Ke("\\n",!1),ze=function(){return` +`},fa="\\r",Cg=Ke("\\r",!1),KE=function(){return"\r"},Dp="\\t",UE=Ke("\\t",!1),sr=function(){return" "},Tn="\\v",Ml=Ke("\\v",!1),Rp=function(){return"\v"},Ks=/^[\\'"?]/,ha=Ve(["\\","'",'"',"?"],!1,!1),ln=function(C){return String.fromCharCode(parseInt(C,16))},Ne="\\x",mg=Ke("\\x",!1),Kl="\\u",Us=Ke("\\u",!1),Ul="\\U",wA=Ke("\\U",!1),Eg=function(C){return String.fromCodePoint(parseInt(C,16))},Ig=/^[0-7]/,pa=Ve([["0","7"]],!1,!1),da=/^[0-9a-fA-f]/,tt=Ve([["0","9"],["a","f"],["A","f"]],!1,!1),Bo=it(),BA="{}",Fp=Ke("{}",!1),Ca=function(){return"{}"},Hl="-",Gl=Ke("-",!1),QA="+",ma=Ke("+",!1),Np=".",HE=Ke(".",!1),Yl=function(C,Q,R){return{type:"number",value:(C==="-"?-1:1)*parseFloat(Q.join("")+"."+R.join(""))}},GE=function(C,Q){return{type:"number",value:(C==="-"?-1:1)*parseInt(Q.join(""))}},Tp=function(C){return{type:"variable",...C}},jl=function(C){return{type:"variable",name:C}},Lr=function(C){return C},YE="*",Hs=Ke("*",!1),Gs="/",yg=Ke("/",!1),bA=function(C,Q,R){return{type:Q==="*"?"multiplication":"division",right:R}},D=function(C,Q){return Q.reduce((R,U)=>({left:R,...U}),C)},j=function(C,Q,R){return{type:Q==="+"?"addition":"subtraction",right:R}},pe="$((",Le=Ke("$((",!1),ke="))",Je=Ke("))",!1),pt=function(C){return C},Xt="$(",Ea=Ke("$(",!1),R1=function(C){return C},Ys="${",wg=Ke("${",!1),Wb=":-",F1=Ke(":-",!1),N1=function(C,Q){return{name:C,defaultValue:Q}},zb=":-}",T1=Ke(":-}",!1),L1=function(C){return{name:C,defaultValue:[]}},Vb=":+",O1=Ke(":+",!1),M1=function(C,Q){return{name:C,alternativeValue:Q}},Xb=":+}",K1=Ke(":+}",!1),U1=function(C){return{name:C,alternativeValue:[]}},Zb=function(C){return{name:C}},H1="$",G1=Ke("$",!1),Y1=function(C){return e.isGlobPattern(C)},j1=function(C){return C},_b=/^[a-zA-Z0-9_]/,$b=Ve([["a","z"],["A","Z"],["0","9"],"_"],!1,!1),eS=function(){return Ie()},ql=/^[$@*?#a-zA-Z0-9_\-]/,jE=Ve(["$","@","*","?","#",["a","z"],["A","Z"],["0","9"],"_","-"],!1,!1),tS=/^[()}<>$|&; \t"']/,rS=Ve(["(",")","}","<",">","$","|","&",";"," "," ",'"',"'"],!1,!1),iS=/^[<>&; \t"']/,qE=Ve(["<",">","&",";"," "," ",'"',"'"],!1,!1),Jl=/^[ \t]/,Bg=Ve([" "," "],!1,!1),f=0,E=0,w=[{line:1,column:1}],k=0,L=[],T=0,$;if("startRule"in e){if(!(e.startRule in i))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');n=i[e.startRule]}function Ie(){return r.substring(E,f)}function Oe(){return ri(E,f)}function rt(C,Q){throw Q=Q!==void 0?Q:ri(E,f),Ln([Ii(C)],r.substring(E,f),Q)}function ot(C,Q){throw Q=Q!==void 0?Q:ri(E,f),yi(C,Q)}function Ke(C,Q){return{type:"literal",text:C,ignoreCase:Q}}function Ve(C,Q,R){return{type:"class",parts:C,inverted:Q,ignoreCase:R}}function it(){return{type:"any"}}function wt(){return{type:"end"}}function Ii(C){return{type:"other",description:C}}function cn(C){var Q=w[C],R;if(Q)return Q;for(R=C-1;!w[R];)R--;for(Q=w[R],Q={line:Q.line,column:Q.column};Rk&&(k=f,L=[]),L.push(C))}function yi(C,Q){return new $l(C,null,null,Q)}function Ln(C,Q,R){return new $l($l.buildMessage(C,Q),C,Q,R)}function Ia(){var C,Q,R;for(C=f,Q=[],R=Me();R!==t;)Q.push(R),R=Me();return Q!==t?(R=Sr(),R===t&&(R=null),R!==t?(E=C,Q=s(R),C=Q):(f=C,C=t)):(f=C,C=t),C}function Sr(){var C,Q,R,U,le;if(C=f,Q=nS(),Q!==t){for(R=[],U=Me();U!==t;)R.push(U),U=Me();R!==t?(U=q1(),U!==t?(le=Cge(),le===t&&(le=null),le!==t?(E=C,Q=o(Q,U,le),C=Q):(f=C,C=t)):(f=C,C=t)):(f=C,C=t)}else f=C,C=t;if(C===t)if(C=f,Q=nS(),Q!==t){for(R=[],U=Me();U!==t;)R.push(U),U=Me();R!==t?(U=q1(),U===t&&(U=null),U!==t?(E=C,Q=a(Q,U),C=Q):(f=C,C=t)):(f=C,C=t)}else f=C,C=t;return C}function Cge(){var C,Q,R,U,le;for(C=f,Q=[],R=Me();R!==t;)Q.push(R),R=Me();if(Q!==t)if(R=Sr(),R!==t){for(U=[],le=Me();le!==t;)U.push(le),le=Me();U!==t?(E=C,Q=l(R),C=Q):(f=C,C=t)}else f=C,C=t;else f=C,C=t;return C}function q1(){var C;return r.charCodeAt(f)===59?(C=c,f++):(C=t,T===0&&Be(u)),C===t&&(r.charCodeAt(f)===38?(C=g,f++):(C=t,T===0&&Be(h))),C}function nS(){var C,Q,R;return C=f,Q=J1(),Q!==t?(R=mge(),R===t&&(R=null),R!==t?(E=C,Q=p(Q,R),C=Q):(f=C,C=t)):(f=C,C=t),C}function mge(){var C,Q,R,U,le,Qe,ft;for(C=f,Q=[],R=Me();R!==t;)Q.push(R),R=Me();if(Q!==t)if(R=Ege(),R!==t){for(U=[],le=Me();le!==t;)U.push(le),le=Me();if(U!==t)if(le=nS(),le!==t){for(Qe=[],ft=Me();ft!==t;)Qe.push(ft),ft=Me();Qe!==t?(E=C,Q=d(R,le),C=Q):(f=C,C=t)}else f=C,C=t;else f=C,C=t}else f=C,C=t;else f=C,C=t;return C}function Ege(){var C;return r.substr(f,2)===m?(C=m,f+=2):(C=t,T===0&&Be(y)),C===t&&(r.substr(f,2)===B?(C=B,f+=2):(C=t,T===0&&Be(S))),C}function J1(){var C,Q,R;return C=f,Q=wge(),Q!==t?(R=Ige(),R===t&&(R=null),R!==t?(E=C,Q=P(Q,R),C=Q):(f=C,C=t)):(f=C,C=t),C}function Ige(){var C,Q,R,U,le,Qe,ft;for(C=f,Q=[],R=Me();R!==t;)Q.push(R),R=Me();if(Q!==t)if(R=yge(),R!==t){for(U=[],le=Me();le!==t;)U.push(le),le=Me();if(U!==t)if(le=J1(),le!==t){for(Qe=[],ft=Me();ft!==t;)Qe.push(ft),ft=Me();Qe!==t?(E=C,Q=F(R,le),C=Q):(f=C,C=t)}else f=C,C=t;else f=C,C=t}else f=C,C=t;else f=C,C=t;return C}function yge(){var C;return r.substr(f,2)===H?(C=H,f+=2):(C=t,T===0&&Be(q)),C===t&&(r.charCodeAt(f)===124?(C=_,f++):(C=t,T===0&&Be(X))),C}function JE(){var C,Q,R,U,le,Qe;if(C=f,Q=nK(),Q!==t)if(r.charCodeAt(f)===61?(R=W,f++):(R=t,T===0&&Be(Z)),R!==t)if(U=V1(),U!==t){for(le=[],Qe=Me();Qe!==t;)le.push(Qe),Qe=Me();le!==t?(E=C,Q=A(Q,U),C=Q):(f=C,C=t)}else f=C,C=t;else f=C,C=t;else f=C,C=t;if(C===t)if(C=f,Q=nK(),Q!==t)if(r.charCodeAt(f)===61?(R=W,f++):(R=t,T===0&&Be(Z)),R!==t){for(U=[],le=Me();le!==t;)U.push(le),le=Me();U!==t?(E=C,Q=se(Q),C=Q):(f=C,C=t)}else f=C,C=t;else f=C,C=t;return C}function wge(){var C,Q,R,U,le,Qe,ft,It,Gr,gi,ss;for(C=f,Q=[],R=Me();R!==t;)Q.push(R),R=Me();if(Q!==t)if(r.charCodeAt(f)===40?(R=ue,f++):(R=t,T===0&&Be(ee)),R!==t){for(U=[],le=Me();le!==t;)U.push(le),le=Me();if(U!==t)if(le=Sr(),le!==t){for(Qe=[],ft=Me();ft!==t;)Qe.push(ft),ft=Me();if(Qe!==t)if(r.charCodeAt(f)===41?(ft=O,f++):(ft=t,T===0&&Be(N)),ft!==t){for(It=[],Gr=Me();Gr!==t;)It.push(Gr),Gr=Me();if(It!==t){for(Gr=[],gi=Lp();gi!==t;)Gr.push(gi),gi=Lp();if(Gr!==t){for(gi=[],ss=Me();ss!==t;)gi.push(ss),ss=Me();gi!==t?(E=C,Q=ce(le,Gr),C=Q):(f=C,C=t)}else f=C,C=t}else f=C,C=t}else f=C,C=t;else f=C,C=t}else f=C,C=t;else f=C,C=t}else f=C,C=t;else f=C,C=t;if(C===t){for(C=f,Q=[],R=Me();R!==t;)Q.push(R),R=Me();if(Q!==t)if(r.charCodeAt(f)===123?(R=he,f++):(R=t,T===0&&Be(Pe)),R!==t){for(U=[],le=Me();le!==t;)U.push(le),le=Me();if(U!==t)if(le=Sr(),le!==t){for(Qe=[],ft=Me();ft!==t;)Qe.push(ft),ft=Me();if(Qe!==t)if(r.charCodeAt(f)===125?(ft=De,f++):(ft=t,T===0&&Be(Re)),ft!==t){for(It=[],Gr=Me();Gr!==t;)It.push(Gr),Gr=Me();if(It!==t){for(Gr=[],gi=Lp();gi!==t;)Gr.push(gi),gi=Lp();if(Gr!==t){for(gi=[],ss=Me();ss!==t;)gi.push(ss),ss=Me();gi!==t?(E=C,Q=oe(le,Gr),C=Q):(f=C,C=t)}else f=C,C=t}else f=C,C=t}else f=C,C=t;else f=C,C=t}else f=C,C=t;else f=C,C=t}else f=C,C=t;else f=C,C=t;if(C===t){for(C=f,Q=[],R=Me();R!==t;)Q.push(R),R=Me();if(Q!==t){for(R=[],U=JE();U!==t;)R.push(U),U=JE();if(R!==t){for(U=[],le=Me();le!==t;)U.push(le),le=Me();if(U!==t){if(le=[],Qe=z1(),Qe!==t)for(;Qe!==t;)le.push(Qe),Qe=z1();else le=t;if(le!==t){for(Qe=[],ft=Me();ft!==t;)Qe.push(ft),ft=Me();Qe!==t?(E=C,Q=Ae(R,le),C=Q):(f=C,C=t)}else f=C,C=t}else f=C,C=t}else f=C,C=t}else f=C,C=t;if(C===t){for(C=f,Q=[],R=Me();R!==t;)Q.push(R),R=Me();if(Q!==t){if(R=[],U=JE(),U!==t)for(;U!==t;)R.push(U),U=JE();else R=t;if(R!==t){for(U=[],le=Me();le!==t;)U.push(le),le=Me();U!==t?(E=C,Q=ye(R),C=Q):(f=C,C=t)}else f=C,C=t}else f=C,C=t}}}return C}function W1(){var C,Q,R,U,le;for(C=f,Q=[],R=Me();R!==t;)Q.push(R),R=Me();if(Q!==t){if(R=[],U=WE(),U!==t)for(;U!==t;)R.push(U),U=WE();else R=t;if(R!==t){for(U=[],le=Me();le!==t;)U.push(le),le=Me();U!==t?(E=C,Q=ge(R),C=Q):(f=C,C=t)}else f=C,C=t}else f=C,C=t;return C}function z1(){var C,Q,R;for(C=f,Q=[],R=Me();R!==t;)Q.push(R),R=Me();if(Q!==t?(R=Lp(),R!==t?(E=C,Q=ae(R),C=Q):(f=C,C=t)):(f=C,C=t),C===t){for(C=f,Q=[],R=Me();R!==t;)Q.push(R),R=Me();Q!==t?(R=WE(),R!==t?(E=C,Q=ae(R),C=Q):(f=C,C=t)):(f=C,C=t)}return C}function Lp(){var C,Q,R,U,le;for(C=f,Q=[],R=Me();R!==t;)Q.push(R),R=Me();return Q!==t?(je.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be(ie)),R===t&&(R=null),R!==t?(U=Bge(),U!==t?(le=WE(),le!==t?(E=C,Q=Y(R,U,le),C=Q):(f=C,C=t)):(f=C,C=t)):(f=C,C=t)):(f=C,C=t),C}function Bge(){var C;return r.substr(f,2)===fe?(C=fe,f+=2):(C=t,T===0&&Be(re)),C===t&&(r.substr(f,2)===de?(C=de,f+=2):(C=t,T===0&&Be(Ze)),C===t&&(r.charCodeAt(f)===62?(C=vt,f++):(C=t,T===0&&Be(mt)),C===t&&(r.substr(f,3)===Tr?(C=Tr,f+=3):(C=t,T===0&&Be(ei)),C===t&&(r.substr(f,2)===ci?(C=ci,f+=2):(C=t,T===0&&Be(gr)),C===t&&(r.charCodeAt(f)===60?(C=ui,f++):(C=t,T===0&&Be(ti))))))),C}function WE(){var C,Q,R;for(C=f,Q=[],R=Me();R!==t;)Q.push(R),R=Me();return Q!==t?(R=V1(),R!==t?(E=C,Q=ae(R),C=Q):(f=C,C=t)):(f=C,C=t),C}function V1(){var C,Q,R;if(C=f,Q=[],R=X1(),R!==t)for(;R!==t;)Q.push(R),R=X1();else Q=t;return Q!==t&&(E=C,Q=Ms(Q)),C=Q,C}function X1(){var C,Q;return C=f,Q=Qge(),Q!==t&&(E=C,Q=fr(Q)),C=Q,C===t&&(C=f,Q=bge(),Q!==t&&(E=C,Q=fr(Q)),C=Q,C===t&&(C=f,Q=Sge(),Q!==t&&(E=C,Q=fr(Q)),C=Q,C===t&&(C=f,Q=vge(),Q!==t&&(E=C,Q=fr(Q)),C=Q))),C}function Qge(){var C,Q,R,U;return C=f,r.substr(f,2)===Ei?(Q=Ei,f+=2):(Q=t,T===0&&Be(ts)),Q!==t?(R=kge(),R!==t?(r.charCodeAt(f)===39?(U=ua,f++):(U=t,T===0&&Be(CA)),U!==t?(E=C,Q=gg(R),C=Q):(f=C,C=t)):(f=C,C=t)):(f=C,C=t),C}function bge(){var C,Q,R,U;return C=f,r.charCodeAt(f)===39?(Q=ua,f++):(Q=t,T===0&&Be(CA)),Q!==t?(R=xge(),R!==t?(r.charCodeAt(f)===39?(U=ua,f++):(U=t,T===0&&Be(CA)),U!==t?(E=C,Q=gg(R),C=Q):(f=C,C=t)):(f=C,C=t)):(f=C,C=t),C}function Sge(){var C,Q,R,U;if(C=f,r.substr(f,2)===rs?(Q=rs,f+=2):(Q=t,T===0&&Be(mA)),Q!==t&&(E=C,Q=ga()),C=Q,C===t)if(C=f,r.charCodeAt(f)===34?(Q=Bp,f++):(Q=t,T===0&&Be(EA)),Q!==t){for(R=[],U=Z1();U!==t;)R.push(U),U=Z1();R!==t?(r.charCodeAt(f)===34?(U=Bp,f++):(U=t,T===0&&Be(EA)),U!==t?(E=C,Q=IA(R),C=Q):(f=C,C=t)):(f=C,C=t)}else f=C,C=t;return C}function vge(){var C,Q,R;if(C=f,Q=[],R=_1(),R!==t)for(;R!==t;)Q.push(R),R=_1();else Q=t;return Q!==t&&(E=C,Q=IA(Q)),C=Q,C}function Z1(){var C,Q;return C=f,Q=rK(),Q!==t&&(E=C,Q=Ir(Q)),C=Q,C===t&&(C=f,Q=iK(),Q!==t&&(E=C,Q=Nl(Q)),C=Q,C===t&&(C=f,Q=AS(),Q!==t&&(E=C,Q=fg(Q)),C=Q,C===t&&(C=f,Q=Pge(),Q!==t&&(E=C,Q=Io(Q)),C=Q))),C}function _1(){var C,Q;return C=f,Q=rK(),Q!==t&&(E=C,Q=hg(Q)),C=Q,C===t&&(C=f,Q=iK(),Q!==t&&(E=C,Q=Qp(Q)),C=Q,C===t&&(C=f,Q=AS(),Q!==t&&(E=C,Q=bp(Q)),C=Q,C===t&&(C=f,Q=Fge(),Q!==t&&(E=C,Q=br(Q)),C=Q,C===t&&(C=f,Q=Rge(),Q!==t&&(E=C,Q=Io(Q)),C=Q)))),C}function xge(){var C,Q,R;for(C=f,Q=[],ne.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be(yo));R!==t;)Q.push(R),ne.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be(yo));return Q!==t&&(E=C,Q=Fn(Q)),C=Q,C}function Pge(){var C,Q,R;if(C=f,Q=[],R=$1(),R===t&&(pg.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be(yt))),R!==t)for(;R!==t;)Q.push(R),R=$1(),R===t&&(pg.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be(yt)));else Q=t;return Q!==t&&(E=C,Q=Fn(Q)),C=Q,C}function $1(){var C,Q,R;return C=f,r.substr(f,2)===Tl?(Q=Tl,f+=2):(Q=t,T===0&&Be(Nn)),Q!==t&&(E=C,Q=is()),C=Q,C===t&&(C=f,r.charCodeAt(f)===92?(Q=ns,f++):(Q=t,T===0&&Be(ut)),Q!==t?(wo.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be(At)),R!==t?(E=C,Q=An(R),C=Q):(f=C,C=t)):(f=C,C=t)),C}function kge(){var C,Q,R;for(C=f,Q=[],R=eK(),R===t&&(ne.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be(yo)));R!==t;)Q.push(R),R=eK(),R===t&&(ne.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be(yo)));return Q!==t&&(E=C,Q=Fn(Q)),C=Q,C}function eK(){var C,Q,R;return C=f,r.substr(f,2)===b?(Q=b,f+=2):(Q=t,T===0&&Be(Ft)),Q!==t&&(E=C,Q=dg()),C=Q,C===t&&(C=f,r.substr(f,2)===Ll?(Q=Ll,f+=2):(Q=t,T===0&&Be(Sp)),Q!==t&&(E=C,Q=vp()),C=Q,C===t&&(C=f,r.charCodeAt(f)===92?(Q=ns,f++):(Q=t,T===0&&Be(ut)),Q!==t?(xp.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be(Pp)),R!==t?(E=C,Q=kp(),C=Q):(f=C,C=t)):(f=C,C=t),C===t&&(C=f,r.substr(f,2)===G?(Q=G,f+=2):(Q=t,T===0&&Be(Et)),Q!==t&&(E=C,Q=yA()),C=Q,C===t&&(C=f,r.substr(f,2)===Wi?(Q=Wi,f+=2):(Q=t,T===0&&Be(Ol)),Q!==t&&(E=C,Q=ze()),C=Q,C===t&&(C=f,r.substr(f,2)===fa?(Q=fa,f+=2):(Q=t,T===0&&Be(Cg)),Q!==t&&(E=C,Q=KE()),C=Q,C===t&&(C=f,r.substr(f,2)===Dp?(Q=Dp,f+=2):(Q=t,T===0&&Be(UE)),Q!==t&&(E=C,Q=sr()),C=Q,C===t&&(C=f,r.substr(f,2)===Tn?(Q=Tn,f+=2):(Q=t,T===0&&Be(Ml)),Q!==t&&(E=C,Q=Rp()),C=Q,C===t&&(C=f,r.charCodeAt(f)===92?(Q=ns,f++):(Q=t,T===0&&Be(ut)),Q!==t?(Ks.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be(ha)),R!==t?(E=C,Q=An(R),C=Q):(f=C,C=t)):(f=C,C=t),C===t&&(C=Dge()))))))))),C}function Dge(){var C,Q,R,U,le,Qe,ft,It,Gr,gi,ss,lS;return C=f,r.charCodeAt(f)===92?(Q=ns,f++):(Q=t,T===0&&Be(ut)),Q!==t?(R=sS(),R!==t?(E=C,Q=ln(R),C=Q):(f=C,C=t)):(f=C,C=t),C===t&&(C=f,r.substr(f,2)===Ne?(Q=Ne,f+=2):(Q=t,T===0&&Be(mg)),Q!==t?(R=f,U=f,le=sS(),le!==t?(Qe=On(),Qe!==t?(le=[le,Qe],U=le):(f=U,U=t)):(f=U,U=t),U===t&&(U=sS()),U!==t?R=r.substring(R,f):R=U,R!==t?(E=C,Q=ln(R),C=Q):(f=C,C=t)):(f=C,C=t),C===t&&(C=f,r.substr(f,2)===Kl?(Q=Kl,f+=2):(Q=t,T===0&&Be(Us)),Q!==t?(R=f,U=f,le=On(),le!==t?(Qe=On(),Qe!==t?(ft=On(),ft!==t?(It=On(),It!==t?(le=[le,Qe,ft,It],U=le):(f=U,U=t)):(f=U,U=t)):(f=U,U=t)):(f=U,U=t),U!==t?R=r.substring(R,f):R=U,R!==t?(E=C,Q=ln(R),C=Q):(f=C,C=t)):(f=C,C=t),C===t&&(C=f,r.substr(f,2)===Ul?(Q=Ul,f+=2):(Q=t,T===0&&Be(wA)),Q!==t?(R=f,U=f,le=On(),le!==t?(Qe=On(),Qe!==t?(ft=On(),ft!==t?(It=On(),It!==t?(Gr=On(),Gr!==t?(gi=On(),gi!==t?(ss=On(),ss!==t?(lS=On(),lS!==t?(le=[le,Qe,ft,It,Gr,gi,ss,lS],U=le):(f=U,U=t)):(f=U,U=t)):(f=U,U=t)):(f=U,U=t)):(f=U,U=t)):(f=U,U=t)):(f=U,U=t)):(f=U,U=t),U!==t?R=r.substring(R,f):R=U,R!==t?(E=C,Q=Eg(R),C=Q):(f=C,C=t)):(f=C,C=t)))),C}function sS(){var C;return Ig.test(r.charAt(f))?(C=r.charAt(f),f++):(C=t,T===0&&Be(pa)),C}function On(){var C;return da.test(r.charAt(f))?(C=r.charAt(f),f++):(C=t,T===0&&Be(tt)),C}function Rge(){var C,Q,R,U,le;if(C=f,Q=[],R=f,r.charCodeAt(f)===92?(U=ns,f++):(U=t,T===0&&Be(ut)),U!==t?(r.length>f?(le=r.charAt(f),f++):(le=t,T===0&&Be(Bo)),le!==t?(E=R,U=An(le),R=U):(f=R,R=t)):(f=R,R=t),R===t&&(R=f,r.substr(f,2)===BA?(U=BA,f+=2):(U=t,T===0&&Be(Fp)),U!==t&&(E=R,U=Ca()),R=U,R===t&&(R=f,U=f,T++,le=sK(),T--,le===t?U=void 0:(f=U,U=t),U!==t?(r.length>f?(le=r.charAt(f),f++):(le=t,T===0&&Be(Bo)),le!==t?(E=R,U=An(le),R=U):(f=R,R=t)):(f=R,R=t))),R!==t)for(;R!==t;)Q.push(R),R=f,r.charCodeAt(f)===92?(U=ns,f++):(U=t,T===0&&Be(ut)),U!==t?(r.length>f?(le=r.charAt(f),f++):(le=t,T===0&&Be(Bo)),le!==t?(E=R,U=An(le),R=U):(f=R,R=t)):(f=R,R=t),R===t&&(R=f,r.substr(f,2)===BA?(U=BA,f+=2):(U=t,T===0&&Be(Fp)),U!==t&&(E=R,U=Ca()),R=U,R===t&&(R=f,U=f,T++,le=sK(),T--,le===t?U=void 0:(f=U,U=t),U!==t?(r.length>f?(le=r.charAt(f),f++):(le=t,T===0&&Be(Bo)),le!==t?(E=R,U=An(le),R=U):(f=R,R=t)):(f=R,R=t)));else Q=t;return Q!==t&&(E=C,Q=Fn(Q)),C=Q,C}function oS(){var C,Q,R,U,le,Qe;if(C=f,r.charCodeAt(f)===45?(Q=Hl,f++):(Q=t,T===0&&Be(Gl)),Q===t&&(r.charCodeAt(f)===43?(Q=QA,f++):(Q=t,T===0&&Be(ma))),Q===t&&(Q=null),Q!==t){if(R=[],je.test(r.charAt(f))?(U=r.charAt(f),f++):(U=t,T===0&&Be(ie)),U!==t)for(;U!==t;)R.push(U),je.test(r.charAt(f))?(U=r.charAt(f),f++):(U=t,T===0&&Be(ie));else R=t;if(R!==t)if(r.charCodeAt(f)===46?(U=Np,f++):(U=t,T===0&&Be(HE)),U!==t){if(le=[],je.test(r.charAt(f))?(Qe=r.charAt(f),f++):(Qe=t,T===0&&Be(ie)),Qe!==t)for(;Qe!==t;)le.push(Qe),je.test(r.charAt(f))?(Qe=r.charAt(f),f++):(Qe=t,T===0&&Be(ie));else le=t;le!==t?(E=C,Q=Yl(Q,R,le),C=Q):(f=C,C=t)}else f=C,C=t;else f=C,C=t}else f=C,C=t;if(C===t){if(C=f,r.charCodeAt(f)===45?(Q=Hl,f++):(Q=t,T===0&&Be(Gl)),Q===t&&(r.charCodeAt(f)===43?(Q=QA,f++):(Q=t,T===0&&Be(ma))),Q===t&&(Q=null),Q!==t){if(R=[],je.test(r.charAt(f))?(U=r.charAt(f),f++):(U=t,T===0&&Be(ie)),U!==t)for(;U!==t;)R.push(U),je.test(r.charAt(f))?(U=r.charAt(f),f++):(U=t,T===0&&Be(ie));else R=t;R!==t?(E=C,Q=GE(Q,R),C=Q):(f=C,C=t)}else f=C,C=t;if(C===t&&(C=f,Q=AS(),Q!==t&&(E=C,Q=Tp(Q)),C=Q,C===t&&(C=f,Q=Wl(),Q!==t&&(E=C,Q=jl(Q)),C=Q,C===t)))if(C=f,r.charCodeAt(f)===40?(Q=ue,f++):(Q=t,T===0&&Be(ee)),Q!==t){for(R=[],U=Me();U!==t;)R.push(U),U=Me();if(R!==t)if(U=tK(),U!==t){for(le=[],Qe=Me();Qe!==t;)le.push(Qe),Qe=Me();le!==t?(r.charCodeAt(f)===41?(Qe=O,f++):(Qe=t,T===0&&Be(N)),Qe!==t?(E=C,Q=Lr(U),C=Q):(f=C,C=t)):(f=C,C=t)}else f=C,C=t;else f=C,C=t}else f=C,C=t}return C}function aS(){var C,Q,R,U,le,Qe,ft,It;if(C=f,Q=oS(),Q!==t){for(R=[],U=f,le=[],Qe=Me();Qe!==t;)le.push(Qe),Qe=Me();if(le!==t)if(r.charCodeAt(f)===42?(Qe=YE,f++):(Qe=t,T===0&&Be(Hs)),Qe===t&&(r.charCodeAt(f)===47?(Qe=Gs,f++):(Qe=t,T===0&&Be(yg))),Qe!==t){for(ft=[],It=Me();It!==t;)ft.push(It),It=Me();ft!==t?(It=oS(),It!==t?(E=U,le=bA(Q,Qe,It),U=le):(f=U,U=t)):(f=U,U=t)}else f=U,U=t;else f=U,U=t;for(;U!==t;){for(R.push(U),U=f,le=[],Qe=Me();Qe!==t;)le.push(Qe),Qe=Me();if(le!==t)if(r.charCodeAt(f)===42?(Qe=YE,f++):(Qe=t,T===0&&Be(Hs)),Qe===t&&(r.charCodeAt(f)===47?(Qe=Gs,f++):(Qe=t,T===0&&Be(yg))),Qe!==t){for(ft=[],It=Me();It!==t;)ft.push(It),It=Me();ft!==t?(It=oS(),It!==t?(E=U,le=bA(Q,Qe,It),U=le):(f=U,U=t)):(f=U,U=t)}else f=U,U=t;else f=U,U=t}R!==t?(E=C,Q=D(Q,R),C=Q):(f=C,C=t)}else f=C,C=t;return C}function tK(){var C,Q,R,U,le,Qe,ft,It;if(C=f,Q=aS(),Q!==t){for(R=[],U=f,le=[],Qe=Me();Qe!==t;)le.push(Qe),Qe=Me();if(le!==t)if(r.charCodeAt(f)===43?(Qe=QA,f++):(Qe=t,T===0&&Be(ma)),Qe===t&&(r.charCodeAt(f)===45?(Qe=Hl,f++):(Qe=t,T===0&&Be(Gl))),Qe!==t){for(ft=[],It=Me();It!==t;)ft.push(It),It=Me();ft!==t?(It=aS(),It!==t?(E=U,le=j(Q,Qe,It),U=le):(f=U,U=t)):(f=U,U=t)}else f=U,U=t;else f=U,U=t;for(;U!==t;){for(R.push(U),U=f,le=[],Qe=Me();Qe!==t;)le.push(Qe),Qe=Me();if(le!==t)if(r.charCodeAt(f)===43?(Qe=QA,f++):(Qe=t,T===0&&Be(ma)),Qe===t&&(r.charCodeAt(f)===45?(Qe=Hl,f++):(Qe=t,T===0&&Be(Gl))),Qe!==t){for(ft=[],It=Me();It!==t;)ft.push(It),It=Me();ft!==t?(It=aS(),It!==t?(E=U,le=j(Q,Qe,It),U=le):(f=U,U=t)):(f=U,U=t)}else f=U,U=t;else f=U,U=t}R!==t?(E=C,Q=D(Q,R),C=Q):(f=C,C=t)}else f=C,C=t;return C}function rK(){var C,Q,R,U,le,Qe;if(C=f,r.substr(f,3)===pe?(Q=pe,f+=3):(Q=t,T===0&&Be(Le)),Q!==t){for(R=[],U=Me();U!==t;)R.push(U),U=Me();if(R!==t)if(U=tK(),U!==t){for(le=[],Qe=Me();Qe!==t;)le.push(Qe),Qe=Me();le!==t?(r.substr(f,2)===ke?(Qe=ke,f+=2):(Qe=t,T===0&&Be(Je)),Qe!==t?(E=C,Q=pt(U),C=Q):(f=C,C=t)):(f=C,C=t)}else f=C,C=t;else f=C,C=t}else f=C,C=t;return C}function iK(){var C,Q,R,U;return C=f,r.substr(f,2)===Xt?(Q=Xt,f+=2):(Q=t,T===0&&Be(Ea)),Q!==t?(R=Sr(),R!==t?(r.charCodeAt(f)===41?(U=O,f++):(U=t,T===0&&Be(N)),U!==t?(E=C,Q=R1(R),C=Q):(f=C,C=t)):(f=C,C=t)):(f=C,C=t),C}function AS(){var C,Q,R,U,le,Qe;return C=f,r.substr(f,2)===Ys?(Q=Ys,f+=2):(Q=t,T===0&&Be(wg)),Q!==t?(R=Wl(),R!==t?(r.substr(f,2)===Wb?(U=Wb,f+=2):(U=t,T===0&&Be(F1)),U!==t?(le=W1(),le!==t?(r.charCodeAt(f)===125?(Qe=De,f++):(Qe=t,T===0&&Be(Re)),Qe!==t?(E=C,Q=N1(R,le),C=Q):(f=C,C=t)):(f=C,C=t)):(f=C,C=t)):(f=C,C=t)):(f=C,C=t),C===t&&(C=f,r.substr(f,2)===Ys?(Q=Ys,f+=2):(Q=t,T===0&&Be(wg)),Q!==t?(R=Wl(),R!==t?(r.substr(f,3)===zb?(U=zb,f+=3):(U=t,T===0&&Be(T1)),U!==t?(E=C,Q=L1(R),C=Q):(f=C,C=t)):(f=C,C=t)):(f=C,C=t),C===t&&(C=f,r.substr(f,2)===Ys?(Q=Ys,f+=2):(Q=t,T===0&&Be(wg)),Q!==t?(R=Wl(),R!==t?(r.substr(f,2)===Vb?(U=Vb,f+=2):(U=t,T===0&&Be(O1)),U!==t?(le=W1(),le!==t?(r.charCodeAt(f)===125?(Qe=De,f++):(Qe=t,T===0&&Be(Re)),Qe!==t?(E=C,Q=M1(R,le),C=Q):(f=C,C=t)):(f=C,C=t)):(f=C,C=t)):(f=C,C=t)):(f=C,C=t),C===t&&(C=f,r.substr(f,2)===Ys?(Q=Ys,f+=2):(Q=t,T===0&&Be(wg)),Q!==t?(R=Wl(),R!==t?(r.substr(f,3)===Xb?(U=Xb,f+=3):(U=t,T===0&&Be(K1)),U!==t?(E=C,Q=U1(R),C=Q):(f=C,C=t)):(f=C,C=t)):(f=C,C=t),C===t&&(C=f,r.substr(f,2)===Ys?(Q=Ys,f+=2):(Q=t,T===0&&Be(wg)),Q!==t?(R=Wl(),R!==t?(r.charCodeAt(f)===125?(U=De,f++):(U=t,T===0&&Be(Re)),U!==t?(E=C,Q=Zb(R),C=Q):(f=C,C=t)):(f=C,C=t)):(f=C,C=t),C===t&&(C=f,r.charCodeAt(f)===36?(Q=H1,f++):(Q=t,T===0&&Be(G1)),Q!==t?(R=Wl(),R!==t?(E=C,Q=Zb(R),C=Q):(f=C,C=t)):(f=C,C=t)))))),C}function Fge(){var C,Q,R;return C=f,Q=Nge(),Q!==t?(E=f,R=Y1(Q),R?R=void 0:R=t,R!==t?(E=C,Q=j1(Q),C=Q):(f=C,C=t)):(f=C,C=t),C}function Nge(){var C,Q,R,U,le;if(C=f,Q=[],R=f,U=f,T++,le=oK(),T--,le===t?U=void 0:(f=U,U=t),U!==t?(r.length>f?(le=r.charAt(f),f++):(le=t,T===0&&Be(Bo)),le!==t?(E=R,U=An(le),R=U):(f=R,R=t)):(f=R,R=t),R!==t)for(;R!==t;)Q.push(R),R=f,U=f,T++,le=oK(),T--,le===t?U=void 0:(f=U,U=t),U!==t?(r.length>f?(le=r.charAt(f),f++):(le=t,T===0&&Be(Bo)),le!==t?(E=R,U=An(le),R=U):(f=R,R=t)):(f=R,R=t);else Q=t;return Q!==t&&(E=C,Q=Fn(Q)),C=Q,C}function nK(){var C,Q,R;if(C=f,Q=[],_b.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be($b)),R!==t)for(;R!==t;)Q.push(R),_b.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be($b));else Q=t;return Q!==t&&(E=C,Q=eS()),C=Q,C}function Wl(){var C,Q,R;if(C=f,Q=[],ql.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be(jE)),R!==t)for(;R!==t;)Q.push(R),ql.test(r.charAt(f))?(R=r.charAt(f),f++):(R=t,T===0&&Be(jE));else Q=t;return Q!==t&&(E=C,Q=eS()),C=Q,C}function sK(){var C;return tS.test(r.charAt(f))?(C=r.charAt(f),f++):(C=t,T===0&&Be(rS)),C}function oK(){var C;return iS.test(r.charAt(f))?(C=r.charAt(f),f++):(C=t,T===0&&Be(qE)),C}function Me(){var C,Q;if(C=[],Jl.test(r.charAt(f))?(Q=r.charAt(f),f++):(Q=t,T===0&&Be(Bg)),Q!==t)for(;Q!==t;)C.push(Q),Jl.test(r.charAt(f))?(Q=r.charAt(f),f++):(Q=t,T===0&&Be(Bg));else C=t;return C}if($=n(),$!==t&&f===r.length)return $;throw $!==t&&f{"use strict";function Ofe(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function tc(r,e,t,i){this.message=r,this.expected=e,this.found=t,this.location=i,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,tc)}Ofe(tc,Error);tc.buildMessage=function(r,e){var t={literal:function(c){return'"'+n(c.text)+'"'},class:function(c){var u="",g;for(g=0;g0){for(g=1,h=1;gH&&(H=S,q=[]),q.push(ie))}function Re(ie,Y){return new tc(ie,null,null,Y)}function oe(ie,Y,fe){return new tc(tc.buildMessage(ie,Y),ie,Y,fe)}function Ae(){var ie,Y,fe,re;return ie=S,Y=ye(),Y!==t?(r.charCodeAt(S)===47?(fe=s,S++):(fe=t,_===0&&De(o)),fe!==t?(re=ye(),re!==t?(P=ie,Y=a(Y,re),ie=Y):(S=ie,ie=t)):(S=ie,ie=t)):(S=ie,ie=t),ie===t&&(ie=S,Y=ye(),Y!==t&&(P=ie,Y=l(Y)),ie=Y),ie}function ye(){var ie,Y,fe,re;return ie=S,Y=ge(),Y!==t?(r.charCodeAt(S)===64?(fe=c,S++):(fe=t,_===0&&De(u)),fe!==t?(re=je(),re!==t?(P=ie,Y=g(Y,re),ie=Y):(S=ie,ie=t)):(S=ie,ie=t)):(S=ie,ie=t),ie===t&&(ie=S,Y=ge(),Y!==t&&(P=ie,Y=h(Y)),ie=Y),ie}function ge(){var ie,Y,fe,re,de;return ie=S,r.charCodeAt(S)===64?(Y=c,S++):(Y=t,_===0&&De(u)),Y!==t?(fe=ae(),fe!==t?(r.charCodeAt(S)===47?(re=s,S++):(re=t,_===0&&De(o)),re!==t?(de=ae(),de!==t?(P=ie,Y=p(),ie=Y):(S=ie,ie=t)):(S=ie,ie=t)):(S=ie,ie=t)):(S=ie,ie=t),ie===t&&(ie=S,Y=ae(),Y!==t&&(P=ie,Y=p()),ie=Y),ie}function ae(){var ie,Y,fe;if(ie=S,Y=[],d.test(r.charAt(S))?(fe=r.charAt(S),S++):(fe=t,_===0&&De(m)),fe!==t)for(;fe!==t;)Y.push(fe),d.test(r.charAt(S))?(fe=r.charAt(S),S++):(fe=t,_===0&&De(m));else Y=t;return Y!==t&&(P=ie,Y=p()),ie=Y,ie}function je(){var ie,Y,fe;if(ie=S,Y=[],y.test(r.charAt(S))?(fe=r.charAt(S),S++):(fe=t,_===0&&De(B)),fe!==t)for(;fe!==t;)Y.push(fe),y.test(r.charAt(S))?(fe=r.charAt(S),S++):(fe=t,_===0&&De(B));else Y=t;return Y!==t&&(P=ie,Y=p()),ie=Y,ie}if(X=n(),X!==t&&S===r.length)return X;throw X!==t&&S{"use strict";function wU(r){return typeof r>"u"||r===null}function Kfe(r){return typeof r=="object"&&r!==null}function Ufe(r){return Array.isArray(r)?r:wU(r)?[]:[r]}function Hfe(r,e){var t,i,n,s;if(e)for(s=Object.keys(e),t=0,i=s.length;t{"use strict";function Zp(r,e){Error.call(this),this.name="YAMLException",this.reason=r,this.mark=e,this.message=(this.reason||"(unknown reason)")+(this.mark?" "+this.mark.toString():""),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack||""}Zp.prototype=Object.create(Error.prototype);Zp.prototype.constructor=Zp;Zp.prototype.toString=function(e){var t=this.name+": ";return t+=this.reason||"(unknown reason)",!e&&this.mark&&(t+=" "+this.mark.toString()),t};BU.exports=Zp});var SU=I((NZe,bU)=>{"use strict";var QU=ic();function GS(r,e,t,i,n){this.name=r,this.buffer=e,this.position=t,this.line=i,this.column=n}GS.prototype.getSnippet=function(e,t){var i,n,s,o,a;if(!this.buffer)return null;for(e=e||4,t=t||75,i="",n=this.position;n>0&&`\0\r +\x85\u2028\u2029`.indexOf(this.buffer.charAt(n-1))===-1;)if(n-=1,this.position-n>t/2-1){i=" ... ",n+=5;break}for(s="",o=this.position;ot/2-1){s=" ... ",o-=5;break}return a=this.buffer.slice(n,o),QU.repeat(" ",e)+i+a+s+` +`+QU.repeat(" ",e+this.position-n+i.length)+"^"};GS.prototype.toString=function(e){var t,i="";return this.name&&(i+='in "'+this.name+'" '),i+="at line "+(this.line+1)+", column "+(this.column+1),e||(t=this.getSnippet(),t&&(i+=`: +`+t)),i};bU.exports=GS});var ii=I((TZe,xU)=>{"use strict";var vU=Tg(),jfe=["kind","resolve","construct","instanceOf","predicate","represent","defaultStyle","styleAliases"],qfe=["scalar","sequence","mapping"];function Jfe(r){var e={};return r!==null&&Object.keys(r).forEach(function(t){r[t].forEach(function(i){e[String(i)]=t})}),e}function Wfe(r,e){if(e=e||{},Object.keys(e).forEach(function(t){if(jfe.indexOf(t)===-1)throw new vU('Unknown option "'+t+'" is met in definition of "'+r+'" YAML type.')}),this.tag=r,this.kind=e.kind||null,this.resolve=e.resolve||function(){return!0},this.construct=e.construct||function(t){return t},this.instanceOf=e.instanceOf||null,this.predicate=e.predicate||null,this.represent=e.represent||null,this.defaultStyle=e.defaultStyle||null,this.styleAliases=Jfe(e.styleAliases||null),qfe.indexOf(this.kind)===-1)throw new vU('Unknown kind "'+this.kind+'" is specified for "'+r+'" YAML type.')}xU.exports=Wfe});var nc=I((LZe,kU)=>{"use strict";var PU=ic(),CI=Tg(),zfe=ii();function YS(r,e,t){var i=[];return r.include.forEach(function(n){t=YS(n,e,t)}),r[e].forEach(function(n){t.forEach(function(s,o){s.tag===n.tag&&s.kind===n.kind&&i.push(o)}),t.push(n)}),t.filter(function(n,s){return i.indexOf(s)===-1})}function Vfe(){var r={scalar:{},sequence:{},mapping:{},fallback:{}},e,t;function i(n){r[n.kind][n.tag]=r.fallback[n.tag]=n}for(e=0,t=arguments.length;e{"use strict";var Xfe=ii();DU.exports=new Xfe("tag:yaml.org,2002:str",{kind:"scalar",construct:function(r){return r!==null?r:""}})});var NU=I((MZe,FU)=>{"use strict";var Zfe=ii();FU.exports=new Zfe("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(r){return r!==null?r:[]}})});var LU=I((KZe,TU)=>{"use strict";var _fe=ii();TU.exports=new _fe("tag:yaml.org,2002:map",{kind:"mapping",construct:function(r){return r!==null?r:{}}})});var mI=I((UZe,OU)=>{"use strict";var $fe=nc();OU.exports=new $fe({explicit:[RU(),NU(),LU()]})});var KU=I((HZe,MU)=>{"use strict";var ehe=ii();function the(r){if(r===null)return!0;var e=r.length;return e===1&&r==="~"||e===4&&(r==="null"||r==="Null"||r==="NULL")}function rhe(){return null}function ihe(r){return r===null}MU.exports=new ehe("tag:yaml.org,2002:null",{kind:"scalar",resolve:the,construct:rhe,predicate:ihe,represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"}},defaultStyle:"lowercase"})});var HU=I((GZe,UU)=>{"use strict";var nhe=ii();function she(r){if(r===null)return!1;var e=r.length;return e===4&&(r==="true"||r==="True"||r==="TRUE")||e===5&&(r==="false"||r==="False"||r==="FALSE")}function ohe(r){return r==="true"||r==="True"||r==="TRUE"}function ahe(r){return Object.prototype.toString.call(r)==="[object Boolean]"}UU.exports=new nhe("tag:yaml.org,2002:bool",{kind:"scalar",resolve:she,construct:ohe,predicate:ahe,represent:{lowercase:function(r){return r?"true":"false"},uppercase:function(r){return r?"TRUE":"FALSE"},camelcase:function(r){return r?"True":"False"}},defaultStyle:"lowercase"})});var YU=I((YZe,GU)=>{"use strict";var Ahe=ic(),lhe=ii();function che(r){return 48<=r&&r<=57||65<=r&&r<=70||97<=r&&r<=102}function uhe(r){return 48<=r&&r<=55}function ghe(r){return 48<=r&&r<=57}function fhe(r){if(r===null)return!1;var e=r.length,t=0,i=!1,n;if(!e)return!1;if(n=r[t],(n==="-"||n==="+")&&(n=r[++t]),n==="0"){if(t+1===e)return!0;if(n=r[++t],n==="b"){for(t++;t=0?"0b"+r.toString(2):"-0b"+r.toString(2).slice(1)},octal:function(r){return r>=0?"0"+r.toString(8):"-0"+r.toString(8).slice(1)},decimal:function(r){return r.toString(10)},hexadecimal:function(r){return r>=0?"0x"+r.toString(16).toUpperCase():"-0x"+r.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}})});var JU=I((jZe,qU)=>{"use strict";var jU=ic(),dhe=ii(),Che=new RegExp("^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");function mhe(r){return!(r===null||!Che.test(r)||r[r.length-1]==="_")}function Ehe(r){var e,t,i,n;return e=r.replace(/_/g,"").toLowerCase(),t=e[0]==="-"?-1:1,n=[],"+-".indexOf(e[0])>=0&&(e=e.slice(1)),e===".inf"?t===1?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:e===".nan"?NaN:e.indexOf(":")>=0?(e.split(":").forEach(function(s){n.unshift(parseFloat(s,10))}),e=0,i=1,n.forEach(function(s){e+=s*i,i*=60}),t*e):t*parseFloat(e,10)}var Ihe=/^[-+]?[0-9]+e/;function yhe(r,e){var t;if(isNaN(r))switch(e){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===r)switch(e){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===r)switch(e){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(jU.isNegativeZero(r))return"-0.0";return t=r.toString(10),Ihe.test(t)?t.replace("e",".e"):t}function whe(r){return Object.prototype.toString.call(r)==="[object Number]"&&(r%1!==0||jU.isNegativeZero(r))}qU.exports=new dhe("tag:yaml.org,2002:float",{kind:"scalar",resolve:mhe,construct:Ehe,predicate:whe,represent:yhe,defaultStyle:"lowercase"})});var jS=I((qZe,WU)=>{"use strict";var Bhe=nc();WU.exports=new Bhe({include:[mI()],implicit:[KU(),HU(),YU(),JU()]})});var qS=I((JZe,zU)=>{"use strict";var Qhe=nc();zU.exports=new Qhe({include:[jS()]})});var _U=I((WZe,ZU)=>{"use strict";var bhe=ii(),VU=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),XU=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");function She(r){return r===null?!1:VU.exec(r)!==null||XU.exec(r)!==null}function vhe(r){var e,t,i,n,s,o,a,l=0,c=null,u,g,h;if(e=VU.exec(r),e===null&&(e=XU.exec(r)),e===null)throw new Error("Date resolve error");if(t=+e[1],i=+e[2]-1,n=+e[3],!e[4])return new Date(Date.UTC(t,i,n));if(s=+e[4],o=+e[5],a=+e[6],e[7]){for(l=e[7].slice(0,3);l.length<3;)l+="0";l=+l}return e[9]&&(u=+e[10],g=+(e[11]||0),c=(u*60+g)*6e4,e[9]==="-"&&(c=-c)),h=new Date(Date.UTC(t,i,n,s,o,a,l)),c&&h.setTime(h.getTime()-c),h}function xhe(r){return r.toISOString()}ZU.exports=new bhe("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:She,construct:vhe,instanceOf:Date,represent:xhe})});var e2=I((zZe,$U)=>{"use strict";var Phe=ii();function khe(r){return r==="<<"||r===null}$U.exports=new Phe("tag:yaml.org,2002:merge",{kind:"scalar",resolve:khe})});var i2=I((VZe,r2)=>{"use strict";var sc;try{t2=J,sc=t2("buffer").Buffer}catch{}var t2,Dhe=ii(),JS=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= +\r`;function Rhe(r){if(r===null)return!1;var e,t,i=0,n=r.length,s=JS;for(t=0;t64)){if(e<0)return!1;i+=6}return i%8===0}function Fhe(r){var e,t,i=r.replace(/[\r\n=]/g,""),n=i.length,s=JS,o=0,a=[];for(e=0;e>16&255),a.push(o>>8&255),a.push(o&255)),o=o<<6|s.indexOf(i.charAt(e));return t=n%4*6,t===0?(a.push(o>>16&255),a.push(o>>8&255),a.push(o&255)):t===18?(a.push(o>>10&255),a.push(o>>2&255)):t===12&&a.push(o>>4&255),sc?sc.from?sc.from(a):new sc(a):a}function Nhe(r){var e="",t=0,i,n,s=r.length,o=JS;for(i=0;i>18&63],e+=o[t>>12&63],e+=o[t>>6&63],e+=o[t&63]),t=(t<<8)+r[i];return n=s%3,n===0?(e+=o[t>>18&63],e+=o[t>>12&63],e+=o[t>>6&63],e+=o[t&63]):n===2?(e+=o[t>>10&63],e+=o[t>>4&63],e+=o[t<<2&63],e+=o[64]):n===1&&(e+=o[t>>2&63],e+=o[t<<4&63],e+=o[64],e+=o[64]),e}function The(r){return sc&&sc.isBuffer(r)}r2.exports=new Dhe("tag:yaml.org,2002:binary",{kind:"scalar",resolve:Rhe,construct:Fhe,predicate:The,represent:Nhe})});var s2=I((ZZe,n2)=>{"use strict";var Lhe=ii(),Ohe=Object.prototype.hasOwnProperty,Mhe=Object.prototype.toString;function Khe(r){if(r===null)return!0;var e=[],t,i,n,s,o,a=r;for(t=0,i=a.length;t{"use strict";var Hhe=ii(),Ghe=Object.prototype.toString;function Yhe(r){if(r===null)return!0;var e,t,i,n,s,o=r;for(s=new Array(o.length),e=0,t=o.length;e{"use strict";var qhe=ii(),Jhe=Object.prototype.hasOwnProperty;function Whe(r){if(r===null)return!0;var e,t=r;for(e in t)if(Jhe.call(t,e)&&t[e]!==null)return!1;return!0}function zhe(r){return r!==null?r:{}}A2.exports=new qhe("tag:yaml.org,2002:set",{kind:"mapping",resolve:Whe,construct:zhe})});var Og=I((e_e,c2)=>{"use strict";var Vhe=nc();c2.exports=new Vhe({include:[qS()],implicit:[_U(),e2()],explicit:[i2(),s2(),a2(),l2()]})});var g2=I((t_e,u2)=>{"use strict";var Xhe=ii();function Zhe(){return!0}function _he(){}function $he(){return""}function epe(r){return typeof r>"u"}u2.exports=new Xhe("tag:yaml.org,2002:js/undefined",{kind:"scalar",resolve:Zhe,construct:_he,predicate:epe,represent:$he})});var h2=I((r_e,f2)=>{"use strict";var tpe=ii();function rpe(r){if(r===null||r.length===0)return!1;var e=r,t=/\/([gim]*)$/.exec(r),i="";return!(e[0]==="/"&&(t&&(i=t[1]),i.length>3||e[e.length-i.length-1]!=="/"))}function ipe(r){var e=r,t=/\/([gim]*)$/.exec(r),i="";return e[0]==="/"&&(t&&(i=t[1]),e=e.slice(1,e.length-i.length-1)),new RegExp(e,i)}function npe(r){var e="/"+r.source+"/";return r.global&&(e+="g"),r.multiline&&(e+="m"),r.ignoreCase&&(e+="i"),e}function spe(r){return Object.prototype.toString.call(r)==="[object RegExp]"}f2.exports=new tpe("tag:yaml.org,2002:js/regexp",{kind:"scalar",resolve:rpe,construct:ipe,predicate:spe,represent:npe})});var C2=I((i_e,d2)=>{"use strict";var EI;try{p2=J,EI=p2("esprima")}catch{typeof window<"u"&&(EI=window.esprima)}var p2,ope=ii();function ape(r){if(r===null)return!1;try{var e="("+r+")",t=EI.parse(e,{range:!0});return!(t.type!=="Program"||t.body.length!==1||t.body[0].type!=="ExpressionStatement"||t.body[0].expression.type!=="ArrowFunctionExpression"&&t.body[0].expression.type!=="FunctionExpression")}catch{return!1}}function Ape(r){var e="("+r+")",t=EI.parse(e,{range:!0}),i=[],n;if(t.type!=="Program"||t.body.length!==1||t.body[0].type!=="ExpressionStatement"||t.body[0].expression.type!=="ArrowFunctionExpression"&&t.body[0].expression.type!=="FunctionExpression")throw new Error("Failed to resolve function");return t.body[0].expression.params.forEach(function(s){i.push(s.name)}),n=t.body[0].expression.body.range,t.body[0].expression.body.type==="BlockStatement"?new Function(i,e.slice(n[0]+1,n[1]-1)):new Function(i,"return "+e.slice(n[0],n[1]))}function lpe(r){return r.toString()}function cpe(r){return Object.prototype.toString.call(r)==="[object Function]"}d2.exports=new ope("tag:yaml.org,2002:js/function",{kind:"scalar",resolve:ape,construct:Ape,predicate:cpe,represent:lpe})});var _p=I((s_e,E2)=>{"use strict";var m2=nc();E2.exports=m2.DEFAULT=new m2({include:[Og()],explicit:[g2(),h2(),C2()]})});var M2=I((o_e,$p)=>{"use strict";var Qa=ic(),S2=Tg(),upe=SU(),v2=Og(),gpe=_p(),kA=Object.prototype.hasOwnProperty,II=1,x2=2,P2=3,yI=4,WS=1,fpe=2,I2=3,hpe=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,ppe=/[\x85\u2028\u2029]/,dpe=/[,\[\]\{\}]/,k2=/^(?:!|!!|![a-z\-]+!)$/i,D2=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;function y2(r){return Object.prototype.toString.call(r)}function vo(r){return r===10||r===13}function ac(r){return r===9||r===32}function fn(r){return r===9||r===32||r===10||r===13}function Mg(r){return r===44||r===91||r===93||r===123||r===125}function Cpe(r){var e;return 48<=r&&r<=57?r-48:(e=r|32,97<=e&&e<=102?e-97+10:-1)}function mpe(r){return r===120?2:r===117?4:r===85?8:0}function Epe(r){return 48<=r&&r<=57?r-48:-1}function w2(r){return r===48?"\0":r===97?"\x07":r===98?"\b":r===116||r===9?" ":r===110?` +`:r===118?"\v":r===102?"\f":r===114?"\r":r===101?"\x1B":r===32?" ":r===34?'"':r===47?"/":r===92?"\\":r===78?"\x85":r===95?"\xA0":r===76?"\u2028":r===80?"\u2029":""}function Ipe(r){return r<=65535?String.fromCharCode(r):String.fromCharCode((r-65536>>10)+55296,(r-65536&1023)+56320)}var R2=new Array(256),F2=new Array(256);for(oc=0;oc<256;oc++)R2[oc]=w2(oc)?1:0,F2[oc]=w2(oc);var oc;function ype(r,e){this.input=r,this.filename=e.filename||null,this.schema=e.schema||gpe,this.onWarning=e.onWarning||null,this.legacy=e.legacy||!1,this.json=e.json||!1,this.listener=e.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=r.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.documents=[]}function N2(r,e){return new S2(e,new upe(r.filename,r.input,r.position,r.line,r.position-r.lineStart))}function gt(r,e){throw N2(r,e)}function wI(r,e){r.onWarning&&r.onWarning.call(null,N2(r,e))}var B2={YAML:function(e,t,i){var n,s,o;e.version!==null&>(e,"duplication of %YAML directive"),i.length!==1&>(e,"YAML directive accepts exactly one argument"),n=/^([0-9]+)\.([0-9]+)$/.exec(i[0]),n===null&>(e,"ill-formed argument of the YAML directive"),s=parseInt(n[1],10),o=parseInt(n[2],10),s!==1&>(e,"unacceptable YAML version of the document"),e.version=i[0],e.checkLineBreaks=o<2,o!==1&&o!==2&&wI(e,"unsupported YAML version of the document")},TAG:function(e,t,i){var n,s;i.length!==2&>(e,"TAG directive accepts exactly two arguments"),n=i[0],s=i[1],k2.test(n)||gt(e,"ill-formed tag handle (first argument) of the TAG directive"),kA.call(e.tagMap,n)&>(e,'there is a previously declared suffix for "'+n+'" tag handle'),D2.test(s)||gt(e,"ill-formed tag prefix (second argument) of the TAG directive"),e.tagMap[n]=s}};function PA(r,e,t,i){var n,s,o,a;if(e1&&(r.result+=Qa.repeat(` +`,e-1))}function wpe(r,e,t){var i,n,s,o,a,l,c,u,g=r.kind,h=r.result,p;if(p=r.input.charCodeAt(r.position),fn(p)||Mg(p)||p===35||p===38||p===42||p===33||p===124||p===62||p===39||p===34||p===37||p===64||p===96||(p===63||p===45)&&(n=r.input.charCodeAt(r.position+1),fn(n)||t&&Mg(n)))return!1;for(r.kind="scalar",r.result="",s=o=r.position,a=!1;p!==0;){if(p===58){if(n=r.input.charCodeAt(r.position+1),fn(n)||t&&Mg(n))break}else if(p===35){if(i=r.input.charCodeAt(r.position-1),fn(i))break}else{if(r.position===r.lineStart&&BI(r)||t&&Mg(p))break;if(vo(p))if(l=r.line,c=r.lineStart,u=r.lineIndent,qr(r,!1,-1),r.lineIndent>=e){a=!0,p=r.input.charCodeAt(r.position);continue}else{r.position=o,r.line=l,r.lineStart=c,r.lineIndent=u;break}}a&&(PA(r,s,o,!1),VS(r,r.line-l),s=o=r.position,a=!1),ac(p)||(o=r.position+1),p=r.input.charCodeAt(++r.position)}return PA(r,s,o,!1),r.result?!0:(r.kind=g,r.result=h,!1)}function Bpe(r,e){var t,i,n;if(t=r.input.charCodeAt(r.position),t!==39)return!1;for(r.kind="scalar",r.result="",r.position++,i=n=r.position;(t=r.input.charCodeAt(r.position))!==0;)if(t===39)if(PA(r,i,r.position,!0),t=r.input.charCodeAt(++r.position),t===39)i=r.position,r.position++,n=r.position;else return!0;else vo(t)?(PA(r,i,n,!0),VS(r,qr(r,!1,e)),i=n=r.position):r.position===r.lineStart&&BI(r)?gt(r,"unexpected end of the document within a single quoted scalar"):(r.position++,n=r.position);gt(r,"unexpected end of the stream within a single quoted scalar")}function Qpe(r,e){var t,i,n,s,o,a;if(a=r.input.charCodeAt(r.position),a!==34)return!1;for(r.kind="scalar",r.result="",r.position++,t=i=r.position;(a=r.input.charCodeAt(r.position))!==0;){if(a===34)return PA(r,t,r.position,!0),r.position++,!0;if(a===92){if(PA(r,t,r.position,!0),a=r.input.charCodeAt(++r.position),vo(a))qr(r,!1,e);else if(a<256&&R2[a])r.result+=F2[a],r.position++;else if((o=mpe(a))>0){for(n=o,s=0;n>0;n--)a=r.input.charCodeAt(++r.position),(o=Cpe(a))>=0?s=(s<<4)+o:gt(r,"expected hexadecimal character");r.result+=Ipe(s),r.position++}else gt(r,"unknown escape sequence");t=i=r.position}else vo(a)?(PA(r,t,i,!0),VS(r,qr(r,!1,e)),t=i=r.position):r.position===r.lineStart&&BI(r)?gt(r,"unexpected end of the document within a double quoted scalar"):(r.position++,i=r.position)}gt(r,"unexpected end of the stream within a double quoted scalar")}function bpe(r,e){var t=!0,i,n=r.tag,s,o=r.anchor,a,l,c,u,g,h={},p,d,m,y;if(y=r.input.charCodeAt(r.position),y===91)l=93,g=!1,s=[];else if(y===123)l=125,g=!0,s={};else return!1;for(r.anchor!==null&&(r.anchorMap[r.anchor]=s),y=r.input.charCodeAt(++r.position);y!==0;){if(qr(r,!0,e),y=r.input.charCodeAt(r.position),y===l)return r.position++,r.tag=n,r.anchor=o,r.kind=g?"mapping":"sequence",r.result=s,!0;t||gt(r,"missed comma between flow collection entries"),d=p=m=null,c=u=!1,y===63&&(a=r.input.charCodeAt(r.position+1),fn(a)&&(c=u=!0,r.position++,qr(r,!0,e))),i=r.line,Ug(r,e,II,!1,!0),d=r.tag,p=r.result,qr(r,!0,e),y=r.input.charCodeAt(r.position),(u||r.line===i)&&y===58&&(c=!0,y=r.input.charCodeAt(++r.position),qr(r,!0,e),Ug(r,e,II,!1,!0),m=r.result),g?Kg(r,s,h,d,p,m):c?s.push(Kg(r,null,h,d,p,m)):s.push(p),qr(r,!0,e),y=r.input.charCodeAt(r.position),y===44?(t=!0,y=r.input.charCodeAt(++r.position)):t=!1}gt(r,"unexpected end of the stream within a flow collection")}function Spe(r,e){var t,i,n=WS,s=!1,o=!1,a=e,l=0,c=!1,u,g;if(g=r.input.charCodeAt(r.position),g===124)i=!1;else if(g===62)i=!0;else return!1;for(r.kind="scalar",r.result="";g!==0;)if(g=r.input.charCodeAt(++r.position),g===43||g===45)WS===n?n=g===43?I2:fpe:gt(r,"repeat of a chomping mode identifier");else if((u=Epe(g))>=0)u===0?gt(r,"bad explicit indentation width of a block scalar; it cannot be less than one"):o?gt(r,"repeat of an indentation width identifier"):(a=e+u-1,o=!0);else break;if(ac(g)){do g=r.input.charCodeAt(++r.position);while(ac(g));if(g===35)do g=r.input.charCodeAt(++r.position);while(!vo(g)&&g!==0)}for(;g!==0;){for(zS(r),r.lineIndent=0,g=r.input.charCodeAt(r.position);(!o||r.lineIndenta&&(a=r.lineIndent),vo(g)){l++;continue}if(r.lineIndente)&&l!==0)gt(r,"bad indentation of a sequence entry");else if(r.lineIndente)&&(Ug(r,e,yI,!0,n)&&(d?h=r.result:p=r.result),d||(Kg(r,c,u,g,h,p,s,o),g=h=p=null),qr(r,!0,-1),y=r.input.charCodeAt(r.position)),r.lineIndent>e&&y!==0)gt(r,"bad indentation of a mapping entry");else if(r.lineIndente?l=1:r.lineIndent===e?l=0:r.lineIndente?l=1:r.lineIndent===e?l=0:r.lineIndent tag; it should be "scalar", not "'+r.kind+'"'),g=0,h=r.implicitTypes.length;g tag; it should be "'+p.kind+'", not "'+r.kind+'"'),p.resolve(r.result)?(r.result=p.construct(r.result),r.anchor!==null&&(r.anchorMap[r.anchor]=r.result)):gt(r,"cannot resolve a node with !<"+r.tag+"> explicit tag")):gt(r,"unknown tag !<"+r.tag+">");return r.listener!==null&&r.listener("close",r),r.tag!==null||r.anchor!==null||u}function Dpe(r){var e=r.position,t,i,n,s=!1,o;for(r.version=null,r.checkLineBreaks=r.legacy,r.tagMap={},r.anchorMap={};(o=r.input.charCodeAt(r.position))!==0&&(qr(r,!0,-1),o=r.input.charCodeAt(r.position),!(r.lineIndent>0||o!==37));){for(s=!0,o=r.input.charCodeAt(++r.position),t=r.position;o!==0&&!fn(o);)o=r.input.charCodeAt(++r.position);for(i=r.input.slice(t,r.position),n=[],i.length<1&>(r,"directive name must not be less than one character in length");o!==0;){for(;ac(o);)o=r.input.charCodeAt(++r.position);if(o===35){do o=r.input.charCodeAt(++r.position);while(o!==0&&!vo(o));break}if(vo(o))break;for(t=r.position;o!==0&&!fn(o);)o=r.input.charCodeAt(++r.position);n.push(r.input.slice(t,r.position))}o!==0&&zS(r),kA.call(B2,i)?B2[i](r,i,n):wI(r,'unknown document directive "'+i+'"')}if(qr(r,!0,-1),r.lineIndent===0&&r.input.charCodeAt(r.position)===45&&r.input.charCodeAt(r.position+1)===45&&r.input.charCodeAt(r.position+2)===45?(r.position+=3,qr(r,!0,-1)):s&>(r,"directives end mark is expected"),Ug(r,r.lineIndent-1,yI,!1,!0),qr(r,!0,-1),r.checkLineBreaks&&ppe.test(r.input.slice(e,r.position))&&wI(r,"non-ASCII line breaks are interpreted as content"),r.documents.push(r.result),r.position===r.lineStart&&BI(r)){r.input.charCodeAt(r.position)===46&&(r.position+=3,qr(r,!0,-1));return}if(r.position"u"&&(t=e,e=null);var i=T2(r,t);if(typeof e!="function")return i;for(var n=0,s=i.length;n"u"&&(t=e,e=null),L2(r,e,Qa.extend({schema:v2},t))}function Fpe(r,e){return O2(r,Qa.extend({schema:v2},e))}$p.exports.loadAll=L2;$p.exports.load=O2;$p.exports.safeLoadAll=Rpe;$p.exports.safeLoad=Fpe});var aH=I((a_e,$S)=>{"use strict";var td=ic(),rd=Tg(),Npe=_p(),Tpe=Og(),J2=Object.prototype.toString,W2=Object.prototype.hasOwnProperty,Lpe=9,ed=10,Ope=13,Mpe=32,Kpe=33,Upe=34,z2=35,Hpe=37,Gpe=38,Ype=39,jpe=42,V2=44,qpe=45,X2=58,Jpe=61,Wpe=62,zpe=63,Vpe=64,Z2=91,_2=93,Xpe=96,$2=123,Zpe=124,eH=125,Ni={};Ni[0]="\\0";Ni[7]="\\a";Ni[8]="\\b";Ni[9]="\\t";Ni[10]="\\n";Ni[11]="\\v";Ni[12]="\\f";Ni[13]="\\r";Ni[27]="\\e";Ni[34]='\\"';Ni[92]="\\\\";Ni[133]="\\N";Ni[160]="\\_";Ni[8232]="\\L";Ni[8233]="\\P";var _pe=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"];function $pe(r,e){var t,i,n,s,o,a,l;if(e===null)return{};for(t={},i=Object.keys(e),n=0,s=i.length;n0?r.charCodeAt(s-1):null,h=h&&H2(o,a)}else{for(s=0;si&&r[g+1]!==" ",g=s);else if(!Hg(o))return QI;a=s>0?r.charCodeAt(s-1):null,h=h&&H2(o,a)}c=c||u&&s-g-1>i&&r[g+1]!==" "}return!l&&!c?h&&!n(r)?rH:iH:t>9&&tH(r)?QI:c?sH:nH}function sde(r,e,t,i){r.dump=function(){if(e.length===0)return"''";if(!r.noCompatMode&&_pe.indexOf(e)!==-1)return"'"+e+"'";var n=r.indent*Math.max(1,t),s=r.lineWidth===-1?-1:Math.max(Math.min(r.lineWidth,40),r.lineWidth-n),o=i||r.flowLevel>-1&&t>=r.flowLevel;function a(l){return tde(r,l)}switch(nde(e,o,r.indent,s,a)){case rH:return e;case iH:return"'"+e.replace(/'/g,"''")+"'";case nH:return"|"+G2(e,r.indent)+Y2(U2(e,n));case sH:return">"+G2(e,r.indent)+Y2(U2(ode(e,s),n));case QI:return'"'+ade(e,s)+'"';default:throw new rd("impossible error: invalid scalar style")}}()}function G2(r,e){var t=tH(r)?String(e):"",i=r[r.length-1]===` +`,n=i&&(r[r.length-2]===` +`||r===` +`),s=n?"+":i?"":"-";return t+s+` +`}function Y2(r){return r[r.length-1]===` +`?r.slice(0,-1):r}function ode(r,e){for(var t=/(\n+)([^\n]*)/g,i=function(){var c=r.indexOf(` +`);return c=c!==-1?c:r.length,t.lastIndex=c,j2(r.slice(0,c),e)}(),n=r[0]===` +`||r[0]===" ",s,o;o=t.exec(r);){var a=o[1],l=o[2];s=l[0]===" ",i+=a+(!n&&!s&&l!==""?` +`:"")+j2(l,e),n=s}return i}function j2(r,e){if(r===""||r[0]===" ")return r;for(var t=/ [^ ]/g,i,n=0,s,o=0,a=0,l="";i=t.exec(r);)a=i.index,a-n>e&&(s=o>n?o:a,l+=` +`+r.slice(n,s),n=s+1),o=a;return l+=` +`,r.length-n>e&&o>n?l+=r.slice(n,o)+` +`+r.slice(o+1):l+=r.slice(n),l.slice(1)}function ade(r){for(var e="",t,i,n,s=0;s=55296&&t<=56319&&(i=r.charCodeAt(s+1),i>=56320&&i<=57343)){e+=K2((t-55296)*1024+i-56320+65536),s++;continue}n=Ni[t],e+=!n&&Hg(t)?r[s]:n||K2(t)}return e}function Ade(r,e,t){var i="",n=r.tag,s,o;for(s=0,o=t.length;s1024&&(u+="? "),u+=r.dump+(r.condenseFlow?'"':"")+":"+(r.condenseFlow?"":" "),Ac(r,e,c,!1,!1)&&(u+=r.dump,i+=u));r.tag=n,r.dump="{"+i+"}"}function ude(r,e,t,i){var n="",s=r.tag,o=Object.keys(t),a,l,c,u,g,h;if(r.sortKeys===!0)o.sort();else if(typeof r.sortKeys=="function")o.sort(r.sortKeys);else if(r.sortKeys)throw new rd("sortKeys must be a boolean or a function");for(a=0,l=o.length;a1024,g&&(r.dump&&ed===r.dump.charCodeAt(0)?h+="?":h+="? "),h+=r.dump,g&&(h+=XS(r,e)),Ac(r,e+1,u,!0,g)&&(r.dump&&ed===r.dump.charCodeAt(0)?h+=":":h+=": ",h+=r.dump,n+=h));r.tag=s,r.dump=n||"{}"}function q2(r,e,t){var i,n,s,o,a,l;for(n=t?r.explicitTypes:r.implicitTypes,s=0,o=n.length;s tag resolver accepts not "'+l+'" style');r.dump=i}return!0}return!1}function Ac(r,e,t,i,n,s){r.tag=null,r.dump=t,q2(r,t,!1)||q2(r,t,!0);var o=J2.call(r.dump);i&&(i=r.flowLevel<0||r.flowLevel>e);var a=o==="[object Object]"||o==="[object Array]",l,c;if(a&&(l=r.duplicates.indexOf(t),c=l!==-1),(r.tag!==null&&r.tag!=="?"||c||r.indent!==2&&e>0)&&(n=!1),c&&r.usedDuplicates[l])r.dump="*ref_"+l;else{if(a&&c&&!r.usedDuplicates[l]&&(r.usedDuplicates[l]=!0),o==="[object Object]")i&&Object.keys(r.dump).length!==0?(ude(r,e,r.dump,n),c&&(r.dump="&ref_"+l+r.dump)):(cde(r,e,r.dump),c&&(r.dump="&ref_"+l+" "+r.dump));else if(o==="[object Array]"){var u=r.noArrayIndent&&e>0?e-1:e;i&&r.dump.length!==0?(lde(r,u,r.dump,n),c&&(r.dump="&ref_"+l+r.dump)):(Ade(r,u,r.dump),c&&(r.dump="&ref_"+l+" "+r.dump))}else if(o==="[object String]")r.tag!=="?"&&sde(r,r.dump,e,s);else{if(r.skipInvalid)return!1;throw new rd("unacceptable kind of an object to dump "+o)}r.tag!==null&&r.tag!=="?"&&(r.dump="!<"+r.tag+"> "+r.dump)}return!0}function gde(r,e){var t=[],i=[],n,s;for(ZS(r,t,i),n=0,s=i.length;n{"use strict";var bI=M2(),AH=aH();function SI(r){return function(){throw new Error("Function "+r+" is deprecated and cannot be used.")}}Dr.exports.Type=ii();Dr.exports.Schema=nc();Dr.exports.FAILSAFE_SCHEMA=mI();Dr.exports.JSON_SCHEMA=jS();Dr.exports.CORE_SCHEMA=qS();Dr.exports.DEFAULT_SAFE_SCHEMA=Og();Dr.exports.DEFAULT_FULL_SCHEMA=_p();Dr.exports.load=bI.load;Dr.exports.loadAll=bI.loadAll;Dr.exports.safeLoad=bI.safeLoad;Dr.exports.safeLoadAll=bI.safeLoadAll;Dr.exports.dump=AH.dump;Dr.exports.safeDump=AH.safeDump;Dr.exports.YAMLException=Tg();Dr.exports.MINIMAL_SCHEMA=mI();Dr.exports.SAFE_SCHEMA=Og();Dr.exports.DEFAULT_SCHEMA=_p();Dr.exports.scan=SI("scan");Dr.exports.parse=SI("parse");Dr.exports.compose=SI("compose");Dr.exports.addConstructor=SI("addConstructor")});var uH=I((l_e,cH)=>{"use strict";var hde=lH();cH.exports=hde});var fH=I((c_e,gH)=>{"use strict";function pde(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function lc(r,e,t,i){this.message=r,this.expected=e,this.found=t,this.location=i,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,lc)}pde(lc,Error);lc.buildMessage=function(r,e){var t={literal:function(c){return'"'+n(c.text)+'"'},class:function(c){var u="",g;for(g=0;g0){for(g=1,h=1;g({[Le]:pe})))},H=function(D){return D},q=function(D){return D},_=Ks("correct indentation"),X=" ",W=sr(" ",!1),Z=function(D){return D.length===bA*yg},A=function(D){return D.length===(bA+1)*yg},se=function(){return bA++,!0},ue=function(){return bA--,!0},ee=function(){return Cg()},O=Ks("pseudostring"),N=/^[^\r\n\t ?:,\][{}#&*!|>'"%@`\-]/,ce=Tn(["\r",` +`," "," ","?",":",",","]","[","{","}","#","&","*","!","|",">","'",'"',"%","@","`","-"],!0,!1),he=/^[^\r\n\t ,\][{}:#"']/,Pe=Tn(["\r",` +`," "," ",",","]","[","{","}",":","#",'"',"'"],!0,!1),De=function(){return Cg().replace(/^ *| *$/g,"")},Re="--",oe=sr("--",!1),Ae=/^[a-zA-Z\/0-9]/,ye=Tn([["a","z"],["A","Z"],"/",["0","9"]],!1,!1),ge=/^[^\r\n\t :,]/,ae=Tn(["\r",` +`," "," ",":",","],!0,!1),je="null",ie=sr("null",!1),Y=function(){return null},fe="true",re=sr("true",!1),de=function(){return!0},Ze="false",vt=sr("false",!1),mt=function(){return!1},Tr=Ks("string"),ei='"',ci=sr('"',!1),gr=function(){return""},ui=function(D){return D},ti=function(D){return D.join("")},Ms=/^[^"\\\0-\x1F\x7F]/,fr=Tn(['"',"\\",["\0",""],"\x7F"],!0,!1),Ei='\\"',ts=sr('\\"',!1),ua=function(){return'"'},CA="\\\\",gg=sr("\\\\",!1),rs=function(){return"\\"},mA="\\/",ga=sr("\\/",!1),Bp=function(){return"/"},EA="\\b",IA=sr("\\b",!1),Ir=function(){return"\b"},Nl="\\f",fg=sr("\\f",!1),Io=function(){return"\f"},hg="\\n",Qp=sr("\\n",!1),bp=function(){return` +`},br="\\r",ne=sr("\\r",!1),yo=function(){return"\r"},Fn="\\t",pg=sr("\\t",!1),yt=function(){return" "},Tl="\\u",Nn=sr("\\u",!1),is=function(D,j,pe,Le){return String.fromCharCode(parseInt(`0x${D}${j}${pe}${Le}`))},ns=/^[0-9a-fA-F]/,ut=Tn([["0","9"],["a","f"],["A","F"]],!1,!1),wo=Ks("blank space"),At=/^[ \t]/,An=Tn([" "," "],!1,!1),b=Ks("white space"),Ft=/^[ \t\n\r]/,dg=Tn([" "," ",` +`,"\r"],!1,!1),Ll=`\r +`,Sp=sr(`\r +`,!1),vp=` +`,xp=sr(` +`,!1),Pp="\r",kp=sr("\r",!1),G=0,Et=0,yA=[{line:1,column:1}],Wi=0,Ol=[],ze=0,fa;if("startRule"in e){if(!(e.startRule in i))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');n=i[e.startRule]}function Cg(){return r.substring(Et,G)}function KE(){return ln(Et,G)}function Dp(D,j){throw j=j!==void 0?j:ln(Et,G),Kl([Ks(D)],r.substring(Et,G),j)}function UE(D,j){throw j=j!==void 0?j:ln(Et,G),mg(D,j)}function sr(D,j){return{type:"literal",text:D,ignoreCase:j}}function Tn(D,j,pe){return{type:"class",parts:D,inverted:j,ignoreCase:pe}}function Ml(){return{type:"any"}}function Rp(){return{type:"end"}}function Ks(D){return{type:"other",description:D}}function ha(D){var j=yA[D],pe;if(j)return j;for(pe=D-1;!yA[pe];)pe--;for(j=yA[pe],j={line:j.line,column:j.column};peWi&&(Wi=G,Ol=[]),Ol.push(D))}function mg(D,j){return new lc(D,null,null,j)}function Kl(D,j,pe){return new lc(lc.buildMessage(D,j),D,j,pe)}function Us(){var D;return D=Eg(),D}function Ul(){var D,j,pe;for(D=G,j=[],pe=wA();pe!==t;)j.push(pe),pe=wA();return j!==t&&(Et=D,j=s(j)),D=j,D}function wA(){var D,j,pe,Le,ke;return D=G,j=da(),j!==t?(r.charCodeAt(G)===45?(pe=o,G++):(pe=t,ze===0&&Ne(a)),pe!==t?(Le=Lr(),Le!==t?(ke=pa(),ke!==t?(Et=D,j=l(ke),D=j):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t),D}function Eg(){var D,j,pe;for(D=G,j=[],pe=Ig();pe!==t;)j.push(pe),pe=Ig();return j!==t&&(Et=D,j=c(j)),D=j,D}function Ig(){var D,j,pe,Le,ke,Je,pt,Xt,Ea;if(D=G,j=Lr(),j===t&&(j=null),j!==t){if(pe=G,r.charCodeAt(G)===35?(Le=u,G++):(Le=t,ze===0&&Ne(g)),Le!==t){if(ke=[],Je=G,pt=G,ze++,Xt=Gs(),ze--,Xt===t?pt=void 0:(G=pt,pt=t),pt!==t?(r.length>G?(Xt=r.charAt(G),G++):(Xt=t,ze===0&&Ne(h)),Xt!==t?(pt=[pt,Xt],Je=pt):(G=Je,Je=t)):(G=Je,Je=t),Je!==t)for(;Je!==t;)ke.push(Je),Je=G,pt=G,ze++,Xt=Gs(),ze--,Xt===t?pt=void 0:(G=pt,pt=t),pt!==t?(r.length>G?(Xt=r.charAt(G),G++):(Xt=t,ze===0&&Ne(h)),Xt!==t?(pt=[pt,Xt],Je=pt):(G=Je,Je=t)):(G=Je,Je=t);else ke=t;ke!==t?(Le=[Le,ke],pe=Le):(G=pe,pe=t)}else G=pe,pe=t;if(pe===t&&(pe=null),pe!==t){if(Le=[],ke=Hs(),ke!==t)for(;ke!==t;)Le.push(ke),ke=Hs();else Le=t;Le!==t?(Et=D,j=p(),D=j):(G=D,D=t)}else G=D,D=t}else G=D,D=t;if(D===t&&(D=G,j=da(),j!==t?(pe=Fp(),pe!==t?(Le=Lr(),Le===t&&(Le=null),Le!==t?(r.charCodeAt(G)===58?(ke=d,G++):(ke=t,ze===0&&Ne(m)),ke!==t?(Je=Lr(),Je===t&&(Je=null),Je!==t?(pt=pa(),pt!==t?(Et=D,j=y(pe,pt),D=j):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t),D===t&&(D=G,j=da(),j!==t?(pe=Ca(),pe!==t?(Le=Lr(),Le===t&&(Le=null),Le!==t?(r.charCodeAt(G)===58?(ke=d,G++):(ke=t,ze===0&&Ne(m)),ke!==t?(Je=Lr(),Je===t&&(Je=null),Je!==t?(pt=pa(),pt!==t?(Et=D,j=y(pe,pt),D=j):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t),D===t))){if(D=G,j=da(),j!==t)if(pe=Ca(),pe!==t)if(Le=Lr(),Le!==t)if(ke=Gl(),ke!==t){if(Je=[],pt=Hs(),pt!==t)for(;pt!==t;)Je.push(pt),pt=Hs();else Je=t;Je!==t?(Et=D,j=y(pe,ke),D=j):(G=D,D=t)}else G=D,D=t;else G=D,D=t;else G=D,D=t;else G=D,D=t;if(D===t)if(D=G,j=da(),j!==t)if(pe=Ca(),pe!==t){if(Le=[],ke=G,Je=Lr(),Je===t&&(Je=null),Je!==t?(r.charCodeAt(G)===44?(pt=B,G++):(pt=t,ze===0&&Ne(S)),pt!==t?(Xt=Lr(),Xt===t&&(Xt=null),Xt!==t?(Ea=Ca(),Ea!==t?(Et=ke,Je=P(pe,Ea),ke=Je):(G=ke,ke=t)):(G=ke,ke=t)):(G=ke,ke=t)):(G=ke,ke=t),ke!==t)for(;ke!==t;)Le.push(ke),ke=G,Je=Lr(),Je===t&&(Je=null),Je!==t?(r.charCodeAt(G)===44?(pt=B,G++):(pt=t,ze===0&&Ne(S)),pt!==t?(Xt=Lr(),Xt===t&&(Xt=null),Xt!==t?(Ea=Ca(),Ea!==t?(Et=ke,Je=P(pe,Ea),ke=Je):(G=ke,ke=t)):(G=ke,ke=t)):(G=ke,ke=t)):(G=ke,ke=t);else Le=t;Le!==t?(ke=Lr(),ke===t&&(ke=null),ke!==t?(r.charCodeAt(G)===58?(Je=d,G++):(Je=t,ze===0&&Ne(m)),Je!==t?(pt=Lr(),pt===t&&(pt=null),pt!==t?(Xt=pa(),Xt!==t?(Et=D,j=F(pe,Le,Xt),D=j):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)}else G=D,D=t;else G=D,D=t}return D}function pa(){var D,j,pe,Le,ke,Je,pt;if(D=G,j=G,ze++,pe=G,Le=Gs(),Le!==t?(ke=tt(),ke!==t?(r.charCodeAt(G)===45?(Je=o,G++):(Je=t,ze===0&&Ne(a)),Je!==t?(pt=Lr(),pt!==t?(Le=[Le,ke,Je,pt],pe=Le):(G=pe,pe=t)):(G=pe,pe=t)):(G=pe,pe=t)):(G=pe,pe=t),ze--,pe!==t?(G=j,j=void 0):j=t,j!==t?(pe=Hs(),pe!==t?(Le=Bo(),Le!==t?(ke=Ul(),ke!==t?(Je=BA(),Je!==t?(Et=D,j=H(ke),D=j):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t),D===t&&(D=G,j=Gs(),j!==t?(pe=Bo(),pe!==t?(Le=Eg(),Le!==t?(ke=BA(),ke!==t?(Et=D,j=H(Le),D=j):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t),D===t))if(D=G,j=Hl(),j!==t){if(pe=[],Le=Hs(),Le!==t)for(;Le!==t;)pe.push(Le),Le=Hs();else pe=t;pe!==t?(Et=D,j=q(j),D=j):(G=D,D=t)}else G=D,D=t;return D}function da(){var D,j,pe;for(ze++,D=G,j=[],r.charCodeAt(G)===32?(pe=X,G++):(pe=t,ze===0&&Ne(W));pe!==t;)j.push(pe),r.charCodeAt(G)===32?(pe=X,G++):(pe=t,ze===0&&Ne(W));return j!==t?(Et=G,pe=Z(j),pe?pe=void 0:pe=t,pe!==t?(j=[j,pe],D=j):(G=D,D=t)):(G=D,D=t),ze--,D===t&&(j=t,ze===0&&Ne(_)),D}function tt(){var D,j,pe;for(D=G,j=[],r.charCodeAt(G)===32?(pe=X,G++):(pe=t,ze===0&&Ne(W));pe!==t;)j.push(pe),r.charCodeAt(G)===32?(pe=X,G++):(pe=t,ze===0&&Ne(W));return j!==t?(Et=G,pe=A(j),pe?pe=void 0:pe=t,pe!==t?(j=[j,pe],D=j):(G=D,D=t)):(G=D,D=t),D}function Bo(){var D;return Et=G,D=se(),D?D=void 0:D=t,D}function BA(){var D;return Et=G,D=ue(),D?D=void 0:D=t,D}function Fp(){var D;return D=Yl(),D===t&&(D=QA()),D}function Ca(){var D,j,pe;if(D=Yl(),D===t){if(D=G,j=[],pe=ma(),pe!==t)for(;pe!==t;)j.push(pe),pe=ma();else j=t;j!==t&&(Et=D,j=ee()),D=j}return D}function Hl(){var D;return D=Np(),D===t&&(D=HE(),D===t&&(D=Yl(),D===t&&(D=QA()))),D}function Gl(){var D;return D=Np(),D===t&&(D=Yl(),D===t&&(D=ma())),D}function QA(){var D,j,pe,Le,ke,Je;if(ze++,D=G,N.test(r.charAt(G))?(j=r.charAt(G),G++):(j=t,ze===0&&Ne(ce)),j!==t){for(pe=[],Le=G,ke=Lr(),ke===t&&(ke=null),ke!==t?(he.test(r.charAt(G))?(Je=r.charAt(G),G++):(Je=t,ze===0&&Ne(Pe)),Je!==t?(ke=[ke,Je],Le=ke):(G=Le,Le=t)):(G=Le,Le=t);Le!==t;)pe.push(Le),Le=G,ke=Lr(),ke===t&&(ke=null),ke!==t?(he.test(r.charAt(G))?(Je=r.charAt(G),G++):(Je=t,ze===0&&Ne(Pe)),Je!==t?(ke=[ke,Je],Le=ke):(G=Le,Le=t)):(G=Le,Le=t);pe!==t?(Et=D,j=De(),D=j):(G=D,D=t)}else G=D,D=t;return ze--,D===t&&(j=t,ze===0&&Ne(O)),D}function ma(){var D,j,pe,Le,ke;if(D=G,r.substr(G,2)===Re?(j=Re,G+=2):(j=t,ze===0&&Ne(oe)),j===t&&(j=null),j!==t)if(Ae.test(r.charAt(G))?(pe=r.charAt(G),G++):(pe=t,ze===0&&Ne(ye)),pe!==t){for(Le=[],ge.test(r.charAt(G))?(ke=r.charAt(G),G++):(ke=t,ze===0&&Ne(ae));ke!==t;)Le.push(ke),ge.test(r.charAt(G))?(ke=r.charAt(G),G++):(ke=t,ze===0&&Ne(ae));Le!==t?(Et=D,j=De(),D=j):(G=D,D=t)}else G=D,D=t;else G=D,D=t;return D}function Np(){var D,j;return D=G,r.substr(G,4)===je?(j=je,G+=4):(j=t,ze===0&&Ne(ie)),j!==t&&(Et=D,j=Y()),D=j,D}function HE(){var D,j;return D=G,r.substr(G,4)===fe?(j=fe,G+=4):(j=t,ze===0&&Ne(re)),j!==t&&(Et=D,j=de()),D=j,D===t&&(D=G,r.substr(G,5)===Ze?(j=Ze,G+=5):(j=t,ze===0&&Ne(vt)),j!==t&&(Et=D,j=mt()),D=j),D}function Yl(){var D,j,pe,Le;return ze++,D=G,r.charCodeAt(G)===34?(j=ei,G++):(j=t,ze===0&&Ne(ci)),j!==t?(r.charCodeAt(G)===34?(pe=ei,G++):(pe=t,ze===0&&Ne(ci)),pe!==t?(Et=D,j=gr(),D=j):(G=D,D=t)):(G=D,D=t),D===t&&(D=G,r.charCodeAt(G)===34?(j=ei,G++):(j=t,ze===0&&Ne(ci)),j!==t?(pe=GE(),pe!==t?(r.charCodeAt(G)===34?(Le=ei,G++):(Le=t,ze===0&&Ne(ci)),Le!==t?(Et=D,j=ui(pe),D=j):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)),ze--,D===t&&(j=t,ze===0&&Ne(Tr)),D}function GE(){var D,j,pe;if(D=G,j=[],pe=Tp(),pe!==t)for(;pe!==t;)j.push(pe),pe=Tp();else j=t;return j!==t&&(Et=D,j=ti(j)),D=j,D}function Tp(){var D,j,pe,Le,ke,Je;return Ms.test(r.charAt(G))?(D=r.charAt(G),G++):(D=t,ze===0&&Ne(fr)),D===t&&(D=G,r.substr(G,2)===Ei?(j=Ei,G+=2):(j=t,ze===0&&Ne(ts)),j!==t&&(Et=D,j=ua()),D=j,D===t&&(D=G,r.substr(G,2)===CA?(j=CA,G+=2):(j=t,ze===0&&Ne(gg)),j!==t&&(Et=D,j=rs()),D=j,D===t&&(D=G,r.substr(G,2)===mA?(j=mA,G+=2):(j=t,ze===0&&Ne(ga)),j!==t&&(Et=D,j=Bp()),D=j,D===t&&(D=G,r.substr(G,2)===EA?(j=EA,G+=2):(j=t,ze===0&&Ne(IA)),j!==t&&(Et=D,j=Ir()),D=j,D===t&&(D=G,r.substr(G,2)===Nl?(j=Nl,G+=2):(j=t,ze===0&&Ne(fg)),j!==t&&(Et=D,j=Io()),D=j,D===t&&(D=G,r.substr(G,2)===hg?(j=hg,G+=2):(j=t,ze===0&&Ne(Qp)),j!==t&&(Et=D,j=bp()),D=j,D===t&&(D=G,r.substr(G,2)===br?(j=br,G+=2):(j=t,ze===0&&Ne(ne)),j!==t&&(Et=D,j=yo()),D=j,D===t&&(D=G,r.substr(G,2)===Fn?(j=Fn,G+=2):(j=t,ze===0&&Ne(pg)),j!==t&&(Et=D,j=yt()),D=j,D===t&&(D=G,r.substr(G,2)===Tl?(j=Tl,G+=2):(j=t,ze===0&&Ne(Nn)),j!==t?(pe=jl(),pe!==t?(Le=jl(),Le!==t?(ke=jl(),ke!==t?(Je=jl(),Je!==t?(Et=D,j=is(pe,Le,ke,Je),D=j):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)):(G=D,D=t)))))))))),D}function jl(){var D;return ns.test(r.charAt(G))?(D=r.charAt(G),G++):(D=t,ze===0&&Ne(ut)),D}function Lr(){var D,j;if(ze++,D=[],At.test(r.charAt(G))?(j=r.charAt(G),G++):(j=t,ze===0&&Ne(An)),j!==t)for(;j!==t;)D.push(j),At.test(r.charAt(G))?(j=r.charAt(G),G++):(j=t,ze===0&&Ne(An));else D=t;return ze--,D===t&&(j=t,ze===0&&Ne(wo)),D}function YE(){var D,j;if(ze++,D=[],Ft.test(r.charAt(G))?(j=r.charAt(G),G++):(j=t,ze===0&&Ne(dg)),j!==t)for(;j!==t;)D.push(j),Ft.test(r.charAt(G))?(j=r.charAt(G),G++):(j=t,ze===0&&Ne(dg));else D=t;return ze--,D===t&&(j=t,ze===0&&Ne(b)),D}function Hs(){var D,j,pe,Le,ke,Je;if(D=G,j=Gs(),j!==t){for(pe=[],Le=G,ke=Lr(),ke===t&&(ke=null),ke!==t?(Je=Gs(),Je!==t?(ke=[ke,Je],Le=ke):(G=Le,Le=t)):(G=Le,Le=t);Le!==t;)pe.push(Le),Le=G,ke=Lr(),ke===t&&(ke=null),ke!==t?(Je=Gs(),Je!==t?(ke=[ke,Je],Le=ke):(G=Le,Le=t)):(G=Le,Le=t);pe!==t?(j=[j,pe],D=j):(G=D,D=t)}else G=D,D=t;return D}function Gs(){var D;return r.substr(G,2)===Ll?(D=Ll,G+=2):(D=t,ze===0&&Ne(Sp)),D===t&&(r.charCodeAt(G)===10?(D=vp,G++):(D=t,ze===0&&Ne(xp)),D===t&&(r.charCodeAt(G)===13?(D=Pp,G++):(D=t,ze===0&&Ne(kp)))),D}let yg=2,bA=0;if(fa=n(),fa!==t&&G===r.length)return fa;throw fa!==t&&G{"use strict";var yde=r=>{let e=!1,t=!1,i=!1;for(let n=0;n{if(!(typeof r=="string"||Array.isArray(r)))throw new TypeError("Expected the input to be `string | string[]`");e=Object.assign({pascalCase:!1},e);let t=n=>e.pascalCase?n.charAt(0).toUpperCase()+n.slice(1):n;return Array.isArray(r)?r=r.map(n=>n.trim()).filter(n=>n.length).join("-"):r=r.trim(),r.length===0?"":r.length===1?e.pascalCase?r.toUpperCase():r.toLowerCase():(r!==r.toLowerCase()&&(r=yde(r)),r=r.replace(/^[_.\- ]+/,"").toLowerCase().replace(/[_.\- ]+(\w|$)/g,(n,s)=>s.toUpperCase()).replace(/\d+(\w|$)/g,n=>n.toUpperCase()),t(r))};tv.exports=mH;tv.exports.default=mH});var IH=I((d_e,wde)=>{wde.exports=[{name:"AppVeyor",constant:"APPVEYOR",env:"APPVEYOR",pr:"APPVEYOR_PULL_REQUEST_NUMBER"},{name:"Azure Pipelines",constant:"AZURE_PIPELINES",env:"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI",pr:"SYSTEM_PULLREQUEST_PULLREQUESTID"},{name:"Appcircle",constant:"APPCIRCLE",env:"AC_APPCIRCLE"},{name:"Bamboo",constant:"BAMBOO",env:"bamboo_planKey"},{name:"Bitbucket Pipelines",constant:"BITBUCKET",env:"BITBUCKET_COMMIT",pr:"BITBUCKET_PR_ID"},{name:"Bitrise",constant:"BITRISE",env:"BITRISE_IO",pr:"BITRISE_PULL_REQUEST"},{name:"Buddy",constant:"BUDDY",env:"BUDDY_WORKSPACE_ID",pr:"BUDDY_EXECUTION_PULL_REQUEST_ID"},{name:"Buildkite",constant:"BUILDKITE",env:"BUILDKITE",pr:{env:"BUILDKITE_PULL_REQUEST",ne:"false"}},{name:"CircleCI",constant:"CIRCLE",env:"CIRCLECI",pr:"CIRCLE_PULL_REQUEST"},{name:"Cirrus CI",constant:"CIRRUS",env:"CIRRUS_CI",pr:"CIRRUS_PR"},{name:"AWS CodeBuild",constant:"CODEBUILD",env:"CODEBUILD_BUILD_ARN"},{name:"Codefresh",constant:"CODEFRESH",env:"CF_BUILD_ID",pr:{any:["CF_PULL_REQUEST_NUMBER","CF_PULL_REQUEST_ID"]}},{name:"Codeship",constant:"CODESHIP",env:{CI_NAME:"codeship"}},{name:"Drone",constant:"DRONE",env:"DRONE",pr:{DRONE_BUILD_EVENT:"pull_request"}},{name:"dsari",constant:"DSARI",env:"DSARI"},{name:"GitHub Actions",constant:"GITHUB_ACTIONS",env:"GITHUB_ACTIONS",pr:{GITHUB_EVENT_NAME:"pull_request"}},{name:"GitLab CI",constant:"GITLAB",env:"GITLAB_CI",pr:"CI_MERGE_REQUEST_ID"},{name:"GoCD",constant:"GOCD",env:"GO_PIPELINE_LABEL"},{name:"LayerCI",constant:"LAYERCI",env:"LAYERCI",pr:"LAYERCI_PULL_REQUEST"},{name:"Hudson",constant:"HUDSON",env:"HUDSON_URL"},{name:"Jenkins",constant:"JENKINS",env:["JENKINS_URL","BUILD_ID"],pr:{any:["ghprbPullId","CHANGE_ID"]}},{name:"Magnum CI",constant:"MAGNUM",env:"MAGNUM"},{name:"Netlify CI",constant:"NETLIFY",env:"NETLIFY",pr:{env:"PULL_REQUEST",ne:"false"}},{name:"Nevercode",constant:"NEVERCODE",env:"NEVERCODE",pr:{env:"NEVERCODE_PULL_REQUEST",ne:"false"}},{name:"Render",constant:"RENDER",env:"RENDER",pr:{IS_PULL_REQUEST:"true"}},{name:"Sail CI",constant:"SAIL",env:"SAILCI",pr:"SAIL_PULL_REQUEST_NUMBER"},{name:"Semaphore",constant:"SEMAPHORE",env:"SEMAPHORE",pr:"PULL_REQUEST_NUMBER"},{name:"Screwdriver",constant:"SCREWDRIVER",env:"SCREWDRIVER",pr:{env:"SD_PULL_REQUEST",ne:"false"}},{name:"Shippable",constant:"SHIPPABLE",env:"SHIPPABLE",pr:{IS_PULL_REQUEST:"true"}},{name:"Solano CI",constant:"SOLANO",env:"TDDIUM",pr:"TDDIUM_PR_ID"},{name:"Strider CD",constant:"STRIDER",env:"STRIDER"},{name:"TaskCluster",constant:"TASKCLUSTER",env:["TASK_ID","RUN_ID"]},{name:"TeamCity",constant:"TEAMCITY",env:"TEAMCITY_VERSION"},{name:"Travis CI",constant:"TRAVIS",env:"TRAVIS",pr:{env:"TRAVIS_PULL_REQUEST",ne:"false"}},{name:"Vercel",constant:"VERCEL",env:"NOW_BUILDER"},{name:"Visual Studio App Center",constant:"APPCENTER",env:"APPCENTER_BUILD_ID"}]});var cc=I(Kn=>{"use strict";var wH=IH(),xo=process.env;Object.defineProperty(Kn,"_vendors",{value:wH.map(function(r){return r.constant})});Kn.name=null;Kn.isPR=null;wH.forEach(function(r){let t=(Array.isArray(r.env)?r.env:[r.env]).every(function(i){return yH(i)});if(Kn[r.constant]=t,t)switch(Kn.name=r.name,typeof r.pr){case"string":Kn.isPR=!!xo[r.pr];break;case"object":"env"in r.pr?Kn.isPR=r.pr.env in xo&&xo[r.pr.env]!==r.pr.ne:"any"in r.pr?Kn.isPR=r.pr.any.some(function(i){return!!xo[i]}):Kn.isPR=yH(r.pr);break;default:Kn.isPR=null}});Kn.isCI=!!(xo.CI||xo.CONTINUOUS_INTEGRATION||xo.BUILD_NUMBER||xo.RUN_ID||Kn.name);function yH(r){return typeof r=="string"?!!xo[r]:Object.keys(r).every(function(e){return xo[e]===r[e]})}});var hn={};ct(hn,{KeyRelationship:()=>uc,applyCascade:()=>Ad,base64RegExp:()=>vH,colorStringAlphaRegExp:()=>SH,colorStringRegExp:()=>bH,computeKey:()=>DA,getPrintable:()=>Jr,hasExactLength:()=>RH,hasForbiddenKeys:()=>eCe,hasKeyRelationship:()=>Av,hasMaxLength:()=>Ode,hasMinLength:()=>Lde,hasMutuallyExclusiveKeys:()=>tCe,hasRequiredKeys:()=>$de,hasUniqueItems:()=>Mde,isArray:()=>xde,isAtLeast:()=>Hde,isAtMost:()=>Gde,isBase64:()=>Zde,isBoolean:()=>bde,isDate:()=>vde,isDict:()=>kde,isEnum:()=>Xi,isHexColor:()=>Xde,isISO8601:()=>Vde,isInExclusiveRange:()=>jde,isInInclusiveRange:()=>Yde,isInstanceOf:()=>Rde,isInteger:()=>qde,isJSON:()=>_de,isLiteral:()=>Bde,isLowerCase:()=>Jde,isNegative:()=>Kde,isNullable:()=>Tde,isNumber:()=>Sde,isObject:()=>Dde,isOneOf:()=>Fde,isOptional:()=>Nde,isPositive:()=>Ude,isString:()=>ad,isTuple:()=>Pde,isUUID4:()=>zde,isUnknown:()=>DH,isUpperCase:()=>Wde,iso8601RegExp:()=>av,makeCoercionFn:()=>gc,makeSetter:()=>kH,makeTrait:()=>PH,makeValidator:()=>Bt,matchesRegExp:()=>ld,plural:()=>RI,pushError:()=>ht,simpleKeyRegExp:()=>QH,uuid4RegExp:()=>xH});function Bt({test:r}){return PH(r)()}function Jr(r){return r===null?"null":r===void 0?"undefined":r===""?"an empty string":JSON.stringify(r)}function DA(r,e){var t,i,n;return typeof e=="number"?`${(t=r==null?void 0:r.p)!==null&&t!==void 0?t:"."}[${e}]`:QH.test(e)?`${(i=r==null?void 0:r.p)!==null&&i!==void 0?i:""}.${e}`:`${(n=r==null?void 0:r.p)!==null&&n!==void 0?n:"."}[${JSON.stringify(e)}]`}function gc(r,e){return t=>{let i=r[e];return r[e]=t,gc(r,e).bind(null,i)}}function kH(r,e){return t=>{r[e]=t}}function RI(r,e,t){return r===1?e:t}function ht({errors:r,p:e}={},t){return r==null||r.push(`${e!=null?e:"."}: ${t}`),!1}function Bde(r){return Bt({test:(e,t)=>e!==r?ht(t,`Expected a literal (got ${Jr(r)})`):!0})}function Xi(r){let e=Array.isArray(r)?r:Object.values(r),t=new Set(e);return Bt({test:(i,n)=>t.has(i)?!0:ht(n,`Expected a valid enumeration value (got ${Jr(i)})`)})}var QH,bH,SH,vH,xH,av,PH,DH,ad,Qde,bde,Sde,vde,xde,Pde,kde,Dde,Rde,Fde,Ad,Nde,Tde,Lde,Ode,RH,Mde,Kde,Ude,Hde,Gde,Yde,jde,qde,ld,Jde,Wde,zde,Vde,Xde,Zde,_de,$de,eCe,tCe,uc,rCe,Av,as=Uge(()=>{QH=/^[a-zA-Z_][a-zA-Z0-9_]*$/,bH=/^#[0-9a-f]{6}$/i,SH=/^#[0-9a-f]{6}([0-9a-f]{2})?$/i,vH=/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/,xH=/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$/i,av=/^(?:[1-9]\d{3}(-?)(?:(?:0[1-9]|1[0-2])\1(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])\1(?:29|30)|(?:0[13578]|1[02])(?:\1)31|00[1-9]|0[1-9]\d|[12]\d{2}|3(?:[0-5]\d|6[0-5]))|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)(?:(-?)02(?:\2)29|-?366))T(?:[01]\d|2[0-3])(:?)[0-5]\d(?:\3[0-5]\d)?(?:Z|[+-][01]\d(?:\3[0-5]\d)?)$/,PH=r=>()=>r;DH=()=>Bt({test:(r,e)=>!0});ad=()=>Bt({test:(r,e)=>typeof r!="string"?ht(e,`Expected a string (got ${Jr(r)})`):!0});Qde=new Map([["true",!0],["True",!0],["1",!0],[1,!0],["false",!1],["False",!1],["0",!1],[0,!1]]),bde=()=>Bt({test:(r,e)=>{var t;if(typeof r!="boolean"){if(typeof(e==null?void 0:e.coercions)<"u"){if(typeof(e==null?void 0:e.coercion)>"u")return ht(e,"Unbound coercion result");let i=Qde.get(r);if(typeof i<"u")return e.coercions.push([(t=e.p)!==null&&t!==void 0?t:".",e.coercion.bind(null,i)]),!0}return ht(e,`Expected a boolean (got ${Jr(r)})`)}return!0}}),Sde=()=>Bt({test:(r,e)=>{var t;if(typeof r!="number"){if(typeof(e==null?void 0:e.coercions)<"u"){if(typeof(e==null?void 0:e.coercion)>"u")return ht(e,"Unbound coercion result");let i;if(typeof r=="string"){let n;try{n=JSON.parse(r)}catch{}if(typeof n=="number")if(JSON.stringify(n)===r)i=n;else return ht(e,`Received a number that can't be safely represented by the runtime (${r})`)}if(typeof i<"u")return e.coercions.push([(t=e.p)!==null&&t!==void 0?t:".",e.coercion.bind(null,i)]),!0}return ht(e,`Expected a number (got ${Jr(r)})`)}return!0}}),vde=()=>Bt({test:(r,e)=>{var t;if(!(r instanceof Date)){if(typeof(e==null?void 0:e.coercions)<"u"){if(typeof(e==null?void 0:e.coercion)>"u")return ht(e,"Unbound coercion result");let i;if(typeof r=="string"&&av.test(r))i=new Date(r);else{let n;if(typeof r=="string"){let s;try{s=JSON.parse(r)}catch{}typeof s=="number"&&(n=s)}else typeof r=="number"&&(n=r);if(typeof n<"u")if(Number.isSafeInteger(n)||!Number.isSafeInteger(n*1e3))i=new Date(n*1e3);else return ht(e,`Received a timestamp that can't be safely represented by the runtime (${r})`)}if(typeof i<"u")return e.coercions.push([(t=e.p)!==null&&t!==void 0?t:".",e.coercion.bind(null,i)]),!0}return ht(e,`Expected a date (got ${Jr(r)})`)}return!0}}),xde=(r,{delimiter:e}={})=>Bt({test:(t,i)=>{var n;if(typeof t=="string"&&typeof e<"u"&&typeof(i==null?void 0:i.coercions)<"u"){if(typeof(i==null?void 0:i.coercion)>"u")return ht(i,"Unbound coercion result");t=t.split(e),i.coercions.push([(n=i.p)!==null&&n!==void 0?n:".",i.coercion.bind(null,t)])}if(!Array.isArray(t))return ht(i,`Expected an array (got ${Jr(t)})`);let s=!0;for(let o=0,a=t.length;o{let t=RH(r.length);return Bt({test:(i,n)=>{var s;if(typeof i=="string"&&typeof e<"u"&&typeof(n==null?void 0:n.coercions)<"u"){if(typeof(n==null?void 0:n.coercion)>"u")return ht(n,"Unbound coercion result");i=i.split(e),n.coercions.push([(s=n.p)!==null&&s!==void 0?s:".",n.coercion.bind(null,i)])}if(!Array.isArray(i))return ht(n,`Expected a tuple (got ${Jr(i)})`);let o=t(i,Object.assign({},n));for(let a=0,l=i.length;aBt({test:(t,i)=>{if(typeof t!="object"||t===null)return ht(i,`Expected an object (got ${Jr(t)})`);let n=Object.keys(t),s=!0;for(let o=0,a=n.length;o{let t=Object.keys(r);return Bt({test:(i,n)=>{if(typeof i!="object"||i===null)return ht(n,`Expected an object (got ${Jr(i)})`);let s=new Set([...t,...Object.keys(i)]),o={},a=!0;for(let l of s){if(l==="constructor"||l==="__proto__")a=ht(Object.assign(Object.assign({},n),{p:DA(n,l)}),"Unsafe property name");else{let c=Object.prototype.hasOwnProperty.call(r,l)?r[l]:void 0,u=Object.prototype.hasOwnProperty.call(i,l)?i[l]:void 0;typeof c<"u"?a=c(u,Object.assign(Object.assign({},n),{p:DA(n,l),coercion:gc(i,l)}))&&a:e===null?a=ht(Object.assign(Object.assign({},n),{p:DA(n,l)}),`Extraneous property (got ${Jr(u)})`):Object.defineProperty(o,l,{enumerable:!0,get:()=>u,set:kH(i,l)})}if(!a&&(n==null?void 0:n.errors)==null)break}return e!==null&&(a||(n==null?void 0:n.errors)!=null)&&(a=e(o,n)&&a),a}})},Rde=r=>Bt({test:(e,t)=>e instanceof r?!0:ht(t,`Expected an instance of ${r.name} (got ${Jr(e)})`)}),Fde=(r,{exclusive:e=!1}={})=>Bt({test:(t,i)=>{var n,s,o;let a=[],l=typeof(i==null?void 0:i.errors)<"u"?[]:void 0;for(let c=0,u=r.length;c1?ht(i,`Expected to match exactly a single predicate (matched ${a.join(", ")})`):(o=i==null?void 0:i.errors)===null||o===void 0||o.push(...l),!1}}),Ad=(r,e)=>Bt({test:(t,i)=>{var n,s;let o={value:t},a=typeof(i==null?void 0:i.coercions)<"u"?gc(o,"value"):void 0,l=typeof(i==null?void 0:i.coercions)<"u"?[]:void 0;if(!r(t,Object.assign(Object.assign({},i),{coercion:a,coercions:l})))return!1;let c=[];if(typeof l<"u")for(let[,u]of l)c.push(u());try{if(typeof(i==null?void 0:i.coercions)<"u"){if(o.value!==t){if(typeof(i==null?void 0:i.coercion)>"u")return ht(i,"Unbound coercion result");i.coercions.push([(n=i.p)!==null&&n!==void 0?n:".",i.coercion.bind(null,o.value)])}(s=i==null?void 0:i.coercions)===null||s===void 0||s.push(...l)}return e.every(u=>u(o.value,i))}finally{for(let u of c)u()}}}),Nde=r=>Bt({test:(e,t)=>typeof e>"u"?!0:r(e,t)}),Tde=r=>Bt({test:(e,t)=>e===null?!0:r(e,t)}),Lde=r=>Bt({test:(e,t)=>e.length>=r?!0:ht(t,`Expected to have a length of at least ${r} elements (got ${e.length})`)}),Ode=r=>Bt({test:(e,t)=>e.length<=r?!0:ht(t,`Expected to have a length of at most ${r} elements (got ${e.length})`)}),RH=r=>Bt({test:(e,t)=>e.length!==r?ht(t,`Expected to have a length of exactly ${r} elements (got ${e.length})`):!0}),Mde=({map:r}={})=>Bt({test:(e,t)=>{let i=new Set,n=new Set;for(let s=0,o=e.length;sBt({test:(r,e)=>r<=0?!0:ht(e,`Expected to be negative (got ${r})`)}),Ude=()=>Bt({test:(r,e)=>r>=0?!0:ht(e,`Expected to be positive (got ${r})`)}),Hde=r=>Bt({test:(e,t)=>e>=r?!0:ht(t,`Expected to be at least ${r} (got ${e})`)}),Gde=r=>Bt({test:(e,t)=>e<=r?!0:ht(t,`Expected to be at most ${r} (got ${e})`)}),Yde=(r,e)=>Bt({test:(t,i)=>t>=r&&t<=e?!0:ht(i,`Expected to be in the [${r}; ${e}] range (got ${t})`)}),jde=(r,e)=>Bt({test:(t,i)=>t>=r&&tBt({test:(e,t)=>e!==Math.round(e)?ht(t,`Expected to be an integer (got ${e})`):Number.isSafeInteger(e)?!0:ht(t,`Expected to be a safe integer (got ${e})`)}),ld=r=>Bt({test:(e,t)=>r.test(e)?!0:ht(t,`Expected to match the pattern ${r.toString()} (got ${Jr(e)})`)}),Jde=()=>Bt({test:(r,e)=>r!==r.toLowerCase()?ht(e,`Expected to be all-lowercase (got ${r})`):!0}),Wde=()=>Bt({test:(r,e)=>r!==r.toUpperCase()?ht(e,`Expected to be all-uppercase (got ${r})`):!0}),zde=()=>Bt({test:(r,e)=>xH.test(r)?!0:ht(e,`Expected to be a valid UUID v4 (got ${Jr(r)})`)}),Vde=()=>Bt({test:(r,e)=>av.test(r)?!1:ht(e,`Expected to be a valid ISO 8601 date string (got ${Jr(r)})`)}),Xde=({alpha:r=!1})=>Bt({test:(e,t)=>(r?bH.test(e):SH.test(e))?!0:ht(t,`Expected to be a valid hexadecimal color string (got ${Jr(e)})`)}),Zde=()=>Bt({test:(r,e)=>vH.test(r)?!0:ht(e,`Expected to be a valid base 64 string (got ${Jr(r)})`)}),_de=(r=DH())=>Bt({test:(e,t)=>{let i;try{i=JSON.parse(e)}catch{return ht(t,`Expected to be a valid JSON string (got ${Jr(e)})`)}return r(i,t)}}),$de=r=>{let e=new Set(r);return Bt({test:(t,i)=>{let n=new Set(Object.keys(t)),s=[];for(let o of e)n.has(o)||s.push(o);return s.length>0?ht(i,`Missing required ${RI(s.length,"property","properties")} ${s.map(o=>`"${o}"`).join(", ")}`):!0}})},eCe=r=>{let e=new Set(r);return Bt({test:(t,i)=>{let n=new Set(Object.keys(t)),s=[];for(let o of e)n.has(o)&&s.push(o);return s.length>0?ht(i,`Forbidden ${RI(s.length,"property","properties")} ${s.map(o=>`"${o}"`).join(", ")}`):!0}})},tCe=r=>{let e=new Set(r);return Bt({test:(t,i)=>{let n=new Set(Object.keys(t)),s=[];for(let o of e)n.has(o)&&s.push(o);return s.length>1?ht(i,`Mutually exclusive properties ${s.map(o=>`"${o}"`).join(", ")}`):!0}})};(function(r){r.Forbids="Forbids",r.Requires="Requires"})(uc||(uc={}));rCe={[uc.Forbids]:{expect:!1,message:"forbids using"},[uc.Requires]:{expect:!0,message:"requires using"}},Av=(r,e,t,{ignore:i=[]}={})=>{let n=new Set(i),s=new Set(t),o=rCe[e];return Bt({test:(a,l)=>{let c=new Set(Object.keys(a));if(!c.has(r)||n.has(a[r]))return!0;let u=[];for(let g of s)(c.has(g)&&!n.has(a[g]))!==o.expect&&u.push(g);return u.length>=1?ht(l,`Property "${r}" ${o.message} ${RI(u.length,"property","properties")} ${u.map(g=>`"${g}"`).join(", ")}`):!0}})}});var VH=I((d$e,zH)=>{"use strict";zH.exports=(r,...e)=>new Promise(t=>{t(r(...e))})});var Wg=I((C$e,dv)=>{"use strict";var ECe=VH(),XH=r=>{if(r<1)throw new TypeError("Expected `concurrency` to be a number from 1 and up");let e=[],t=0,i=()=>{t--,e.length>0&&e.shift()()},n=(a,l,...c)=>{t++;let u=ECe(a,...c);l(u),u.then(i,i)},s=(a,l,...c)=>{tnew Promise(c=>s(a,c,...l));return Object.defineProperties(o,{activeCount:{get:()=>t},pendingCount:{get:()=>e.length}}),o};dv.exports=XH;dv.exports.default=XH});var hd=I((E$e,ZH)=>{var ICe="2.0.0",yCe=Number.MAX_SAFE_INTEGER||9007199254740991,wCe=16;ZH.exports={SEMVER_SPEC_VERSION:ICe,MAX_LENGTH:256,MAX_SAFE_INTEGER:yCe,MAX_SAFE_COMPONENT_LENGTH:wCe}});var pd=I((I$e,_H)=>{var BCe=typeof process=="object"&&process.env&&process.env.NODE_DEBUG&&/\bsemver\b/i.test(process.env.NODE_DEBUG)?(...r)=>console.error("SEMVER",...r):()=>{};_H.exports=BCe});var fc=I((FA,$H)=>{var{MAX_SAFE_COMPONENT_LENGTH:Cv}=hd(),QCe=pd();FA=$H.exports={};var bCe=FA.re=[],$e=FA.src=[],et=FA.t={},SCe=0,Qt=(r,e,t)=>{let i=SCe++;QCe(i,e),et[r]=i,$e[i]=e,bCe[i]=new RegExp(e,t?"g":void 0)};Qt("NUMERICIDENTIFIER","0|[1-9]\\d*");Qt("NUMERICIDENTIFIERLOOSE","[0-9]+");Qt("NONNUMERICIDENTIFIER","\\d*[a-zA-Z-][a-zA-Z0-9-]*");Qt("MAINVERSION",`(${$e[et.NUMERICIDENTIFIER]})\\.(${$e[et.NUMERICIDENTIFIER]})\\.(${$e[et.NUMERICIDENTIFIER]})`);Qt("MAINVERSIONLOOSE",`(${$e[et.NUMERICIDENTIFIERLOOSE]})\\.(${$e[et.NUMERICIDENTIFIERLOOSE]})\\.(${$e[et.NUMERICIDENTIFIERLOOSE]})`);Qt("PRERELEASEIDENTIFIER",`(?:${$e[et.NUMERICIDENTIFIER]}|${$e[et.NONNUMERICIDENTIFIER]})`);Qt("PRERELEASEIDENTIFIERLOOSE",`(?:${$e[et.NUMERICIDENTIFIERLOOSE]}|${$e[et.NONNUMERICIDENTIFIER]})`);Qt("PRERELEASE",`(?:-(${$e[et.PRERELEASEIDENTIFIER]}(?:\\.${$e[et.PRERELEASEIDENTIFIER]})*))`);Qt("PRERELEASELOOSE",`(?:-?(${$e[et.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${$e[et.PRERELEASEIDENTIFIERLOOSE]})*))`);Qt("BUILDIDENTIFIER","[0-9A-Za-z-]+");Qt("BUILD",`(?:\\+(${$e[et.BUILDIDENTIFIER]}(?:\\.${$e[et.BUILDIDENTIFIER]})*))`);Qt("FULLPLAIN",`v?${$e[et.MAINVERSION]}${$e[et.PRERELEASE]}?${$e[et.BUILD]}?`);Qt("FULL",`^${$e[et.FULLPLAIN]}$`);Qt("LOOSEPLAIN",`[v=\\s]*${$e[et.MAINVERSIONLOOSE]}${$e[et.PRERELEASELOOSE]}?${$e[et.BUILD]}?`);Qt("LOOSE",`^${$e[et.LOOSEPLAIN]}$`);Qt("GTLT","((?:<|>)?=?)");Qt("XRANGEIDENTIFIERLOOSE",`${$e[et.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);Qt("XRANGEIDENTIFIER",`${$e[et.NUMERICIDENTIFIER]}|x|X|\\*`);Qt("XRANGEPLAIN",`[v=\\s]*(${$e[et.XRANGEIDENTIFIER]})(?:\\.(${$e[et.XRANGEIDENTIFIER]})(?:\\.(${$e[et.XRANGEIDENTIFIER]})(?:${$e[et.PRERELEASE]})?${$e[et.BUILD]}?)?)?`);Qt("XRANGEPLAINLOOSE",`[v=\\s]*(${$e[et.XRANGEIDENTIFIERLOOSE]})(?:\\.(${$e[et.XRANGEIDENTIFIERLOOSE]})(?:\\.(${$e[et.XRANGEIDENTIFIERLOOSE]})(?:${$e[et.PRERELEASELOOSE]})?${$e[et.BUILD]}?)?)?`);Qt("XRANGE",`^${$e[et.GTLT]}\\s*${$e[et.XRANGEPLAIN]}$`);Qt("XRANGELOOSE",`^${$e[et.GTLT]}\\s*${$e[et.XRANGEPLAINLOOSE]}$`);Qt("COERCE",`(^|[^\\d])(\\d{1,${Cv}})(?:\\.(\\d{1,${Cv}}))?(?:\\.(\\d{1,${Cv}}))?(?:$|[^\\d])`);Qt("COERCERTL",$e[et.COERCE],!0);Qt("LONETILDE","(?:~>?)");Qt("TILDETRIM",`(\\s*)${$e[et.LONETILDE]}\\s+`,!0);FA.tildeTrimReplace="$1~";Qt("TILDE",`^${$e[et.LONETILDE]}${$e[et.XRANGEPLAIN]}$`);Qt("TILDELOOSE",`^${$e[et.LONETILDE]}${$e[et.XRANGEPLAINLOOSE]}$`);Qt("LONECARET","(?:\\^)");Qt("CARETTRIM",`(\\s*)${$e[et.LONECARET]}\\s+`,!0);FA.caretTrimReplace="$1^";Qt("CARET",`^${$e[et.LONECARET]}${$e[et.XRANGEPLAIN]}$`);Qt("CARETLOOSE",`^${$e[et.LONECARET]}${$e[et.XRANGEPLAINLOOSE]}$`);Qt("COMPARATORLOOSE",`^${$e[et.GTLT]}\\s*(${$e[et.LOOSEPLAIN]})$|^$`);Qt("COMPARATOR",`^${$e[et.GTLT]}\\s*(${$e[et.FULLPLAIN]})$|^$`);Qt("COMPARATORTRIM",`(\\s*)${$e[et.GTLT]}\\s*(${$e[et.LOOSEPLAIN]}|${$e[et.XRANGEPLAIN]})`,!0);FA.comparatorTrimReplace="$1$2$3";Qt("HYPHENRANGE",`^\\s*(${$e[et.XRANGEPLAIN]})\\s+-\\s+(${$e[et.XRANGEPLAIN]})\\s*$`);Qt("HYPHENRANGELOOSE",`^\\s*(${$e[et.XRANGEPLAINLOOSE]})\\s+-\\s+(${$e[et.XRANGEPLAINLOOSE]})\\s*$`);Qt("STAR","(<|>)?=?\\s*\\*");Qt("GTE0","^\\s*>=\\s*0.0.0\\s*$");Qt("GTE0PRE","^\\s*>=\\s*0.0.0-0\\s*$")});var dd=I((y$e,eG)=>{var vCe=["includePrerelease","loose","rtl"],xCe=r=>r?typeof r!="object"?{loose:!0}:vCe.filter(e=>r[e]).reduce((e,t)=>(e[t]=!0,e),{}):{};eG.exports=xCe});var MI=I((w$e,iG)=>{var tG=/^[0-9]+$/,rG=(r,e)=>{let t=tG.test(r),i=tG.test(e);return t&&i&&(r=+r,e=+e),r===e?0:t&&!i?-1:i&&!t?1:rrG(e,r);iG.exports={compareIdentifiers:rG,rcompareIdentifiers:PCe}});var Li=I((B$e,aG)=>{var KI=pd(),{MAX_LENGTH:nG,MAX_SAFE_INTEGER:UI}=hd(),{re:sG,t:oG}=fc(),kCe=dd(),{compareIdentifiers:Cd}=MI(),Gn=class{constructor(e,t){if(t=kCe(t),e instanceof Gn){if(e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease)return e;e=e.version}else if(typeof e!="string")throw new TypeError(`Invalid Version: ${e}`);if(e.length>nG)throw new TypeError(`version is longer than ${nG} characters`);KI("SemVer",e,t),this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease;let i=e.trim().match(t.loose?sG[oG.LOOSE]:sG[oG.FULL]);if(!i)throw new TypeError(`Invalid Version: ${e}`);if(this.raw=e,this.major=+i[1],this.minor=+i[2],this.patch=+i[3],this.major>UI||this.major<0)throw new TypeError("Invalid major version");if(this.minor>UI||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>UI||this.patch<0)throw new TypeError("Invalid patch version");i[4]?this.prerelease=i[4].split(".").map(n=>{if(/^[0-9]+$/.test(n)){let s=+n;if(s>=0&&s=0;)typeof this.prerelease[i]=="number"&&(this.prerelease[i]++,i=-2);i===-1&&this.prerelease.push(0)}t&&(this.prerelease[0]===t?isNaN(this.prerelease[1])&&(this.prerelease=[t,0]):this.prerelease=[t,0]);break;default:throw new Error(`invalid increment argument: ${e}`)}return this.format(),this.raw=this.version,this}};aG.exports=Gn});var hc=I((Q$e,uG)=>{var{MAX_LENGTH:DCe}=hd(),{re:AG,t:lG}=fc(),cG=Li(),RCe=dd(),FCe=(r,e)=>{if(e=RCe(e),r instanceof cG)return r;if(typeof r!="string"||r.length>DCe||!(e.loose?AG[lG.LOOSE]:AG[lG.FULL]).test(r))return null;try{return new cG(r,e)}catch{return null}};uG.exports=FCe});var fG=I((b$e,gG)=>{var NCe=hc(),TCe=(r,e)=>{let t=NCe(r,e);return t?t.version:null};gG.exports=TCe});var pG=I((S$e,hG)=>{var LCe=hc(),OCe=(r,e)=>{let t=LCe(r.trim().replace(/^[=v]+/,""),e);return t?t.version:null};hG.exports=OCe});var CG=I((v$e,dG)=>{var MCe=Li(),KCe=(r,e,t,i)=>{typeof t=="string"&&(i=t,t=void 0);try{return new MCe(r,t).inc(e,i).version}catch{return null}};dG.exports=KCe});var As=I((x$e,EG)=>{var mG=Li(),UCe=(r,e,t)=>new mG(r,t).compare(new mG(e,t));EG.exports=UCe});var HI=I((P$e,IG)=>{var HCe=As(),GCe=(r,e,t)=>HCe(r,e,t)===0;IG.exports=GCe});var BG=I((k$e,wG)=>{var yG=hc(),YCe=HI(),jCe=(r,e)=>{if(YCe(r,e))return null;{let t=yG(r),i=yG(e),n=t.prerelease.length||i.prerelease.length,s=n?"pre":"",o=n?"prerelease":"";for(let a in t)if((a==="major"||a==="minor"||a==="patch")&&t[a]!==i[a])return s+a;return o}};wG.exports=jCe});var bG=I((D$e,QG)=>{var qCe=Li(),JCe=(r,e)=>new qCe(r,e).major;QG.exports=JCe});var vG=I((R$e,SG)=>{var WCe=Li(),zCe=(r,e)=>new WCe(r,e).minor;SG.exports=zCe});var PG=I((F$e,xG)=>{var VCe=Li(),XCe=(r,e)=>new VCe(r,e).patch;xG.exports=XCe});var DG=I((N$e,kG)=>{var ZCe=hc(),_Ce=(r,e)=>{let t=ZCe(r,e);return t&&t.prerelease.length?t.prerelease:null};kG.exports=_Ce});var FG=I((T$e,RG)=>{var $Ce=As(),eme=(r,e,t)=>$Ce(e,r,t);RG.exports=eme});var TG=I((L$e,NG)=>{var tme=As(),rme=(r,e)=>tme(r,e,!0);NG.exports=rme});var GI=I((O$e,OG)=>{var LG=Li(),ime=(r,e,t)=>{let i=new LG(r,t),n=new LG(e,t);return i.compare(n)||i.compareBuild(n)};OG.exports=ime});var KG=I((M$e,MG)=>{var nme=GI(),sme=(r,e)=>r.sort((t,i)=>nme(t,i,e));MG.exports=sme});var HG=I((K$e,UG)=>{var ome=GI(),ame=(r,e)=>r.sort((t,i)=>ome(i,t,e));UG.exports=ame});var md=I((U$e,GG)=>{var Ame=As(),lme=(r,e,t)=>Ame(r,e,t)>0;GG.exports=lme});var YI=I((H$e,YG)=>{var cme=As(),ume=(r,e,t)=>cme(r,e,t)<0;YG.exports=ume});var mv=I((G$e,jG)=>{var gme=As(),fme=(r,e,t)=>gme(r,e,t)!==0;jG.exports=fme});var jI=I((Y$e,qG)=>{var hme=As(),pme=(r,e,t)=>hme(r,e,t)>=0;qG.exports=pme});var qI=I((j$e,JG)=>{var dme=As(),Cme=(r,e,t)=>dme(r,e,t)<=0;JG.exports=Cme});var Ev=I((q$e,WG)=>{var mme=HI(),Eme=mv(),Ime=md(),yme=jI(),wme=YI(),Bme=qI(),Qme=(r,e,t,i)=>{switch(e){case"===":return typeof r=="object"&&(r=r.version),typeof t=="object"&&(t=t.version),r===t;case"!==":return typeof r=="object"&&(r=r.version),typeof t=="object"&&(t=t.version),r!==t;case"":case"=":case"==":return mme(r,t,i);case"!=":return Eme(r,t,i);case">":return Ime(r,t,i);case">=":return yme(r,t,i);case"<":return wme(r,t,i);case"<=":return Bme(r,t,i);default:throw new TypeError(`Invalid operator: ${e}`)}};WG.exports=Qme});var VG=I((J$e,zG)=>{var bme=Li(),Sme=hc(),{re:JI,t:WI}=fc(),vme=(r,e)=>{if(r instanceof bme)return r;if(typeof r=="number"&&(r=String(r)),typeof r!="string")return null;e=e||{};let t=null;if(!e.rtl)t=r.match(JI[WI.COERCE]);else{let i;for(;(i=JI[WI.COERCERTL].exec(r))&&(!t||t.index+t[0].length!==r.length);)(!t||i.index+i[0].length!==t.index+t[0].length)&&(t=i),JI[WI.COERCERTL].lastIndex=i.index+i[1].length+i[2].length;JI[WI.COERCERTL].lastIndex=-1}return t===null?null:Sme(`${t[2]}.${t[3]||"0"}.${t[4]||"0"}`,e)};zG.exports=vme});var ZG=I((W$e,XG)=>{"use strict";XG.exports=function(r){r.prototype[Symbol.iterator]=function*(){for(let e=this.head;e;e=e.next)yield e.value}}});var zI=I((z$e,_G)=>{"use strict";_G.exports=Mt;Mt.Node=pc;Mt.create=Mt;function Mt(r){var e=this;if(e instanceof Mt||(e=new Mt),e.tail=null,e.head=null,e.length=0,r&&typeof r.forEach=="function")r.forEach(function(n){e.push(n)});else if(arguments.length>0)for(var t=0,i=arguments.length;t1)t=e;else if(this.head)i=this.head.next,t=this.head.value;else throw new TypeError("Reduce of empty list with no initial value");for(var n=0;i!==null;n++)t=r(t,i.value,n),i=i.next;return t};Mt.prototype.reduceReverse=function(r,e){var t,i=this.tail;if(arguments.length>1)t=e;else if(this.tail)i=this.tail.prev,t=this.tail.value;else throw new TypeError("Reduce of empty list with no initial value");for(var n=this.length-1;i!==null;n--)t=r(t,i.value,n),i=i.prev;return t};Mt.prototype.toArray=function(){for(var r=new Array(this.length),e=0,t=this.head;t!==null;e++)r[e]=t.value,t=t.next;return r};Mt.prototype.toArrayReverse=function(){for(var r=new Array(this.length),e=0,t=this.tail;t!==null;e++)r[e]=t.value,t=t.prev;return r};Mt.prototype.slice=function(r,e){e=e||this.length,e<0&&(e+=this.length),r=r||0,r<0&&(r+=this.length);var t=new Mt;if(ethis.length&&(e=this.length);for(var i=0,n=this.head;n!==null&&ithis.length&&(e=this.length);for(var i=this.length,n=this.tail;n!==null&&i>e;i--)n=n.prev;for(;n!==null&&i>r;i--,n=n.prev)t.push(n.value);return t};Mt.prototype.splice=function(r,e,...t){r>this.length&&(r=this.length-1),r<0&&(r=this.length+r);for(var i=0,n=this.head;n!==null&&i{"use strict";var Dme=zI(),dc=Symbol("max"),xa=Symbol("length"),zg=Symbol("lengthCalculator"),Id=Symbol("allowStale"),Cc=Symbol("maxAge"),va=Symbol("dispose"),$G=Symbol("noDisposeOnSet"),hi=Symbol("lruList"),Xs=Symbol("cache"),tY=Symbol("updateAgeOnGet"),Iv=()=>1,wv=class{constructor(e){if(typeof e=="number"&&(e={max:e}),e||(e={}),e.max&&(typeof e.max!="number"||e.max<0))throw new TypeError("max must be a non-negative number");let t=this[dc]=e.max||1/0,i=e.length||Iv;if(this[zg]=typeof i!="function"?Iv:i,this[Id]=e.stale||!1,e.maxAge&&typeof e.maxAge!="number")throw new TypeError("maxAge must be a number");this[Cc]=e.maxAge||0,this[va]=e.dispose,this[$G]=e.noDisposeOnSet||!1,this[tY]=e.updateAgeOnGet||!1,this.reset()}set max(e){if(typeof e!="number"||e<0)throw new TypeError("max must be a non-negative number");this[dc]=e||1/0,Ed(this)}get max(){return this[dc]}set allowStale(e){this[Id]=!!e}get allowStale(){return this[Id]}set maxAge(e){if(typeof e!="number")throw new TypeError("maxAge must be a non-negative number");this[Cc]=e,Ed(this)}get maxAge(){return this[Cc]}set lengthCalculator(e){typeof e!="function"&&(e=Iv),e!==this[zg]&&(this[zg]=e,this[xa]=0,this[hi].forEach(t=>{t.length=this[zg](t.value,t.key),this[xa]+=t.length})),Ed(this)}get lengthCalculator(){return this[zg]}get length(){return this[xa]}get itemCount(){return this[hi].length}rforEach(e,t){t=t||this;for(let i=this[hi].tail;i!==null;){let n=i.prev;eY(this,e,i,t),i=n}}forEach(e,t){t=t||this;for(let i=this[hi].head;i!==null;){let n=i.next;eY(this,e,i,t),i=n}}keys(){return this[hi].toArray().map(e=>e.key)}values(){return this[hi].toArray().map(e=>e.value)}reset(){this[va]&&this[hi]&&this[hi].length&&this[hi].forEach(e=>this[va](e.key,e.value)),this[Xs]=new Map,this[hi]=new Dme,this[xa]=0}dump(){return this[hi].map(e=>VI(this,e)?!1:{k:e.key,v:e.value,e:e.now+(e.maxAge||0)}).toArray().filter(e=>e)}dumpLru(){return this[hi]}set(e,t,i){if(i=i||this[Cc],i&&typeof i!="number")throw new TypeError("maxAge must be a number");let n=i?Date.now():0,s=this[zg](t,e);if(this[Xs].has(e)){if(s>this[dc])return Vg(this,this[Xs].get(e)),!1;let l=this[Xs].get(e).value;return this[va]&&(this[$G]||this[va](e,l.value)),l.now=n,l.maxAge=i,l.value=t,this[xa]+=s-l.length,l.length=s,this.get(e),Ed(this),!0}let o=new Bv(e,t,s,n,i);return o.length>this[dc]?(this[va]&&this[va](e,t),!1):(this[xa]+=o.length,this[hi].unshift(o),this[Xs].set(e,this[hi].head),Ed(this),!0)}has(e){if(!this[Xs].has(e))return!1;let t=this[Xs].get(e).value;return!VI(this,t)}get(e){return yv(this,e,!0)}peek(e){return yv(this,e,!1)}pop(){let e=this[hi].tail;return e?(Vg(this,e),e.value):null}del(e){Vg(this,this[Xs].get(e))}load(e){this.reset();let t=Date.now();for(let i=e.length-1;i>=0;i--){let n=e[i],s=n.e||0;if(s===0)this.set(n.k,n.v);else{let o=s-t;o>0&&this.set(n.k,n.v,o)}}}prune(){this[Xs].forEach((e,t)=>yv(this,t,!1))}},yv=(r,e,t)=>{let i=r[Xs].get(e);if(i){let n=i.value;if(VI(r,n)){if(Vg(r,i),!r[Id])return}else t&&(r[tY]&&(i.value.now=Date.now()),r[hi].unshiftNode(i));return n.value}},VI=(r,e)=>{if(!e||!e.maxAge&&!r[Cc])return!1;let t=Date.now()-e.now;return e.maxAge?t>e.maxAge:r[Cc]&&t>r[Cc]},Ed=r=>{if(r[xa]>r[dc])for(let e=r[hi].tail;r[xa]>r[dc]&&e!==null;){let t=e.prev;Vg(r,e),e=t}},Vg=(r,e)=>{if(e){let t=e.value;r[va]&&r[va](t.key,t.value),r[xa]-=t.length,r[Xs].delete(t.key),r[hi].removeNode(e)}},Bv=class{constructor(e,t,i,n,s){this.key=e,this.value=t,this.length=i,this.now=n,this.maxAge=s||0}},eY=(r,e,t,i)=>{let n=t.value;VI(r,n)&&(Vg(r,t),r[Id]||(n=void 0)),n&&e.call(i,n.value,n.key,r)};rY.exports=wv});var ls=I((X$e,aY)=>{var mc=class{constructor(e,t){if(t=Fme(t),e instanceof mc)return e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease?e:new mc(e.raw,t);if(e instanceof Qv)return this.raw=e.value,this.set=[[e]],this.format(),this;if(this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease,this.raw=e,this.set=e.split(/\s*\|\|\s*/).map(i=>this.parseRange(i.trim())).filter(i=>i.length),!this.set.length)throw new TypeError(`Invalid SemVer Range: ${e}`);if(this.set.length>1){let i=this.set[0];if(this.set=this.set.filter(n=>!sY(n[0])),this.set.length===0)this.set=[i];else if(this.set.length>1){for(let n of this.set)if(n.length===1&&Mme(n[0])){this.set=[n];break}}}this.format()}format(){return this.range=this.set.map(e=>e.join(" ").trim()).join("||").trim(),this.range}toString(){return this.range}parseRange(e){e=e.trim();let i=`parseRange:${Object.keys(this.options).join(",")}:${e}`,n=nY.get(i);if(n)return n;let s=this.options.loose,o=s?Oi[bi.HYPHENRANGELOOSE]:Oi[bi.HYPHENRANGE];e=e.replace(o,zme(this.options.includePrerelease)),Mr("hyphen replace",e),e=e.replace(Oi[bi.COMPARATORTRIM],Tme),Mr("comparator trim",e,Oi[bi.COMPARATORTRIM]),e=e.replace(Oi[bi.TILDETRIM],Lme),e=e.replace(Oi[bi.CARETTRIM],Ome),e=e.split(/\s+/).join(" ");let a=s?Oi[bi.COMPARATORLOOSE]:Oi[bi.COMPARATOR],l=e.split(" ").map(h=>Kme(h,this.options)).join(" ").split(/\s+/).map(h=>Wme(h,this.options)).filter(this.options.loose?h=>!!h.match(a):()=>!0).map(h=>new Qv(h,this.options)),c=l.length,u=new Map;for(let h of l){if(sY(h))return[h];u.set(h.value,h)}u.size>1&&u.has("")&&u.delete("");let g=[...u.values()];return nY.set(i,g),g}intersects(e,t){if(!(e instanceof mc))throw new TypeError("a Range is required");return this.set.some(i=>oY(i,t)&&e.set.some(n=>oY(n,t)&&i.every(s=>n.every(o=>s.intersects(o,t)))))}test(e){if(!e)return!1;if(typeof e=="string")try{e=new Nme(e,this.options)}catch{return!1}for(let t=0;tr.value==="<0.0.0-0",Mme=r=>r.value==="",oY=(r,e)=>{let t=!0,i=r.slice(),n=i.pop();for(;t&&i.length;)t=i.every(s=>n.intersects(s,e)),n=i.pop();return t},Kme=(r,e)=>(Mr("comp",r,e),r=Gme(r,e),Mr("caret",r),r=Ume(r,e),Mr("tildes",r),r=jme(r,e),Mr("xrange",r),r=Jme(r,e),Mr("stars",r),r),_i=r=>!r||r.toLowerCase()==="x"||r==="*",Ume=(r,e)=>r.trim().split(/\s+/).map(t=>Hme(t,e)).join(" "),Hme=(r,e)=>{let t=e.loose?Oi[bi.TILDELOOSE]:Oi[bi.TILDE];return r.replace(t,(i,n,s,o,a)=>{Mr("tilde",r,i,n,s,o,a);let l;return _i(n)?l="":_i(s)?l=`>=${n}.0.0 <${+n+1}.0.0-0`:_i(o)?l=`>=${n}.${s}.0 <${n}.${+s+1}.0-0`:a?(Mr("replaceTilde pr",a),l=`>=${n}.${s}.${o}-${a} <${n}.${+s+1}.0-0`):l=`>=${n}.${s}.${o} <${n}.${+s+1}.0-0`,Mr("tilde return",l),l})},Gme=(r,e)=>r.trim().split(/\s+/).map(t=>Yme(t,e)).join(" "),Yme=(r,e)=>{Mr("caret",r,e);let t=e.loose?Oi[bi.CARETLOOSE]:Oi[bi.CARET],i=e.includePrerelease?"-0":"";return r.replace(t,(n,s,o,a,l)=>{Mr("caret",r,n,s,o,a,l);let c;return _i(s)?c="":_i(o)?c=`>=${s}.0.0${i} <${+s+1}.0.0-0`:_i(a)?s==="0"?c=`>=${s}.${o}.0${i} <${s}.${+o+1}.0-0`:c=`>=${s}.${o}.0${i} <${+s+1}.0.0-0`:l?(Mr("replaceCaret pr",l),s==="0"?o==="0"?c=`>=${s}.${o}.${a}-${l} <${s}.${o}.${+a+1}-0`:c=`>=${s}.${o}.${a}-${l} <${s}.${+o+1}.0-0`:c=`>=${s}.${o}.${a}-${l} <${+s+1}.0.0-0`):(Mr("no pr"),s==="0"?o==="0"?c=`>=${s}.${o}.${a}${i} <${s}.${o}.${+a+1}-0`:c=`>=${s}.${o}.${a}${i} <${s}.${+o+1}.0-0`:c=`>=${s}.${o}.${a} <${+s+1}.0.0-0`),Mr("caret return",c),c})},jme=(r,e)=>(Mr("replaceXRanges",r,e),r.split(/\s+/).map(t=>qme(t,e)).join(" ")),qme=(r,e)=>{r=r.trim();let t=e.loose?Oi[bi.XRANGELOOSE]:Oi[bi.XRANGE];return r.replace(t,(i,n,s,o,a,l)=>{Mr("xRange",r,i,n,s,o,a,l);let c=_i(s),u=c||_i(o),g=u||_i(a),h=g;return n==="="&&h&&(n=""),l=e.includePrerelease?"-0":"",c?n===">"||n==="<"?i="<0.0.0-0":i="*":n&&h?(u&&(o=0),a=0,n===">"?(n=">=",u?(s=+s+1,o=0,a=0):(o=+o+1,a=0)):n==="<="&&(n="<",u?s=+s+1:o=+o+1),n==="<"&&(l="-0"),i=`${n+s}.${o}.${a}${l}`):u?i=`>=${s}.0.0${l} <${+s+1}.0.0-0`:g&&(i=`>=${s}.${o}.0${l} <${s}.${+o+1}.0-0`),Mr("xRange return",i),i})},Jme=(r,e)=>(Mr("replaceStars",r,e),r.trim().replace(Oi[bi.STAR],"")),Wme=(r,e)=>(Mr("replaceGTE0",r,e),r.trim().replace(Oi[e.includePrerelease?bi.GTE0PRE:bi.GTE0],"")),zme=r=>(e,t,i,n,s,o,a,l,c,u,g,h,p)=>(_i(i)?t="":_i(n)?t=`>=${i}.0.0${r?"-0":""}`:_i(s)?t=`>=${i}.${n}.0${r?"-0":""}`:o?t=`>=${t}`:t=`>=${t}${r?"-0":""}`,_i(c)?l="":_i(u)?l=`<${+c+1}.0.0-0`:_i(g)?l=`<${c}.${+u+1}.0-0`:h?l=`<=${c}.${u}.${g}-${h}`:r?l=`<${c}.${u}.${+g+1}-0`:l=`<=${l}`,`${t} ${l}`.trim()),Vme=(r,e,t)=>{for(let i=0;i0){let n=r[i].semver;if(n.major===e.major&&n.minor===e.minor&&n.patch===e.patch)return!0}return!1}return!0}});var yd=I((Z$e,gY)=>{var wd=Symbol("SemVer ANY"),Xg=class{static get ANY(){return wd}constructor(e,t){if(t=Xme(t),e instanceof Xg){if(e.loose===!!t.loose)return e;e=e.value}Sv("comparator",e,t),this.options=t,this.loose=!!t.loose,this.parse(e),this.semver===wd?this.value="":this.value=this.operator+this.semver.version,Sv("comp",this)}parse(e){let t=this.options.loose?AY[lY.COMPARATORLOOSE]:AY[lY.COMPARATOR],i=e.match(t);if(!i)throw new TypeError(`Invalid comparator: ${e}`);this.operator=i[1]!==void 0?i[1]:"",this.operator==="="&&(this.operator=""),i[2]?this.semver=new cY(i[2],this.options.loose):this.semver=wd}toString(){return this.value}test(e){if(Sv("Comparator.test",e,this.options.loose),this.semver===wd||e===wd)return!0;if(typeof e=="string")try{e=new cY(e,this.options)}catch{return!1}return bv(e,this.operator,this.semver,this.options)}intersects(e,t){if(!(e instanceof Xg))throw new TypeError("a Comparator is required");if((!t||typeof t!="object")&&(t={loose:!!t,includePrerelease:!1}),this.operator==="")return this.value===""?!0:new uY(e.value,t).test(this.value);if(e.operator==="")return e.value===""?!0:new uY(this.value,t).test(e.semver);let i=(this.operator===">="||this.operator===">")&&(e.operator===">="||e.operator===">"),n=(this.operator==="<="||this.operator==="<")&&(e.operator==="<="||e.operator==="<"),s=this.semver.version===e.semver.version,o=(this.operator===">="||this.operator==="<=")&&(e.operator===">="||e.operator==="<="),a=bv(this.semver,"<",e.semver,t)&&(this.operator===">="||this.operator===">")&&(e.operator==="<="||e.operator==="<"),l=bv(this.semver,">",e.semver,t)&&(this.operator==="<="||this.operator==="<")&&(e.operator===">="||e.operator===">");return i||n||s&&o||a||l}};gY.exports=Xg;var Xme=dd(),{re:AY,t:lY}=fc(),bv=Ev(),Sv=pd(),cY=Li(),uY=ls()});var Bd=I((_$e,fY)=>{var Zme=ls(),_me=(r,e,t)=>{try{e=new Zme(e,t)}catch{return!1}return e.test(r)};fY.exports=_me});var pY=I(($$e,hY)=>{var $me=ls(),eEe=(r,e)=>new $me(r,e).set.map(t=>t.map(i=>i.value).join(" ").trim().split(" "));hY.exports=eEe});var CY=I((eet,dY)=>{var tEe=Li(),rEe=ls(),iEe=(r,e,t)=>{let i=null,n=null,s=null;try{s=new rEe(e,t)}catch{return null}return r.forEach(o=>{s.test(o)&&(!i||n.compare(o)===-1)&&(i=o,n=new tEe(i,t))}),i};dY.exports=iEe});var EY=I((tet,mY)=>{var nEe=Li(),sEe=ls(),oEe=(r,e,t)=>{let i=null,n=null,s=null;try{s=new sEe(e,t)}catch{return null}return r.forEach(o=>{s.test(o)&&(!i||n.compare(o)===1)&&(i=o,n=new nEe(i,t))}),i};mY.exports=oEe});var wY=I((ret,yY)=>{var vv=Li(),aEe=ls(),IY=md(),AEe=(r,e)=>{r=new aEe(r,e);let t=new vv("0.0.0");if(r.test(t)||(t=new vv("0.0.0-0"),r.test(t)))return t;t=null;for(let i=0;i{let a=new vv(o.semver.version);switch(o.operator){case">":a.prerelease.length===0?a.patch++:a.prerelease.push(0),a.raw=a.format();case"":case">=":(!s||IY(a,s))&&(s=a);break;case"<":case"<=":break;default:throw new Error(`Unexpected operation: ${o.operator}`)}}),s&&(!t||IY(t,s))&&(t=s)}return t&&r.test(t)?t:null};yY.exports=AEe});var QY=I((iet,BY)=>{var lEe=ls(),cEe=(r,e)=>{try{return new lEe(r,e).range||"*"}catch{return null}};BY.exports=cEe});var XI=I((net,xY)=>{var uEe=Li(),vY=yd(),{ANY:gEe}=vY,fEe=ls(),hEe=Bd(),bY=md(),SY=YI(),pEe=qI(),dEe=jI(),CEe=(r,e,t,i)=>{r=new uEe(r,i),e=new fEe(e,i);let n,s,o,a,l;switch(t){case">":n=bY,s=pEe,o=SY,a=">",l=">=";break;case"<":n=SY,s=dEe,o=bY,a="<",l="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(hEe(r,e,i))return!1;for(let c=0;c{p.semver===gEe&&(p=new vY(">=0.0.0")),g=g||p,h=h||p,n(p.semver,g.semver,i)?g=p:o(p.semver,h.semver,i)&&(h=p)}),g.operator===a||g.operator===l||(!h.operator||h.operator===a)&&s(r,h.semver))return!1;if(h.operator===l&&o(r,h.semver))return!1}return!0};xY.exports=CEe});var kY=I((set,PY)=>{var mEe=XI(),EEe=(r,e,t)=>mEe(r,e,">",t);PY.exports=EEe});var RY=I((oet,DY)=>{var IEe=XI(),yEe=(r,e,t)=>IEe(r,e,"<",t);DY.exports=yEe});var TY=I((aet,NY)=>{var FY=ls(),wEe=(r,e,t)=>(r=new FY(r,t),e=new FY(e,t),r.intersects(e));NY.exports=wEe});var OY=I((Aet,LY)=>{var BEe=Bd(),QEe=As();LY.exports=(r,e,t)=>{let i=[],n=null,s=null,o=r.sort((u,g)=>QEe(u,g,t));for(let u of o)BEe(u,e,t)?(s=u,n||(n=u)):(s&&i.push([n,s]),s=null,n=null);n&&i.push([n,null]);let a=[];for(let[u,g]of i)u===g?a.push(u):!g&&u===o[0]?a.push("*"):g?u===o[0]?a.push(`<=${g}`):a.push(`${u} - ${g}`):a.push(`>=${u}`);let l=a.join(" || "),c=typeof e.raw=="string"?e.raw:String(e);return l.length{var MY=ls(),ZI=yd(),{ANY:xv}=ZI,Qd=Bd(),Pv=As(),bEe=(r,e,t={})=>{if(r===e)return!0;r=new MY(r,t),e=new MY(e,t);let i=!1;e:for(let n of r.set){for(let s of e.set){let o=SEe(n,s,t);if(i=i||o!==null,o)continue e}if(i)return!1}return!0},SEe=(r,e,t)=>{if(r===e)return!0;if(r.length===1&&r[0].semver===xv){if(e.length===1&&e[0].semver===xv)return!0;t.includePrerelease?r=[new ZI(">=0.0.0-0")]:r=[new ZI(">=0.0.0")]}if(e.length===1&&e[0].semver===xv){if(t.includePrerelease)return!0;e=[new ZI(">=0.0.0")]}let i=new Set,n,s;for(let p of r)p.operator===">"||p.operator===">="?n=KY(n,p,t):p.operator==="<"||p.operator==="<="?s=UY(s,p,t):i.add(p.semver);if(i.size>1)return null;let o;if(n&&s){if(o=Pv(n.semver,s.semver,t),o>0)return null;if(o===0&&(n.operator!==">="||s.operator!=="<="))return null}for(let p of i){if(n&&!Qd(p,String(n),t)||s&&!Qd(p,String(s),t))return null;for(let d of e)if(!Qd(p,String(d),t))return!1;return!0}let a,l,c,u,g=s&&!t.includePrerelease&&s.semver.prerelease.length?s.semver:!1,h=n&&!t.includePrerelease&&n.semver.prerelease.length?n.semver:!1;g&&g.prerelease.length===1&&s.operator==="<"&&g.prerelease[0]===0&&(g=!1);for(let p of e){if(u=u||p.operator===">"||p.operator===">=",c=c||p.operator==="<"||p.operator==="<=",n){if(h&&p.semver.prerelease&&p.semver.prerelease.length&&p.semver.major===h.major&&p.semver.minor===h.minor&&p.semver.patch===h.patch&&(h=!1),p.operator===">"||p.operator===">="){if(a=KY(n,p,t),a===p&&a!==n)return!1}else if(n.operator===">="&&!Qd(n.semver,String(p),t))return!1}if(s){if(g&&p.semver.prerelease&&p.semver.prerelease.length&&p.semver.major===g.major&&p.semver.minor===g.minor&&p.semver.patch===g.patch&&(g=!1),p.operator==="<"||p.operator==="<="){if(l=UY(s,p,t),l===p&&l!==s)return!1}else if(s.operator==="<="&&!Qd(s.semver,String(p),t))return!1}if(!p.operator&&(s||n)&&o!==0)return!1}return!(n&&c&&!s&&o!==0||s&&u&&!n&&o!==0||h||g)},KY=(r,e,t)=>{if(!r)return e;let i=Pv(r.semver,e.semver,t);return i>0?r:i<0||e.operator===">"&&r.operator===">="?e:r},UY=(r,e,t)=>{if(!r)return e;let i=Pv(r.semver,e.semver,t);return i<0?r:i>0||e.operator==="<"&&r.operator==="<="?e:r};HY.exports=bEe});var Wr=I((uet,YY)=>{var kv=fc();YY.exports={re:kv.re,src:kv.src,tokens:kv.t,SEMVER_SPEC_VERSION:hd().SEMVER_SPEC_VERSION,SemVer:Li(),compareIdentifiers:MI().compareIdentifiers,rcompareIdentifiers:MI().rcompareIdentifiers,parse:hc(),valid:fG(),clean:pG(),inc:CG(),diff:BG(),major:bG(),minor:vG(),patch:PG(),prerelease:DG(),compare:As(),rcompare:FG(),compareLoose:TG(),compareBuild:GI(),sort:KG(),rsort:HG(),gt:md(),lt:YI(),eq:HI(),neq:mv(),gte:jI(),lte:qI(),cmp:Ev(),coerce:VG(),Comparator:yd(),Range:ls(),satisfies:Bd(),toComparators:pY(),maxSatisfying:CY(),minSatisfying:EY(),minVersion:wY(),validRange:QY(),outside:XI(),gtr:kY(),ltr:RY(),intersects:TY(),simplifyRange:OY(),subset:GY()}});var Dv=I(_I=>{"use strict";Object.defineProperty(_I,"__esModule",{value:!0});_I.VERSION=void 0;_I.VERSION="9.1.0"});var Kt=I((exports,module)=>{"use strict";var __spreadArray=exports&&exports.__spreadArray||function(r,e,t){if(t||arguments.length===2)for(var i=0,n=e.length,s;i{(function(r,e){typeof define=="function"&&define.amd?define([],e):typeof $I=="object"&&$I.exports?$I.exports=e():r.regexpToAst=e()})(typeof self<"u"?self:jY,function(){function r(){}r.prototype.saveState=function(){return{idx:this.idx,input:this.input,groupIdx:this.groupIdx}},r.prototype.restoreState=function(d){this.idx=d.idx,this.input=d.input,this.groupIdx=d.groupIdx},r.prototype.pattern=function(d){this.idx=0,this.input=d,this.groupIdx=0,this.consumeChar("/");var m=this.disjunction();this.consumeChar("/");for(var y={type:"Flags",loc:{begin:this.idx,end:d.length},global:!1,ignoreCase:!1,multiLine:!1,unicode:!1,sticky:!1};this.isRegExpFlag();)switch(this.popChar()){case"g":o(y,"global");break;case"i":o(y,"ignoreCase");break;case"m":o(y,"multiLine");break;case"u":o(y,"unicode");break;case"y":o(y,"sticky");break}if(this.idx!==this.input.length)throw Error("Redundant input: "+this.input.substring(this.idx));return{type:"Pattern",flags:y,value:m,loc:this.loc(0)}},r.prototype.disjunction=function(){var d=[],m=this.idx;for(d.push(this.alternative());this.peekChar()==="|";)this.consumeChar("|"),d.push(this.alternative());return{type:"Disjunction",value:d,loc:this.loc(m)}},r.prototype.alternative=function(){for(var d=[],m=this.idx;this.isTerm();)d.push(this.term());return{type:"Alternative",value:d,loc:this.loc(m)}},r.prototype.term=function(){return this.isAssertion()?this.assertion():this.atom()},r.prototype.assertion=function(){var d=this.idx;switch(this.popChar()){case"^":return{type:"StartAnchor",loc:this.loc(d)};case"$":return{type:"EndAnchor",loc:this.loc(d)};case"\\":switch(this.popChar()){case"b":return{type:"WordBoundary",loc:this.loc(d)};case"B":return{type:"NonWordBoundary",loc:this.loc(d)}}throw Error("Invalid Assertion Escape");case"(":this.consumeChar("?");var m;switch(this.popChar()){case"=":m="Lookahead";break;case"!":m="NegativeLookahead";break}a(m);var y=this.disjunction();return this.consumeChar(")"),{type:m,value:y,loc:this.loc(d)}}l()},r.prototype.quantifier=function(d){var m,y=this.idx;switch(this.popChar()){case"*":m={atLeast:0,atMost:1/0};break;case"+":m={atLeast:1,atMost:1/0};break;case"?":m={atLeast:0,atMost:1};break;case"{":var B=this.integerIncludingZero();switch(this.popChar()){case"}":m={atLeast:B,atMost:B};break;case",":var S;this.isDigit()?(S=this.integerIncludingZero(),m={atLeast:B,atMost:S}):m={atLeast:B,atMost:1/0},this.consumeChar("}");break}if(d===!0&&m===void 0)return;a(m);break}if(!(d===!0&&m===void 0))return a(m),this.peekChar(0)==="?"?(this.consumeChar("?"),m.greedy=!1):m.greedy=!0,m.type="Quantifier",m.loc=this.loc(y),m},r.prototype.atom=function(){var d,m=this.idx;switch(this.peekChar()){case".":d=this.dotAll();break;case"\\":d=this.atomEscape();break;case"[":d=this.characterClass();break;case"(":d=this.group();break}return d===void 0&&this.isPatternCharacter()&&(d=this.patternCharacter()),a(d),d.loc=this.loc(m),this.isQuantifier()&&(d.quantifier=this.quantifier()),d},r.prototype.dotAll=function(){return this.consumeChar("."),{type:"Set",complement:!0,value:[n(` +`),n("\r"),n("\u2028"),n("\u2029")]}},r.prototype.atomEscape=function(){switch(this.consumeChar("\\"),this.peekChar()){case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":return this.decimalEscapeAtom();case"d":case"D":case"s":case"S":case"w":case"W":return this.characterClassEscape();case"f":case"n":case"r":case"t":case"v":return this.controlEscapeAtom();case"c":return this.controlLetterEscapeAtom();case"0":return this.nulCharacterAtom();case"x":return this.hexEscapeSequenceAtom();case"u":return this.regExpUnicodeEscapeSequenceAtom();default:return this.identityEscapeAtom()}},r.prototype.decimalEscapeAtom=function(){var d=this.positiveInteger();return{type:"GroupBackReference",value:d}},r.prototype.characterClassEscape=function(){var d,m=!1;switch(this.popChar()){case"d":d=u;break;case"D":d=u,m=!0;break;case"s":d=h;break;case"S":d=h,m=!0;break;case"w":d=g;break;case"W":d=g,m=!0;break}return a(d),{type:"Set",value:d,complement:m}},r.prototype.controlEscapeAtom=function(){var d;switch(this.popChar()){case"f":d=n("\f");break;case"n":d=n(` +`);break;case"r":d=n("\r");break;case"t":d=n(" ");break;case"v":d=n("\v");break}return a(d),{type:"Character",value:d}},r.prototype.controlLetterEscapeAtom=function(){this.consumeChar("c");var d=this.popChar();if(/[a-zA-Z]/.test(d)===!1)throw Error("Invalid ");var m=d.toUpperCase().charCodeAt(0)-64;return{type:"Character",value:m}},r.prototype.nulCharacterAtom=function(){return this.consumeChar("0"),{type:"Character",value:n("\0")}},r.prototype.hexEscapeSequenceAtom=function(){return this.consumeChar("x"),this.parseHexDigits(2)},r.prototype.regExpUnicodeEscapeSequenceAtom=function(){return this.consumeChar("u"),this.parseHexDigits(4)},r.prototype.identityEscapeAtom=function(){var d=this.popChar();return{type:"Character",value:n(d)}},r.prototype.classPatternCharacterAtom=function(){switch(this.peekChar()){case` +`:case"\r":case"\u2028":case"\u2029":case"\\":case"]":throw Error("TBD");default:var d=this.popChar();return{type:"Character",value:n(d)}}},r.prototype.characterClass=function(){var d=[],m=!1;for(this.consumeChar("["),this.peekChar(0)==="^"&&(this.consumeChar("^"),m=!0);this.isClassAtom();){var y=this.classAtom(),B=y.type==="Character";if(B&&this.isRangeDash()){this.consumeChar("-");var S=this.classAtom(),P=S.type==="Character";if(P){if(S.value=this.input.length)throw Error("Unexpected end of input");this.idx++},r.prototype.loc=function(d){return{begin:d,end:this.idx}};var e=/[0-9a-fA-F]/,t=/[0-9]/,i=/[1-9]/;function n(d){return d.charCodeAt(0)}function s(d,m){d.length!==void 0?d.forEach(function(y){m.push(y)}):m.push(d)}function o(d,m){if(d[m]===!0)throw"duplicate flag "+m;d[m]=!0}function a(d){if(d===void 0)throw Error("Internal Error - Should never get here!")}function l(){throw Error("Internal Error - Should never get here!")}var c,u=[];for(c=n("0");c<=n("9");c++)u.push(c);var g=[n("_")].concat(u);for(c=n("a");c<=n("z");c++)g.push(c);for(c=n("A");c<=n("Z");c++)g.push(c);var h=[n(" "),n("\f"),n(` +`),n("\r"),n(" "),n("\v"),n(" "),n("\xA0"),n("\u1680"),n("\u2000"),n("\u2001"),n("\u2002"),n("\u2003"),n("\u2004"),n("\u2005"),n("\u2006"),n("\u2007"),n("\u2008"),n("\u2009"),n("\u200A"),n("\u2028"),n("\u2029"),n("\u202F"),n("\u205F"),n("\u3000"),n("\uFEFF")];function p(){}return p.prototype.visitChildren=function(d){for(var m in d){var y=d[m];d.hasOwnProperty(m)&&(y.type!==void 0?this.visit(y):Array.isArray(y)&&y.forEach(function(B){this.visit(B)},this))}},p.prototype.visit=function(d){switch(d.type){case"Pattern":this.visitPattern(d);break;case"Flags":this.visitFlags(d);break;case"Disjunction":this.visitDisjunction(d);break;case"Alternative":this.visitAlternative(d);break;case"StartAnchor":this.visitStartAnchor(d);break;case"EndAnchor":this.visitEndAnchor(d);break;case"WordBoundary":this.visitWordBoundary(d);break;case"NonWordBoundary":this.visitNonWordBoundary(d);break;case"Lookahead":this.visitLookahead(d);break;case"NegativeLookahead":this.visitNegativeLookahead(d);break;case"Character":this.visitCharacter(d);break;case"Set":this.visitSet(d);break;case"Group":this.visitGroup(d);break;case"GroupBackReference":this.visitGroupBackReference(d);break;case"Quantifier":this.visitQuantifier(d);break}this.visitChildren(d)},p.prototype.visitPattern=function(d){},p.prototype.visitFlags=function(d){},p.prototype.visitDisjunction=function(d){},p.prototype.visitAlternative=function(d){},p.prototype.visitStartAnchor=function(d){},p.prototype.visitEndAnchor=function(d){},p.prototype.visitWordBoundary=function(d){},p.prototype.visitNonWordBoundary=function(d){},p.prototype.visitLookahead=function(d){},p.prototype.visitNegativeLookahead=function(d){},p.prototype.visitCharacter=function(d){},p.prototype.visitSet=function(d){},p.prototype.visitGroup=function(d){},p.prototype.visitGroupBackReference=function(d){},p.prototype.visitQuantifier=function(d){},{RegExpParser:r,BaseRegExpVisitor:p,VERSION:"0.5.0"}})});var ry=I(Zg=>{"use strict";Object.defineProperty(Zg,"__esModule",{value:!0});Zg.clearRegExpParserCache=Zg.getRegExpAst=void 0;var vEe=ey(),ty={},xEe=new vEe.RegExpParser;function PEe(r){var e=r.toString();if(ty.hasOwnProperty(e))return ty[e];var t=xEe.pattern(e);return ty[e]=t,t}Zg.getRegExpAst=PEe;function kEe(){ty={}}Zg.clearRegExpParserCache=kEe});var VY=I(Cn=>{"use strict";var DEe=Cn&&Cn.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Cn,"__esModule",{value:!0});Cn.canMatchCharCode=Cn.firstCharOptimizedIndices=Cn.getOptimizedStartCodesIndices=Cn.failedOptimizationPrefixMsg=void 0;var JY=ey(),cs=Kt(),WY=ry(),Pa=Fv(),zY="Complement Sets are not supported for first char optimization";Cn.failedOptimizationPrefixMsg=`Unable to use "first char" lexer optimizations: +`;function REe(r,e){e===void 0&&(e=!1);try{var t=(0,WY.getRegExpAst)(r),i=ny(t.value,{},t.flags.ignoreCase);return i}catch(s){if(s.message===zY)e&&(0,cs.PRINT_WARNING)(""+Cn.failedOptimizationPrefixMsg+(" Unable to optimize: < "+r.toString()+` > +`)+` Complement Sets cannot be automatically optimized. + This will disable the lexer's first char optimizations. + See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#COMPLEMENT for details.`);else{var n="";e&&(n=` + This will disable the lexer's first char optimizations. + See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#REGEXP_PARSING for details.`),(0,cs.PRINT_ERROR)(Cn.failedOptimizationPrefixMsg+` +`+(" Failed parsing: < "+r.toString()+` > +`)+(" Using the regexp-to-ast library version: "+JY.VERSION+` +`)+" Please open an issue at: https://github.com/bd82/regexp-to-ast/issues"+n)}}return[]}Cn.getOptimizedStartCodesIndices=REe;function ny(r,e,t){switch(r.type){case"Disjunction":for(var i=0;i=Pa.minOptimizationVal)for(var h=u.from>=Pa.minOptimizationVal?u.from:Pa.minOptimizationVal,p=u.to,d=(0,Pa.charCodeToOptimizedIndex)(h),m=(0,Pa.charCodeToOptimizedIndex)(p),y=d;y<=m;y++)e[y]=y}}});break;case"Group":ny(o.value,e,t);break;default:throw Error("Non Exhaustive Match")}var a=o.quantifier!==void 0&&o.quantifier.atLeast===0;if(o.type==="Group"&&Rv(o)===!1||o.type!=="Group"&&a===!1)break}break;default:throw Error("non exhaustive match!")}return(0,cs.values)(e)}Cn.firstCharOptimizedIndices=ny;function iy(r,e,t){var i=(0,Pa.charCodeToOptimizedIndex)(r);e[i]=i,t===!0&&FEe(r,e)}function FEe(r,e){var t=String.fromCharCode(r),i=t.toUpperCase();if(i!==t){var n=(0,Pa.charCodeToOptimizedIndex)(i.charCodeAt(0));e[n]=n}else{var s=t.toLowerCase();if(s!==t){var n=(0,Pa.charCodeToOptimizedIndex)(s.charCodeAt(0));e[n]=n}}}function qY(r,e){return(0,cs.find)(r.value,function(t){if(typeof t=="number")return(0,cs.contains)(e,t);var i=t;return(0,cs.find)(e,function(n){return i.from<=n&&n<=i.to})!==void 0})}function Rv(r){return r.quantifier&&r.quantifier.atLeast===0?!0:r.value?(0,cs.isArray)(r.value)?(0,cs.every)(r.value,Rv):Rv(r.value):!1}var NEe=function(r){DEe(e,r);function e(t){var i=r.call(this)||this;return i.targetCharCodes=t,i.found=!1,i}return e.prototype.visitChildren=function(t){if(this.found!==!0){switch(t.type){case"Lookahead":this.visitLookahead(t);return;case"NegativeLookahead":this.visitNegativeLookahead(t);return}r.prototype.visitChildren.call(this,t)}},e.prototype.visitCharacter=function(t){(0,cs.contains)(this.targetCharCodes,t.value)&&(this.found=!0)},e.prototype.visitSet=function(t){t.complement?qY(t,this.targetCharCodes)===void 0&&(this.found=!0):qY(t,this.targetCharCodes)!==void 0&&(this.found=!0)},e}(JY.BaseRegExpVisitor);function TEe(r,e){if(e instanceof RegExp){var t=(0,WY.getRegExpAst)(e),i=new NEe(r);return i.visit(t),i.found}else return(0,cs.find)(e,function(n){return(0,cs.contains)(r,n.charCodeAt(0))})!==void 0}Cn.canMatchCharCode=TEe});var Fv=I(We=>{"use strict";var XY=We&&We.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(We,"__esModule",{value:!0});We.charCodeToOptimizedIndex=We.minOptimizationVal=We.buildLineBreakIssueMessage=We.LineTerminatorOptimizedTester=We.isShortPattern=We.isCustomPattern=We.cloneEmptyGroups=We.performWarningRuntimeChecks=We.performRuntimeChecks=We.addStickyFlag=We.addStartOfInput=We.findUnreachablePatterns=We.findModesThatDoNotExist=We.findInvalidGroupType=We.findDuplicatePatterns=We.findUnsupportedFlags=We.findStartOfInputAnchor=We.findEmptyMatchRegExps=We.findEndOfInputAnchor=We.findInvalidPatterns=We.findMissingPatterns=We.validatePatterns=We.analyzeTokenTypes=We.enableSticky=We.disableSticky=We.SUPPORT_STICKY=We.MODES=We.DEFAULT_MODE=void 0;var ZY=ey(),tr=bd(),Se=Kt(),_g=VY(),_Y=ry(),ko="PATTERN";We.DEFAULT_MODE="defaultMode";We.MODES="modes";We.SUPPORT_STICKY=typeof new RegExp("(?:)").sticky=="boolean";function LEe(){We.SUPPORT_STICKY=!1}We.disableSticky=LEe;function OEe(){We.SUPPORT_STICKY=!0}We.enableSticky=OEe;function MEe(r,e){e=(0,Se.defaults)(e,{useSticky:We.SUPPORT_STICKY,debug:!1,safeMode:!1,positionTracking:"full",lineTerminatorCharacters:["\r",` +`],tracer:function(S,P){return P()}});var t=e.tracer;t("initCharCodeToOptimizedIndexMap",function(){zEe()});var i;t("Reject Lexer.NA",function(){i=(0,Se.reject)(r,function(S){return S[ko]===tr.Lexer.NA})});var n=!1,s;t("Transform Patterns",function(){n=!1,s=(0,Se.map)(i,function(S){var P=S[ko];if((0,Se.isRegExp)(P)){var F=P.source;return F.length===1&&F!=="^"&&F!=="$"&&F!=="."&&!P.ignoreCase?F:F.length===2&&F[0]==="\\"&&!(0,Se.contains)(["d","D","s","S","t","r","n","t","0","c","b","B","f","v","w","W"],F[1])?F[1]:e.useSticky?Lv(P):Tv(P)}else{if((0,Se.isFunction)(P))return n=!0,{exec:P};if((0,Se.has)(P,"exec"))return n=!0,P;if(typeof P=="string"){if(P.length===1)return P;var H=P.replace(/[\\^$.*+?()[\]{}|]/g,"\\$&"),q=new RegExp(H);return e.useSticky?Lv(q):Tv(q)}else throw Error("non exhaustive match")}})});var o,a,l,c,u;t("misc mapping",function(){o=(0,Se.map)(i,function(S){return S.tokenTypeIdx}),a=(0,Se.map)(i,function(S){var P=S.GROUP;if(P!==tr.Lexer.SKIPPED){if((0,Se.isString)(P))return P;if((0,Se.isUndefined)(P))return!1;throw Error("non exhaustive match")}}),l=(0,Se.map)(i,function(S){var P=S.LONGER_ALT;if(P){var F=(0,Se.isArray)(P)?(0,Se.map)(P,function(H){return(0,Se.indexOf)(i,H)}):[(0,Se.indexOf)(i,P)];return F}}),c=(0,Se.map)(i,function(S){return S.PUSH_MODE}),u=(0,Se.map)(i,function(S){return(0,Se.has)(S,"POP_MODE")})});var g;t("Line Terminator Handling",function(){var S=gj(e.lineTerminatorCharacters);g=(0,Se.map)(i,function(P){return!1}),e.positionTracking!=="onlyOffset"&&(g=(0,Se.map)(i,function(P){if((0,Se.has)(P,"LINE_BREAKS"))return P.LINE_BREAKS;if(cj(P,S)===!1)return(0,_g.canMatchCharCode)(S,P.PATTERN)}))});var h,p,d,m;t("Misc Mapping #2",function(){h=(0,Se.map)(i,Mv),p=(0,Se.map)(s,lj),d=(0,Se.reduce)(i,function(S,P){var F=P.GROUP;return(0,Se.isString)(F)&&F!==tr.Lexer.SKIPPED&&(S[F]=[]),S},{}),m=(0,Se.map)(s,function(S,P){return{pattern:s[P],longerAlt:l[P],canLineTerminator:g[P],isCustom:h[P],short:p[P],group:a[P],push:c[P],pop:u[P],tokenTypeIdx:o[P],tokenType:i[P]}})});var y=!0,B=[];return e.safeMode||t("First Char Optimization",function(){B=(0,Se.reduce)(i,function(S,P,F){if(typeof P.PATTERN=="string"){var H=P.PATTERN.charCodeAt(0),q=Ov(H);Nv(S,q,m[F])}else if((0,Se.isArray)(P.START_CHARS_HINT)){var _;(0,Se.forEach)(P.START_CHARS_HINT,function(W){var Z=typeof W=="string"?W.charCodeAt(0):W,A=Ov(Z);_!==A&&(_=A,Nv(S,A,m[F]))})}else if((0,Se.isRegExp)(P.PATTERN))if(P.PATTERN.unicode)y=!1,e.ensureOptimizations&&(0,Se.PRINT_ERROR)(""+_g.failedOptimizationPrefixMsg+(" Unable to analyze < "+P.PATTERN.toString()+` > pattern. +`)+` The regexp unicode flag is not currently supported by the regexp-to-ast library. + This will disable the lexer's first char optimizations. + For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#UNICODE_OPTIMIZE`);else{var X=(0,_g.getOptimizedStartCodesIndices)(P.PATTERN,e.ensureOptimizations);(0,Se.isEmpty)(X)&&(y=!1),(0,Se.forEach)(X,function(W){Nv(S,W,m[F])})}else e.ensureOptimizations&&(0,Se.PRINT_ERROR)(""+_g.failedOptimizationPrefixMsg+(" TokenType: <"+P.name+`> is using a custom token pattern without providing parameter. +`)+` This will disable the lexer's first char optimizations. + For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#CUSTOM_OPTIMIZE`),y=!1;return S},[])}),t("ArrayPacking",function(){B=(0,Se.packArray)(B)}),{emptyGroups:d,patternIdxToConfig:m,charCodeToPatternIdxToConfig:B,hasCustom:n,canBeOptimized:y}}We.analyzeTokenTypes=MEe;function KEe(r,e){var t=[],i=$Y(r);t=t.concat(i.errors);var n=ej(i.valid),s=n.valid;return t=t.concat(n.errors),t=t.concat(UEe(s)),t=t.concat(oj(s)),t=t.concat(aj(s,e)),t=t.concat(Aj(s)),t}We.validatePatterns=KEe;function UEe(r){var e=[],t=(0,Se.filter)(r,function(i){return(0,Se.isRegExp)(i[ko])});return e=e.concat(tj(t)),e=e.concat(ij(t)),e=e.concat(nj(t)),e=e.concat(sj(t)),e=e.concat(rj(t)),e}function $Y(r){var e=(0,Se.filter)(r,function(n){return!(0,Se.has)(n,ko)}),t=(0,Se.map)(e,function(n){return{message:"Token Type: ->"+n.name+"<- missing static 'PATTERN' property",type:tr.LexerDefinitionErrorType.MISSING_PATTERN,tokenTypes:[n]}}),i=(0,Se.difference)(r,e);return{errors:t,valid:i}}We.findMissingPatterns=$Y;function ej(r){var e=(0,Se.filter)(r,function(n){var s=n[ko];return!(0,Se.isRegExp)(s)&&!(0,Se.isFunction)(s)&&!(0,Se.has)(s,"exec")&&!(0,Se.isString)(s)}),t=(0,Se.map)(e,function(n){return{message:"Token Type: ->"+n.name+"<- static 'PATTERN' can only be a RegExp, a Function matching the {CustomPatternMatcherFunc} type or an Object matching the {ICustomPattern} interface.",type:tr.LexerDefinitionErrorType.INVALID_PATTERN,tokenTypes:[n]}}),i=(0,Se.difference)(r,e);return{errors:t,valid:i}}We.findInvalidPatterns=ej;var HEe=/[^\\][\$]/;function tj(r){var e=function(n){XY(s,n);function s(){var o=n!==null&&n.apply(this,arguments)||this;return o.found=!1,o}return s.prototype.visitEndAnchor=function(o){this.found=!0},s}(ZY.BaseRegExpVisitor),t=(0,Se.filter)(r,function(n){var s=n[ko];try{var o=(0,_Y.getRegExpAst)(s),a=new e;return a.visit(o),a.found}catch{return HEe.test(s.source)}}),i=(0,Se.map)(t,function(n){return{message:`Unexpected RegExp Anchor Error: + Token Type: ->`+n.name+`<- static 'PATTERN' cannot contain end of input anchor '$' + See chevrotain.io/docs/guide/resolving_lexer_errors.html#ANCHORS for details.`,type:tr.LexerDefinitionErrorType.EOI_ANCHOR_FOUND,tokenTypes:[n]}});return i}We.findEndOfInputAnchor=tj;function rj(r){var e=(0,Se.filter)(r,function(i){var n=i[ko];return n.test("")}),t=(0,Se.map)(e,function(i){return{message:"Token Type: ->"+i.name+"<- static 'PATTERN' must not match an empty string",type:tr.LexerDefinitionErrorType.EMPTY_MATCH_PATTERN,tokenTypes:[i]}});return t}We.findEmptyMatchRegExps=rj;var GEe=/[^\\[][\^]|^\^/;function ij(r){var e=function(n){XY(s,n);function s(){var o=n!==null&&n.apply(this,arguments)||this;return o.found=!1,o}return s.prototype.visitStartAnchor=function(o){this.found=!0},s}(ZY.BaseRegExpVisitor),t=(0,Se.filter)(r,function(n){var s=n[ko];try{var o=(0,_Y.getRegExpAst)(s),a=new e;return a.visit(o),a.found}catch{return GEe.test(s.source)}}),i=(0,Se.map)(t,function(n){return{message:`Unexpected RegExp Anchor Error: + Token Type: ->`+n.name+`<- static 'PATTERN' cannot contain start of input anchor '^' + See https://chevrotain.io/docs/guide/resolving_lexer_errors.html#ANCHORS for details.`,type:tr.LexerDefinitionErrorType.SOI_ANCHOR_FOUND,tokenTypes:[n]}});return i}We.findStartOfInputAnchor=ij;function nj(r){var e=(0,Se.filter)(r,function(i){var n=i[ko];return n instanceof RegExp&&(n.multiline||n.global)}),t=(0,Se.map)(e,function(i){return{message:"Token Type: ->"+i.name+"<- static 'PATTERN' may NOT contain global('g') or multiline('m')",type:tr.LexerDefinitionErrorType.UNSUPPORTED_FLAGS_FOUND,tokenTypes:[i]}});return t}We.findUnsupportedFlags=nj;function sj(r){var e=[],t=(0,Se.map)(r,function(s){return(0,Se.reduce)(r,function(o,a){return s.PATTERN.source===a.PATTERN.source&&!(0,Se.contains)(e,a)&&a.PATTERN!==tr.Lexer.NA&&(e.push(a),o.push(a)),o},[])});t=(0,Se.compact)(t);var i=(0,Se.filter)(t,function(s){return s.length>1}),n=(0,Se.map)(i,function(s){var o=(0,Se.map)(s,function(l){return l.name}),a=(0,Se.first)(s).PATTERN;return{message:"The same RegExp pattern ->"+a+"<-"+("has been used in all of the following Token Types: "+o.join(", ")+" <-"),type:tr.LexerDefinitionErrorType.DUPLICATE_PATTERNS_FOUND,tokenTypes:s}});return n}We.findDuplicatePatterns=sj;function oj(r){var e=(0,Se.filter)(r,function(i){if(!(0,Se.has)(i,"GROUP"))return!1;var n=i.GROUP;return n!==tr.Lexer.SKIPPED&&n!==tr.Lexer.NA&&!(0,Se.isString)(n)}),t=(0,Se.map)(e,function(i){return{message:"Token Type: ->"+i.name+"<- static 'GROUP' can only be Lexer.SKIPPED/Lexer.NA/A String",type:tr.LexerDefinitionErrorType.INVALID_GROUP_TYPE_FOUND,tokenTypes:[i]}});return t}We.findInvalidGroupType=oj;function aj(r,e){var t=(0,Se.filter)(r,function(n){return n.PUSH_MODE!==void 0&&!(0,Se.contains)(e,n.PUSH_MODE)}),i=(0,Se.map)(t,function(n){var s="Token Type: ->"+n.name+"<- static 'PUSH_MODE' value cannot refer to a Lexer Mode ->"+n.PUSH_MODE+"<-which does not exist";return{message:s,type:tr.LexerDefinitionErrorType.PUSH_MODE_DOES_NOT_EXIST,tokenTypes:[n]}});return i}We.findModesThatDoNotExist=aj;function Aj(r){var e=[],t=(0,Se.reduce)(r,function(i,n,s){var o=n.PATTERN;return o===tr.Lexer.NA||((0,Se.isString)(o)?i.push({str:o,idx:s,tokenType:n}):(0,Se.isRegExp)(o)&&jEe(o)&&i.push({str:o.source,idx:s,tokenType:n})),i},[]);return(0,Se.forEach)(r,function(i,n){(0,Se.forEach)(t,function(s){var o=s.str,a=s.idx,l=s.tokenType;if(n"+i.name+"<-")+`in the lexer's definition. +See https://chevrotain.io/docs/guide/resolving_lexer_errors.html#UNREACHABLE`;e.push({message:c,type:tr.LexerDefinitionErrorType.UNREACHABLE_PATTERN,tokenTypes:[i,l]})}})}),e}We.findUnreachablePatterns=Aj;function YEe(r,e){if((0,Se.isRegExp)(e)){var t=e.exec(r);return t!==null&&t.index===0}else{if((0,Se.isFunction)(e))return e(r,0,[],{});if((0,Se.has)(e,"exec"))return e.exec(r,0,[],{});if(typeof e=="string")return e===r;throw Error("non exhaustive match")}}function jEe(r){var e=[".","\\","[","]","|","^","$","(",")","?","*","+","{"];return(0,Se.find)(e,function(t){return r.source.indexOf(t)!==-1})===void 0}function Tv(r){var e=r.ignoreCase?"i":"";return new RegExp("^(?:"+r.source+")",e)}We.addStartOfInput=Tv;function Lv(r){var e=r.ignoreCase?"iy":"y";return new RegExp(""+r.source,e)}We.addStickyFlag=Lv;function qEe(r,e,t){var i=[];return(0,Se.has)(r,We.DEFAULT_MODE)||i.push({message:"A MultiMode Lexer cannot be initialized without a <"+We.DEFAULT_MODE+`> property in its definition +`,type:tr.LexerDefinitionErrorType.MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE}),(0,Se.has)(r,We.MODES)||i.push({message:"A MultiMode Lexer cannot be initialized without a <"+We.MODES+`> property in its definition +`,type:tr.LexerDefinitionErrorType.MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY}),(0,Se.has)(r,We.MODES)&&(0,Se.has)(r,We.DEFAULT_MODE)&&!(0,Se.has)(r.modes,r.defaultMode)&&i.push({message:"A MultiMode Lexer cannot be initialized with a "+We.DEFAULT_MODE+": <"+r.defaultMode+`>which does not exist +`,type:tr.LexerDefinitionErrorType.MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST}),(0,Se.has)(r,We.MODES)&&(0,Se.forEach)(r.modes,function(n,s){(0,Se.forEach)(n,function(o,a){(0,Se.isUndefined)(o)&&i.push({message:"A Lexer cannot be initialized using an undefined Token Type. Mode:"+("<"+s+"> at index: <"+a+`> +`),type:tr.LexerDefinitionErrorType.LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED})})}),i}We.performRuntimeChecks=qEe;function JEe(r,e,t){var i=[],n=!1,s=(0,Se.compact)((0,Se.flatten)((0,Se.mapValues)(r.modes,function(l){return l}))),o=(0,Se.reject)(s,function(l){return l[ko]===tr.Lexer.NA}),a=gj(t);return e&&(0,Se.forEach)(o,function(l){var c=cj(l,a);if(c!==!1){var u=uj(l,c),g={message:u,type:c.issue,tokenType:l};i.push(g)}else(0,Se.has)(l,"LINE_BREAKS")?l.LINE_BREAKS===!0&&(n=!0):(0,_g.canMatchCharCode)(a,l.PATTERN)&&(n=!0)}),e&&!n&&i.push({message:`Warning: No LINE_BREAKS Found. + This Lexer has been defined to track line and column information, + But none of the Token Types can be identified as matching a line terminator. + See https://chevrotain.io/docs/guide/resolving_lexer_errors.html#LINE_BREAKS + for details.`,type:tr.LexerDefinitionErrorType.NO_LINE_BREAKS_FLAGS}),i}We.performWarningRuntimeChecks=JEe;function WEe(r){var e={},t=(0,Se.keys)(r);return(0,Se.forEach)(t,function(i){var n=r[i];if((0,Se.isArray)(n))e[i]=[];else throw Error("non exhaustive match")}),e}We.cloneEmptyGroups=WEe;function Mv(r){var e=r.PATTERN;if((0,Se.isRegExp)(e))return!1;if((0,Se.isFunction)(e))return!0;if((0,Se.has)(e,"exec"))return!0;if((0,Se.isString)(e))return!1;throw Error("non exhaustive match")}We.isCustomPattern=Mv;function lj(r){return(0,Se.isString)(r)&&r.length===1?r.charCodeAt(0):!1}We.isShortPattern=lj;We.LineTerminatorOptimizedTester={test:function(r){for(var e=r.length,t=this.lastIndex;t Token Type +`)+(" Root cause: "+e.errMsg+`. +`)+" For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#IDENTIFY_TERMINATOR";if(e.issue===tr.LexerDefinitionErrorType.CUSTOM_LINE_BREAK)return`Warning: A Custom Token Pattern should specify the option. +`+(" The problem is in the <"+r.name+`> Token Type +`)+" For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#CUSTOM_LINE_BREAK";throw Error("non exhaustive match")}We.buildLineBreakIssueMessage=uj;function gj(r){var e=(0,Se.map)(r,function(t){return(0,Se.isString)(t)&&t.length>0?t.charCodeAt(0):t});return e}function Nv(r,e,t){r[e]===void 0?r[e]=[t]:r[e].push(t)}We.minOptimizationVal=256;var sy=[];function Ov(r){return r255?255+~~(r/255):r}}});var $g=I(Dt=>{"use strict";Object.defineProperty(Dt,"__esModule",{value:!0});Dt.isTokenType=Dt.hasExtendingTokensTypesMapProperty=Dt.hasExtendingTokensTypesProperty=Dt.hasCategoriesProperty=Dt.hasShortKeyProperty=Dt.singleAssignCategoriesToksMap=Dt.assignCategoriesMapProp=Dt.assignCategoriesTokensProp=Dt.assignTokenDefaultProps=Dt.expandCategories=Dt.augmentTokenTypes=Dt.tokenIdxToClass=Dt.tokenShortNameIdx=Dt.tokenStructuredMatcherNoCategories=Dt.tokenStructuredMatcher=void 0;var zr=Kt();function VEe(r,e){var t=r.tokenTypeIdx;return t===e.tokenTypeIdx?!0:e.isParent===!0&&e.categoryMatchesMap[t]===!0}Dt.tokenStructuredMatcher=VEe;function XEe(r,e){return r.tokenTypeIdx===e.tokenTypeIdx}Dt.tokenStructuredMatcherNoCategories=XEe;Dt.tokenShortNameIdx=1;Dt.tokenIdxToClass={};function ZEe(r){var e=fj(r);hj(e),dj(e),pj(e),(0,zr.forEach)(e,function(t){t.isParent=t.categoryMatches.length>0})}Dt.augmentTokenTypes=ZEe;function fj(r){for(var e=(0,zr.cloneArr)(r),t=r,i=!0;i;){t=(0,zr.compact)((0,zr.flatten)((0,zr.map)(t,function(s){return s.CATEGORIES})));var n=(0,zr.difference)(t,e);e=e.concat(n),(0,zr.isEmpty)(n)?i=!1:t=n}return e}Dt.expandCategories=fj;function hj(r){(0,zr.forEach)(r,function(e){Cj(e)||(Dt.tokenIdxToClass[Dt.tokenShortNameIdx]=e,e.tokenTypeIdx=Dt.tokenShortNameIdx++),Kv(e)&&!(0,zr.isArray)(e.CATEGORIES)&&(e.CATEGORIES=[e.CATEGORIES]),Kv(e)||(e.CATEGORIES=[]),mj(e)||(e.categoryMatches=[]),Ej(e)||(e.categoryMatchesMap={})})}Dt.assignTokenDefaultProps=hj;function pj(r){(0,zr.forEach)(r,function(e){e.categoryMatches=[],(0,zr.forEach)(e.categoryMatchesMap,function(t,i){e.categoryMatches.push(Dt.tokenIdxToClass[i].tokenTypeIdx)})})}Dt.assignCategoriesTokensProp=pj;function dj(r){(0,zr.forEach)(r,function(e){Uv([],e)})}Dt.assignCategoriesMapProp=dj;function Uv(r,e){(0,zr.forEach)(r,function(t){e.categoryMatchesMap[t.tokenTypeIdx]=!0}),(0,zr.forEach)(e.CATEGORIES,function(t){var i=r.concat(e);(0,zr.contains)(i,t)||Uv(i,t)})}Dt.singleAssignCategoriesToksMap=Uv;function Cj(r){return(0,zr.has)(r,"tokenTypeIdx")}Dt.hasShortKeyProperty=Cj;function Kv(r){return(0,zr.has)(r,"CATEGORIES")}Dt.hasCategoriesProperty=Kv;function mj(r){return(0,zr.has)(r,"categoryMatches")}Dt.hasExtendingTokensTypesProperty=mj;function Ej(r){return(0,zr.has)(r,"categoryMatchesMap")}Dt.hasExtendingTokensTypesMapProperty=Ej;function _Ee(r){return(0,zr.has)(r,"tokenTypeIdx")}Dt.isTokenType=_Ee});var Hv=I(oy=>{"use strict";Object.defineProperty(oy,"__esModule",{value:!0});oy.defaultLexerErrorProvider=void 0;oy.defaultLexerErrorProvider={buildUnableToPopLexerModeMessage:function(r){return"Unable to pop Lexer Mode after encountering Token ->"+r.image+"<- The Mode Stack is empty"},buildUnexpectedCharactersMessage:function(r,e,t,i,n){return"unexpected character: ->"+r.charAt(e)+"<- at offset: "+e+","+(" skipped "+t+" characters.")}}});var bd=I(Ec=>{"use strict";Object.defineProperty(Ec,"__esModule",{value:!0});Ec.Lexer=Ec.LexerDefinitionErrorType=void 0;var Zs=Fv(),rr=Kt(),$Ee=$g(),eIe=Hv(),tIe=ry(),rIe;(function(r){r[r.MISSING_PATTERN=0]="MISSING_PATTERN",r[r.INVALID_PATTERN=1]="INVALID_PATTERN",r[r.EOI_ANCHOR_FOUND=2]="EOI_ANCHOR_FOUND",r[r.UNSUPPORTED_FLAGS_FOUND=3]="UNSUPPORTED_FLAGS_FOUND",r[r.DUPLICATE_PATTERNS_FOUND=4]="DUPLICATE_PATTERNS_FOUND",r[r.INVALID_GROUP_TYPE_FOUND=5]="INVALID_GROUP_TYPE_FOUND",r[r.PUSH_MODE_DOES_NOT_EXIST=6]="PUSH_MODE_DOES_NOT_EXIST",r[r.MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE=7]="MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE",r[r.MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY=8]="MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY",r[r.MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST=9]="MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST",r[r.LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED=10]="LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED",r[r.SOI_ANCHOR_FOUND=11]="SOI_ANCHOR_FOUND",r[r.EMPTY_MATCH_PATTERN=12]="EMPTY_MATCH_PATTERN",r[r.NO_LINE_BREAKS_FLAGS=13]="NO_LINE_BREAKS_FLAGS",r[r.UNREACHABLE_PATTERN=14]="UNREACHABLE_PATTERN",r[r.IDENTIFY_TERMINATOR=15]="IDENTIFY_TERMINATOR",r[r.CUSTOM_LINE_BREAK=16]="CUSTOM_LINE_BREAK"})(rIe=Ec.LexerDefinitionErrorType||(Ec.LexerDefinitionErrorType={}));var Sd={deferDefinitionErrorsHandling:!1,positionTracking:"full",lineTerminatorsPattern:/\n|\r\n?/g,lineTerminatorCharacters:[` +`,"\r"],ensureOptimizations:!1,safeMode:!1,errorMessageProvider:eIe.defaultLexerErrorProvider,traceInitPerf:!1,skipValidations:!1};Object.freeze(Sd);var iIe=function(){function r(e,t){var i=this;if(t===void 0&&(t=Sd),this.lexerDefinition=e,this.lexerDefinitionErrors=[],this.lexerDefinitionWarning=[],this.patternIdxToConfig={},this.charCodeToPatternIdxToConfig={},this.modes=[],this.emptyGroups={},this.config=void 0,this.trackStartLines=!0,this.trackEndLines=!0,this.hasCustom=!1,this.canModeBeOptimized={},typeof t=="boolean")throw Error(`The second argument to the Lexer constructor is now an ILexerConfig Object. +a boolean 2nd argument is no longer supported`);this.config=(0,rr.merge)(Sd,t);var n=this.config.traceInitPerf;n===!0?(this.traceInitMaxIdent=1/0,this.traceInitPerf=!0):typeof n=="number"&&(this.traceInitMaxIdent=n,this.traceInitPerf=!0),this.traceInitIndent=-1,this.TRACE_INIT("Lexer Constructor",function(){var s,o=!0;i.TRACE_INIT("Lexer Config handling",function(){if(i.config.lineTerminatorsPattern===Sd.lineTerminatorsPattern)i.config.lineTerminatorsPattern=Zs.LineTerminatorOptimizedTester;else if(i.config.lineTerminatorCharacters===Sd.lineTerminatorCharacters)throw Error(`Error: Missing property on the Lexer config. + For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#MISSING_LINE_TERM_CHARS`);if(t.safeMode&&t.ensureOptimizations)throw Error('"safeMode" and "ensureOptimizations" flags are mutually exclusive.');i.trackStartLines=/full|onlyStart/i.test(i.config.positionTracking),i.trackEndLines=/full/i.test(i.config.positionTracking),(0,rr.isArray)(e)?(s={modes:{}},s.modes[Zs.DEFAULT_MODE]=(0,rr.cloneArr)(e),s[Zs.DEFAULT_MODE]=Zs.DEFAULT_MODE):(o=!1,s=(0,rr.cloneObj)(e))}),i.config.skipValidations===!1&&(i.TRACE_INIT("performRuntimeChecks",function(){i.lexerDefinitionErrors=i.lexerDefinitionErrors.concat((0,Zs.performRuntimeChecks)(s,i.trackStartLines,i.config.lineTerminatorCharacters))}),i.TRACE_INIT("performWarningRuntimeChecks",function(){i.lexerDefinitionWarning=i.lexerDefinitionWarning.concat((0,Zs.performWarningRuntimeChecks)(s,i.trackStartLines,i.config.lineTerminatorCharacters))})),s.modes=s.modes?s.modes:{},(0,rr.forEach)(s.modes,function(u,g){s.modes[g]=(0,rr.reject)(u,function(h){return(0,rr.isUndefined)(h)})});var a=(0,rr.keys)(s.modes);if((0,rr.forEach)(s.modes,function(u,g){i.TRACE_INIT("Mode: <"+g+"> processing",function(){if(i.modes.push(g),i.config.skipValidations===!1&&i.TRACE_INIT("validatePatterns",function(){i.lexerDefinitionErrors=i.lexerDefinitionErrors.concat((0,Zs.validatePatterns)(u,a))}),(0,rr.isEmpty)(i.lexerDefinitionErrors)){(0,$Ee.augmentTokenTypes)(u);var h;i.TRACE_INIT("analyzeTokenTypes",function(){h=(0,Zs.analyzeTokenTypes)(u,{lineTerminatorCharacters:i.config.lineTerminatorCharacters,positionTracking:t.positionTracking,ensureOptimizations:t.ensureOptimizations,safeMode:t.safeMode,tracer:i.TRACE_INIT.bind(i)})}),i.patternIdxToConfig[g]=h.patternIdxToConfig,i.charCodeToPatternIdxToConfig[g]=h.charCodeToPatternIdxToConfig,i.emptyGroups=(0,rr.merge)(i.emptyGroups,h.emptyGroups),i.hasCustom=h.hasCustom||i.hasCustom,i.canModeBeOptimized[g]=h.canBeOptimized}})}),i.defaultMode=s.defaultMode,!(0,rr.isEmpty)(i.lexerDefinitionErrors)&&!i.config.deferDefinitionErrorsHandling){var l=(0,rr.map)(i.lexerDefinitionErrors,function(u){return u.message}),c=l.join(`----------------------- +`);throw new Error(`Errors detected in definition of Lexer: +`+c)}(0,rr.forEach)(i.lexerDefinitionWarning,function(u){(0,rr.PRINT_WARNING)(u.message)}),i.TRACE_INIT("Choosing sub-methods implementations",function(){if(Zs.SUPPORT_STICKY?(i.chopInput=rr.IDENTITY,i.match=i.matchWithTest):(i.updateLastIndex=rr.NOOP,i.match=i.matchWithExec),o&&(i.handleModes=rr.NOOP),i.trackStartLines===!1&&(i.computeNewColumn=rr.IDENTITY),i.trackEndLines===!1&&(i.updateTokenEndLineColumnLocation=rr.NOOP),/full/i.test(i.config.positionTracking))i.createTokenInstance=i.createFullToken;else if(/onlyStart/i.test(i.config.positionTracking))i.createTokenInstance=i.createStartOnlyToken;else if(/onlyOffset/i.test(i.config.positionTracking))i.createTokenInstance=i.createOffsetOnlyToken;else throw Error('Invalid config option: "'+i.config.positionTracking+'"');i.hasCustom?(i.addToken=i.addTokenUsingPush,i.handlePayload=i.handlePayloadWithCustom):(i.addToken=i.addTokenUsingMemberAccess,i.handlePayload=i.handlePayloadNoCustom)}),i.TRACE_INIT("Failed Optimization Warnings",function(){var u=(0,rr.reduce)(i.canModeBeOptimized,function(g,h,p){return h===!1&&g.push(p),g},[]);if(t.ensureOptimizations&&!(0,rr.isEmpty)(u))throw Error("Lexer Modes: < "+u.join(", ")+` > cannot be optimized. + Disable the "ensureOptimizations" lexer config flag to silently ignore this and run the lexer in an un-optimized mode. + Or inspect the console log for details on how to resolve these issues.`)}),i.TRACE_INIT("clearRegExpParserCache",function(){(0,tIe.clearRegExpParserCache)()}),i.TRACE_INIT("toFastProperties",function(){(0,rr.toFastProperties)(i)})})}return r.prototype.tokenize=function(e,t){if(t===void 0&&(t=this.defaultMode),!(0,rr.isEmpty)(this.lexerDefinitionErrors)){var i=(0,rr.map)(this.lexerDefinitionErrors,function(o){return o.message}),n=i.join(`----------------------- +`);throw new Error(`Unable to Tokenize because Errors detected in definition of Lexer: +`+n)}var s=this.tokenizeInternal(e,t);return s},r.prototype.tokenizeInternal=function(e,t){var i=this,n,s,o,a,l,c,u,g,h,p,d,m,y,B,S,P,F=e,H=F.length,q=0,_=0,X=this.hasCustom?0:Math.floor(e.length/10),W=new Array(X),Z=[],A=this.trackStartLines?1:void 0,se=this.trackStartLines?1:void 0,ue=(0,Zs.cloneEmptyGroups)(this.emptyGroups),ee=this.trackStartLines,O=this.config.lineTerminatorsPattern,N=0,ce=[],he=[],Pe=[],De=[];Object.freeze(De);var Re=void 0;function oe(){return ce}function Ae(fr){var Ei=(0,Zs.charCodeToOptimizedIndex)(fr),ts=he[Ei];return ts===void 0?De:ts}var ye=function(fr){if(Pe.length===1&&fr.tokenType.PUSH_MODE===void 0){var Ei=i.config.errorMessageProvider.buildUnableToPopLexerModeMessage(fr);Z.push({offset:fr.startOffset,line:fr.startLine!==void 0?fr.startLine:void 0,column:fr.startColumn!==void 0?fr.startColumn:void 0,length:fr.image.length,message:Ei})}else{Pe.pop();var ts=(0,rr.last)(Pe);ce=i.patternIdxToConfig[ts],he=i.charCodeToPatternIdxToConfig[ts],N=ce.length;var ua=i.canModeBeOptimized[ts]&&i.config.safeMode===!1;he&&ua?Re=Ae:Re=oe}};function ge(fr){Pe.push(fr),he=this.charCodeToPatternIdxToConfig[fr],ce=this.patternIdxToConfig[fr],N=ce.length,N=ce.length;var Ei=this.canModeBeOptimized[fr]&&this.config.safeMode===!1;he&&Ei?Re=Ae:Re=oe}ge.call(this,t);for(var ae;qc.length){c=a,u=g,ae=Ze;break}}}break}}if(c!==null){if(h=c.length,p=ae.group,p!==void 0&&(d=ae.tokenTypeIdx,m=this.createTokenInstance(c,q,d,ae.tokenType,A,se,h),this.handlePayload(m,u),p===!1?_=this.addToken(W,_,m):ue[p].push(m)),e=this.chopInput(e,h),q=q+h,se=this.computeNewColumn(se,h),ee===!0&&ae.canLineTerminator===!0){var mt=0,Tr=void 0,ei=void 0;O.lastIndex=0;do Tr=O.test(c),Tr===!0&&(ei=O.lastIndex-1,mt++);while(Tr===!0);mt!==0&&(A=A+mt,se=h-ei,this.updateTokenEndLineColumnLocation(m,p,ei,mt,A,se,h))}this.handleModes(ae,ye,ge,m)}else{for(var ci=q,gr=A,ui=se,ti=!1;!ti&&q <"+e+">");var n=(0,rr.timer)(t),s=n.time,o=n.value,a=s>10?console.warn:console.log;return this.traceInitIndent time: "+s+"ms"),this.traceInitIndent--,o}else return t()},r.SKIPPED="This marks a skipped Token pattern, this means each token identified by it willbe consumed and then thrown into oblivion, this can be used to for example to completely ignore whitespace.",r.NA=/NOT_APPLICABLE/,r}();Ec.Lexer=iIe});var NA=I(Si=>{"use strict";Object.defineProperty(Si,"__esModule",{value:!0});Si.tokenMatcher=Si.createTokenInstance=Si.EOF=Si.createToken=Si.hasTokenLabel=Si.tokenName=Si.tokenLabel=void 0;var _s=Kt(),nIe=bd(),Gv=$g();function sIe(r){return xj(r)?r.LABEL:r.name}Si.tokenLabel=sIe;function oIe(r){return r.name}Si.tokenName=oIe;function xj(r){return(0,_s.isString)(r.LABEL)&&r.LABEL!==""}Si.hasTokenLabel=xj;var aIe="parent",Ij="categories",yj="label",wj="group",Bj="push_mode",Qj="pop_mode",bj="longer_alt",Sj="line_breaks",vj="start_chars_hint";function Pj(r){return AIe(r)}Si.createToken=Pj;function AIe(r){var e=r.pattern,t={};if(t.name=r.name,(0,_s.isUndefined)(e)||(t.PATTERN=e),(0,_s.has)(r,aIe))throw`The parent property is no longer supported. +See: https://github.com/chevrotain/chevrotain/issues/564#issuecomment-349062346 for details.`;return(0,_s.has)(r,Ij)&&(t.CATEGORIES=r[Ij]),(0,Gv.augmentTokenTypes)([t]),(0,_s.has)(r,yj)&&(t.LABEL=r[yj]),(0,_s.has)(r,wj)&&(t.GROUP=r[wj]),(0,_s.has)(r,Qj)&&(t.POP_MODE=r[Qj]),(0,_s.has)(r,Bj)&&(t.PUSH_MODE=r[Bj]),(0,_s.has)(r,bj)&&(t.LONGER_ALT=r[bj]),(0,_s.has)(r,Sj)&&(t.LINE_BREAKS=r[Sj]),(0,_s.has)(r,vj)&&(t.START_CHARS_HINT=r[vj]),t}Si.EOF=Pj({name:"EOF",pattern:nIe.Lexer.NA});(0,Gv.augmentTokenTypes)([Si.EOF]);function lIe(r,e,t,i,n,s,o,a){return{image:e,startOffset:t,endOffset:i,startLine:n,endLine:s,startColumn:o,endColumn:a,tokenTypeIdx:r.tokenTypeIdx,tokenType:r}}Si.createTokenInstance=lIe;function cIe(r,e){return(0,Gv.tokenStructuredMatcher)(r,e)}Si.tokenMatcher=cIe});var mn=I(qt=>{"use strict";var ka=qt&&qt.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(qt,"__esModule",{value:!0});qt.serializeProduction=qt.serializeGrammar=qt.Terminal=qt.Alternation=qt.RepetitionWithSeparator=qt.Repetition=qt.RepetitionMandatoryWithSeparator=qt.RepetitionMandatory=qt.Option=qt.Alternative=qt.Rule=qt.NonTerminal=qt.AbstractProduction=void 0;var or=Kt(),uIe=NA(),Do=function(){function r(e){this._definition=e}return Object.defineProperty(r.prototype,"definition",{get:function(){return this._definition},set:function(e){this._definition=e},enumerable:!1,configurable:!0}),r.prototype.accept=function(e){e.visit(this),(0,or.forEach)(this.definition,function(t){t.accept(e)})},r}();qt.AbstractProduction=Do;var kj=function(r){ka(e,r);function e(t){var i=r.call(this,[])||this;return i.idx=1,(0,or.assign)(i,(0,or.pick)(t,function(n){return n!==void 0})),i}return Object.defineProperty(e.prototype,"definition",{get:function(){return this.referencedRule!==void 0?this.referencedRule.definition:[]},set:function(t){},enumerable:!1,configurable:!0}),e.prototype.accept=function(t){t.visit(this)},e}(Do);qt.NonTerminal=kj;var Dj=function(r){ka(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.orgText="",(0,or.assign)(i,(0,or.pick)(t,function(n){return n!==void 0})),i}return e}(Do);qt.Rule=Dj;var Rj=function(r){ka(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.ignoreAmbiguities=!1,(0,or.assign)(i,(0,or.pick)(t,function(n){return n!==void 0})),i}return e}(Do);qt.Alternative=Rj;var Fj=function(r){ka(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,or.assign)(i,(0,or.pick)(t,function(n){return n!==void 0})),i}return e}(Do);qt.Option=Fj;var Nj=function(r){ka(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,or.assign)(i,(0,or.pick)(t,function(n){return n!==void 0})),i}return e}(Do);qt.RepetitionMandatory=Nj;var Tj=function(r){ka(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,or.assign)(i,(0,or.pick)(t,function(n){return n!==void 0})),i}return e}(Do);qt.RepetitionMandatoryWithSeparator=Tj;var Lj=function(r){ka(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,or.assign)(i,(0,or.pick)(t,function(n){return n!==void 0})),i}return e}(Do);qt.Repetition=Lj;var Oj=function(r){ka(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,or.assign)(i,(0,or.pick)(t,function(n){return n!==void 0})),i}return e}(Do);qt.RepetitionWithSeparator=Oj;var Mj=function(r){ka(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,i.ignoreAmbiguities=!1,i.hasPredicates=!1,(0,or.assign)(i,(0,or.pick)(t,function(n){return n!==void 0})),i}return Object.defineProperty(e.prototype,"definition",{get:function(){return this._definition},set:function(t){this._definition=t},enumerable:!1,configurable:!0}),e}(Do);qt.Alternation=Mj;var ay=function(){function r(e){this.idx=1,(0,or.assign)(this,(0,or.pick)(e,function(t){return t!==void 0}))}return r.prototype.accept=function(e){e.visit(this)},r}();qt.Terminal=ay;function gIe(r){return(0,or.map)(r,vd)}qt.serializeGrammar=gIe;function vd(r){function e(s){return(0,or.map)(s,vd)}if(r instanceof kj){var t={type:"NonTerminal",name:r.nonTerminalName,idx:r.idx};return(0,or.isString)(r.label)&&(t.label=r.label),t}else{if(r instanceof Rj)return{type:"Alternative",definition:e(r.definition)};if(r instanceof Fj)return{type:"Option",idx:r.idx,definition:e(r.definition)};if(r instanceof Nj)return{type:"RepetitionMandatory",idx:r.idx,definition:e(r.definition)};if(r instanceof Tj)return{type:"RepetitionMandatoryWithSeparator",idx:r.idx,separator:vd(new ay({terminalType:r.separator})),definition:e(r.definition)};if(r instanceof Oj)return{type:"RepetitionWithSeparator",idx:r.idx,separator:vd(new ay({terminalType:r.separator})),definition:e(r.definition)};if(r instanceof Lj)return{type:"Repetition",idx:r.idx,definition:e(r.definition)};if(r instanceof Mj)return{type:"Alternation",idx:r.idx,definition:e(r.definition)};if(r instanceof ay){var i={type:"Terminal",name:r.terminalType.name,label:(0,uIe.tokenLabel)(r.terminalType),idx:r.idx};(0,or.isString)(r.label)&&(i.terminalLabel=r.label);var n=r.terminalType.PATTERN;return r.terminalType.PATTERN&&(i.pattern=(0,or.isRegExp)(n)?n.source:n),i}else{if(r instanceof Dj)return{type:"Rule",name:r.name,orgText:r.orgText,definition:e(r.definition)};throw Error("non exhaustive match")}}}qt.serializeProduction=vd});var ly=I(Ay=>{"use strict";Object.defineProperty(Ay,"__esModule",{value:!0});Ay.RestWalker=void 0;var Yv=Kt(),En=mn(),fIe=function(){function r(){}return r.prototype.walk=function(e,t){var i=this;t===void 0&&(t=[]),(0,Yv.forEach)(e.definition,function(n,s){var o=(0,Yv.drop)(e.definition,s+1);if(n instanceof En.NonTerminal)i.walkProdRef(n,o,t);else if(n instanceof En.Terminal)i.walkTerminal(n,o,t);else if(n instanceof En.Alternative)i.walkFlat(n,o,t);else if(n instanceof En.Option)i.walkOption(n,o,t);else if(n instanceof En.RepetitionMandatory)i.walkAtLeastOne(n,o,t);else if(n instanceof En.RepetitionMandatoryWithSeparator)i.walkAtLeastOneSep(n,o,t);else if(n instanceof En.RepetitionWithSeparator)i.walkManySep(n,o,t);else if(n instanceof En.Repetition)i.walkMany(n,o,t);else if(n instanceof En.Alternation)i.walkOr(n,o,t);else throw Error("non exhaustive match")})},r.prototype.walkTerminal=function(e,t,i){},r.prototype.walkProdRef=function(e,t,i){},r.prototype.walkFlat=function(e,t,i){var n=t.concat(i);this.walk(e,n)},r.prototype.walkOption=function(e,t,i){var n=t.concat(i);this.walk(e,n)},r.prototype.walkAtLeastOne=function(e,t,i){var n=[new En.Option({definition:e.definition})].concat(t,i);this.walk(e,n)},r.prototype.walkAtLeastOneSep=function(e,t,i){var n=Kj(e,t,i);this.walk(e,n)},r.prototype.walkMany=function(e,t,i){var n=[new En.Option({definition:e.definition})].concat(t,i);this.walk(e,n)},r.prototype.walkManySep=function(e,t,i){var n=Kj(e,t,i);this.walk(e,n)},r.prototype.walkOr=function(e,t,i){var n=this,s=t.concat(i);(0,Yv.forEach)(e.definition,function(o){var a=new En.Alternative({definition:[o]});n.walk(a,s)})},r}();Ay.RestWalker=fIe;function Kj(r,e,t){var i=[new En.Option({definition:[new En.Terminal({terminalType:r.separator})].concat(r.definition)})],n=i.concat(e,t);return n}});var ef=I(cy=>{"use strict";Object.defineProperty(cy,"__esModule",{value:!0});cy.GAstVisitor=void 0;var Ro=mn(),hIe=function(){function r(){}return r.prototype.visit=function(e){var t=e;switch(t.constructor){case Ro.NonTerminal:return this.visitNonTerminal(t);case Ro.Alternative:return this.visitAlternative(t);case Ro.Option:return this.visitOption(t);case Ro.RepetitionMandatory:return this.visitRepetitionMandatory(t);case Ro.RepetitionMandatoryWithSeparator:return this.visitRepetitionMandatoryWithSeparator(t);case Ro.RepetitionWithSeparator:return this.visitRepetitionWithSeparator(t);case Ro.Repetition:return this.visitRepetition(t);case Ro.Alternation:return this.visitAlternation(t);case Ro.Terminal:return this.visitTerminal(t);case Ro.Rule:return this.visitRule(t);default:throw Error("non exhaustive match")}},r.prototype.visitNonTerminal=function(e){},r.prototype.visitAlternative=function(e){},r.prototype.visitOption=function(e){},r.prototype.visitRepetition=function(e){},r.prototype.visitRepetitionMandatory=function(e){},r.prototype.visitRepetitionMandatoryWithSeparator=function(e){},r.prototype.visitRepetitionWithSeparator=function(e){},r.prototype.visitAlternation=function(e){},r.prototype.visitTerminal=function(e){},r.prototype.visitRule=function(e){},r}();cy.GAstVisitor=hIe});var Pd=I(Mi=>{"use strict";var pIe=Mi&&Mi.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Mi,"__esModule",{value:!0});Mi.collectMethods=Mi.DslMethodsCollectorVisitor=Mi.getProductionDslName=Mi.isBranchingProd=Mi.isOptionalProd=Mi.isSequenceProd=void 0;var xd=Kt(),wr=mn(),dIe=ef();function CIe(r){return r instanceof wr.Alternative||r instanceof wr.Option||r instanceof wr.Repetition||r instanceof wr.RepetitionMandatory||r instanceof wr.RepetitionMandatoryWithSeparator||r instanceof wr.RepetitionWithSeparator||r instanceof wr.Terminal||r instanceof wr.Rule}Mi.isSequenceProd=CIe;function jv(r,e){e===void 0&&(e=[]);var t=r instanceof wr.Option||r instanceof wr.Repetition||r instanceof wr.RepetitionWithSeparator;return t?!0:r instanceof wr.Alternation?(0,xd.some)(r.definition,function(i){return jv(i,e)}):r instanceof wr.NonTerminal&&(0,xd.contains)(e,r)?!1:r instanceof wr.AbstractProduction?(r instanceof wr.NonTerminal&&e.push(r),(0,xd.every)(r.definition,function(i){return jv(i,e)})):!1}Mi.isOptionalProd=jv;function mIe(r){return r instanceof wr.Alternation}Mi.isBranchingProd=mIe;function EIe(r){if(r instanceof wr.NonTerminal)return"SUBRULE";if(r instanceof wr.Option)return"OPTION";if(r instanceof wr.Alternation)return"OR";if(r instanceof wr.RepetitionMandatory)return"AT_LEAST_ONE";if(r instanceof wr.RepetitionMandatoryWithSeparator)return"AT_LEAST_ONE_SEP";if(r instanceof wr.RepetitionWithSeparator)return"MANY_SEP";if(r instanceof wr.Repetition)return"MANY";if(r instanceof wr.Terminal)return"CONSUME";throw Error("non exhaustive match")}Mi.getProductionDslName=EIe;var Uj=function(r){pIe(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.separator="-",t.dslMethods={option:[],alternation:[],repetition:[],repetitionWithSeparator:[],repetitionMandatory:[],repetitionMandatoryWithSeparator:[]},t}return e.prototype.reset=function(){this.dslMethods={option:[],alternation:[],repetition:[],repetitionWithSeparator:[],repetitionMandatory:[],repetitionMandatoryWithSeparator:[]}},e.prototype.visitTerminal=function(t){var i=t.terminalType.name+this.separator+"Terminal";(0,xd.has)(this.dslMethods,i)||(this.dslMethods[i]=[]),this.dslMethods[i].push(t)},e.prototype.visitNonTerminal=function(t){var i=t.nonTerminalName+this.separator+"Terminal";(0,xd.has)(this.dslMethods,i)||(this.dslMethods[i]=[]),this.dslMethods[i].push(t)},e.prototype.visitOption=function(t){this.dslMethods.option.push(t)},e.prototype.visitRepetitionWithSeparator=function(t){this.dslMethods.repetitionWithSeparator.push(t)},e.prototype.visitRepetitionMandatory=function(t){this.dslMethods.repetitionMandatory.push(t)},e.prototype.visitRepetitionMandatoryWithSeparator=function(t){this.dslMethods.repetitionMandatoryWithSeparator.push(t)},e.prototype.visitRepetition=function(t){this.dslMethods.repetition.push(t)},e.prototype.visitAlternation=function(t){this.dslMethods.alternation.push(t)},e}(dIe.GAstVisitor);Mi.DslMethodsCollectorVisitor=Uj;var uy=new Uj;function IIe(r){uy.reset(),r.accept(uy);var e=uy.dslMethods;return uy.reset(),e}Mi.collectMethods=IIe});var Jv=I(Fo=>{"use strict";Object.defineProperty(Fo,"__esModule",{value:!0});Fo.firstForTerminal=Fo.firstForBranching=Fo.firstForSequence=Fo.first=void 0;var gy=Kt(),Hj=mn(),qv=Pd();function fy(r){if(r instanceof Hj.NonTerminal)return fy(r.referencedRule);if(r instanceof Hj.Terminal)return jj(r);if((0,qv.isSequenceProd)(r))return Gj(r);if((0,qv.isBranchingProd)(r))return Yj(r);throw Error("non exhaustive match")}Fo.first=fy;function Gj(r){for(var e=[],t=r.definition,i=0,n=t.length>i,s,o=!0;n&&o;)s=t[i],o=(0,qv.isOptionalProd)(s),e=e.concat(fy(s)),i=i+1,n=t.length>i;return(0,gy.uniq)(e)}Fo.firstForSequence=Gj;function Yj(r){var e=(0,gy.map)(r.definition,function(t){return fy(t)});return(0,gy.uniq)((0,gy.flatten)(e))}Fo.firstForBranching=Yj;function jj(r){return[r.terminalType]}Fo.firstForTerminal=jj});var Wv=I(hy=>{"use strict";Object.defineProperty(hy,"__esModule",{value:!0});hy.IN=void 0;hy.IN="_~IN~_"});var Vj=I(us=>{"use strict";var yIe=us&&us.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(us,"__esModule",{value:!0});us.buildInProdFollowPrefix=us.buildBetweenProdsFollowPrefix=us.computeAllProdsFollows=us.ResyncFollowsWalker=void 0;var wIe=ly(),BIe=Jv(),qj=Kt(),Jj=Wv(),QIe=mn(),Wj=function(r){yIe(e,r);function e(t){var i=r.call(this)||this;return i.topProd=t,i.follows={},i}return e.prototype.startWalking=function(){return this.walk(this.topProd),this.follows},e.prototype.walkTerminal=function(t,i,n){},e.prototype.walkProdRef=function(t,i,n){var s=zj(t.referencedRule,t.idx)+this.topProd.name,o=i.concat(n),a=new QIe.Alternative({definition:o}),l=(0,BIe.first)(a);this.follows[s]=l},e}(wIe.RestWalker);us.ResyncFollowsWalker=Wj;function bIe(r){var e={};return(0,qj.forEach)(r,function(t){var i=new Wj(t).startWalking();(0,qj.assign)(e,i)}),e}us.computeAllProdsFollows=bIe;function zj(r,e){return r.name+e+Jj.IN}us.buildBetweenProdsFollowPrefix=zj;function SIe(r){var e=r.terminalType.name;return e+r.idx+Jj.IN}us.buildInProdFollowPrefix=SIe});var kd=I(Da=>{"use strict";Object.defineProperty(Da,"__esModule",{value:!0});Da.defaultGrammarValidatorErrorProvider=Da.defaultGrammarResolverErrorProvider=Da.defaultParserErrorProvider=void 0;var tf=NA(),vIe=Kt(),$s=Kt(),zv=mn(),Xj=Pd();Da.defaultParserErrorProvider={buildMismatchTokenMessage:function(r){var e=r.expected,t=r.actual,i=r.previous,n=r.ruleName,s=(0,tf.hasTokenLabel)(e),o=s?"--> "+(0,tf.tokenLabel)(e)+" <--":"token of type --> "+e.name+" <--",a="Expecting "+o+" but found --> '"+t.image+"' <--";return a},buildNotAllInputParsedMessage:function(r){var e=r.firstRedundant,t=r.ruleName;return"Redundant input, expecting EOF but found: "+e.image},buildNoViableAltMessage:function(r){var e=r.expectedPathsPerAlt,t=r.actual,i=r.previous,n=r.customUserDescription,s=r.ruleName,o="Expecting: ",a=(0,$s.first)(t).image,l=` +but found: '`+a+"'";if(n)return o+n+l;var c=(0,$s.reduce)(e,function(p,d){return p.concat(d)},[]),u=(0,$s.map)(c,function(p){return"["+(0,$s.map)(p,function(d){return(0,tf.tokenLabel)(d)}).join(", ")+"]"}),g=(0,$s.map)(u,function(p,d){return" "+(d+1)+". "+p}),h=`one of these possible Token sequences: +`+g.join(` +`);return o+h+l},buildEarlyExitMessage:function(r){var e=r.expectedIterationPaths,t=r.actual,i=r.customUserDescription,n=r.ruleName,s="Expecting: ",o=(0,$s.first)(t).image,a=` +but found: '`+o+"'";if(i)return s+i+a;var l=(0,$s.map)(e,function(u){return"["+(0,$s.map)(u,function(g){return(0,tf.tokenLabel)(g)}).join(",")+"]"}),c=`expecting at least one iteration which starts with one of these possible Token sequences:: + `+("<"+l.join(" ,")+">");return s+c+a}};Object.freeze(Da.defaultParserErrorProvider);Da.defaultGrammarResolverErrorProvider={buildRuleNotFoundError:function(r,e){var t="Invalid grammar, reference to a rule which is not defined: ->"+e.nonTerminalName+`<- +inside top level rule: ->`+r.name+"<-";return t}};Da.defaultGrammarValidatorErrorProvider={buildDuplicateFoundError:function(r,e){function t(u){return u instanceof zv.Terminal?u.terminalType.name:u instanceof zv.NonTerminal?u.nonTerminalName:""}var i=r.name,n=(0,$s.first)(e),s=n.idx,o=(0,Xj.getProductionDslName)(n),a=t(n),l=s>0,c="->"+o+(l?s:"")+"<- "+(a?"with argument: ->"+a+"<-":"")+` + appears more than once (`+e.length+" times) in the top level rule: ->"+i+`<-. + For further details see: https://chevrotain.io/docs/FAQ.html#NUMERICAL_SUFFIXES + `;return c=c.replace(/[ \t]+/g," "),c=c.replace(/\s\s+/g,` +`),c},buildNamespaceConflictError:function(r){var e=`Namespace conflict found in grammar. +`+("The grammar has both a Terminal(Token) and a Non-Terminal(Rule) named: <"+r.name+`>. +`)+`To resolve this make sure each Terminal and Non-Terminal names are unique +This is easy to accomplish by using the convention that Terminal names start with an uppercase letter +and Non-Terminal names start with a lower case letter.`;return e},buildAlternationPrefixAmbiguityError:function(r){var e=(0,$s.map)(r.prefixPath,function(n){return(0,tf.tokenLabel)(n)}).join(", "),t=r.alternation.idx===0?"":r.alternation.idx,i="Ambiguous alternatives: <"+r.ambiguityIndices.join(" ,")+`> due to common lookahead prefix +`+("in inside <"+r.topLevelRule.name+`> Rule, +`)+("<"+e+`> may appears as a prefix path in all these alternatives. +`)+`See: https://chevrotain.io/docs/guide/resolving_grammar_errors.html#COMMON_PREFIX +For Further details.`;return i},buildAlternationAmbiguityError:function(r){var e=(0,$s.map)(r.prefixPath,function(n){return(0,tf.tokenLabel)(n)}).join(", "),t=r.alternation.idx===0?"":r.alternation.idx,i="Ambiguous Alternatives Detected: <"+r.ambiguityIndices.join(" ,")+"> in "+(" inside <"+r.topLevelRule.name+`> Rule, +`)+("<"+e+`> may appears as a prefix path in all these alternatives. +`);return i=i+`See: https://chevrotain.io/docs/guide/resolving_grammar_errors.html#AMBIGUOUS_ALTERNATIVES +For Further details.`,i},buildEmptyRepetitionError:function(r){var e=(0,Xj.getProductionDslName)(r.repetition);r.repetition.idx!==0&&(e+=r.repetition.idx);var t="The repetition <"+e+"> within Rule <"+r.topLevelRule.name+`> can never consume any tokens. +This could lead to an infinite loop.`;return t},buildTokenNameError:function(r){return"deprecated"},buildEmptyAlternationError:function(r){var e="Ambiguous empty alternative: <"+(r.emptyChoiceIdx+1)+">"+(" in inside <"+r.topLevelRule.name+`> Rule. +`)+"Only the last alternative may be an empty alternative.";return e},buildTooManyAlternativesError:function(r){var e=`An Alternation cannot have more than 256 alternatives: +`+(" inside <"+r.topLevelRule.name+`> Rule. + has `+(r.alternation.definition.length+1)+" alternatives.");return e},buildLeftRecursionError:function(r){var e=r.topLevelRule.name,t=vIe.map(r.leftRecursionPath,function(s){return s.name}),i=e+" --> "+t.concat([e]).join(" --> "),n=`Left Recursion found in grammar. +`+("rule: <"+e+`> can be invoked from itself (directly or indirectly) +`)+(`without consuming any Tokens. The grammar path that causes this is: + `+i+` +`)+` To fix this refactor your grammar to remove the left recursion. +see: https://en.wikipedia.org/wiki/LL_parser#Left_Factoring.`;return n},buildInvalidRuleNameError:function(r){return"deprecated"},buildDuplicateRuleNameError:function(r){var e;r.topLevelRule instanceof zv.Rule?e=r.topLevelRule.name:e=r.topLevelRule;var t="Duplicate definition, rule: ->"+e+"<- is already defined in the grammar: ->"+r.grammarName+"<-";return t}}});var $j=I(TA=>{"use strict";var xIe=TA&&TA.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(TA,"__esModule",{value:!0});TA.GastRefResolverVisitor=TA.resolveGrammar=void 0;var PIe=Yn(),Zj=Kt(),kIe=ef();function DIe(r,e){var t=new _j(r,e);return t.resolveRefs(),t.errors}TA.resolveGrammar=DIe;var _j=function(r){xIe(e,r);function e(t,i){var n=r.call(this)||this;return n.nameToTopRule=t,n.errMsgProvider=i,n.errors=[],n}return e.prototype.resolveRefs=function(){var t=this;(0,Zj.forEach)((0,Zj.values)(this.nameToTopRule),function(i){t.currTopLevel=i,i.accept(t)})},e.prototype.visitNonTerminal=function(t){var i=this.nameToTopRule[t.nonTerminalName];if(i)t.referencedRule=i;else{var n=this.errMsgProvider.buildRuleNotFoundError(this.currTopLevel,t);this.errors.push({message:n,type:PIe.ParserDefinitionErrorType.UNRESOLVED_SUBRULE_REF,ruleName:this.currTopLevel.name,unresolvedRefName:t.nonTerminalName})}},e}(kIe.GAstVisitor);TA.GastRefResolverVisitor=_j});var Rd=I(Rr=>{"use strict";var Ic=Rr&&Rr.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Rr,"__esModule",{value:!0});Rr.nextPossibleTokensAfter=Rr.possiblePathsFrom=Rr.NextTerminalAfterAtLeastOneSepWalker=Rr.NextTerminalAfterAtLeastOneWalker=Rr.NextTerminalAfterManySepWalker=Rr.NextTerminalAfterManyWalker=Rr.AbstractNextTerminalAfterProductionWalker=Rr.NextAfterTokenWalker=Rr.AbstractNextPossibleTokensWalker=void 0;var eq=ly(),Lt=Kt(),RIe=Jv(),Pt=mn(),tq=function(r){Ic(e,r);function e(t,i){var n=r.call(this)||this;return n.topProd=t,n.path=i,n.possibleTokTypes=[],n.nextProductionName="",n.nextProductionOccurrence=0,n.found=!1,n.isAtEndOfPath=!1,n}return e.prototype.startWalking=function(){if(this.found=!1,this.path.ruleStack[0]!==this.topProd.name)throw Error("The path does not start with the walker's top Rule!");return this.ruleStack=(0,Lt.cloneArr)(this.path.ruleStack).reverse(),this.occurrenceStack=(0,Lt.cloneArr)(this.path.occurrenceStack).reverse(),this.ruleStack.pop(),this.occurrenceStack.pop(),this.updateExpectedNext(),this.walk(this.topProd),this.possibleTokTypes},e.prototype.walk=function(t,i){i===void 0&&(i=[]),this.found||r.prototype.walk.call(this,t,i)},e.prototype.walkProdRef=function(t,i,n){if(t.referencedRule.name===this.nextProductionName&&t.idx===this.nextProductionOccurrence){var s=i.concat(n);this.updateExpectedNext(),this.walk(t.referencedRule,s)}},e.prototype.updateExpectedNext=function(){(0,Lt.isEmpty)(this.ruleStack)?(this.nextProductionName="",this.nextProductionOccurrence=0,this.isAtEndOfPath=!0):(this.nextProductionName=this.ruleStack.pop(),this.nextProductionOccurrence=this.occurrenceStack.pop())},e}(eq.RestWalker);Rr.AbstractNextPossibleTokensWalker=tq;var FIe=function(r){Ic(e,r);function e(t,i){var n=r.call(this,t,i)||this;return n.path=i,n.nextTerminalName="",n.nextTerminalOccurrence=0,n.nextTerminalName=n.path.lastTok.name,n.nextTerminalOccurrence=n.path.lastTokOccurrence,n}return e.prototype.walkTerminal=function(t,i,n){if(this.isAtEndOfPath&&t.terminalType.name===this.nextTerminalName&&t.idx===this.nextTerminalOccurrence&&!this.found){var s=i.concat(n),o=new Pt.Alternative({definition:s});this.possibleTokTypes=(0,RIe.first)(o),this.found=!0}},e}(tq);Rr.NextAfterTokenWalker=FIe;var Dd=function(r){Ic(e,r);function e(t,i){var n=r.call(this)||this;return n.topRule=t,n.occurrence=i,n.result={token:void 0,occurrence:void 0,isEndOfRule:void 0},n}return e.prototype.startWalking=function(){return this.walk(this.topRule),this.result},e}(eq.RestWalker);Rr.AbstractNextTerminalAfterProductionWalker=Dd;var NIe=function(r){Ic(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.walkMany=function(t,i,n){if(t.idx===this.occurrence){var s=(0,Lt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof Pt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkMany.call(this,t,i,n)},e}(Dd);Rr.NextTerminalAfterManyWalker=NIe;var TIe=function(r){Ic(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.walkManySep=function(t,i,n){if(t.idx===this.occurrence){var s=(0,Lt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof Pt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkManySep.call(this,t,i,n)},e}(Dd);Rr.NextTerminalAfterManySepWalker=TIe;var LIe=function(r){Ic(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.walkAtLeastOne=function(t,i,n){if(t.idx===this.occurrence){var s=(0,Lt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof Pt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkAtLeastOne.call(this,t,i,n)},e}(Dd);Rr.NextTerminalAfterAtLeastOneWalker=LIe;var OIe=function(r){Ic(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.walkAtLeastOneSep=function(t,i,n){if(t.idx===this.occurrence){var s=(0,Lt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof Pt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkAtLeastOneSep.call(this,t,i,n)},e}(Dd);Rr.NextTerminalAfterAtLeastOneSepWalker=OIe;function rq(r,e,t){t===void 0&&(t=[]),t=(0,Lt.cloneArr)(t);var i=[],n=0;function s(c){return c.concat((0,Lt.drop)(r,n+1))}function o(c){var u=rq(s(c),e,t);return i.concat(u)}for(;t.length=0;ue--){var ee=B.definition[ue],O={idx:d,def:ee.definition.concat((0,Lt.drop)(p)),ruleStack:m,occurrenceStack:y};g.push(O),g.push(o)}else if(B instanceof Pt.Alternative)g.push({idx:d,def:B.definition.concat((0,Lt.drop)(p)),ruleStack:m,occurrenceStack:y});else if(B instanceof Pt.Rule)g.push(KIe(B,d,m,y));else throw Error("non exhaustive match")}}return u}Rr.nextPossibleTokensAfter=MIe;function KIe(r,e,t,i){var n=(0,Lt.cloneArr)(t);n.push(r.name);var s=(0,Lt.cloneArr)(i);return s.push(1),{idx:e,def:r.definition,ruleStack:n,occurrenceStack:s}}});var Fd=I(zt=>{"use strict";var sq=zt&&zt.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(zt,"__esModule",{value:!0});zt.areTokenCategoriesNotUsed=zt.isStrictPrefixOfPath=zt.containsPath=zt.getLookaheadPathsForOptionalProd=zt.getLookaheadPathsForOr=zt.lookAheadSequenceFromAlternatives=zt.buildSingleAlternativeLookaheadFunction=zt.buildAlternativesLookAheadFunc=zt.buildLookaheadFuncForOptionalProd=zt.buildLookaheadFuncForOr=zt.getProdType=zt.PROD_TYPE=void 0;var ir=Kt(),iq=Rd(),UIe=ly(),py=$g(),LA=mn(),HIe=ef(),ni;(function(r){r[r.OPTION=0]="OPTION",r[r.REPETITION=1]="REPETITION",r[r.REPETITION_MANDATORY=2]="REPETITION_MANDATORY",r[r.REPETITION_MANDATORY_WITH_SEPARATOR=3]="REPETITION_MANDATORY_WITH_SEPARATOR",r[r.REPETITION_WITH_SEPARATOR=4]="REPETITION_WITH_SEPARATOR",r[r.ALTERNATION=5]="ALTERNATION"})(ni=zt.PROD_TYPE||(zt.PROD_TYPE={}));function GIe(r){if(r instanceof LA.Option)return ni.OPTION;if(r instanceof LA.Repetition)return ni.REPETITION;if(r instanceof LA.RepetitionMandatory)return ni.REPETITION_MANDATORY;if(r instanceof LA.RepetitionMandatoryWithSeparator)return ni.REPETITION_MANDATORY_WITH_SEPARATOR;if(r instanceof LA.RepetitionWithSeparator)return ni.REPETITION_WITH_SEPARATOR;if(r instanceof LA.Alternation)return ni.ALTERNATION;throw Error("non exhaustive match")}zt.getProdType=GIe;function YIe(r,e,t,i,n,s){var o=aq(r,e,t),a=Zv(o)?py.tokenStructuredMatcherNoCategories:py.tokenStructuredMatcher;return s(o,i,a,n)}zt.buildLookaheadFuncForOr=YIe;function jIe(r,e,t,i,n,s){var o=Aq(r,e,n,t),a=Zv(o)?py.tokenStructuredMatcherNoCategories:py.tokenStructuredMatcher;return s(o[0],a,i)}zt.buildLookaheadFuncForOptionalProd=jIe;function qIe(r,e,t,i){var n=r.length,s=(0,ir.every)(r,function(l){return(0,ir.every)(l,function(c){return c.length===1})});if(e)return function(l){for(var c=(0,ir.map)(l,function(P){return P.GATE}),u=0;u{"use strict";var _v=Jt&&Jt.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Jt,"__esModule",{value:!0});Jt.checkPrefixAlternativesAmbiguities=Jt.validateSomeNonEmptyLookaheadPath=Jt.validateTooManyAlts=Jt.RepetionCollector=Jt.validateAmbiguousAlternationAlternatives=Jt.validateEmptyOrAlternative=Jt.getFirstNoneTerminal=Jt.validateNoLeftRecursion=Jt.validateRuleIsOverridden=Jt.validateRuleDoesNotAlreadyExist=Jt.OccurrenceValidationCollector=Jt.identifyProductionForDuplicates=Jt.validateGrammar=void 0;var _t=Kt(),Br=Kt(),No=Yn(),$v=Pd(),rf=Fd(),XIe=Rd(),eo=mn(),ex=ef();function ZIe(r,e,t,i,n){var s=_t.map(r,function(p){return _Ie(p,i)}),o=_t.map(r,function(p){return tx(p,p,i)}),a=[],l=[],c=[];(0,Br.every)(o,Br.isEmpty)&&(a=(0,Br.map)(r,function(p){return hq(p,i)}),l=(0,Br.map)(r,function(p){return pq(p,e,i)}),c=mq(r,e,i));var u=tye(r,t,i),g=(0,Br.map)(r,function(p){return Cq(p,i)}),h=(0,Br.map)(r,function(p){return fq(p,r,n,i)});return _t.flatten(s.concat(c,o,a,l,u,g,h))}Jt.validateGrammar=ZIe;function _Ie(r,e){var t=new gq;r.accept(t);var i=t.allProductions,n=_t.groupBy(i,cq),s=_t.pick(n,function(a){return a.length>1}),o=_t.map(_t.values(s),function(a){var l=_t.first(a),c=e.buildDuplicateFoundError(r,a),u=(0,$v.getProductionDslName)(l),g={message:c,type:No.ParserDefinitionErrorType.DUPLICATE_PRODUCTIONS,ruleName:r.name,dslName:u,occurrence:l.idx},h=uq(l);return h&&(g.parameter=h),g});return o}function cq(r){return(0,$v.getProductionDslName)(r)+"_#_"+r.idx+"_#_"+uq(r)}Jt.identifyProductionForDuplicates=cq;function uq(r){return r instanceof eo.Terminal?r.terminalType.name:r instanceof eo.NonTerminal?r.nonTerminalName:""}var gq=function(r){_v(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.allProductions=[],t}return e.prototype.visitNonTerminal=function(t){this.allProductions.push(t)},e.prototype.visitOption=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatory=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatoryWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetition=function(t){this.allProductions.push(t)},e.prototype.visitAlternation=function(t){this.allProductions.push(t)},e.prototype.visitTerminal=function(t){this.allProductions.push(t)},e}(ex.GAstVisitor);Jt.OccurrenceValidationCollector=gq;function fq(r,e,t,i){var n=[],s=(0,Br.reduce)(e,function(a,l){return l.name===r.name?a+1:a},0);if(s>1){var o=i.buildDuplicateRuleNameError({topLevelRule:r,grammarName:t});n.push({message:o,type:No.ParserDefinitionErrorType.DUPLICATE_RULE_NAME,ruleName:r.name})}return n}Jt.validateRuleDoesNotAlreadyExist=fq;function $Ie(r,e,t){var i=[],n;return _t.contains(e,r)||(n="Invalid rule override, rule: ->"+r+"<- cannot be overridden in the grammar: ->"+t+"<-as it is not defined in any of the super grammars ",i.push({message:n,type:No.ParserDefinitionErrorType.INVALID_RULE_OVERRIDE,ruleName:r})),i}Jt.validateRuleIsOverridden=$Ie;function tx(r,e,t,i){i===void 0&&(i=[]);var n=[],s=Nd(e.definition);if(_t.isEmpty(s))return[];var o=r.name,a=_t.contains(s,r);a&&n.push({message:t.buildLeftRecursionError({topLevelRule:r,leftRecursionPath:i}),type:No.ParserDefinitionErrorType.LEFT_RECURSION,ruleName:o});var l=_t.difference(s,i.concat([r])),c=_t.map(l,function(u){var g=_t.cloneArr(i);return g.push(u),tx(r,u,t,g)});return n.concat(_t.flatten(c))}Jt.validateNoLeftRecursion=tx;function Nd(r){var e=[];if(_t.isEmpty(r))return e;var t=_t.first(r);if(t instanceof eo.NonTerminal)e.push(t.referencedRule);else if(t instanceof eo.Alternative||t instanceof eo.Option||t instanceof eo.RepetitionMandatory||t instanceof eo.RepetitionMandatoryWithSeparator||t instanceof eo.RepetitionWithSeparator||t instanceof eo.Repetition)e=e.concat(Nd(t.definition));else if(t instanceof eo.Alternation)e=_t.flatten(_t.map(t.definition,function(o){return Nd(o.definition)}));else if(!(t instanceof eo.Terminal))throw Error("non exhaustive match");var i=(0,$v.isOptionalProd)(t),n=r.length>1;if(i&&n){var s=_t.drop(r);return e.concat(Nd(s))}else return e}Jt.getFirstNoneTerminal=Nd;var rx=function(r){_v(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.alternations=[],t}return e.prototype.visitAlternation=function(t){this.alternations.push(t)},e}(ex.GAstVisitor);function hq(r,e){var t=new rx;r.accept(t);var i=t.alternations,n=_t.reduce(i,function(s,o){var a=_t.dropRight(o.definition),l=_t.map(a,function(c,u){var g=(0,XIe.nextPossibleTokensAfter)([c],[],null,1);return _t.isEmpty(g)?{message:e.buildEmptyAlternationError({topLevelRule:r,alternation:o,emptyChoiceIdx:u}),type:No.ParserDefinitionErrorType.NONE_LAST_EMPTY_ALT,ruleName:r.name,occurrence:o.idx,alternative:u+1}:null});return s.concat(_t.compact(l))},[]);return n}Jt.validateEmptyOrAlternative=hq;function pq(r,e,t){var i=new rx;r.accept(i);var n=i.alternations;n=(0,Br.reject)(n,function(o){return o.ignoreAmbiguities===!0});var s=_t.reduce(n,function(o,a){var l=a.idx,c=a.maxLookahead||e,u=(0,rf.getLookaheadPathsForOr)(l,r,c,a),g=eye(u,a,r,t),h=Eq(u,a,r,t);return o.concat(g,h)},[]);return s}Jt.validateAmbiguousAlternationAlternatives=pq;var dq=function(r){_v(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.allProductions=[],t}return e.prototype.visitRepetitionWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatory=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatoryWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetition=function(t){this.allProductions.push(t)},e}(ex.GAstVisitor);Jt.RepetionCollector=dq;function Cq(r,e){var t=new rx;r.accept(t);var i=t.alternations,n=_t.reduce(i,function(s,o){return o.definition.length>255&&s.push({message:e.buildTooManyAlternativesError({topLevelRule:r,alternation:o}),type:No.ParserDefinitionErrorType.TOO_MANY_ALTS,ruleName:r.name,occurrence:o.idx}),s},[]);return n}Jt.validateTooManyAlts=Cq;function mq(r,e,t){var i=[];return(0,Br.forEach)(r,function(n){var s=new dq;n.accept(s);var o=s.allProductions;(0,Br.forEach)(o,function(a){var l=(0,rf.getProdType)(a),c=a.maxLookahead||e,u=a.idx,g=(0,rf.getLookaheadPathsForOptionalProd)(u,n,l,c),h=g[0];if((0,Br.isEmpty)((0,Br.flatten)(h))){var p=t.buildEmptyRepetitionError({topLevelRule:n,repetition:a});i.push({message:p,type:No.ParserDefinitionErrorType.NO_NON_EMPTY_LOOKAHEAD,ruleName:n.name})}})}),i}Jt.validateSomeNonEmptyLookaheadPath=mq;function eye(r,e,t,i){var n=[],s=(0,Br.reduce)(r,function(a,l,c){return e.definition[c].ignoreAmbiguities===!0||(0,Br.forEach)(l,function(u){var g=[c];(0,Br.forEach)(r,function(h,p){c!==p&&(0,rf.containsPath)(h,u)&&e.definition[p].ignoreAmbiguities!==!0&&g.push(p)}),g.length>1&&!(0,rf.containsPath)(n,u)&&(n.push(u),a.push({alts:g,path:u}))}),a},[]),o=_t.map(s,function(a){var l=(0,Br.map)(a.alts,function(u){return u+1}),c=i.buildAlternationAmbiguityError({topLevelRule:t,alternation:e,ambiguityIndices:l,prefixPath:a.path});return{message:c,type:No.ParserDefinitionErrorType.AMBIGUOUS_ALTS,ruleName:t.name,occurrence:e.idx,alternatives:[a.alts]}});return o}function Eq(r,e,t,i){var n=[],s=(0,Br.reduce)(r,function(o,a,l){var c=(0,Br.map)(a,function(u){return{idx:l,path:u}});return o.concat(c)},[]);return(0,Br.forEach)(s,function(o){var a=e.definition[o.idx];if(a.ignoreAmbiguities!==!0){var l=o.idx,c=o.path,u=(0,Br.findAll)(s,function(h){return e.definition[h.idx].ignoreAmbiguities!==!0&&h.idx{"use strict";Object.defineProperty(nf,"__esModule",{value:!0});nf.validateGrammar=nf.resolveGrammar=void 0;var nx=Kt(),rye=$j(),iye=ix(),Iq=kd();function nye(r){r=(0,nx.defaults)(r,{errMsgProvider:Iq.defaultGrammarResolverErrorProvider});var e={};return(0,nx.forEach)(r.rules,function(t){e[t.name]=t}),(0,rye.resolveGrammar)(e,r.errMsgProvider)}nf.resolveGrammar=nye;function sye(r){return r=(0,nx.defaults)(r,{errMsgProvider:Iq.defaultGrammarValidatorErrorProvider}),(0,iye.validateGrammar)(r.rules,r.maxLookahead,r.tokenTypes,r.errMsgProvider,r.grammarName)}nf.validateGrammar=sye});var sf=I(In=>{"use strict";var Td=In&&In.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(In,"__esModule",{value:!0});In.EarlyExitException=In.NotAllInputParsedException=In.NoViableAltException=In.MismatchedTokenException=In.isRecognitionException=void 0;var oye=Kt(),wq="MismatchedTokenException",Bq="NoViableAltException",Qq="EarlyExitException",bq="NotAllInputParsedException",Sq=[wq,Bq,Qq,bq];Object.freeze(Sq);function aye(r){return(0,oye.contains)(Sq,r.name)}In.isRecognitionException=aye;var dy=function(r){Td(e,r);function e(t,i){var n=this.constructor,s=r.call(this,t)||this;return s.token=i,s.resyncedTokens=[],Object.setPrototypeOf(s,n.prototype),Error.captureStackTrace&&Error.captureStackTrace(s,s.constructor),s}return e}(Error),Aye=function(r){Td(e,r);function e(t,i,n){var s=r.call(this,t,i)||this;return s.previousToken=n,s.name=wq,s}return e}(dy);In.MismatchedTokenException=Aye;var lye=function(r){Td(e,r);function e(t,i,n){var s=r.call(this,t,i)||this;return s.previousToken=n,s.name=Bq,s}return e}(dy);In.NoViableAltException=lye;var cye=function(r){Td(e,r);function e(t,i){var n=r.call(this,t,i)||this;return n.name=bq,n}return e}(dy);In.NotAllInputParsedException=cye;var uye=function(r){Td(e,r);function e(t,i,n){var s=r.call(this,t,i)||this;return s.previousToken=n,s.name=Qq,s}return e}(dy);In.EarlyExitException=uye});var ox=I(Ki=>{"use strict";Object.defineProperty(Ki,"__esModule",{value:!0});Ki.attemptInRepetitionRecovery=Ki.Recoverable=Ki.InRuleRecoveryException=Ki.IN_RULE_RECOVERY_EXCEPTION=Ki.EOF_FOLLOW_KEY=void 0;var Cy=NA(),gs=Kt(),gye=sf(),fye=Wv(),hye=Yn();Ki.EOF_FOLLOW_KEY={};Ki.IN_RULE_RECOVERY_EXCEPTION="InRuleRecoveryException";function sx(r){this.name=Ki.IN_RULE_RECOVERY_EXCEPTION,this.message=r}Ki.InRuleRecoveryException=sx;sx.prototype=Error.prototype;var pye=function(){function r(){}return r.prototype.initRecoverable=function(e){this.firstAfterRepMap={},this.resyncFollows={},this.recoveryEnabled=(0,gs.has)(e,"recoveryEnabled")?e.recoveryEnabled:hye.DEFAULT_PARSER_CONFIG.recoveryEnabled,this.recoveryEnabled&&(this.attemptInRepetitionRecovery=vq)},r.prototype.getTokenToInsert=function(e){var t=(0,Cy.createTokenInstance)(e,"",NaN,NaN,NaN,NaN,NaN,NaN);return t.isInsertedInRecovery=!0,t},r.prototype.canTokenTypeBeInsertedInRecovery=function(e){return!0},r.prototype.tryInRepetitionRecovery=function(e,t,i,n){for(var s=this,o=this.findReSyncTokenType(),a=this.exportLexerState(),l=[],c=!1,u=this.LA(1),g=this.LA(1),h=function(){var p=s.LA(0),d=s.errorMessageProvider.buildMismatchTokenMessage({expected:n,actual:u,previous:p,ruleName:s.getCurrRuleFullName()}),m=new gye.MismatchedTokenException(d,u,s.LA(0));m.resyncedTokens=(0,gs.dropRight)(l),s.SAVE_ERROR(m)};!c;)if(this.tokenMatcher(g,n)){h();return}else if(i.call(this)){h(),e.apply(this,t);return}else this.tokenMatcher(g,o)?c=!0:(g=this.SKIP_TOKEN(),this.addToResyncTokens(g,l));this.importLexerState(a)},r.prototype.shouldInRepetitionRecoveryBeTried=function(e,t,i){return!(i===!1||e===void 0||t===void 0||this.tokenMatcher(this.LA(1),e)||this.isBackTracking()||this.canPerformInRuleRecovery(e,this.getFollowsForInRuleRecovery(e,t)))},r.prototype.getFollowsForInRuleRecovery=function(e,t){var i=this.getCurrentGrammarPath(e,t),n=this.getNextPossibleTokenTypes(i);return n},r.prototype.tryInRuleRecovery=function(e,t){if(this.canRecoverWithSingleTokenInsertion(e,t)){var i=this.getTokenToInsert(e);return i}if(this.canRecoverWithSingleTokenDeletion(e)){var n=this.SKIP_TOKEN();return this.consumeToken(),n}throw new sx("sad sad panda")},r.prototype.canPerformInRuleRecovery=function(e,t){return this.canRecoverWithSingleTokenInsertion(e,t)||this.canRecoverWithSingleTokenDeletion(e)},r.prototype.canRecoverWithSingleTokenInsertion=function(e,t){var i=this;if(!this.canTokenTypeBeInsertedInRecovery(e)||(0,gs.isEmpty)(t))return!1;var n=this.LA(1),s=(0,gs.find)(t,function(o){return i.tokenMatcher(n,o)})!==void 0;return s},r.prototype.canRecoverWithSingleTokenDeletion=function(e){var t=this.tokenMatcher(this.LA(2),e);return t},r.prototype.isInCurrentRuleReSyncSet=function(e){var t=this.getCurrFollowKey(),i=this.getFollowSetFromFollowKey(t);return(0,gs.contains)(i,e)},r.prototype.findReSyncTokenType=function(){for(var e=this.flattenFollowSet(),t=this.LA(1),i=2;;){var n=t.tokenType;if((0,gs.contains)(e,n))return n;t=this.LA(i),i++}},r.prototype.getCurrFollowKey=function(){if(this.RULE_STACK.length===1)return Ki.EOF_FOLLOW_KEY;var e=this.getLastExplicitRuleShortName(),t=this.getLastExplicitRuleOccurrenceIndex(),i=this.getPreviousExplicitRuleShortName();return{ruleName:this.shortRuleNameToFullName(e),idxInCallingRule:t,inRule:this.shortRuleNameToFullName(i)}},r.prototype.buildFullFollowKeyStack=function(){var e=this,t=this.RULE_STACK,i=this.RULE_OCCURRENCE_STACK;return(0,gs.map)(t,function(n,s){return s===0?Ki.EOF_FOLLOW_KEY:{ruleName:e.shortRuleNameToFullName(n),idxInCallingRule:i[s],inRule:e.shortRuleNameToFullName(t[s-1])}})},r.prototype.flattenFollowSet=function(){var e=this,t=(0,gs.map)(this.buildFullFollowKeyStack(),function(i){return e.getFollowSetFromFollowKey(i)});return(0,gs.flatten)(t)},r.prototype.getFollowSetFromFollowKey=function(e){if(e===Ki.EOF_FOLLOW_KEY)return[Cy.EOF];var t=e.ruleName+e.idxInCallingRule+fye.IN+e.inRule;return this.resyncFollows[t]},r.prototype.addToResyncTokens=function(e,t){return this.tokenMatcher(e,Cy.EOF)||t.push(e),t},r.prototype.reSyncTo=function(e){for(var t=[],i=this.LA(1);this.tokenMatcher(i,e)===!1;)i=this.SKIP_TOKEN(),this.addToResyncTokens(i,t);return(0,gs.dropRight)(t)},r.prototype.attemptInRepetitionRecovery=function(e,t,i,n,s,o,a){},r.prototype.getCurrentGrammarPath=function(e,t){var i=this.getHumanReadableRuleStack(),n=(0,gs.cloneArr)(this.RULE_OCCURRENCE_STACK),s={ruleStack:i,occurrenceStack:n,lastTok:e,lastTokOccurrence:t};return s},r.prototype.getHumanReadableRuleStack=function(){var e=this;return(0,gs.map)(this.RULE_STACK,function(t){return e.shortRuleNameToFullName(t)})},r}();Ki.Recoverable=pye;function vq(r,e,t,i,n,s,o){var a=this.getKeyForAutomaticLookahead(i,n),l=this.firstAfterRepMap[a];if(l===void 0){var c=this.getCurrRuleFullName(),u=this.getGAstProductions()[c],g=new s(u,n);l=g.startWalking(),this.firstAfterRepMap[a]=l}var h=l.token,p=l.occurrence,d=l.isEndOfRule;this.RULE_STACK.length===1&&d&&h===void 0&&(h=Cy.EOF,p=1),this.shouldInRepetitionRecoveryBeTried(h,p,o)&&this.tryInRepetitionRecovery(r,e,t,h)}Ki.attemptInRepetitionRecovery=vq});var my=I(Yt=>{"use strict";Object.defineProperty(Yt,"__esModule",{value:!0});Yt.getKeyForAutomaticLookahead=Yt.AT_LEAST_ONE_SEP_IDX=Yt.MANY_SEP_IDX=Yt.AT_LEAST_ONE_IDX=Yt.MANY_IDX=Yt.OPTION_IDX=Yt.OR_IDX=Yt.BITS_FOR_ALT_IDX=Yt.BITS_FOR_RULE_IDX=Yt.BITS_FOR_OCCURRENCE_IDX=Yt.BITS_FOR_METHOD_TYPE=void 0;Yt.BITS_FOR_METHOD_TYPE=4;Yt.BITS_FOR_OCCURRENCE_IDX=8;Yt.BITS_FOR_RULE_IDX=12;Yt.BITS_FOR_ALT_IDX=8;Yt.OR_IDX=1<{"use strict";Object.defineProperty(Ey,"__esModule",{value:!0});Ey.LooksAhead=void 0;var Ra=Fd(),to=Kt(),xq=Yn(),Fa=my(),yc=Pd(),Cye=function(){function r(){}return r.prototype.initLooksAhead=function(e){this.dynamicTokensEnabled=(0,to.has)(e,"dynamicTokensEnabled")?e.dynamicTokensEnabled:xq.DEFAULT_PARSER_CONFIG.dynamicTokensEnabled,this.maxLookahead=(0,to.has)(e,"maxLookahead")?e.maxLookahead:xq.DEFAULT_PARSER_CONFIG.maxLookahead,this.lookAheadFuncsCache=(0,to.isES2015MapSupported)()?new Map:[],(0,to.isES2015MapSupported)()?(this.getLaFuncFromCache=this.getLaFuncFromMap,this.setLaFuncCache=this.setLaFuncCacheUsingMap):(this.getLaFuncFromCache=this.getLaFuncFromObj,this.setLaFuncCache=this.setLaFuncUsingObj)},r.prototype.preComputeLookaheadFunctions=function(e){var t=this;(0,to.forEach)(e,function(i){t.TRACE_INIT(i.name+" Rule Lookahead",function(){var n=(0,yc.collectMethods)(i),s=n.alternation,o=n.repetition,a=n.option,l=n.repetitionMandatory,c=n.repetitionMandatoryWithSeparator,u=n.repetitionWithSeparator;(0,to.forEach)(s,function(g){var h=g.idx===0?"":g.idx;t.TRACE_INIT(""+(0,yc.getProductionDslName)(g)+h,function(){var p=(0,Ra.buildLookaheadFuncForOr)(g.idx,i,g.maxLookahead||t.maxLookahead,g.hasPredicates,t.dynamicTokensEnabled,t.lookAheadBuilderForAlternatives),d=(0,Fa.getKeyForAutomaticLookahead)(t.fullRuleNameToShort[i.name],Fa.OR_IDX,g.idx);t.setLaFuncCache(d,p)})}),(0,to.forEach)(o,function(g){t.computeLookaheadFunc(i,g.idx,Fa.MANY_IDX,Ra.PROD_TYPE.REPETITION,g.maxLookahead,(0,yc.getProductionDslName)(g))}),(0,to.forEach)(a,function(g){t.computeLookaheadFunc(i,g.idx,Fa.OPTION_IDX,Ra.PROD_TYPE.OPTION,g.maxLookahead,(0,yc.getProductionDslName)(g))}),(0,to.forEach)(l,function(g){t.computeLookaheadFunc(i,g.idx,Fa.AT_LEAST_ONE_IDX,Ra.PROD_TYPE.REPETITION_MANDATORY,g.maxLookahead,(0,yc.getProductionDslName)(g))}),(0,to.forEach)(c,function(g){t.computeLookaheadFunc(i,g.idx,Fa.AT_LEAST_ONE_SEP_IDX,Ra.PROD_TYPE.REPETITION_MANDATORY_WITH_SEPARATOR,g.maxLookahead,(0,yc.getProductionDslName)(g))}),(0,to.forEach)(u,function(g){t.computeLookaheadFunc(i,g.idx,Fa.MANY_SEP_IDX,Ra.PROD_TYPE.REPETITION_WITH_SEPARATOR,g.maxLookahead,(0,yc.getProductionDslName)(g))})})})},r.prototype.computeLookaheadFunc=function(e,t,i,n,s,o){var a=this;this.TRACE_INIT(""+o+(t===0?"":t),function(){var l=(0,Ra.buildLookaheadFuncForOptionalProd)(t,e,s||a.maxLookahead,a.dynamicTokensEnabled,n,a.lookAheadBuilderForOptional),c=(0,Fa.getKeyForAutomaticLookahead)(a.fullRuleNameToShort[e.name],i,t);a.setLaFuncCache(c,l)})},r.prototype.lookAheadBuilderForOptional=function(e,t,i){return(0,Ra.buildSingleAlternativeLookaheadFunction)(e,t,i)},r.prototype.lookAheadBuilderForAlternatives=function(e,t,i,n){return(0,Ra.buildAlternativesLookAheadFunc)(e,t,i,n)},r.prototype.getKeyForAutomaticLookahead=function(e,t){var i=this.getLastExplicitRuleShortName();return(0,Fa.getKeyForAutomaticLookahead)(i,e,t)},r.prototype.getLaFuncFromCache=function(e){},r.prototype.getLaFuncFromMap=function(e){return this.lookAheadFuncsCache.get(e)},r.prototype.getLaFuncFromObj=function(e){return this.lookAheadFuncsCache[e]},r.prototype.setLaFuncCache=function(e,t){},r.prototype.setLaFuncCacheUsingMap=function(e,t){this.lookAheadFuncsCache.set(e,t)},r.prototype.setLaFuncUsingObj=function(e,t){this.lookAheadFuncsCache[e]=t},r}();Ey.LooksAhead=Cye});var kq=I(To=>{"use strict";Object.defineProperty(To,"__esModule",{value:!0});To.addNoneTerminalToCst=To.addTerminalToCst=To.setNodeLocationFull=To.setNodeLocationOnlyOffset=void 0;function mye(r,e){isNaN(r.startOffset)===!0?(r.startOffset=e.startOffset,r.endOffset=e.endOffset):r.endOffset{"use strict";Object.defineProperty(OA,"__esModule",{value:!0});OA.defineNameProp=OA.functionName=OA.classNameFromInstance=void 0;var wye=Kt();function Bye(r){return Rq(r.constructor)}OA.classNameFromInstance=Bye;var Dq="name";function Rq(r){var e=r.name;return e||"anonymous"}OA.functionName=Rq;function Qye(r,e){var t=Object.getOwnPropertyDescriptor(r,Dq);return(0,wye.isUndefined)(t)||t.configurable?(Object.defineProperty(r,Dq,{enumerable:!1,configurable:!0,writable:!1,value:e}),!0):!1}OA.defineNameProp=Qye});var Oq=I(vi=>{"use strict";Object.defineProperty(vi,"__esModule",{value:!0});vi.validateRedundantMethods=vi.validateMissingCstMethods=vi.validateVisitor=vi.CstVisitorDefinitionError=vi.createBaseVisitorConstructorWithDefaults=vi.createBaseSemanticVisitorConstructor=vi.defaultVisit=void 0;var fs=Kt(),Ld=ax();function Fq(r,e){for(var t=(0,fs.keys)(r),i=t.length,n=0;n: + `+(""+s.join(` + +`).replace(/\n/g,` + `)))}}};return t.prototype=i,t.prototype.constructor=t,t._RULE_NAMES=e,t}vi.createBaseSemanticVisitorConstructor=bye;function Sye(r,e,t){var i=function(){};(0,Ld.defineNameProp)(i,r+"BaseSemanticsWithDefaults");var n=Object.create(t.prototype);return(0,fs.forEach)(e,function(s){n[s]=Fq}),i.prototype=n,i.prototype.constructor=i,i}vi.createBaseVisitorConstructorWithDefaults=Sye;var Ax;(function(r){r[r.REDUNDANT_METHOD=0]="REDUNDANT_METHOD",r[r.MISSING_METHOD=1]="MISSING_METHOD"})(Ax=vi.CstVisitorDefinitionError||(vi.CstVisitorDefinitionError={}));function Nq(r,e){var t=Tq(r,e),i=Lq(r,e);return t.concat(i)}vi.validateVisitor=Nq;function Tq(r,e){var t=(0,fs.map)(e,function(i){if(!(0,fs.isFunction)(r[i]))return{msg:"Missing visitor method: <"+i+"> on "+(0,Ld.functionName)(r.constructor)+" CST Visitor.",type:Ax.MISSING_METHOD,methodName:i}});return(0,fs.compact)(t)}vi.validateMissingCstMethods=Tq;var vye=["constructor","visit","validateVisitor"];function Lq(r,e){var t=[];for(var i in r)(0,fs.isFunction)(r[i])&&!(0,fs.contains)(vye,i)&&!(0,fs.contains)(e,i)&&t.push({msg:"Redundant visitor method: <"+i+"> on "+(0,Ld.functionName)(r.constructor)+` CST Visitor +There is no Grammar Rule corresponding to this method's name. +`,type:Ax.REDUNDANT_METHOD,methodName:i});return t}vi.validateRedundantMethods=Lq});var Kq=I(Iy=>{"use strict";Object.defineProperty(Iy,"__esModule",{value:!0});Iy.TreeBuilder=void 0;var of=kq(),Vr=Kt(),Mq=Oq(),xye=Yn(),Pye=function(){function r(){}return r.prototype.initTreeBuilder=function(e){if(this.CST_STACK=[],this.outputCst=e.outputCst,this.nodeLocationTracking=(0,Vr.has)(e,"nodeLocationTracking")?e.nodeLocationTracking:xye.DEFAULT_PARSER_CONFIG.nodeLocationTracking,!this.outputCst)this.cstInvocationStateUpdate=Vr.NOOP,this.cstFinallyStateUpdate=Vr.NOOP,this.cstPostTerminal=Vr.NOOP,this.cstPostNonTerminal=Vr.NOOP,this.cstPostRule=Vr.NOOP;else if(/full/i.test(this.nodeLocationTracking))this.recoveryEnabled?(this.setNodeLocationFromToken=of.setNodeLocationFull,this.setNodeLocationFromNode=of.setNodeLocationFull,this.cstPostRule=Vr.NOOP,this.setInitialNodeLocation=this.setInitialNodeLocationFullRecovery):(this.setNodeLocationFromToken=Vr.NOOP,this.setNodeLocationFromNode=Vr.NOOP,this.cstPostRule=this.cstPostRuleFull,this.setInitialNodeLocation=this.setInitialNodeLocationFullRegular);else if(/onlyOffset/i.test(this.nodeLocationTracking))this.recoveryEnabled?(this.setNodeLocationFromToken=of.setNodeLocationOnlyOffset,this.setNodeLocationFromNode=of.setNodeLocationOnlyOffset,this.cstPostRule=Vr.NOOP,this.setInitialNodeLocation=this.setInitialNodeLocationOnlyOffsetRecovery):(this.setNodeLocationFromToken=Vr.NOOP,this.setNodeLocationFromNode=Vr.NOOP,this.cstPostRule=this.cstPostRuleOnlyOffset,this.setInitialNodeLocation=this.setInitialNodeLocationOnlyOffsetRegular);else if(/none/i.test(this.nodeLocationTracking))this.setNodeLocationFromToken=Vr.NOOP,this.setNodeLocationFromNode=Vr.NOOP,this.cstPostRule=Vr.NOOP,this.setInitialNodeLocation=Vr.NOOP;else throw Error('Invalid config option: "'+e.nodeLocationTracking+'"')},r.prototype.setInitialNodeLocationOnlyOffsetRecovery=function(e){e.location={startOffset:NaN,endOffset:NaN}},r.prototype.setInitialNodeLocationOnlyOffsetRegular=function(e){e.location={startOffset:this.LA(1).startOffset,endOffset:NaN}},r.prototype.setInitialNodeLocationFullRecovery=function(e){e.location={startOffset:NaN,startLine:NaN,startColumn:NaN,endOffset:NaN,endLine:NaN,endColumn:NaN}},r.prototype.setInitialNodeLocationFullRegular=function(e){var t=this.LA(1);e.location={startOffset:t.startOffset,startLine:t.startLine,startColumn:t.startColumn,endOffset:NaN,endLine:NaN,endColumn:NaN}},r.prototype.cstInvocationStateUpdate=function(e,t){var i={name:e,children:{}};this.setInitialNodeLocation(i),this.CST_STACK.push(i)},r.prototype.cstFinallyStateUpdate=function(){this.CST_STACK.pop()},r.prototype.cstPostRuleFull=function(e){var t=this.LA(0),i=e.location;i.startOffset<=t.startOffset?(i.endOffset=t.endOffset,i.endLine=t.endLine,i.endColumn=t.endColumn):(i.startOffset=NaN,i.startLine=NaN,i.startColumn=NaN)},r.prototype.cstPostRuleOnlyOffset=function(e){var t=this.LA(0),i=e.location;i.startOffset<=t.startOffset?i.endOffset=t.endOffset:i.startOffset=NaN},r.prototype.cstPostTerminal=function(e,t){var i=this.CST_STACK[this.CST_STACK.length-1];(0,of.addTerminalToCst)(i,t,e),this.setNodeLocationFromToken(i.location,t)},r.prototype.cstPostNonTerminal=function(e,t){var i=this.CST_STACK[this.CST_STACK.length-1];(0,of.addNoneTerminalToCst)(i,t,e),this.setNodeLocationFromNode(i.location,e.location)},r.prototype.getBaseCstVisitorConstructor=function(){if((0,Vr.isUndefined)(this.baseCstVisitorConstructor)){var e=(0,Mq.createBaseSemanticVisitorConstructor)(this.className,(0,Vr.keys)(this.gastProductionsCache));return this.baseCstVisitorConstructor=e,e}return this.baseCstVisitorConstructor},r.prototype.getBaseCstVisitorConstructorWithDefaults=function(){if((0,Vr.isUndefined)(this.baseCstVisitorWithDefaultsConstructor)){var e=(0,Mq.createBaseVisitorConstructorWithDefaults)(this.className,(0,Vr.keys)(this.gastProductionsCache),this.getBaseCstVisitorConstructor());return this.baseCstVisitorWithDefaultsConstructor=e,e}return this.baseCstVisitorWithDefaultsConstructor},r.prototype.getLastExplicitRuleShortName=function(){var e=this.RULE_STACK;return e[e.length-1]},r.prototype.getPreviousExplicitRuleShortName=function(){var e=this.RULE_STACK;return e[e.length-2]},r.prototype.getLastExplicitRuleOccurrenceIndex=function(){var e=this.RULE_OCCURRENCE_STACK;return e[e.length-1]},r}();Iy.TreeBuilder=Pye});var Hq=I(yy=>{"use strict";Object.defineProperty(yy,"__esModule",{value:!0});yy.LexerAdapter=void 0;var Uq=Yn(),kye=function(){function r(){}return r.prototype.initLexerAdapter=function(){this.tokVector=[],this.tokVectorLength=0,this.currIdx=-1},Object.defineProperty(r.prototype,"input",{get:function(){return this.tokVector},set:function(e){if(this.selfAnalysisDone!==!0)throw Error("Missing invocation at the end of the Parser's constructor.");this.reset(),this.tokVector=e,this.tokVectorLength=e.length},enumerable:!1,configurable:!0}),r.prototype.SKIP_TOKEN=function(){return this.currIdx<=this.tokVector.length-2?(this.consumeToken(),this.LA(1)):Uq.END_OF_FILE},r.prototype.LA=function(e){var t=this.currIdx+e;return t<0||this.tokVectorLength<=t?Uq.END_OF_FILE:this.tokVector[t]},r.prototype.consumeToken=function(){this.currIdx++},r.prototype.exportLexerState=function(){return this.currIdx},r.prototype.importLexerState=function(e){this.currIdx=e},r.prototype.resetLexerState=function(){this.currIdx=-1},r.prototype.moveToTerminatedState=function(){this.currIdx=this.tokVector.length-1},r.prototype.getLexerPosition=function(){return this.exportLexerState()},r}();yy.LexerAdapter=kye});var Yq=I(wy=>{"use strict";Object.defineProperty(wy,"__esModule",{value:!0});wy.RecognizerApi=void 0;var Gq=Kt(),Dye=sf(),lx=Yn(),Rye=kd(),Fye=ix(),Nye=mn(),Tye=function(){function r(){}return r.prototype.ACTION=function(e){return e.call(this)},r.prototype.consume=function(e,t,i){return this.consumeInternal(t,e,i)},r.prototype.subrule=function(e,t,i){return this.subruleInternal(t,e,i)},r.prototype.option=function(e,t){return this.optionInternal(t,e)},r.prototype.or=function(e,t){return this.orInternal(t,e)},r.prototype.many=function(e,t){return this.manyInternal(e,t)},r.prototype.atLeastOne=function(e,t){return this.atLeastOneInternal(e,t)},r.prototype.CONSUME=function(e,t){return this.consumeInternal(e,0,t)},r.prototype.CONSUME1=function(e,t){return this.consumeInternal(e,1,t)},r.prototype.CONSUME2=function(e,t){return this.consumeInternal(e,2,t)},r.prototype.CONSUME3=function(e,t){return this.consumeInternal(e,3,t)},r.prototype.CONSUME4=function(e,t){return this.consumeInternal(e,4,t)},r.prototype.CONSUME5=function(e,t){return this.consumeInternal(e,5,t)},r.prototype.CONSUME6=function(e,t){return this.consumeInternal(e,6,t)},r.prototype.CONSUME7=function(e,t){return this.consumeInternal(e,7,t)},r.prototype.CONSUME8=function(e,t){return this.consumeInternal(e,8,t)},r.prototype.CONSUME9=function(e,t){return this.consumeInternal(e,9,t)},r.prototype.SUBRULE=function(e,t){return this.subruleInternal(e,0,t)},r.prototype.SUBRULE1=function(e,t){return this.subruleInternal(e,1,t)},r.prototype.SUBRULE2=function(e,t){return this.subruleInternal(e,2,t)},r.prototype.SUBRULE3=function(e,t){return this.subruleInternal(e,3,t)},r.prototype.SUBRULE4=function(e,t){return this.subruleInternal(e,4,t)},r.prototype.SUBRULE5=function(e,t){return this.subruleInternal(e,5,t)},r.prototype.SUBRULE6=function(e,t){return this.subruleInternal(e,6,t)},r.prototype.SUBRULE7=function(e,t){return this.subruleInternal(e,7,t)},r.prototype.SUBRULE8=function(e,t){return this.subruleInternal(e,8,t)},r.prototype.SUBRULE9=function(e,t){return this.subruleInternal(e,9,t)},r.prototype.OPTION=function(e){return this.optionInternal(e,0)},r.prototype.OPTION1=function(e){return this.optionInternal(e,1)},r.prototype.OPTION2=function(e){return this.optionInternal(e,2)},r.prototype.OPTION3=function(e){return this.optionInternal(e,3)},r.prototype.OPTION4=function(e){return this.optionInternal(e,4)},r.prototype.OPTION5=function(e){return this.optionInternal(e,5)},r.prototype.OPTION6=function(e){return this.optionInternal(e,6)},r.prototype.OPTION7=function(e){return this.optionInternal(e,7)},r.prototype.OPTION8=function(e){return this.optionInternal(e,8)},r.prototype.OPTION9=function(e){return this.optionInternal(e,9)},r.prototype.OR=function(e){return this.orInternal(e,0)},r.prototype.OR1=function(e){return this.orInternal(e,1)},r.prototype.OR2=function(e){return this.orInternal(e,2)},r.prototype.OR3=function(e){return this.orInternal(e,3)},r.prototype.OR4=function(e){return this.orInternal(e,4)},r.prototype.OR5=function(e){return this.orInternal(e,5)},r.prototype.OR6=function(e){return this.orInternal(e,6)},r.prototype.OR7=function(e){return this.orInternal(e,7)},r.prototype.OR8=function(e){return this.orInternal(e,8)},r.prototype.OR9=function(e){return this.orInternal(e,9)},r.prototype.MANY=function(e){this.manyInternal(0,e)},r.prototype.MANY1=function(e){this.manyInternal(1,e)},r.prototype.MANY2=function(e){this.manyInternal(2,e)},r.prototype.MANY3=function(e){this.manyInternal(3,e)},r.prototype.MANY4=function(e){this.manyInternal(4,e)},r.prototype.MANY5=function(e){this.manyInternal(5,e)},r.prototype.MANY6=function(e){this.manyInternal(6,e)},r.prototype.MANY7=function(e){this.manyInternal(7,e)},r.prototype.MANY8=function(e){this.manyInternal(8,e)},r.prototype.MANY9=function(e){this.manyInternal(9,e)},r.prototype.MANY_SEP=function(e){this.manySepFirstInternal(0,e)},r.prototype.MANY_SEP1=function(e){this.manySepFirstInternal(1,e)},r.prototype.MANY_SEP2=function(e){this.manySepFirstInternal(2,e)},r.prototype.MANY_SEP3=function(e){this.manySepFirstInternal(3,e)},r.prototype.MANY_SEP4=function(e){this.manySepFirstInternal(4,e)},r.prototype.MANY_SEP5=function(e){this.manySepFirstInternal(5,e)},r.prototype.MANY_SEP6=function(e){this.manySepFirstInternal(6,e)},r.prototype.MANY_SEP7=function(e){this.manySepFirstInternal(7,e)},r.prototype.MANY_SEP8=function(e){this.manySepFirstInternal(8,e)},r.prototype.MANY_SEP9=function(e){this.manySepFirstInternal(9,e)},r.prototype.AT_LEAST_ONE=function(e){this.atLeastOneInternal(0,e)},r.prototype.AT_LEAST_ONE1=function(e){return this.atLeastOneInternal(1,e)},r.prototype.AT_LEAST_ONE2=function(e){this.atLeastOneInternal(2,e)},r.prototype.AT_LEAST_ONE3=function(e){this.atLeastOneInternal(3,e)},r.prototype.AT_LEAST_ONE4=function(e){this.atLeastOneInternal(4,e)},r.prototype.AT_LEAST_ONE5=function(e){this.atLeastOneInternal(5,e)},r.prototype.AT_LEAST_ONE6=function(e){this.atLeastOneInternal(6,e)},r.prototype.AT_LEAST_ONE7=function(e){this.atLeastOneInternal(7,e)},r.prototype.AT_LEAST_ONE8=function(e){this.atLeastOneInternal(8,e)},r.prototype.AT_LEAST_ONE9=function(e){this.atLeastOneInternal(9,e)},r.prototype.AT_LEAST_ONE_SEP=function(e){this.atLeastOneSepFirstInternal(0,e)},r.prototype.AT_LEAST_ONE_SEP1=function(e){this.atLeastOneSepFirstInternal(1,e)},r.prototype.AT_LEAST_ONE_SEP2=function(e){this.atLeastOneSepFirstInternal(2,e)},r.prototype.AT_LEAST_ONE_SEP3=function(e){this.atLeastOneSepFirstInternal(3,e)},r.prototype.AT_LEAST_ONE_SEP4=function(e){this.atLeastOneSepFirstInternal(4,e)},r.prototype.AT_LEAST_ONE_SEP5=function(e){this.atLeastOneSepFirstInternal(5,e)},r.prototype.AT_LEAST_ONE_SEP6=function(e){this.atLeastOneSepFirstInternal(6,e)},r.prototype.AT_LEAST_ONE_SEP7=function(e){this.atLeastOneSepFirstInternal(7,e)},r.prototype.AT_LEAST_ONE_SEP8=function(e){this.atLeastOneSepFirstInternal(8,e)},r.prototype.AT_LEAST_ONE_SEP9=function(e){this.atLeastOneSepFirstInternal(9,e)},r.prototype.RULE=function(e,t,i){if(i===void 0&&(i=lx.DEFAULT_RULE_CONFIG),(0,Gq.contains)(this.definedRulesNames,e)){var n=Rye.defaultGrammarValidatorErrorProvider.buildDuplicateRuleNameError({topLevelRule:e,grammarName:this.className}),s={message:n,type:lx.ParserDefinitionErrorType.DUPLICATE_RULE_NAME,ruleName:e};this.definitionErrors.push(s)}this.definedRulesNames.push(e);var o=this.defineRule(e,t,i);return this[e]=o,o},r.prototype.OVERRIDE_RULE=function(e,t,i){i===void 0&&(i=lx.DEFAULT_RULE_CONFIG);var n=[];n=n.concat((0,Fye.validateRuleIsOverridden)(e,this.definedRulesNames,this.className)),this.definitionErrors=this.definitionErrors.concat(n);var s=this.defineRule(e,t,i);return this[e]=s,s},r.prototype.BACKTRACK=function(e,t){return function(){this.isBackTrackingStack.push(1);var i=this.saveRecogState();try{return e.apply(this,t),!0}catch(n){if((0,Dye.isRecognitionException)(n))return!1;throw n}finally{this.reloadRecogState(i),this.isBackTrackingStack.pop()}}},r.prototype.getGAstProductions=function(){return this.gastProductionsCache},r.prototype.getSerializedGastProductions=function(){return(0,Nye.serializeGrammar)((0,Gq.values)(this.gastProductionsCache))},r}();wy.RecognizerApi=Tye});var Wq=I(Qy=>{"use strict";Object.defineProperty(Qy,"__esModule",{value:!0});Qy.RecognizerEngine=void 0;var xr=Kt(),jn=my(),By=sf(),jq=Fd(),af=Rd(),qq=Yn(),Lye=ox(),Jq=NA(),Od=$g(),Oye=ax(),Mye=function(){function r(){}return r.prototype.initRecognizerEngine=function(e,t){if(this.className=(0,Oye.classNameFromInstance)(this),this.shortRuleNameToFull={},this.fullRuleNameToShort={},this.ruleShortNameIdx=256,this.tokenMatcher=Od.tokenStructuredMatcherNoCategories,this.definedRulesNames=[],this.tokensMap={},this.isBackTrackingStack=[],this.RULE_STACK=[],this.RULE_OCCURRENCE_STACK=[],this.gastProductionsCache={},(0,xr.has)(t,"serializedGrammar"))throw Error(`The Parser's configuration can no longer contain a property. + See: https://chevrotain.io/docs/changes/BREAKING_CHANGES.html#_6-0-0 + For Further details.`);if((0,xr.isArray)(e)){if((0,xr.isEmpty)(e))throw Error(`A Token Vocabulary cannot be empty. + Note that the first argument for the parser constructor + is no longer a Token vector (since v4.0).`);if(typeof e[0].startOffset=="number")throw Error(`The Parser constructor no longer accepts a token vector as the first argument. + See: https://chevrotain.io/docs/changes/BREAKING_CHANGES.html#_4-0-0 + For Further details.`)}if((0,xr.isArray)(e))this.tokensMap=(0,xr.reduce)(e,function(o,a){return o[a.name]=a,o},{});else if((0,xr.has)(e,"modes")&&(0,xr.every)((0,xr.flatten)((0,xr.values)(e.modes)),Od.isTokenType)){var i=(0,xr.flatten)((0,xr.values)(e.modes)),n=(0,xr.uniq)(i);this.tokensMap=(0,xr.reduce)(n,function(o,a){return o[a.name]=a,o},{})}else if((0,xr.isObject)(e))this.tokensMap=(0,xr.cloneObj)(e);else throw new Error(" argument must be An Array of Token constructors, A dictionary of Token constructors or an IMultiModeLexerDefinition");this.tokensMap.EOF=Jq.EOF;var s=(0,xr.every)((0,xr.values)(e),function(o){return(0,xr.isEmpty)(o.categoryMatches)});this.tokenMatcher=s?Od.tokenStructuredMatcherNoCategories:Od.tokenStructuredMatcher,(0,Od.augmentTokenTypes)((0,xr.values)(this.tokensMap))},r.prototype.defineRule=function(e,t,i){if(this.selfAnalysisDone)throw Error("Grammar rule <"+e+`> may not be defined after the 'performSelfAnalysis' method has been called' +Make sure that all grammar rule definitions are done before 'performSelfAnalysis' is called.`);var n=(0,xr.has)(i,"resyncEnabled")?i.resyncEnabled:qq.DEFAULT_RULE_CONFIG.resyncEnabled,s=(0,xr.has)(i,"recoveryValueFunc")?i.recoveryValueFunc:qq.DEFAULT_RULE_CONFIG.recoveryValueFunc,o=this.ruleShortNameIdx<t},r.prototype.orInternal=function(e,t){var i=this.getKeyForAutomaticLookahead(jn.OR_IDX,t),n=(0,xr.isArray)(e)?e:e.DEF,s=this.getLaFuncFromCache(i),o=s.call(this,n);if(o!==void 0){var a=n[o];return a.ALT.call(this)}this.raiseNoAltException(t,e.ERR_MSG)},r.prototype.ruleFinallyStateUpdate=function(){if(this.RULE_STACK.pop(),this.RULE_OCCURRENCE_STACK.pop(),this.cstFinallyStateUpdate(),this.RULE_STACK.length===0&&this.isAtEndOfInput()===!1){var e=this.LA(1),t=this.errorMessageProvider.buildNotAllInputParsedMessage({firstRedundant:e,ruleName:this.getCurrRuleFullName()});this.SAVE_ERROR(new By.NotAllInputParsedException(t,e))}},r.prototype.subruleInternal=function(e,t,i){var n;try{var s=i!==void 0?i.ARGS:void 0;return n=e.call(this,t,s),this.cstPostNonTerminal(n,i!==void 0&&i.LABEL!==void 0?i.LABEL:e.ruleName),n}catch(o){this.subruleInternalError(o,i,e.ruleName)}},r.prototype.subruleInternalError=function(e,t,i){throw(0,By.isRecognitionException)(e)&&e.partialCstResult!==void 0&&(this.cstPostNonTerminal(e.partialCstResult,t!==void 0&&t.LABEL!==void 0?t.LABEL:i),delete e.partialCstResult),e},r.prototype.consumeInternal=function(e,t,i){var n;try{var s=this.LA(1);this.tokenMatcher(s,e)===!0?(this.consumeToken(),n=s):this.consumeInternalError(e,s,i)}catch(o){n=this.consumeInternalRecovery(e,t,o)}return this.cstPostTerminal(i!==void 0&&i.LABEL!==void 0?i.LABEL:e.name,n),n},r.prototype.consumeInternalError=function(e,t,i){var n,s=this.LA(0);throw i!==void 0&&i.ERR_MSG?n=i.ERR_MSG:n=this.errorMessageProvider.buildMismatchTokenMessage({expected:e,actual:t,previous:s,ruleName:this.getCurrRuleFullName()}),this.SAVE_ERROR(new By.MismatchedTokenException(n,t,s))},r.prototype.consumeInternalRecovery=function(e,t,i){if(this.recoveryEnabled&&i.name==="MismatchedTokenException"&&!this.isBackTracking()){var n=this.getFollowsForInRuleRecovery(e,t);try{return this.tryInRuleRecovery(e,n)}catch(s){throw s.name===Lye.IN_RULE_RECOVERY_EXCEPTION?i:s}}else throw i},r.prototype.saveRecogState=function(){var e=this.errors,t=(0,xr.cloneArr)(this.RULE_STACK);return{errors:e,lexerState:this.exportLexerState(),RULE_STACK:t,CST_STACK:this.CST_STACK}},r.prototype.reloadRecogState=function(e){this.errors=e.errors,this.importLexerState(e.lexerState),this.RULE_STACK=e.RULE_STACK},r.prototype.ruleInvocationStateUpdate=function(e,t,i){this.RULE_OCCURRENCE_STACK.push(i),this.RULE_STACK.push(e),this.cstInvocationStateUpdate(t,e)},r.prototype.isBackTracking=function(){return this.isBackTrackingStack.length!==0},r.prototype.getCurrRuleFullName=function(){var e=this.getLastExplicitRuleShortName();return this.shortRuleNameToFull[e]},r.prototype.shortRuleNameToFullName=function(e){return this.shortRuleNameToFull[e]},r.prototype.isAtEndOfInput=function(){return this.tokenMatcher(this.LA(1),Jq.EOF)},r.prototype.reset=function(){this.resetLexerState(),this.isBackTrackingStack=[],this.errors=[],this.RULE_STACK=[],this.CST_STACK=[],this.RULE_OCCURRENCE_STACK=[]},r}();Qy.RecognizerEngine=Mye});var Vq=I(by=>{"use strict";Object.defineProperty(by,"__esModule",{value:!0});by.ErrorHandler=void 0;var cx=sf(),ux=Kt(),zq=Fd(),Kye=Yn(),Uye=function(){function r(){}return r.prototype.initErrorHandler=function(e){this._errors=[],this.errorMessageProvider=(0,ux.has)(e,"errorMessageProvider")?e.errorMessageProvider:Kye.DEFAULT_PARSER_CONFIG.errorMessageProvider},r.prototype.SAVE_ERROR=function(e){if((0,cx.isRecognitionException)(e))return e.context={ruleStack:this.getHumanReadableRuleStack(),ruleOccurrenceStack:(0,ux.cloneArr)(this.RULE_OCCURRENCE_STACK)},this._errors.push(e),e;throw Error("Trying to save an Error which is not a RecognitionException")},Object.defineProperty(r.prototype,"errors",{get:function(){return(0,ux.cloneArr)(this._errors)},set:function(e){this._errors=e},enumerable:!1,configurable:!0}),r.prototype.raiseEarlyExitException=function(e,t,i){for(var n=this.getCurrRuleFullName(),s=this.getGAstProductions()[n],o=(0,zq.getLookaheadPathsForOptionalProd)(e,s,t,this.maxLookahead),a=o[0],l=[],c=1;c<=this.maxLookahead;c++)l.push(this.LA(c));var u=this.errorMessageProvider.buildEarlyExitMessage({expectedIterationPaths:a,actual:l,previous:this.LA(0),customUserDescription:i,ruleName:n});throw this.SAVE_ERROR(new cx.EarlyExitException(u,this.LA(1),this.LA(0)))},r.prototype.raiseNoAltException=function(e,t){for(var i=this.getCurrRuleFullName(),n=this.getGAstProductions()[i],s=(0,zq.getLookaheadPathsForOr)(e,n,this.maxLookahead),o=[],a=1;a<=this.maxLookahead;a++)o.push(this.LA(a));var l=this.LA(0),c=this.errorMessageProvider.buildNoViableAltMessage({expectedPathsPerAlt:s,actual:o,previous:l,customUserDescription:t,ruleName:this.getCurrRuleFullName()});throw this.SAVE_ERROR(new cx.NoViableAltException(c,this.LA(1),l))},r}();by.ErrorHandler=Uye});var _q=I(Sy=>{"use strict";Object.defineProperty(Sy,"__esModule",{value:!0});Sy.ContentAssist=void 0;var Xq=Rd(),Zq=Kt(),Hye=function(){function r(){}return r.prototype.initContentAssist=function(){},r.prototype.computeContentAssist=function(e,t){var i=this.gastProductionsCache[e];if((0,Zq.isUndefined)(i))throw Error("Rule ->"+e+"<- does not exist in this grammar.");return(0,Xq.nextPossibleTokensAfter)([i],t,this.tokenMatcher,this.maxLookahead)},r.prototype.getNextPossibleTokenTypes=function(e){var t=(0,Zq.first)(e.ruleStack),i=this.getGAstProductions(),n=i[t],s=new Xq.NextAfterTokenWalker(n,e).startWalking();return s},r}();Sy.ContentAssist=Hye});var oJ=I(Py=>{"use strict";Object.defineProperty(Py,"__esModule",{value:!0});Py.GastRecorder=void 0;var yn=Kt(),Lo=mn(),Gye=bd(),rJ=$g(),iJ=NA(),Yye=Yn(),jye=my(),xy={description:"This Object indicates the Parser is during Recording Phase"};Object.freeze(xy);var $q=!0,eJ=Math.pow(2,jye.BITS_FOR_OCCURRENCE_IDX)-1,nJ=(0,iJ.createToken)({name:"RECORDING_PHASE_TOKEN",pattern:Gye.Lexer.NA});(0,rJ.augmentTokenTypes)([nJ]);var sJ=(0,iJ.createTokenInstance)(nJ,`This IToken indicates the Parser is in Recording Phase + See: https://chevrotain.io/docs/guide/internals.html#grammar-recording for details`,-1,-1,-1,-1,-1,-1);Object.freeze(sJ);var qye={name:`This CSTNode indicates the Parser is in Recording Phase + See: https://chevrotain.io/docs/guide/internals.html#grammar-recording for details`,children:{}},Jye=function(){function r(){}return r.prototype.initGastRecorder=function(e){this.recordingProdStack=[],this.RECORDING_PHASE=!1},r.prototype.enableRecording=function(){var e=this;this.RECORDING_PHASE=!0,this.TRACE_INIT("Enable Recording",function(){for(var t=function(n){var s=n>0?n:"";e["CONSUME"+s]=function(o,a){return this.consumeInternalRecord(o,n,a)},e["SUBRULE"+s]=function(o,a){return this.subruleInternalRecord(o,n,a)},e["OPTION"+s]=function(o){return this.optionInternalRecord(o,n)},e["OR"+s]=function(o){return this.orInternalRecord(o,n)},e["MANY"+s]=function(o){this.manyInternalRecord(n,o)},e["MANY_SEP"+s]=function(o){this.manySepFirstInternalRecord(n,o)},e["AT_LEAST_ONE"+s]=function(o){this.atLeastOneInternalRecord(n,o)},e["AT_LEAST_ONE_SEP"+s]=function(o){this.atLeastOneSepFirstInternalRecord(n,o)}},i=0;i<10;i++)t(i);e.consume=function(n,s,o){return this.consumeInternalRecord(s,n,o)},e.subrule=function(n,s,o){return this.subruleInternalRecord(s,n,o)},e.option=function(n,s){return this.optionInternalRecord(s,n)},e.or=function(n,s){return this.orInternalRecord(s,n)},e.many=function(n,s){this.manyInternalRecord(n,s)},e.atLeastOne=function(n,s){this.atLeastOneInternalRecord(n,s)},e.ACTION=e.ACTION_RECORD,e.BACKTRACK=e.BACKTRACK_RECORD,e.LA=e.LA_RECORD})},r.prototype.disableRecording=function(){var e=this;this.RECORDING_PHASE=!1,this.TRACE_INIT("Deleting Recording methods",function(){for(var t=0;t<10;t++){var i=t>0?t:"";delete e["CONSUME"+i],delete e["SUBRULE"+i],delete e["OPTION"+i],delete e["OR"+i],delete e["MANY"+i],delete e["MANY_SEP"+i],delete e["AT_LEAST_ONE"+i],delete e["AT_LEAST_ONE_SEP"+i]}delete e.consume,delete e.subrule,delete e.option,delete e.or,delete e.many,delete e.atLeastOne,delete e.ACTION,delete e.BACKTRACK,delete e.LA})},r.prototype.ACTION_RECORD=function(e){},r.prototype.BACKTRACK_RECORD=function(e,t){return function(){return!0}},r.prototype.LA_RECORD=function(e){return Yye.END_OF_FILE},r.prototype.topLevelRuleRecord=function(e,t){try{var i=new Lo.Rule({definition:[],name:e});return i.name=e,this.recordingProdStack.push(i),t.call(this),this.recordingProdStack.pop(),i}catch(n){if(n.KNOWN_RECORDER_ERROR!==!0)try{n.message=n.message+` + This error was thrown during the "grammar recording phase" For more info see: + https://chevrotain.io/docs/guide/internals.html#grammar-recording`}catch{throw n}throw n}},r.prototype.optionInternalRecord=function(e,t){return Md.call(this,Lo.Option,e,t)},r.prototype.atLeastOneInternalRecord=function(e,t){Md.call(this,Lo.RepetitionMandatory,t,e)},r.prototype.atLeastOneSepFirstInternalRecord=function(e,t){Md.call(this,Lo.RepetitionMandatoryWithSeparator,t,e,$q)},r.prototype.manyInternalRecord=function(e,t){Md.call(this,Lo.Repetition,t,e)},r.prototype.manySepFirstInternalRecord=function(e,t){Md.call(this,Lo.RepetitionWithSeparator,t,e,$q)},r.prototype.orInternalRecord=function(e,t){return Wye.call(this,e,t)},r.prototype.subruleInternalRecord=function(e,t,i){if(vy(t),!e||(0,yn.has)(e,"ruleName")===!1){var n=new Error(" argument is invalid"+(" expecting a Parser method reference but got: <"+JSON.stringify(e)+">")+(` + inside top level rule: <`+this.recordingProdStack[0].name+">"));throw n.KNOWN_RECORDER_ERROR=!0,n}var s=(0,yn.peek)(this.recordingProdStack),o=e.ruleName,a=new Lo.NonTerminal({idx:t,nonTerminalName:o,label:i==null?void 0:i.LABEL,referencedRule:void 0});return s.definition.push(a),this.outputCst?qye:xy},r.prototype.consumeInternalRecord=function(e,t,i){if(vy(t),!(0,rJ.hasShortKeyProperty)(e)){var n=new Error(" argument is invalid"+(" expecting a TokenType reference but got: <"+JSON.stringify(e)+">")+(` + inside top level rule: <`+this.recordingProdStack[0].name+">"));throw n.KNOWN_RECORDER_ERROR=!0,n}var s=(0,yn.peek)(this.recordingProdStack),o=new Lo.Terminal({idx:t,terminalType:e,label:i==null?void 0:i.LABEL});return s.definition.push(o),sJ},r}();Py.GastRecorder=Jye;function Md(r,e,t,i){i===void 0&&(i=!1),vy(t);var n=(0,yn.peek)(this.recordingProdStack),s=(0,yn.isFunction)(e)?e:e.DEF,o=new r({definition:[],idx:t});return i&&(o.separator=e.SEP),(0,yn.has)(e,"MAX_LOOKAHEAD")&&(o.maxLookahead=e.MAX_LOOKAHEAD),this.recordingProdStack.push(o),s.call(this),n.definition.push(o),this.recordingProdStack.pop(),xy}function Wye(r,e){var t=this;vy(e);var i=(0,yn.peek)(this.recordingProdStack),n=(0,yn.isArray)(r)===!1,s=n===!1?r:r.DEF,o=new Lo.Alternation({definition:[],idx:e,ignoreAmbiguities:n&&r.IGNORE_AMBIGUITIES===!0});(0,yn.has)(r,"MAX_LOOKAHEAD")&&(o.maxLookahead=r.MAX_LOOKAHEAD);var a=(0,yn.some)(s,function(l){return(0,yn.isFunction)(l.GATE)});return o.hasPredicates=a,i.definition.push(o),(0,yn.forEach)(s,function(l){var c=new Lo.Alternative({definition:[]});o.definition.push(c),(0,yn.has)(l,"IGNORE_AMBIGUITIES")?c.ignoreAmbiguities=l.IGNORE_AMBIGUITIES:(0,yn.has)(l,"GATE")&&(c.ignoreAmbiguities=!0),t.recordingProdStack.push(c),l.ALT.call(t),t.recordingProdStack.pop()}),xy}function tJ(r){return r===0?"":""+r}function vy(r){if(r<0||r>eJ){var e=new Error("Invalid DSL Method idx value: <"+r+`> + `+("Idx value must be a none negative value smaller than "+(eJ+1)));throw e.KNOWN_RECORDER_ERROR=!0,e}}});var AJ=I(ky=>{"use strict";Object.defineProperty(ky,"__esModule",{value:!0});ky.PerformanceTracer=void 0;var aJ=Kt(),zye=Yn(),Vye=function(){function r(){}return r.prototype.initPerformanceTracer=function(e){if((0,aJ.has)(e,"traceInitPerf")){var t=e.traceInitPerf,i=typeof t=="number";this.traceInitMaxIdent=i?t:1/0,this.traceInitPerf=i?t>0:t}else this.traceInitMaxIdent=0,this.traceInitPerf=zye.DEFAULT_PARSER_CONFIG.traceInitPerf;this.traceInitIndent=-1},r.prototype.TRACE_INIT=function(e,t){if(this.traceInitPerf===!0){this.traceInitIndent++;var i=new Array(this.traceInitIndent+1).join(" ");this.traceInitIndent <"+e+">");var n=(0,aJ.timer)(t),s=n.time,o=n.value,a=s>10?console.warn:console.log;return this.traceInitIndent time: "+s+"ms"),this.traceInitIndent--,o}else return t()},r}();ky.PerformanceTracer=Vye});var lJ=I(Dy=>{"use strict";Object.defineProperty(Dy,"__esModule",{value:!0});Dy.applyMixins=void 0;function Xye(r,e){e.forEach(function(t){var i=t.prototype;Object.getOwnPropertyNames(i).forEach(function(n){if(n!=="constructor"){var s=Object.getOwnPropertyDescriptor(i,n);s&&(s.get||s.set)?Object.defineProperty(r.prototype,n,s):r.prototype[n]=t.prototype[n]}})})}Dy.applyMixins=Xye});var Yn=I(hr=>{"use strict";var gJ=hr&&hr.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(hr,"__esModule",{value:!0});hr.EmbeddedActionsParser=hr.CstParser=hr.Parser=hr.EMPTY_ALT=hr.ParserDefinitionErrorType=hr.DEFAULT_RULE_CONFIG=hr.DEFAULT_PARSER_CONFIG=hr.END_OF_FILE=void 0;var $i=Kt(),Zye=Vj(),cJ=NA(),fJ=kd(),uJ=yq(),_ye=ox(),$ye=Pq(),ewe=Kq(),twe=Hq(),rwe=Yq(),iwe=Wq(),nwe=Vq(),swe=_q(),owe=oJ(),awe=AJ(),Awe=lJ();hr.END_OF_FILE=(0,cJ.createTokenInstance)(cJ.EOF,"",NaN,NaN,NaN,NaN,NaN,NaN);Object.freeze(hr.END_OF_FILE);hr.DEFAULT_PARSER_CONFIG=Object.freeze({recoveryEnabled:!1,maxLookahead:3,dynamicTokensEnabled:!1,outputCst:!0,errorMessageProvider:fJ.defaultParserErrorProvider,nodeLocationTracking:"none",traceInitPerf:!1,skipValidations:!1});hr.DEFAULT_RULE_CONFIG=Object.freeze({recoveryValueFunc:function(){},resyncEnabled:!0});var lwe;(function(r){r[r.INVALID_RULE_NAME=0]="INVALID_RULE_NAME",r[r.DUPLICATE_RULE_NAME=1]="DUPLICATE_RULE_NAME",r[r.INVALID_RULE_OVERRIDE=2]="INVALID_RULE_OVERRIDE",r[r.DUPLICATE_PRODUCTIONS=3]="DUPLICATE_PRODUCTIONS",r[r.UNRESOLVED_SUBRULE_REF=4]="UNRESOLVED_SUBRULE_REF",r[r.LEFT_RECURSION=5]="LEFT_RECURSION",r[r.NONE_LAST_EMPTY_ALT=6]="NONE_LAST_EMPTY_ALT",r[r.AMBIGUOUS_ALTS=7]="AMBIGUOUS_ALTS",r[r.CONFLICT_TOKENS_RULES_NAMESPACE=8]="CONFLICT_TOKENS_RULES_NAMESPACE",r[r.INVALID_TOKEN_NAME=9]="INVALID_TOKEN_NAME",r[r.NO_NON_EMPTY_LOOKAHEAD=10]="NO_NON_EMPTY_LOOKAHEAD",r[r.AMBIGUOUS_PREFIX_ALTS=11]="AMBIGUOUS_PREFIX_ALTS",r[r.TOO_MANY_ALTS=12]="TOO_MANY_ALTS"})(lwe=hr.ParserDefinitionErrorType||(hr.ParserDefinitionErrorType={}));function cwe(r){return r===void 0&&(r=void 0),function(){return r}}hr.EMPTY_ALT=cwe;var Ry=function(){function r(e,t){this.definitionErrors=[],this.selfAnalysisDone=!1;var i=this;if(i.initErrorHandler(t),i.initLexerAdapter(),i.initLooksAhead(t),i.initRecognizerEngine(e,t),i.initRecoverable(t),i.initTreeBuilder(t),i.initContentAssist(),i.initGastRecorder(t),i.initPerformanceTracer(t),(0,$i.has)(t,"ignoredIssues"))throw new Error(`The IParserConfig property has been deprecated. + Please use the flag on the relevant DSL method instead. + See: https://chevrotain.io/docs/guide/resolving_grammar_errors.html#IGNORING_AMBIGUITIES + For further details.`);this.skipValidations=(0,$i.has)(t,"skipValidations")?t.skipValidations:hr.DEFAULT_PARSER_CONFIG.skipValidations}return r.performSelfAnalysis=function(e){throw Error("The **static** `performSelfAnalysis` method has been deprecated. \nUse the **instance** method with the same name instead.")},r.prototype.performSelfAnalysis=function(){var e=this;this.TRACE_INIT("performSelfAnalysis",function(){var t;e.selfAnalysisDone=!0;var i=e.className;e.TRACE_INIT("toFastProps",function(){(0,$i.toFastProperties)(e)}),e.TRACE_INIT("Grammar Recording",function(){try{e.enableRecording(),(0,$i.forEach)(e.definedRulesNames,function(s){var o=e[s],a=o.originalGrammarAction,l=void 0;e.TRACE_INIT(s+" Rule",function(){l=e.topLevelRuleRecord(s,a)}),e.gastProductionsCache[s]=l})}finally{e.disableRecording()}});var n=[];if(e.TRACE_INIT("Grammar Resolving",function(){n=(0,uJ.resolveGrammar)({rules:(0,$i.values)(e.gastProductionsCache)}),e.definitionErrors=e.definitionErrors.concat(n)}),e.TRACE_INIT("Grammar Validations",function(){if((0,$i.isEmpty)(n)&&e.skipValidations===!1){var s=(0,uJ.validateGrammar)({rules:(0,$i.values)(e.gastProductionsCache),maxLookahead:e.maxLookahead,tokenTypes:(0,$i.values)(e.tokensMap),errMsgProvider:fJ.defaultGrammarValidatorErrorProvider,grammarName:i});e.definitionErrors=e.definitionErrors.concat(s)}}),(0,$i.isEmpty)(e.definitionErrors)&&(e.recoveryEnabled&&e.TRACE_INIT("computeAllProdsFollows",function(){var s=(0,Zye.computeAllProdsFollows)((0,$i.values)(e.gastProductionsCache));e.resyncFollows=s}),e.TRACE_INIT("ComputeLookaheadFunctions",function(){e.preComputeLookaheadFunctions((0,$i.values)(e.gastProductionsCache))})),!r.DEFER_DEFINITION_ERRORS_HANDLING&&!(0,$i.isEmpty)(e.definitionErrors))throw t=(0,$i.map)(e.definitionErrors,function(s){return s.message}),new Error(`Parser Definition Errors detected: + `+t.join(` +------------------------------- +`))})},r.DEFER_DEFINITION_ERRORS_HANDLING=!1,r}();hr.Parser=Ry;(0,Awe.applyMixins)(Ry,[_ye.Recoverable,$ye.LooksAhead,ewe.TreeBuilder,twe.LexerAdapter,iwe.RecognizerEngine,rwe.RecognizerApi,nwe.ErrorHandler,swe.ContentAssist,owe.GastRecorder,awe.PerformanceTracer]);var uwe=function(r){gJ(e,r);function e(t,i){i===void 0&&(i=hr.DEFAULT_PARSER_CONFIG);var n=this,s=(0,$i.cloneObj)(i);return s.outputCst=!0,n=r.call(this,t,s)||this,n}return e}(Ry);hr.CstParser=uwe;var gwe=function(r){gJ(e,r);function e(t,i){i===void 0&&(i=hr.DEFAULT_PARSER_CONFIG);var n=this,s=(0,$i.cloneObj)(i);return s.outputCst=!1,n=r.call(this,t,s)||this,n}return e}(Ry);hr.EmbeddedActionsParser=gwe});var pJ=I(Fy=>{"use strict";Object.defineProperty(Fy,"__esModule",{value:!0});Fy.createSyntaxDiagramsCode=void 0;var hJ=Dv();function fwe(r,e){var t=e===void 0?{}:e,i=t.resourceBase,n=i===void 0?"https://unpkg.com/chevrotain@"+hJ.VERSION+"/diagrams/":i,s=t.css,o=s===void 0?"https://unpkg.com/chevrotain@"+hJ.VERSION+"/diagrams/diagrams.css":s,a=` + + + + + +`,l=` + +`,c=` +
diff --git a/packages/datagateway-dataview/public/res/default.json b/packages/datagateway-dataview/public/res/default.json index a60da05b0..b97b1f7e5 100644 --- a/packages/datagateway-dataview/public/res/default.json +++ b/packages/datagateway-dataview/public/res/default.json @@ -10,7 +10,7 @@ "open_data_warning": { "message": "Open data", "tooltip": "Only open data is displayed when browsing anonymously. Please login to see embargoed data.", - "studies_tooltip": "Only open data is currently supported by the experiment view. Please browse via facility cycle to view closed data", + "datapublications_tooltip": "Only open data is currently supported by the experiment view. Please browse via facility cycle to view closed data", "tooltip_link": "Click here to learn more about our data policy.", "aria_label": "More information about open data" } @@ -19,7 +19,8 @@ "home": "Home", "instrument_other": "Instruments", "facilityCycle_other": "Facility Cycles", - "study_other": "Experiments", + "dataPublication_other": "Experiments", + "experiment_other": "Investigations", "proposal_other": "Proposals", "investigation_other": "Investigations", "dataset_other": "Datasets", @@ -51,12 +52,13 @@ "end_date": "End Date", "start_date": "Start Date" }, - "studies": { + "datapublications": { "name": "Name", "title": "Title", + "description": "Description", "pid": "DOI", - "end_date": "End Date", - "start_date": "Start Date", + "id": "Data Publication ID", + "publication_date": "Publication Date", "details": { "label": "Experiment Details", "investigations": "View Investigations", @@ -109,9 +111,9 @@ "end_date": "End Date", "start_date": "Start Date", "visit_id": "Experiment Part", - "pid": "Part DOI", + "pid": "DOI", "summary": "Summary", - "doi": "DOI", + "doi": "Part DOI", "size": "Size", "calculate": "Calculate", "datasets": "View Datasets", @@ -192,9 +194,40 @@ "description": "Description", "size": "Size", "location": "Location", + "mod_time": "Last modified on", + "create_time": "Created on", + "doi": "DOI", "parameters": { "label": "Datafile Parameters", "no_parameters": "No parameters" + }, + "unknown": "Unknown" + }, + "preview": { + "preview_datafile": "Preview this datafile", + "preview_unsupported": "Preview not supported for this datafile", + "cannot_preview": "Cannot preview datafile", + "cannot_load_content": "Cannot load datafile content.", + "cannot_load_metadata": "Unable to load metadata", + "unknown_type": "Datafile type not specified.", + "unsupported": "Unsupported datafile type: {{ext}}", + "unexpected_error": "An unexpected error has occurred", + "link_copied": "Link copied to clipboard", + "invalid_datafile": "Invalid datafile", + "loading_metadata": "Loading datafile metadata...", + "txt": { + "file_content_label": "Text content of {{fileName}}", + "reading_content": "Reading content" + }, + "toolbar": { + "back_button_label": "Other datafiles", + "copy_link": "Copy link", + "zoom_control": "Zoom level control for datafile content", + "zoom_in": "Zoom in", + "zoom_out": "Zoom out", + "reset_zoom": "Reset zoom", + "scroll_to_zoom": "Scroll here to zoom in/out", + "show_details": "Show details" } } }, @@ -210,9 +243,14 @@ }, "buttons": { "add_to_cart": "Add to selection", + "cart_loading_tooltip": "Loading selection information...", + "cart_loading_failed_tooltip": "Selection information failed to load, please reload the page or try again later", + "parent_selected_tooltip": "Selection disabled, parent entity has already been added to cart", "remove_from_cart": "Remove from selection", "download": "Download", - "unable_to_download_tooltip": "Unable to download - this item is empty" + "unable_to_download_tooltip": "Unable to download - this item is empty", + "preview": "Preview datafile", + "preview_tooltip": "Preview this datafile" }, "advanced_filters": { "show": "Show Advanced Filters", @@ -292,13 +330,10 @@ "email": "isisdata@stfc.ac.uk", "logo": "https://data.isis.stfc.ac.uk/doi/ISIS/images/dsLogo.png" }, - "distribution": { - "format": "RAW/Nexus", - "content_url": "https://data.isis.stfc.ac.uk" - }, "branding": { "title": "ISIS Neutron and Muon Source", "body": "This is a page describing data taken during an experiment at the ISIS Neutron and Muon Source. Information about the ISIS Neutron and Muon Source can be found at
https://www.isis.stfc.ac.uk." - } + }, + "license": "https://www.isis.stfc.ac.uk/Pages/Data-Policy.aspx" } } diff --git a/packages/datagateway-dataview/server/e2e-settings.json b/packages/datagateway-dataview/server/e2e-settings.json index 62e07f93d..395b7be54 100644 --- a/packages/datagateway-dataview/server/e2e-settings.json +++ b/packages/datagateway-dataview/server/e2e-settings.json @@ -9,16 +9,25 @@ "idsUrl": "https://localhost:8181/ids", "apiUrl": "http://localhost:5000", "downloadApiUrl": "https://localhost:8181/topcat", - "breadcrumbs": { - "proposal": { + "breadcrumbs": [ + { + "matchEntity": "proposal", "replaceEntity": "investigation", - "replaceEntityField": "title" + "replaceEntityField": "title", + "replaceEntityQueryField": "name" }, - "investigation": { + { + "matchEntity": "investigation", "replaceEntityField": "visitId", "parentEntity": "proposal" + }, + { + "matchEntity": "investigation", + "replaceEntity": "dataPublication", + "replaceEntityField": "title", + "parentEntity": "dataPublication" } - }, + ], "helpSteps": [ { "target": "#plugin-link--browse-investigation", diff --git a/packages/datagateway-dataview/server/e2e-test-server.js b/packages/datagateway-dataview/server/e2e-test-server.js index 648ad0bd7..5931bce61 100644 --- a/packages/datagateway-dataview/server/e2e-test-server.js +++ b/packages/datagateway-dataview/server/e2e-test-server.js @@ -1,11 +1,21 @@ -var express = require('express'); -var path = require('path'); -var serveStatic = require('serve-static'); +const express = require('express'); +const path = require('path'); +const serveStatic = require('serve-static'); -var app = express(); +const app = express(); -app.get('/datagateway-dataview-settings.json', function(req, res) { - res.sendFile(path.resolve('./server/e2e-settings.json')); +app.get('/datagateway-dataview-settings.json', function (req, res) { + // detect if the E2E test is running inside CI + // If so, use the settings file specific to E2E + // Otherwise, use the same settings file that is also for running the app normally (yarn start etc). + const isCiEnv = process.env.CI; + res.sendFile( + path.resolve( + isCiEnv + ? './server/e2e-settings.json' + : './public/datagateway-dataview-settings.json' + ) + ); }); app.use( @@ -13,7 +23,7 @@ app.use( serveStatic(path.resolve('./build'), { index: ['index.html', 'index.htm'] }) ); -app.get('/*', function(req, res) { +app.get('/*', function (req, res) { res.sendFile(path.resolve('./build/index.html')); }); diff --git a/packages/datagateway-dataview/src/App.test.tsx b/packages/datagateway-dataview/src/App.test.tsx index f10610160..8cdc7ddd4 100644 --- a/packages/datagateway-dataview/src/App.test.tsx +++ b/packages/datagateway-dataview/src/App.test.tsx @@ -1,42 +1,81 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; +import * as React from 'react'; import App from './App'; -import { createMount } from '@material-ui/core/test-utils'; -import { mount as enzymeMount } from 'enzyme'; -import * as log from 'loglevel'; -import { Provider } from 'react-redux'; +import log from 'loglevel'; +import { render, screen, waitFor } from '@testing-library/react'; +import PageContainer from './page/pageContainer.component'; +import { configureApp, settingsLoaded } from './state/actions'; -jest.mock('loglevel'); +jest + .mock('loglevel') + .mock('./page/pageContainer.component') + .mock('./state/actions', () => ({ + ...jest.requireActual('./state/actions'), + configureApp: jest.fn(), + })) + .mock('react', () => ({ + ...jest.requireActual('react'), + // skip React suspense mechanism and show children directly. + Suspense: ({ children }: { children: React.ReactNode }) => children, + })); describe('App', () => { - let mount: typeof enzymeMount; - - beforeAll(() => { - mount = createMount(); + beforeEach(() => { + jest.restoreAllMocks(); }); - afterAll(() => { - mount.cleanUp(); + it('renders without crashing', async () => { + // pretend app is configured successfully + (configureApp as jest.MockedFn).mockReturnValue( + async (dispatch) => { + dispatch(settingsLoaded()); + } + ); + (PageContainer as jest.Mock).mockImplementation(() =>
page
); + + render(); + + expect(await screen.findByText('page')).toBeInTheDocument(); }); - it('renders without crashing', () => { - const div = document.createElement('div'); - ReactDOM.render(, div); - ReactDOM.unmountComponentAtNode(div); + it('shows loading screen when configuring app', async () => { + (configureApp as jest.MockedFn).mockReturnValue( + () => + new Promise((_) => { + // never resolve the promise to pretend the app is still being configured + }) + ); + (PageContainer as jest.Mock).mockImplementation(() =>
page
); + + render(); + + expect(await screen.findByText('Loading...')).toBeInTheDocument(); + expect(screen.queryByText('page')).toBeNull(); }); - it('catches errors using componentDidCatch and shows fallback UI', () => { - const wrapper = mount(); - const error = new Error('test'); - wrapper.find(Provider).simulateError(error); + it('catches errors using componentDidCatch and shows fallback UI', async () => { + // pretend app is configured successfully + (configureApp as jest.MockedFn).mockReturnValue( + async (dispatch) => { + dispatch(settingsLoaded()); + } + ); + // pretend PageContainer throw an error and see if will catch the error + (PageContainer as jest.Mock).mockImplementation(() => { + throw new Error('test PageContainer error'); + }); + + jest.spyOn(console, 'error').mockImplementation(() => { + // suppress console error + }); - expect(wrapper.exists('.error')).toBe(true); + render(); - expect(log.error).toHaveBeenCalled(); - const mockLog = (log.error as jest.Mock).mock; + await waitFor(() => { + // check that the error is logged + expect(log.error).toHaveBeenCalled(); + }); - expect(mockLog.calls).toContainEqual([ - `datagateway_dataview failed with error: ${error}`, - ]); + // check that fallback UI is shown + expect(await screen.findByText('app.error')).toBeInTheDocument(); }); }); diff --git a/packages/datagateway-dataview/src/App.tsx b/packages/datagateway-dataview/src/App.tsx index 7c2222b88..ccd84b7f1 100644 --- a/packages/datagateway-dataview/src/App.tsx +++ b/packages/datagateway-dataview/src/App.tsx @@ -1,7 +1,3 @@ -import { - createGenerateClassName, - StylesProvider, -} from '@material-ui/core/styles'; import { ConnectedRouter, routerMiddleware } from 'connected-react-router'; import { DGCommonMiddleware, @@ -18,7 +14,7 @@ import { Location, Action, } from 'history'; -import * as log from 'loglevel'; +import log from 'loglevel'; import React from 'react'; import { Translation } from 'react-i18next'; import { batch, connect, Provider } from 'react-redux'; @@ -34,15 +30,6 @@ import AppReducer from './state/reducers/app.reducer'; import { QueryClient, QueryClientProvider } from 'react-query'; import { ReactQueryDevtools } from 'react-query/devtools'; -const generateClassName = createGenerateClassName({ - productionPrefix: 'dgwt', - - // Only set disable when we are in production and not running e2e tests; - // ensures class selectors are working on tests. - disableGlobal: - process.env.NODE_ENV === 'production' && !process.env.REACT_APP_E2E_TESTING, -}); - const history = createBrowserHistory(); // fix query string freeze bug @@ -94,14 +81,12 @@ if (process.env.NODE_ENV === `development`) { /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ const logger = (createLogger as any)({ collapsed: true }); middleware.push(logger); - // eslint-disable-next-line @typescript-eslint/no-var-requires - const whyDidYouRender = require('@welldone-software/why-did-you-render'); - whyDidYouRender(React); } /* eslint-disable no-underscore-dangle, @typescript-eslint/no-explicit-any */ const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; + /* eslint-enable */ function mapPreloaderStateToProps(state: StateType): { loading: boolean } { @@ -130,6 +115,7 @@ document.addEventListener(MicroFrontendId, (e) => { class App extends React.Component { store: Store; + public constructor(props: unknown) { super(props); this.state = { hasError: false }; @@ -198,19 +184,17 @@ class App extends React.Component { - - - - Finished loading - } - > - - - - - + + + Finished loading + } + > + + + + diff --git a/packages/datagateway-dataview/src/__mocks__/axios.ts b/packages/datagateway-dataview/src/__mocks__/axios.ts index 7beb00624..8cfe9dd02 100644 --- a/packages/datagateway-dataview/src/__mocks__/axios.ts +++ b/packages/datagateway-dataview/src/__mocks__/axios.ts @@ -23,6 +23,7 @@ const requests = { post: jest.fn(() => Promise.resolve({ data: {} })), delete: jest.fn(() => Promise.resolve({ data: {} })), CancelToken: axios.CancelToken, + isAxiosError: axios.isAxiosError, }; export default requests; diff --git a/packages/datagateway-dataview/src/__mocks__/lodash.debounce.ts b/packages/datagateway-dataview/src/__mocks__/lodash.debounce.ts index 59142c3e6..3c86a2a0c 100644 --- a/packages/datagateway-dataview/src/__mocks__/lodash.debounce.ts +++ b/packages/datagateway-dataview/src/__mocks__/lodash.debounce.ts @@ -1,5 +1,8 @@ // TODO: move __mocks__ folder back to package root once facebook/create-react-app#7539 is fixed -const func = () => (fn: (args: A) => T): ((args: A) => T) => fn; +const func = + () => + (fn: (args: A) => T): ((args: A) => T) => + fn; export default func; diff --git a/packages/datagateway-dataview/src/__mocks__/loglevel.ts b/packages/datagateway-dataview/src/__mocks__/loglevel.ts new file mode 100644 index 000000000..01d81f572 --- /dev/null +++ b/packages/datagateway-dataview/src/__mocks__/loglevel.ts @@ -0,0 +1,3 @@ +// TODO: move __mocks__ folder back to package root once facebook/create-react-app#7539 is fixed + +export default jest.createMockFromModule('loglevel'); diff --git a/packages/datagateway-dataview/src/index.test.tsx b/packages/datagateway-dataview/src/index.test.tsx index 4dd0f519e..9069caa31 100644 --- a/packages/datagateway-dataview/src/index.test.tsx +++ b/packages/datagateway-dataview/src/index.test.tsx @@ -2,7 +2,7 @@ import axios from 'axios'; import { MicroFrontendId, RegisterRouteType } from 'datagateway-common'; import LogoLight from 'datagateway-common/src/images/datagateway-logo.svg'; import LogoDark from 'datagateway-common/src/images/datgateway-white-text-blue-mark-logo.svg'; -import * as log from 'loglevel'; +import log from 'loglevel'; import { fetchSettings } from './'; jest.mock('loglevel'); @@ -25,11 +25,12 @@ describe('index - fetchSettings', () => { features: {}, idsUrl: 'ids', apiUrl: 'api', - breadcrumbs: { - test: { + breadcrumbs: [ + { + matchEntity: 'test', replaceEntityField: 'title', }, - }, + ], downloadApiUrl: 'download-api', selectAllSetting: false, routes: [ @@ -78,11 +79,12 @@ describe('index - fetchSettings', () => { features: {}, idsUrl: 'ids', apiUrl: 'api', - breadcrumbs: { - test: { + breadcrumbs: [ + { + matchEntity: 'test', replaceEntityField: 'title', }, - }, + ], downloadApiUrl: 'download-api', selectAllSetting: false, routes: [ diff --git a/packages/datagateway-dataview/src/index.tsx b/packages/datagateway-dataview/src/index.tsx index cfb6dfccd..7b9a80eec 100644 --- a/packages/datagateway-dataview/src/index.tsx +++ b/packages/datagateway-dataview/src/index.tsx @@ -8,7 +8,7 @@ import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import singleSpaReact from 'single-spa-react'; -import * as log from 'loglevel'; +import log from 'loglevel'; import { MicroFrontendId, MicroFrontendToken, @@ -41,7 +41,7 @@ function domElementGetter(): HTMLElement { const reactLifecycles = singleSpaReact({ React, ReactDOM, - rootComponent: App, + rootComponent: () => (document.getElementById(pluginName) ? : null), domElementGetter, }); @@ -174,52 +174,27 @@ if ( if (process.env.NODE_ENV === `development`) { settings.then((settingsResult) => { if (settingsResult) { - const splitUrl = settingsResult.downloadApiUrl.split('/'); - const icatUrl = `${splitUrl - .slice(0, splitUrl.length - 1) - .join('/')}/icat`; + const apiUrl = settingsResult.apiUrl; axios - .post( - `${icatUrl}/session`, - `json=${JSON.stringify({ - plugin: 'simple', - credentials: [{ username: 'root' }, { password: 'pw' }], - })}`, - { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - } - ) + .post(`${apiUrl}/sessions`, { + username: 'root', + password: 'pw', + mechanism: 'simple', + }) .then((response) => { - axios - .get(`${settingsResult['apiUrl']}/sessions`, { - headers: { - Authorization: `Bearer ${response.data.sessionId}`, - }, - }) - .then(() => { - const jwtHeader = { alg: 'HS256', typ: 'JWT' }; - const payload = { - sessionId: response.data.sessionId, - username: 'Thomas409', - }; - const jwt = jsrsasign.KJUR.jws.JWS.sign( - 'HS256', - jwtHeader, - payload, - 'shh' - ); - - window.localStorage.setItem(MicroFrontendToken, jwt); - }) - .catch((error) => { - log.error( - `datagateway-api cannot verify ICAT session id: ${error.message}. - This is likely caused if datagateway-api is pointing to a - different ICAT than the one used by the IDS/TopCAT` - ); - }); + const jwtHeader = { alg: 'HS256', typ: 'JWT' }; + const payload = { + sessionId: response.data.sessionID, + username: 'Richard459', + }; + const jwt = jsrsasign.KJUR.jws.JWS.sign( + 'HS256', + jwtHeader, + payload, + 'shh' + ); + + window.localStorage.setItem(MicroFrontendToken, jwt); }) .catch((error) => log.error(`Can't log in to ICAT: ${error.message}`) diff --git a/packages/datagateway-dataview/src/page/__snapshots__/translatedHomePage.component.test.tsx.snap b/packages/datagateway-dataview/src/page/__snapshots__/translatedHomePage.component.test.tsx.snap index d593db8d4..bee184af6 100644 --- a/packages/datagateway-dataview/src/page/__snapshots__/translatedHomePage.component.test.tsx.snap +++ b/packages/datagateway-dataview/src/page/__snapshots__/translatedHomePage.component.test.tsx.snap @@ -1,31 +1,21 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`HomePage translated homepage renders correctly 1`] = ` -
+
- - - Data discovery @@ -34,283 +24,233 @@ exports[`HomePage translated homepage renders correctly 1`] = ` access - - - - +

for large-scale science facilities - - - +

+
+
- - - - - - - - home_page.browse.title - - - home_page.browse.description1 - - - + home_page.browse.title + +

+ home_page.browse.description1 +

+

DataGateway focuses on providing data discovery and data access functionality to the data. - - - - +

- home_page.browse.button - - - - - + + home_page.browse.button + + +
+ +
+ style="background-image: url(testfacility.jpg); background-repeat: no-repeat; background-position: bottom right; background-size: cover; width: 100%; height: 100%; border-radius: 4px;" + > +
+
- - - - - +
+
- - - - - - - home_page.search.title - - - home_page.search.description - - - - home_page.search.button - - - - - - -
+

+ home_page.search.title +

+

+ home_page.search.description +

+ + + + +
- - - - - - home_page.download.title - - - home_page.download.description - - - - home_page.download.button - - - - - - -
+

+ home_page.download.title +

+

+ home_page.download.description +

+ + + + +
- - - home_page.facility.title - - - home_page.facility.description - - - + home_page.facility.title + +

- home_page.facility.button - - - + home_page.facility.description +

+ +
+
-
- - -
- + + + + + `; diff --git a/packages/datagateway-dataview/src/page/__snapshots__/withIdCheck.test.tsx.snap b/packages/datagateway-dataview/src/page/__snapshots__/withIdCheck.test.tsx.snap index 09e6b7619..1f34038e0 100644 --- a/packages/datagateway-dataview/src/page/__snapshots__/withIdCheck.test.tsx.snap +++ b/packages/datagateway-dataview/src/page/__snapshots__/withIdCheck.test.tsx.snap @@ -1,155 +1,132 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`withIdCheck renders component when checkingPromise resolves to be true 1`] = ` - + +
+ test +
+
`; exports[`withIdCheck renders error when checkingPromise does not resolve to be true 1`] = ` - - +
- - - loading.oops - - - -
+
- - We're sorry, it seems as though the URL you requested is attempting to fetch incorrect data. Please double check your URL, navigate back via the breadcrumbs or - - go back to the top level - + . - - - - +

+
+ + `; exports[`withIdCheck renders error when checkingPromise is rejected 1`] = ` - - +
- - - loading.oops - - - -
+
- - We're sorry, it seems as though the URL you requested is attempting to fetch incorrect data. Please double check your URL, navigate back via the breadcrumbs or - - go back to the top level - + . - - - - +

+
+ + `; exports[`withIdCheck renders loading indicator when loading 1`] = ` - - - +
- loading.verifying - - + + + + + +

+ loading.verifying +

+
+ `; diff --git a/packages/datagateway-dataview/src/page/breadcrumbs.component.test.tsx b/packages/datagateway-dataview/src/page/breadcrumbs.component.test.tsx index a8299306a..29c2a5394 100644 --- a/packages/datagateway-dataview/src/page/breadcrumbs.component.test.tsx +++ b/packages/datagateway-dataview/src/page/breadcrumbs.component.test.tsx @@ -1,19 +1,21 @@ -import React from 'react'; +import * as React from 'react'; import { Provider } from 'react-redux'; - -import { createMount } from '@material-ui/core/test-utils'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; -import { Router } from 'react-router'; +import { Router } from 'react-router-dom'; import { dGCommonInitialState } from 'datagateway-common'; import { initialState as dgDataViewInitialState } from '../state/reducers/dgdataview.reducer'; -import { StateType } from '../state/app.types'; -import { createLocation, createMemoryHistory, History } from 'history'; -import { flushPromises } from '../setupTests'; +import type { StateType } from '../state/app.types'; +import { createLocation, createMemoryHistory, type History } from 'history'; import PageBreadcrumbs from './breadcrumbs.component'; import axios from 'axios'; -import { ReactWrapper } from 'enzyme'; -import { QueryClientProvider, QueryClient } from 'react-query'; +import { QueryClient, QueryClientProvider } from 'react-query'; +import { + render, + type RenderResult, + screen, + within, +} from '@testing-library/react'; jest.mock('loglevel'); @@ -21,17 +23,29 @@ jest.mock('loglevel'); const genericRoutes = { investigations: '/browse/investigation', datasets: '/browse/investigation/1/dataset', - datafiles: '/browse/investigation/1/dataset/1/datafile', + datafiles: '/browse/investigation/1/dataset/2/datafile', }; // The ISIS routes to test. const ISISRoutes = { instruments: '/browse/instrument', facilityCycles: '/browse/instrument/1/facilityCycle', - investigations: '/browse/instrument/1/facilityCycle/1/investigation', - datasets: '/browse/instrument/1/facilityCycle/1/investigation/1/dataset', + investigations: '/browse/instrument/1/facilityCycle/2/investigation', + datasets: '/browse/instrument/1/facilityCycle/2/investigation/3/dataset', + datafiles: + '/browse/instrument/1/facilityCycle/2/investigation/3/dataset/4/datafile', +}; + +// The ISIS experiments +const ISISExperimentsRoutes = { + instruments: '/browseDataPublications/instrument', + studyDataPublications: '/browseDataPublications/instrument/1/dataPublication', + investigationDataPublications: + '/browseDataPublications/instrument/1/dataPublication/2/investigation', + datasets: + '/browseDataPublications/instrument/1/dataPublication/2/investigation/3/dataset', datafiles: - '/browse/instrument/1/facilityCycle/1/investigation/1/dataset/1/datafile', + '/browseDataPublications/instrument/1/dataPublication/2/investigation/3/dataset/4/datafile', }; // The DLS routes to test. @@ -40,20 +54,19 @@ const DLSRoutes = { investigations: '/browse/proposal/INVESTIGATION 1/investigation', datasets: '/browse/proposal/INVESTIGATION 1/investigation/1/dataset', datafiles: - '/browse/proposal/INVESTIGATION 1/investigation/1/dataset/1/datafile', + '/browse/proposal/INVESTIGATION 1/investigation/1/dataset/2/datafile', }; describe('PageBreadcrumbs tests (Generic, DLS, ISIS)', () => { - let mount; let state: StateType; let history: History; - const createWrapper = ( + const renderComponent = ( state: StateType, landingPageEntities: string[] = [] - ): ReactWrapper => { + ): RenderResult => { const mockStore = configureStore([thunk]); - return mount( + return render( @@ -65,7 +78,6 @@ describe('PageBreadcrumbs tests (Generic, DLS, ISIS)', () => { }; beforeEach(() => { - mount = createMount(); history = createMemoryHistory(); state = JSON.parse( @@ -74,16 +86,27 @@ describe('PageBreadcrumbs tests (Generic, DLS, ISIS)', () => { ...dgDataViewInitialState, // Set up the breadcrumb settings. - breadcrumbSettings: { - proposal: { + breadcrumbSettings: [ + // DLS settings + { + matchEntity: 'proposal', replaceEntity: 'investigation', replaceEntityField: 'title', + replaceEntityQueryField: 'name', }, - investigation: { + { + matchEntity: 'investigation', replaceEntityField: 'visitId', parentEntity: 'proposal', }, - }, + // ISIS settings + { + matchEntity: 'investigation', + replaceEntity: 'dataPublication', + replaceEntityField: 'title', + parentEntity: 'dataPublication', + }, + ], }, dgcommon: dGCommonInitialState, @@ -95,542 +118,675 @@ describe('PageBreadcrumbs tests (Generic, DLS, ISIS)', () => { }) ); - (axios.get as jest.Mock).mockImplementation(() => - Promise.resolve({ + (axios.get as jest.Mock).mockImplementation((url) => { + const potentialId = parseInt(url.split('/').at(-1)); + let id = 1; + if (!Number.isNaN(potentialId)) { + id = potentialId; + } + return Promise.resolve({ data: { - id: 1, - name: 'Name 1', - title: 'Title 1', - visitId: '1', + id: id, + name: `Name ${id}`, + title: `Title ${id}`, + visitId: `${id}`, }, - }) - ); + }); + }); }); afterEach(() => { - mount.cleanUp(); (axios.get as jest.Mock).mockClear(); }); - it('generic route renders correctly at the base route and does not request', async () => { - // Set up test state pathname. - history.replace(createLocation(genericRoutes['investigations'])); + describe('Generic', () => { + it('generic route renders correctly at the base route and does not request', async () => { + // Set up test state pathname. + history.replace(createLocation(genericRoutes['investigations'])); - // Set up store with test state and mount the breadcrumb. - const wrapper = createWrapper(state); + // Set up store with test state and mount the breadcrumb. + renderComponent(state); - // Flush promises and update the re-render the wrapper. - await flushPromises(); - wrapper.update(); + // Expect the axios.get to not have been made. + expect(axios.get).not.toBeCalled(); - // Expect the axios.get to not have been made. - expect(axios.get).not.toBeCalled(); - - expect(wrapper.find('[data-testid="Breadcrumb-home"] p').text()).toEqual( - 'breadcrumbs.home' - ); - expect(wrapper.find('[data-testid="Breadcrumb-base"] p').text()).toEqual( - 'breadcrumbs.investigation' - ); - }); + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + expect(screen.getByTestId('Breadcrumb-base')).toHaveTextContent( + 'breadcrumbs.investigation' + ); + }); - it('generic route renders correctly at the dataset level and requests the investigation entity', async () => { - // Set up test state pathname. - history.replace( - createLocation({ - pathname: genericRoutes['datasets'], - search: '?view=card', - }) - ); + it('generic route renders correctly at the dataset level and requests the investigation entity', async () => { + // Set up test state pathname. + history.replace( + createLocation({ + pathname: genericRoutes['datasets'], + search: '?view=card', + }) + ); + + // Set up store with test state and mount the breadcrumb. + renderComponent(state); + + // Expect the axios.get to have been called once to get the investigation. + expect(axios.get).toBeCalledTimes(1); + expect(axios.get).toHaveBeenCalledWith('/investigations/1', { + headers: { + Authorization: 'Bearer null', + }, + }); + + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute( + 'href', + '/browse/investigation?view=card' + ); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.investigation'); + + const breadcrumbs = screen.getAllByTestId(/^Breadcrumb-hierarchy-\d+$/); + expect(within(breadcrumbs[0]).getByText('Title 1')).toBeInTheDocument(); + + expect( + within(screen.getByTestId('Breadcrumb-last')).getByText( + 'breadcrumbs.dataset' + ) + ).toBeInTheDocument(); + }); - // Set up store with test state and mount the breadcrumb. - const wrapper = createWrapper(state); + it('generic route renders correctly at the datafile level and requests the investigation & dataset entities', async () => { + // Set up test state pathname. + history.replace(createLocation(genericRoutes['datafiles'])); - // Flush promises and update the re-render the wrapper. - await flushPromises(); - wrapper.update(); + // Set up store with test state and mount the breadcrumb. + renderComponent(state); - // Expect the axios.get to have been called once to get the investigation. - expect(axios.get).toBeCalledTimes(1); - expect(axios.get).toHaveBeenCalledWith('/investigations/1', { - headers: { - Authorization: 'Bearer null', - }, + // Expect the axios.get to have been called twice; first to get the investigation + // and second to get the dataset. + expect(axios.get).toBeCalledTimes(2); + expect(axios.get).toHaveBeenNthCalledWith(1, '/investigations/1', { + headers: { + Authorization: 'Bearer null', + }, + }); + expect(axios.get).toHaveBeenNthCalledWith(2, '/datasets/2', { + headers: { + Authorization: 'Bearer null', + }, + }); + + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute('href', '/browse/investigation'); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.investigation'); + + const breadcrumbs = screen.getAllByTestId(/^Breadcrumb-hierarchy-\d+$/); + expect(within(breadcrumbs[0]).getByText('Title 1')).toBeInTheDocument(); + expect(within(breadcrumbs[1]).getByText('Name 2')).toBeInTheDocument(); + + expect( + within(screen.getByTestId('Breadcrumb-last')).getByText( + 'breadcrumbs.datafile' + ) + ).toBeInTheDocument(); }); - - expect(wrapper.find('[data-testid="Breadcrumb-home"] p').text()).toEqual( - 'breadcrumbs.home' - ); - expect(wrapper.find('[data-testid="Breadcrumb-base"] a').text()).toEqual( - 'breadcrumbs.investigation' - ); - expect( - wrapper.find('[data-testid="Breadcrumb-base"] a').prop('href') - ).toEqual('/browse/investigation?view=card'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] p').text() - ).toEqual('Title 1'); - expect(wrapper.find('[data-testid="Breadcrumb-last"] p').text()).toEqual( - 'breadcrumbs.dataset' - ); }); - it('generic route renders correctly at the datafile level and requests the investigation & dataset entities', async () => { - // Set up test state pathname. - history.replace(createLocation(genericRoutes['datafiles'])); + describe('DLS', () => { + it('DLS route renders correctly at the base level and does not request', async () => { + // Set up test state pathname. + history.replace(createLocation(DLSRoutes['proposals'])); - // Set up store with test state and mount the breadcrumb. - const wrapper = createWrapper(state); + // Set up store with test state and mount the breadcrumb. + renderComponent(state); - // Flush promises and update the re-render the wrapper. - await flushPromises(); - wrapper.update(); + // Expect the axios.get to not have been called. + expect(axios.get).not.toBeCalled(); - // Expect the axios.get to have been called twice; first to get the investigation - // and second to get the dataset. - expect(axios.get).toBeCalledTimes(2); - expect(axios.get).toHaveBeenNthCalledWith(1, '/investigations/1', { - headers: { - Authorization: 'Bearer null', - }, - }); - expect(axios.get).toHaveBeenNthCalledWith(2, '/datasets/1', { - headers: { - Authorization: 'Bearer null', - }, + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.proposal'); }); - expect(wrapper.find('[data-testid="Breadcrumb-home"] p').text()).toEqual( - 'breadcrumbs.home' - ); - expect(wrapper.find('[data-testid="Breadcrumb-base"] a').text()).toEqual( - 'breadcrumbs.investigation' - ); - expect( - wrapper.find('[data-testid="Breadcrumb-base"] a').prop('href') - ).toEqual('/browse/investigation'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] a').text() - ).toEqual('Title 1'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] a').prop('href') - ).toEqual('/browse/investigation/1/dataset'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-2"] p').text() - ).toEqual('Name 1'); - expect(wrapper.find('[data-testid="Breadcrumb-last"] p').text()).toEqual( - 'breadcrumbs.datafile' - ); - }); + it('DLS route renders correctly at the investigation level and requests the proposal entity', async () => { + // Set up test state pathname. + history.replace(createLocation(DLSRoutes['investigations'])); + + // Set up store with test state and mount the breadcrumb. + renderComponent(state); + + // Expect the axios.get to have been called twice. + expect(axios.get).toHaveBeenCalledTimes(1); + expect(axios.get).toHaveBeenCalledWith( + '/investigations/findone?where=' + + JSON.stringify({ name: { eq: 'INVESTIGATION 1' } }), + { + headers: { + Authorization: 'Bearer null', + }, + } + ); - it('DLS route renders correctly at the base level and does not request', async () => { - // Set up test state pathname. - history.replace(createLocation(DLSRoutes['proposals'])); + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute('href', '/browse/proposal'); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.proposal'); + }); + + it('DLS route renders correctly at the dataset level and requests the proposal & investigation entities', async () => { + // Set up test state pathname. + history.replace(createLocation(DLSRoutes['datasets'])); + + // Set up store with test state and mount the breadcrumb. + renderComponent(state); + + // Expect the axios.get to have been called twice. + expect(axios.get).toHaveBeenCalledTimes(2); + expect(axios.get).toHaveBeenNthCalledWith( + 1, + '/investigations/findone?where=' + + JSON.stringify({ name: { eq: 'INVESTIGATION 1' } }), + { + headers: { + Authorization: 'Bearer null', + }, + } + ); + expect(axios.get).toHaveBeenNthCalledWith(2, '/investigations/1', { + headers: { + Authorization: 'Bearer null', + }, + }); + + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute('href', '/browse/proposal'); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.proposal'); + + const breadcrumbs = screen.getAllByTestId(/^Breadcrumb-hierarchy-\d+$/); + expect(breadcrumbs[0]).toHaveAttribute( + 'href', + '/browse/proposal/INVESTIGATION 1/investigation' + ); + expect(within(breadcrumbs[0]).getByText('Title 1')).toBeInTheDocument(); + expect(within(breadcrumbs[1]).getByText('1')).toBeInTheDocument(); + + expect( + within(screen.getByTestId('Breadcrumb-last')).getByText( + 'breadcrumbs.dataset' + ) + ).toBeInTheDocument(); + }); - // Set up store with test state and mount the breadcrumb. - const wrapper = createWrapper(state); + it('DLS route renders correctly at the datafile level and requests the proposal, investigation and dataset entities', async () => { + // Set up test state pathname. + history.replace(createLocation(DLSRoutes['datafiles'])); + + // Set up store with test state and mount the breadcrumb. + renderComponent(state); + + // Expect the axios.get to have been called three times. + expect(axios.get).toHaveBeenCalledTimes(3); + expect(axios.get).toHaveBeenNthCalledWith( + 1, + '/investigations/findone?where=' + + JSON.stringify({ name: { eq: 'INVESTIGATION 1' } }), + { + headers: { + Authorization: 'Bearer null', + }, + } + ); + expect(axios.get).toHaveBeenNthCalledWith(2, '/investigations/1', { + headers: { + Authorization: 'Bearer null', + }, + }); + expect(axios.get).toHaveBeenNthCalledWith(3, '/datasets/2', { + headers: { + Authorization: 'Bearer null', + }, + }); + + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute('href', '/browse/proposal'); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.proposal'); + + const breadcrumbs = screen.getAllByTestId(/^Breadcrumb-hierarchy-\d+$/); + expect(breadcrumbs[0]).toHaveAttribute( + 'href', + '/browse/proposal/INVESTIGATION 1/investigation' + ); + expect(within(breadcrumbs[0]).getByText('Title 1')).toBeInTheDocument(); + expect(breadcrumbs[1]).toHaveAttribute( + 'href', + '/browse/proposal/INVESTIGATION 1/investigation/1/dataset' + ); + expect(within(breadcrumbs[1]).getByText('1')).toBeInTheDocument(); + expect(within(breadcrumbs[2]).getByText('Name 2')).toBeInTheDocument(); + + expect( + within(screen.getByTestId('Breadcrumb-last')).getByText( + 'breadcrumbs.datafile' + ) + ).toBeInTheDocument(); + }); + }); - // Flush promises and update the re-render the wrapper. - await flushPromises(); - wrapper.update(); + describe('ISIS', () => { + it('ISIS route renders correctly at the base level and does not request', async () => { + // Set up test state pathname. + history.replace(createLocation(ISISRoutes['instruments'])); - // Expect the axios.get to not have been called. - expect(axios.get).not.toBeCalled(); + // Set up store with test state and mount the breadcrumb. + renderComponent(state, ['investigation', 'dataset']); - expect(wrapper.find('[data-testid="Breadcrumb-home"] p').text()).toEqual( - 'breadcrumbs.home' - ); - expect(wrapper.find('[data-testid="Breadcrumb-base"] p').text()).toEqual( - 'breadcrumbs.proposal' - ); - }); + // Expect the axios.get not to have been called + expect(axios.get).not.toHaveBeenCalled(); - it('DLS route renders correctly at the investigation level and requests the proposal entity', async () => { - // Set up test state pathname. - history.replace(createLocation(DLSRoutes['investigations'])); + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + expect(screen.getByTestId('Breadcrumb-base')).toHaveTextContent( + 'breadcrumbs.instrument' + ); + }); - // Set up store with test state and mount the breadcrumb. - const wrapper = createWrapper(state); + it('ISIS route renders correctly at the facility cycle level and requests the instrument entity', async () => { + // Set up test state pathname. + history.replace(createLocation(ISISRoutes['facilityCycles'])); - // Flush promises and update the re-render the wrapper. - await flushPromises(); - wrapper.update(); + // Set up store with test state and mount the breadcrumb. + renderComponent(state, ['investigation', 'dataset']); - // Expect the axios.get to have been called twice. - expect(axios.get).toHaveBeenCalledTimes(1); - expect(axios.get).toHaveBeenCalledWith( - '/investigations/findone?where=' + - JSON.stringify({ name: { eq: 'INVESTIGATION 1' } }), - { + // Expect the axios.get to have been called three times. + expect(axios.get).toHaveBeenCalledTimes(1); + expect(axios.get).toHaveBeenCalledWith('/instruments/1', { headers: { Authorization: 'Bearer null', }, - } - ); + }); - expect(wrapper.find('[data-testid="Breadcrumb-home"] p').text()).toEqual( - 'breadcrumbs.home' - ); - expect(wrapper.find('[data-testid="Breadcrumb-base"] a').text()).toEqual( - 'breadcrumbs.proposal' - ); - expect( - wrapper.find('[data-testid="Breadcrumb-base"] a').prop('href') - ).toEqual('/browse/proposal'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] p').text() - ).toEqual('Title 1'); - }); + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute('href', '/browse/instrument'); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.instrument'); + + const breadcrumbs = screen.getAllByTestId(/^Breadcrumb-hierarchy-\d+$/); + expect(within(breadcrumbs[0]).getByText('Name 1')).toBeInTheDocument(); - it('DLS route renders correctly at the dataset level and requests the proposal & investigation entities', async () => { - // Set up test state pathname. - history.replace(createLocation(DLSRoutes['datasets'])); + expect( + within(screen.getByTestId('Breadcrumb-last')).getByText( + 'breadcrumbs.facilityCycle' + ) + ).toBeInTheDocument(); + }); - // Set up store with test state and mount the breadcrumb. - const wrapper = createWrapper(state); + it('ISIS route renders correctly at the investigation level and requests the instrument and facility cycle entities', async () => { + // Set up test state pathname. + history.replace(createLocation(ISISRoutes['investigations'])); - // Flush promises and update the re-render the wrapper. - await flushPromises(); - wrapper.update(); + // Set up store with test state and mount the breadcrumb. + renderComponent(state, ['investigation', 'dataset']); - // Expect the axios.get to have been called twice. - expect(axios.get).toHaveBeenCalledTimes(2); - expect(axios.get).toHaveBeenNthCalledWith( - 1, - '/investigations/findone?where=' + - JSON.stringify({ name: { eq: 'INVESTIGATION 1' } }), - { + // Expect the axios.get to have been called three times. + expect(axios.get).toHaveBeenCalledTimes(2); + expect(axios.get).toHaveBeenNthCalledWith(1, '/instruments/1', { headers: { Authorization: 'Bearer null', }, - } - ); - expect(axios.get).toHaveBeenNthCalledWith(2, '/investigations/1', { - headers: { - Authorization: 'Bearer null', - }, + }); + expect(axios.get).toHaveBeenNthCalledWith(2, '/facilitycycles/2', { + headers: { + Authorization: 'Bearer null', + }, + }); + + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute('href', '/browse/instrument'); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.instrument'); + + const breadcrumbs = screen.getAllByTestId(/^Breadcrumb-hierarchy-\d+$/); + expect(breadcrumbs[0]).toHaveAttribute( + 'href', + '/browse/instrument/1/facilityCycle' + ); + expect(within(breadcrumbs[0]).getByText('Name 1')).toBeInTheDocument(); + expect(within(breadcrumbs[1]).getByText('Name 2')).toBeInTheDocument(); + + expect( + within(screen.getByTestId('Breadcrumb-last')).getByText( + 'breadcrumbs.investigation' + ) + ).toBeInTheDocument(); }); - expect(wrapper.find('[data-testid="Breadcrumb-home"] p').text()).toEqual( - 'breadcrumbs.home' - ); - expect(wrapper.find('[data-testid="Breadcrumb-base"] a').text()).toEqual( - 'breadcrumbs.proposal' - ); - expect( - wrapper.find('[data-testid="Breadcrumb-base"] a').prop('href') - ).toEqual('/browse/proposal'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] a').text() - ).toEqual('Title 1'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] a').prop('href') - ).toEqual('/browse/proposal/INVESTIGATION 1/investigation'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-2"] p').text() - ).toEqual('1'); - expect(wrapper.find('[data-testid="Breadcrumb-last"] p').text()).toEqual( - 'breadcrumbs.dataset' - ); - }); - - it('DLS route renders correctly at the datafile level and requests the proposal, investigation and dataset entities', async () => { - // Set up test state pathname. - history.replace(createLocation(DLSRoutes['datafiles'])); + it('ISIS route renders correctly at the dataset level and requests the instrument, facility cycle and investigation entities', async () => { + // Set up test state pathname. + history.replace(createLocation(ISISRoutes['datasets'])); - // Set up store with test state and mount the breadcrumb. - const wrapper = createWrapper(state); + // Set up store with test state and mount the breadcrumb. + renderComponent(state, ['investigation', 'dataset']); - // Flush promises and update the re-render the wrapper. - await flushPromises(); - wrapper.update(); - - // Expect the axios.get to have been called three times. - expect(axios.get).toHaveBeenCalledTimes(3); - expect(axios.get).toHaveBeenNthCalledWith( - 1, - '/investigations/findone?where=' + - JSON.stringify({ name: { eq: 'INVESTIGATION 1' } }), - { + // Expect the axios.get to have been called three times. + expect(axios.get).toHaveBeenCalledTimes(3); + expect(axios.get).toHaveBeenNthCalledWith(1, '/instruments/1', { headers: { Authorization: 'Bearer null', }, - } - ); - expect(axios.get).toHaveBeenNthCalledWith(2, '/investigations/1', { - headers: { - Authorization: 'Bearer null', - }, - }); - expect(axios.get).toHaveBeenNthCalledWith(3, '/datasets/1', { - headers: { - Authorization: 'Bearer null', - }, + }); + expect(axios.get).toHaveBeenNthCalledWith(2, '/facilitycycles/2', { + headers: { + Authorization: 'Bearer null', + }, + }); + expect(axios.get).toHaveBeenNthCalledWith(3, '/investigations/3', { + headers: { + Authorization: 'Bearer null', + }, + }); + + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute('href', '/browse/instrument'); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.instrument'); + + const breadcrumbs = screen.getAllByTestId(/^Breadcrumb-hierarchy-\d+$/); + expect(breadcrumbs[0]).toHaveAttribute( + 'href', + '/browse/instrument/1/facilityCycle' + ); + expect(within(breadcrumbs[0]).getByText('Name 1')).toBeInTheDocument(); + expect(breadcrumbs[1]).toHaveAttribute( + 'href', + '/browse/instrument/1/facilityCycle/2/investigation' + ); + expect(within(breadcrumbs[1]).getByText('Name 2')).toBeInTheDocument(); + expect(breadcrumbs[2]).toHaveAttribute( + 'href', + '/browse/instrument/1/facilityCycle/2/investigation/3' + ); + expect(within(breadcrumbs[2]).getByText('Title 3')).toBeInTheDocument(); + + expect( + within(screen.getByTestId('Breadcrumb-last')).getByText( + 'breadcrumbs.dataset' + ) + ).toBeInTheDocument(); }); - expect(wrapper.find('[data-testid="Breadcrumb-home"] p').text()).toEqual( - 'breadcrumbs.home' - ); - expect(wrapper.find('[data-testid="Breadcrumb-base"] a').text()).toEqual( - 'breadcrumbs.proposal' - ); - expect( - wrapper.find('[data-testid="Breadcrumb-base"] a').prop('href') - ).toEqual('/browse/proposal'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] a').text() - ).toEqual('Title 1'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] a').prop('href') - ).toEqual('/browse/proposal/INVESTIGATION 1/investigation'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-2"] a').text() - ).toEqual('1'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-2"] a').prop('href') - ).toEqual('/browse/proposal/INVESTIGATION 1/investigation/1/dataset'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-3"] p').text() - ).toEqual('Name 1'); - expect(wrapper.find('[data-testid="Breadcrumb-last"] p').text()).toEqual( - 'breadcrumbs.datafile' - ); - }); + it('ISIS route renders correctly at the datafile level and requests the instrument, facility cycle, investigation and dataset entities', async () => { + // Set up test state pathname. + history.replace(createLocation(ISISRoutes['datafiles'])); - it('ISIS route renders correctly at the base level and does not request', async () => { - // Set up test state pathname. - history.replace(createLocation(ISISRoutes['instruments'])); + // Set up store with test state and mount the breadcrumb. + renderComponent(state, ['investigation', 'dataset']); - // Set up store with test state and mount the breadcrumb. - const wrapper = createWrapper(state, ['investigation', 'dataset']); + // Expect the axios.get to have been called three times. + expect(axios.get).toHaveBeenCalledTimes(4); + expect(axios.get).toHaveBeenNthCalledWith(1, '/instruments/1', { + headers: { + Authorization: 'Bearer null', + }, + }); + expect(axios.get).toHaveBeenNthCalledWith(2, '/facilitycycles/2', { + headers: { + Authorization: 'Bearer null', + }, + }); + expect(axios.get).toHaveBeenNthCalledWith(3, '/investigations/3', { + headers: { + Authorization: 'Bearer null', + }, + }); + expect(axios.get).toHaveBeenNthCalledWith(4, '/datasets/4', { + headers: { + Authorization: 'Bearer null', + }, + }); + + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute('href', '/browse/instrument'); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.instrument'); + + const breadcrumbs = screen.getAllByTestId(/^Breadcrumb-hierarchy-\d+$/); + expect(breadcrumbs[0]).toHaveAttribute( + 'href', + '/browse/instrument/1/facilityCycle' + ); + expect(within(breadcrumbs[0]).getByText('Name 1')).toBeInTheDocument(); + expect(breadcrumbs[1]).toHaveAttribute( + 'href', + '/browse/instrument/1/facilityCycle/2/investigation' + ); + expect(within(breadcrumbs[1]).getByText('Name 2')).toBeInTheDocument(); + expect(breadcrumbs[2]).toHaveAttribute( + 'href', + '/browse/instrument/1/facilityCycle/2/investigation/3' + ); + expect(within(breadcrumbs[2]).getByText('Title 3')).toBeInTheDocument(); + + expect( + within(screen.getByTestId('Breadcrumb-last')).getByText( + 'breadcrumbs.datafile' + ) + ).toBeInTheDocument(); + }); - // Flush promises and update the re-render the wrapper. - await flushPromises(); - wrapper.update(); + it('ISIS experiments route renders correctly at the base level and does not request', async () => { + // Set up test state pathname. + history.replace(createLocation(ISISExperimentsRoutes['instruments'])); - // Expect the axios.get not to have been called - expect(axios.get).not.toHaveBeenCalled(); + // Set up store with test state and mount the breadcrumb. + renderComponent(state, ['investigation', 'dataset']); - expect(wrapper.find('[data-testid="Breadcrumb-home"] p').text()).toEqual( - 'breadcrumbs.home' - ); - expect(wrapper.find('[data-testid="Breadcrumb-base"] p').text()).toEqual( - 'breadcrumbs.instrument' - ); - }); + // Expect the axios.get not to have been called + expect(axios.get).not.toHaveBeenCalled(); - it('ISIS route renders correctly at the facility cycle level and requests the instrument entity', async () => { - // Set up test state pathname. - history.replace(createLocation(ISISRoutes['facilityCycles'])); + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + expect(screen.getByTestId('Breadcrumb-base')).toHaveTextContent( + 'breadcrumbs.instrument' + ); + }); - // Set up store with test state and mount the breadcrumb. - const wrapper = createWrapper(state, ['investigation', 'dataset']); + it('ISIS experiments route renders correctly at the study datapublications level and requests the instrument entity', async () => { + // Set up test state pathname. + history.replace( + createLocation(ISISExperimentsRoutes['studyDataPublications']) + ); - // Flush promises and update the re-render the wrapper. - await flushPromises(); - wrapper.update(); + // Set up store with test state and mount the breadcrumb. + renderComponent(state, ['dataPublication', 'investigation', 'dataset']); - // Expect the axios.get to have been called three times. - expect(axios.get).toHaveBeenCalledTimes(1); - expect(axios.get).toHaveBeenCalledWith('/instruments/1', { - headers: { - Authorization: 'Bearer null', - }, + // Expect the axios.get to have been called 1 time. + expect(axios.get).toHaveBeenCalledTimes(1); + expect(axios.get).toHaveBeenCalledWith('/instruments/1', { + headers: { + Authorization: 'Bearer null', + }, + }); + + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute( + 'href', + '/browseDataPublications/instrument' + ); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.instrument'); + + const breadcrumbs = screen.getAllByTestId(/^Breadcrumb-hierarchy-\d+$/); + expect(within(breadcrumbs[0]).getByText('Name 1')).toBeInTheDocument(); + + expect( + within(screen.getByTestId('Breadcrumb-last')).getByText( + 'breadcrumbs.dataPublication' + ) + ).toBeInTheDocument(); }); - expect(wrapper.find('[data-testid="Breadcrumb-home"] p').text()).toEqual( - 'breadcrumbs.home' - ); - expect(wrapper.find('[data-testid="Breadcrumb-base"] a').text()).toEqual( - 'breadcrumbs.instrument' - ); - expect( - wrapper.find('[data-testid="Breadcrumb-base"] a').prop('href') - ).toEqual('/browse/instrument'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] p').text() - ).toEqual('Name 1'); - expect(wrapper.find('[data-testid="Breadcrumb-last"] p').text()).toEqual( - 'breadcrumbs.facilityCycle' - ); - }); - - it('ISIS route renders correctly at the investigation level and requests the instrument and facility cycle entities', async () => { - // Set up test state pathname. - history.replace(createLocation(ISISRoutes['investigations'])); - - // Set up store with test state and mount the breadcrumb. - const wrapper = createWrapper(state, ['investigation', 'dataset']); + it('ISIS experiments route renders correctly at the data publication investigation level and requests the instrument and datapublication entities', async () => { + // Set up test state pathname. + history.replace( + createLocation(ISISExperimentsRoutes['investigationDataPublications']) + ); - // Flush promises and update the re-render the wrapper. - await flushPromises(); - wrapper.update(); + // Set up store with test state and mount the breadcrumb. + renderComponent(state, ['dataPublication', 'investigation', 'dataset']); - // Expect the axios.get to have been called three times. - expect(axios.get).toHaveBeenCalledTimes(2); - expect(axios.get).toHaveBeenNthCalledWith(1, '/instruments/1', { - headers: { - Authorization: 'Bearer null', - }, - }); - expect(axios.get).toHaveBeenNthCalledWith(2, '/facilitycycles/1', { - headers: { - Authorization: 'Bearer null', - }, + // Expect the axios.get to have been called 2 times. + expect(axios.get).toHaveBeenCalledTimes(2); + expect(axios.get).toHaveBeenNthCalledWith(1, '/instruments/1', { + headers: { + Authorization: 'Bearer null', + }, + }); + expect(axios.get).toHaveBeenNthCalledWith(2, '/datapublications/2', { + headers: { + Authorization: 'Bearer null', + }, + }); + + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute( + 'href', + '/browseDataPublications/instrument' + ); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.instrument'); + + const breadcrumbs = screen.getAllByTestId(/^Breadcrumb-hierarchy-\d+$/); + expect(breadcrumbs[0]).toHaveAttribute( + 'href', + '/browseDataPublications/instrument/1/dataPublication' + ); + expect(within(breadcrumbs[0]).getByText('Name 1')).toBeInTheDocument(); + expect(within(breadcrumbs[1]).getByText('Title 2')).toBeInTheDocument(); + + expect( + within(screen.getByTestId('Breadcrumb-last')).getByText( + 'breadcrumbs.investigation' + ) + ).toBeInTheDocument(); }); - expect(wrapper.find('[data-testid="Breadcrumb-home"] p').text()).toEqual( - 'breadcrumbs.home' - ); - expect(wrapper.find('[data-testid="Breadcrumb-base"] a').text()).toEqual( - 'breadcrumbs.instrument' - ); - expect( - wrapper.find('[data-testid="Breadcrumb-base"] a').prop('href') - ).toEqual('/browse/instrument'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] a').text() - ).toEqual('Name 1'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] a').prop('href') - ).toEqual('/browse/instrument/1/facilityCycle'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-2"] p').text() - ).toEqual('Name 1'); - expect(wrapper.find('[data-testid="Breadcrumb-last"] p').text()).toEqual( - 'breadcrumbs.investigation' - ); - }); - - it('ISIS route renders correctly at the dataset level and requests the instrument, facility cycle and investigation entities', async () => { - // Set up test state pathname. - history.replace(createLocation(ISISRoutes['datasets'])); - - // Set up store with test state and mount the breadcrumb. - const wrapper = createWrapper(state, ['investigation', 'dataset']); + it('ISIS experiments route renders correctly at the dataset level and requests the instrument, data publication and investigation entities', async () => { + // Set up test state pathname. + history.replace(createLocation(ISISExperimentsRoutes['datasets'])); - // Flush promises and update the re-render the wrapper. - await flushPromises(); - wrapper.update(); + // Set up store with test state and mount the breadcrumb. + renderComponent(state, ['dataPublication', 'investigation', 'dataset']); - // Expect the axios.get to have been called three times. - expect(axios.get).toHaveBeenCalledTimes(3); - expect(axios.get).toHaveBeenNthCalledWith(1, '/instruments/1', { - headers: { - Authorization: 'Bearer null', - }, - }); - expect(axios.get).toHaveBeenNthCalledWith(2, '/facilitycycles/1', { - headers: { - Authorization: 'Bearer null', - }, - }); - expect(axios.get).toHaveBeenNthCalledWith(3, '/investigations/1', { - headers: { - Authorization: 'Bearer null', - }, + // Expect the axios.get to have been called three times. + expect(axios.get).toHaveBeenCalledTimes(3); + expect(axios.get).toHaveBeenNthCalledWith(1, '/instruments/1', { + headers: { + Authorization: 'Bearer null', + }, + }); + expect(axios.get).toHaveBeenNthCalledWith(2, '/datapublications/2', { + headers: { + Authorization: 'Bearer null', + }, + }); + expect(axios.get).toHaveBeenNthCalledWith(3, '/datapublications/3', { + headers: { + Authorization: 'Bearer null', + }, + }); + + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute( + 'href', + '/browseDataPublications/instrument' + ); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.instrument'); + + const breadcrumbs = screen.getAllByTestId(/^Breadcrumb-hierarchy-\d+$/); + expect(breadcrumbs[0]).toHaveAttribute( + 'href', + '/browseDataPublications/instrument/1/dataPublication' + ); + expect(within(breadcrumbs[0]).getByText('Name 1')).toBeInTheDocument(); + expect(breadcrumbs[1]).toHaveAttribute( + 'href', + '/browseDataPublications/instrument/1/dataPublication/2' + ); + expect(within(breadcrumbs[1]).getByText('Title 2')).toBeInTheDocument(); + expect(breadcrumbs[2]).toHaveAttribute( + 'href', + '/browseDataPublications/instrument/1/dataPublication/2/investigation/3' + ); + expect(within(breadcrumbs[2]).getByText('Title 3')).toBeInTheDocument(); + + expect( + within(screen.getByTestId('Breadcrumb-last')).getByText( + 'breadcrumbs.dataset' + ) + ).toBeInTheDocument(); }); - expect(wrapper.find('[data-testid="Breadcrumb-home"] p').text()).toEqual( - 'breadcrumbs.home' - ); - expect(wrapper.find('[data-testid="Breadcrumb-base"] a').text()).toEqual( - 'breadcrumbs.instrument' - ); - expect( - wrapper.find('[data-testid="Breadcrumb-base"] a').prop('href') - ).toEqual('/browse/instrument'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] a').text() - ).toEqual('Name 1'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] a').prop('href') - ).toEqual('/browse/instrument/1/facilityCycle'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-2"] a').text() - ).toEqual('Name 1'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-2"] a').prop('href') - ).toEqual('/browse/instrument/1/facilityCycle/1/investigation'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-3"] a').text() - ).toEqual('Title 1'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-3"] a').prop('href') - ).toEqual('/browse/instrument/1/facilityCycle/1/investigation/1'); - expect(wrapper.find('[data-testid="Breadcrumb-last"] p').text()).toEqual( - 'breadcrumbs.dataset' - ); - }); - it('ISIS route renders correctly at the datafile level and requests the instrument, facility cycle, investigation and dataset entities', async () => { - // Set up test state pathname. - history.replace(createLocation(ISISRoutes['datafiles'])); + it('ISIS experiments route renders correctly at the datafile level and requests the instrument, data publication, investigation and dataset entities', async () => { + // Set up test state pathname. + history.replace(createLocation(ISISExperimentsRoutes['datafiles'])); - // Set up store with test state and mount the breadcrumb. - const wrapper = createWrapper(state, ['investigation', 'dataset']); + // Set up store with test state and mount the breadcrumb. + renderComponent(state, ['dataPublication', 'investigation', 'dataset']); - // Flush promises and update the re-render the wrapper. - await flushPromises(); - wrapper.update(); - - // Expect the axios.get to have been called three times. - expect(axios.get).toHaveBeenCalledTimes(4); - expect(axios.get).toHaveBeenNthCalledWith(1, '/instruments/1', { - headers: { - Authorization: 'Bearer null', - }, - }); - expect(axios.get).toHaveBeenNthCalledWith(2, '/facilitycycles/1', { - headers: { - Authorization: 'Bearer null', - }, - }); - expect(axios.get).toHaveBeenNthCalledWith(3, '/investigations/1', { - headers: { - Authorization: 'Bearer null', - }, - }); - expect(axios.get).toHaveBeenNthCalledWith(4, '/datasets/1', { - headers: { - Authorization: 'Bearer null', - }, + // Expect the axios.get to have been called four times. + expect(axios.get).toHaveBeenCalledTimes(4); + expect(axios.get).toHaveBeenNthCalledWith(1, '/instruments/1', { + headers: { + Authorization: 'Bearer null', + }, + }); + expect(axios.get).toHaveBeenNthCalledWith(2, '/datapublications/2', { + headers: { + Authorization: 'Bearer null', + }, + }); + expect(axios.get).toHaveBeenNthCalledWith(3, '/datapublications/3', { + headers: { + Authorization: 'Bearer null', + }, + }); + expect(axios.get).toHaveBeenNthCalledWith(4, '/datasets/4', { + headers: { + Authorization: 'Bearer null', + }, + }); + + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute( + 'href', + '/browseDataPublications/instrument' + ); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.instrument'); + + const breadcrumbs = screen.getAllByTestId(/^Breadcrumb-hierarchy-\d+$/); + expect(breadcrumbs[0]).toHaveAttribute( + 'href', + '/browseDataPublications/instrument/1/dataPublication' + ); + expect(within(breadcrumbs[0]).getByText('Name 1')).toBeInTheDocument(); + expect(breadcrumbs[1]).toHaveAttribute( + 'href', + '/browseDataPublications/instrument/1/dataPublication/2' + ); + expect(within(breadcrumbs[1]).getByText('Title 2')).toBeInTheDocument(); + expect(breadcrumbs[2]).toHaveAttribute( + 'href', + '/browseDataPublications/instrument/1/dataPublication/2/investigation/3' + ); + expect(within(breadcrumbs[2]).getByText('Title 3')).toBeInTheDocument(); + + expect( + within(screen.getByTestId('Breadcrumb-last')).getByText( + 'breadcrumbs.datafile' + ) + ).toBeInTheDocument(); }); - - expect(wrapper.find('[data-testid="Breadcrumb-home"] p').text()).toEqual( - 'breadcrumbs.home' - ); - expect(wrapper.find('[data-testid="Breadcrumb-base"] a').text()).toEqual( - 'breadcrumbs.instrument' - ); - expect( - wrapper.find('[data-testid="Breadcrumb-base"] a').prop('href') - ).toEqual('/browse/instrument'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] a').text() - ).toEqual('Name 1'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-1"] a').prop('href') - ).toEqual('/browse/instrument/1/facilityCycle'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-2"] a').text() - ).toEqual('Name 1'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-2"] a').prop('href') - ).toEqual('/browse/instrument/1/facilityCycle/1/investigation'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-3"] a').text() - ).toEqual('Title 1'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-3"] a').prop('href') - ).toEqual('/browse/instrument/1/facilityCycle/1/investigation/1'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-4"] a').text() - ).toEqual('Name 1'); - expect( - wrapper.find('[data-testid="Breadcrumb-hierarchy-4"] a').prop('href') - ).toEqual('/browse/instrument/1/facilityCycle/1/investigation/1/dataset/1'); - expect(wrapper.find('[data-testid="Breadcrumb-last"] p').text()).toEqual( - 'breadcrumbs.datafile' - ); }); }); diff --git a/packages/datagateway-dataview/src/page/breadcrumbs.component.tsx b/packages/datagateway-dataview/src/page/breadcrumbs.component.tsx index 5e9756c99..59ea7d58d 100644 --- a/packages/datagateway-dataview/src/page/breadcrumbs.component.tsx +++ b/packages/datagateway-dataview/src/page/breadcrumbs.component.tsx @@ -1,13 +1,11 @@ import { Breadcrumbs, - createStyles, + breadcrumbsClasses, Link as MaterialLink, Paper, - Theme, + styled, Typography, - withStyles, -} from '@material-ui/core'; -import { StyleRules } from '@material-ui/core/styles'; +} from '@mui/material'; import axios, { AxiosError } from 'axios'; import { ArrowTooltip, @@ -52,95 +50,6 @@ const Breadcrumb: React.FC = (props: BreadcrumbProps) => { } }; -const breadcrumbsStyles = (theme: Theme): StyleRules => - createStyles({ - root: { - backgroundColor: theme.palette.background.default, - '& li': { - '& a, p': { - color: theme.palette.primary.contrastText, - backgroundColor: theme.palette.primary.light, - display: 'block', - textDecoration: 'none', - position: 'relative', - - /* Positions breadcrumb */ - lineHeight: '28px', - padding: ' 0 4px 0 14px', - textAlign: 'center', - - /* Add the arrow between breadcrumbs */ - '&:after': { - content: '""', - position: 'absolute', - top: '3px', - // half the width/height - right: '-11px', - // width/height same as lineHeight - 2* top height - height: '22px', - width: '22px', - // change skew to alter how shallow the arrow is - transform: 'scale(0.707) rotate(45deg) skew(15deg,15deg)', - zIndex: 1, - boxShadow: `2px -2px 0 2px ${theme.palette.background.default}`, - borderRadius: ' 0 5px 0 50px', - backgroundColor: theme.palette.primary.light, - }, - '&:hover': { - backgroundColor: theme.palette.primary.light, - '&:after': { - backgroundColor: theme.palette.primary.light, - }, - }, - '&:active': { - backgroundColor: theme.palette.grey[600], - '&:after': { - backgroundColor: `${theme.palette.grey[600]} !important`, - }, - }, - }, - }, - /* Every even breadcrumb has a darker background */ - '& li:nth-child(4n + 3)': { - '& a, p': { - backgroundColor: theme.palette.primary.main, - '&:after': { - backgroundColor: theme.palette.primary.main, - }, - }, - }, - '& li:first-child': { - '& a, p': { - paddingLeft: '14px', - }, - }, - '& li:last-child': { - '& a, p': { - /* Curve the last breadcrumb border */ - borderRadius: '0 5px 5px 0', - paddingLeft: '14px', - '&:after': { - content: 'none', - }, - }, - }, - - /* Control the width and shortening of text */ - '& span': { - display: 'block', - whiteSpace: 'nowrap', - // TODO: Remove use of "vw" here? - maxWidth: '20vw', - overflow: 'hidden', - textOverflow: 'ellipsis', - }, - }, - separator: { - marginLeft: 0, - marginRight: 0, - }, - }); - const fetchEntityInformation = async ( apiUrl: string, requestEntityUrl: string, @@ -197,31 +106,43 @@ const useEntityInformation = ( // the entity field we want is the name of the entity. let apiEntity = entity; - // If the entity is a investigation, we always want to fetch the title field. - let requestEntityField = entity === 'investigation' ? 'title' : 'name'; + // If the entity is a investigation or a data publication, we can't use name field as the default + let requestEntityField = + entity === 'investigation' + ? 'title' + : entity === 'dataPublication' + ? 'title' + : 'name'; + + // this is the field we use to lookup the relevant entity in ICAT - it's usually ID + // but for DLS proposals this will be name + let requestQueryField = 'id'; // Use breadcrumb settings in state to customise API call for entities. - if ( - Object.entries(breadcrumbSettings).length !== 0 && - entity in breadcrumbSettings - ) { - const entitySettings = breadcrumbSettings[entity]; - - // Check for a parent entity. - if ( - !entitySettings.parentEntity || - (entitySettings.parentEntity && - currentPathnames.includes(entitySettings.parentEntity)) - ) { - // Get the defined replace entity field. - requestEntityField = entitySettings.replaceEntityField; - - // Get the replace entity, if one has been defined. - if (entitySettings.replaceEntity) { - apiEntity = entitySettings.replaceEntity; + breadcrumbSettings + .filter( + (breadcrumbSetting) => breadcrumbSetting.matchEntity === entity + ) + .forEach((entitySettings) => { + // Check for a parent entity. + if ( + !entitySettings.parentEntity || + (entitySettings.parentEntity && + currentPathnames.includes(entitySettings.parentEntity)) + ) { + // Get the defined replace entity field. + requestEntityField = entitySettings.replaceEntityField; + + // Get the replace entity, if one has been defined. + if (entitySettings.replaceEntity) { + apiEntity = entitySettings.replaceEntity; + } + + if (entitySettings.replaceEntityQueryField) { + requestQueryField = entitySettings.replaceEntityQueryField; + } } - } - } + }); // Create the entity url to request the name, this is pluralised to get the API endpoint. let requestEntityUrl: string; @@ -241,7 +162,7 @@ const useEntityInformation = ( requestEntityUrl = pluralisedApiEntity.toLowerCase() + '/findone?where=' + - JSON.stringify({ name: { eq: entityId } }); + JSON.stringify({ [requestQueryField]: { eq: entityId } }); } queryConfigs.push({ @@ -277,7 +198,91 @@ const useEntityInformation = ( return useQueries(queryConfigs); }; -const StyledBreadcrumbs = withStyles(breadcrumbsStyles)(Breadcrumbs); +const StyledBreadcrumbs = styled(Breadcrumbs)(({ theme }) => ({ + backgroundColor: theme.palette.background.default, + '& li': { + '& a, p': { + color: theme.palette.primary.contrastText, + backgroundColor: theme.palette.primary.light, + display: 'block', + textDecoration: 'none', + position: 'relative', + + /* Positions breadcrumb */ + lineHeight: '28px', + padding: '0 4px 0 14px', + textAlign: 'center', + + /* Add the arrow between breadcrumbs */ + '&:after': { + content: '""', + position: 'absolute', + top: '3px', + // half the width/height + right: '-11px', + // width/height same as lineHeight - 2* top height + height: '22px', + width: '22px', + // change skew to alter how shallow the arrow is + transform: 'scale(0.707) rotate(45deg) skew(15deg,15deg)', + zIndex: 1, + boxShadow: `2px -2px 0 2px ${theme.palette.background.default}`, + borderRadius: ' 0 5px 0 50px', + backgroundColor: theme.palette.primary.light, + }, + '&:hover': { + backgroundColor: `${theme.palette.primary.light} !important`, + '&:after': { + backgroundColor: `${theme.palette.primary.light} !important`, + }, + }, + '&:active': { + backgroundColor: `${theme.palette.grey[600]} !important`, + '&:after': { + backgroundColor: `${theme.palette.grey[600]} !important`, + }, + }, + }, + }, + /* Every even breadcrumb has a darker background */ + '& li:nth-of-type(4n + 3)': { + '& a, p': { + backgroundColor: theme.palette.primary.main, + '&:after': { + backgroundColor: theme.palette.primary.main, + }, + }, + }, + '& li:first-of-type': { + '& a, p': { + paddingLeft: '14px', + }, + }, + '& li:last-of-type': { + '& a, p': { + /* Curve the last breadcrumb border */ + borderRadius: '0 5px 5px 0', + paddingLeft: '14px', + '&:after': { + content: 'none', + }, + }, + }, + + /* Control the width and shortening of text */ + '& span': { + display: 'block', + whiteSpace: 'nowrap', + // TODO: Remove use of "vw" here? + maxWidth: '20vw', + overflow: 'hidden', + textOverflow: 'ellipsis', + }, + [`& .${breadcrumbsClasses.separator}`]: { + marginLeft: 0, + marginRight: 0, + }, +})); interface PageBreadcrumbsProps { landingPageEntities: string[]; @@ -313,7 +318,7 @@ const PageBreadcrumbs: React.FC = ( {/* // Return the base entity as a link. */} { const originalModule = jest.requireActual('datagateway-common'); @@ -26,8 +19,6 @@ jest.mock('datagateway-common', () => { __esModule: true, ...originalModule, useInvestigation: jest.fn(), - useInstrumentsPaginated: jest.fn(), - useFacilityCyclesByInvestigation: jest.fn(), }; }); @@ -45,25 +36,20 @@ jest.mock('react-router-dom', () => { }); describe('DOI Redirect page', () => { - let mount; - let history; + let history: History; let mockInvestigationData: Investigation[] = []; - let mockInstrumentData: Instrument[] = []; - let mockFacilityCycleData: FacilityCycle[] = []; - const createWrapper = (): ReactWrapper => { - return mount( + function renderComponent(): RenderResult { + return render( ); - }; + } beforeEach(() => { - mount = createMount(); - history = createMemoryHistory({ initialEntries: [createLocation('/doi-redirect/LILS/investigation/1')], }); @@ -75,20 +61,26 @@ describe('DOI Redirect page', () => { title: 'Investigation 1', visitId: '1', startDate: '2022-04-01 00:00:00', - }, - ]; - mockInstrumentData = [ - { - id: 2, - name: 'instrument1', - }, - ]; - mockFacilityCycleData = [ - { - id: 3, - name: 'facilitycycle1', - startDate: '2022-04-01 00:00:00', - endDate: '2022-04-02 00:00:00', + investigationInstruments: [ + { + id: 401, + instrument: { + id: 2, + name: 'instrument1', + }, + }, + ], + investigationFacilityCycles: [ + { + id: 633, + facilityCycle: { + id: 3, + name: 'facilitycycle1', + startDate: '2022-04-01 00:00:00', + endDate: '2022-04-02 00:00:00', + }, + }, + ], }, ]; @@ -96,37 +88,14 @@ describe('DOI Redirect page', () => { data: mockInvestigationData, isLoading: false, }); - (useInstrumentsPaginated as jest.Mock).mockReturnValue({ - data: mockInstrumentData, - isLoading: false, - }); - (useFacilityCyclesByInvestigation as jest.Mock).mockReturnValue({ - data: mockFacilityCycleData, - isLoading: false, - isIdle: false, - }); }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); it('redirects to correct link when everything loads correctly', async () => { - createWrapper(); - - expect(useInvestigation).toHaveBeenCalledWith(1); - expect(useInstrumentsPaginated).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigationInstruments.investigation.id': { eq: 1 }, - }), - }, - ]); - expect(useFacilityCyclesByInvestigation).toHaveBeenCalledWith( - '2022-04-01 00:00:00' - ); + renderComponent(); expect(history.location.pathname).toBe( '/browse/instrument/2/facilityCycle/3/investigation/1/dataset' ); @@ -137,51 +106,14 @@ describe('DOI Redirect page', () => { data: [], isLoading: true, }); - let wrapper = createWrapper(); - - expect(wrapper.find('Preloader').exists()).toBe(true); - expect(wrapper.find('Preloader').prop('loading')).toBe(true); - - (useInvestigation as jest.Mock).mockReturnValue({ - data: mockInvestigationData, - isLoading: false, - }); - (useInstrumentsPaginated as jest.Mock).mockReturnValue({ - data: [], - isLoading: true, - }); - wrapper = createWrapper(); - - expect(wrapper.find('Preloader').exists()).toBe(true); - expect(wrapper.find('Preloader').prop('loading')).toBe(true); - - (useInstrumentsPaginated as jest.Mock).mockReturnValue({ - data: mockInstrumentData, - isLoading: false, - }); - (useFacilityCyclesByInvestigation as jest.Mock).mockReturnValue({ - data: [], - isLoading: true, - isIdle: false, - }); - wrapper = createWrapper(); - expect(wrapper.find('Preloader').exists()).toBe(true); - expect(wrapper.find('Preloader').prop('loading')).toBe(true); - - (useFacilityCyclesByInvestigation as jest.Mock).mockReturnValue({ - data: [], - isLoading: false, - isIdle: true, - }); - wrapper = createWrapper(); + renderComponent(); - expect(wrapper.find('Preloader').exists()).toBe(true); - expect(wrapper.find('Preloader').prop('loading')).toBe(true); + expect(screen.getByRole('progressbar')).toBeInTheDocument(); }); - it('throws error and redirects to homepage if data invalid', async () => { - let events = []; + it('throws error and redirects to homepage if no investigation is returned', async () => { + const events: CustomEvent[] = []; document.dispatchEvent = (e: Event) => { events.push(e as CustomEvent); @@ -191,58 +123,7 @@ describe('DOI Redirect page', () => { data: [], isLoading: false, }); - createWrapper(); - - expect(history.location.pathname).toBe('/datagateway'); - expect(log.error).toHaveBeenCalledWith('Invalid DOI redirect'); - expect(events.length).toBe(1); - expect(events[0].detail).toEqual({ - type: NotificationType, - payload: { - severity: 'error', - message: - 'Cannot read the investigation. You may not have read access, or it may not be published yet.', - }, - }); - - history.push('/doi-redirect/LILS/investigation/1'); - events = []; - (log.error as jest.Mock).mockClear(); - (useInvestigation as jest.Mock).mockReturnValue({ - data: mockInvestigationData, - isLoading: false, - }); - (useInstrumentsPaginated as jest.Mock).mockReturnValue({ - data: [], - isLoading: false, - }); - createWrapper(); - - expect(history.location.pathname).toBe('/datagateway'); - expect(log.error).toHaveBeenCalledWith('Invalid DOI redirect'); - expect(events.length).toBe(1); - expect(events[0].detail).toEqual({ - type: NotificationType, - payload: { - severity: 'error', - message: - 'Cannot read the investigation. You may not have read access, or it may not be published yet.', - }, - }); - - history.push('/doi-redirect/LILS/investigation/1'); - events = []; - (log.error as jest.Mock).mockClear(); - (useInstrumentsPaginated as jest.Mock).mockReturnValue({ - data: mockInstrumentData, - isLoading: false, - }); - (useFacilityCyclesByInvestigation as jest.Mock).mockReturnValue({ - data: [], - isLoading: false, - isIdle: false, - }); - createWrapper(); + renderComponent(); expect(history.location.pathname).toBe('/datagateway'); expect(log.error).toHaveBeenCalledWith('Invalid DOI redirect'); diff --git a/packages/datagateway-dataview/src/page/doiRedirect.component.tsx b/packages/datagateway-dataview/src/page/doiRedirect.component.tsx index ce51c2dc0..c48ad1cbc 100644 --- a/packages/datagateway-dataview/src/page/doiRedirect.component.tsx +++ b/packages/datagateway-dataview/src/page/doiRedirect.component.tsx @@ -1,15 +1,15 @@ import { - useInstrumentsPaginated, - useInvestigation, - useFacilityCyclesByInvestigation, - Preloader, + buildDatasetTableUrlForInvestigation, + FACILITY_NAME, MicroFrontendId, NotificationType, + Preloader, + useInvestigation, } from 'datagateway-common'; +import log from 'loglevel'; import React from 'react'; import { Redirect, useParams } from 'react-router-dom'; import { paths } from './pageContainer.component'; -import * as log from 'loglevel'; type DoiRedirectRouteParams = { facilityName: string; @@ -25,67 +25,49 @@ const DoiRedirect: React.FC = () => { const investigationId = parseInt(entityId); - const { - data: investigations, - isLoading: investigationLoading, - } = useInvestigation(investigationId); - const investigation = investigations?.[0]; - - const { - data: instruments, - isLoading: instrumentLoading, - } = useInstrumentsPaginated([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigationInstruments.investigation.id': { eq: investigationId }, - }), - }, - ]); - const instrument = instruments?.[0]; + const { data: investigations, isLoading: isInvestigationLoading } = + useInvestigation(investigationId, [ + { + filterType: 'include', + filterValue: JSON.stringify({ + investigationInstruments: 'instrument', + investigationFacilityCycles: 'facilityCycle', + }), + }, + ]); - const { - data: facilityCycles, - isLoading: facilityCycleLoading, - isIdle: facilityCycleIdle, - } = useFacilityCyclesByInvestigation( - investigation?.startDate?.replace('+', ' ') - ); - const facilityCycle = facilityCycles?.[0]; + const investigation = investigations?.[0]; + const redirectUrl = investigation + ? buildDatasetTableUrlForInvestigation({ + investigation, + facilityName: FACILITY_NAME.isis, + }) + : null; - const loading = - facilityCycleLoading || - instrumentLoading || - investigationLoading || - (!!investigation && facilityCycleIdle); + if (investigation && redirectUrl) { + return ; + } - if (investigation && instrument && facilityCycle) { - return ( - - ); - } else { - if (!loading && (!investigation || !instrument || !facilityCycle)) { - log.error('Invalid DOI redirect'); - document.dispatchEvent( - new CustomEvent(MicroFrontendId, { - detail: { - type: NotificationType, - payload: { - severity: 'error', - message: `Cannot read the ${entityName}. You may not have read access, or it may not be published yet.`, - }, + if (!isInvestigationLoading) { + log.error('Invalid DOI redirect'); + document.dispatchEvent( + new CustomEvent(MicroFrontendId, { + detail: { + type: NotificationType, + payload: { + severity: 'error', + message: `Cannot read the ${entityName}. You may not have read access, or it may not be published yet.`, }, - }) - ); - } - return ( - - - + }, + }) ); } + + return ( + + + + ); }; export default DoiRedirect; diff --git a/packages/datagateway-dataview/src/page/idCheckFunctions.test.ts b/packages/datagateway-dataview/src/page/idCheckFunctions.test.ts index 42ea25157..75f2cb441 100644 --- a/packages/datagateway-dataview/src/page/idCheckFunctions.test.ts +++ b/packages/datagateway-dataview/src/page/idCheckFunctions.test.ts @@ -4,7 +4,8 @@ import { checkInstrumentAndFacilityCycleId, saveApiUrlMiddleware, checkInstrumentId, - checkStudyId, + checkStudyDataPublicationId, + checkDatasetId, } from './idCheckFunctions'; import axios from 'axios'; import { handleICATError, ConfigureURLsType } from 'datagateway-common'; @@ -73,7 +74,7 @@ describe('ID check functions', () => { expect.assertions(2); (axios.get as jest.Mock).mockImplementation(() => Promise.resolve({ - data: { id: 2, name: 'Test dataset', investigation: { id: 1 } }, + data: { id: 2, name: 'Test dataset' }, }) ); @@ -99,6 +100,7 @@ describe('ID check functions', () => { (axios.get as jest.Mock).mockImplementation(() => Promise.reject({ response: { status: 404 }, + isAxiosError: true, }) ); @@ -175,13 +177,18 @@ describe('ID check functions', () => { const result = await checkInstrumentAndFacilityCycleId(1, 2, 3); expect(result).toBe(true); - expect(axios.get).toHaveBeenCalledWith( - '/instruments/1/facilitycycles/2/investigations/', - { - params: { where: { id: { eq: 3 } } }, - headers: { Authorization: 'Bearer null' }, - } - ); + expect(axios.get).toHaveBeenCalledWith('/investigations', { + params: { + where: JSON.stringify({ + id: { eq: 3 }, + investigationInstrument: { instrument: { id: { eq: 1 } } }, + investigationFacilityCycle: { + facilityCycle: { id: { eq: 2 } }, + }, + }), + }, + headers: { Authorization: 'Bearer null' }, + }); }); it('returns false on invalid instrument, facility cycle + investigation triple', async () => { expect.assertions(1); @@ -211,11 +218,11 @@ describe('ID check functions', () => { }); describe('checkInstrumentId', () => { - it('returns true on valid instrument + study pair', async () => { + it('returns true on valid instrument + data publication pair', async () => { expect.assertions(3); (axios.get as jest.Mock).mockImplementation(() => Promise.resolve({ - data: [{ id: 2, name: 'Test study' }], + data: [{ id: 2, name: 'Test Data Publication' }], }) ); @@ -231,13 +238,14 @@ describe('ID check functions', () => { params.append( 'where', JSON.stringify({ - 'studyInvestigations.investigation.investigationInstruments.instrument.id': { - eq: 1, - }, + 'content.dataCollectionInvestigations.investigation.investigationInstruments.instrument.id': + { + eq: 1, + }, }) ); expect(axios.get).toHaveBeenCalledWith( - '/studies/', + '/datapublications/', expect.objectContaining({ params, }) @@ -273,16 +281,16 @@ describe('ID check functions', () => { }); }); - describe('checkStudyId', () => { - it('returns true on valid study + investigation pair', async () => { + describe('checkStudyDataPublicationId', () => { + it('returns true on valid study datapublication + investigation data publication pair', async () => { expect.assertions(3); (axios.get as jest.Mock).mockImplementation(() => Promise.resolve({ - data: [{ id: 3, name: 'Test investigation' }], + data: [{ id: 3, title: 'Test DataPublication' }], }) ); - const result = await checkStudyId(2, 3); + const result = await checkStudyDataPublicationId(2, 3); expect(result).toBe(true); const params = new URLSearchParams(); params.append( @@ -294,13 +302,14 @@ describe('ID check functions', () => { params.append( 'where', JSON.stringify({ - 'studyInvestigations.study.id': { - eq: 2, - }, + 'content.dataCollectionInvestigations.investigation.dataCollectionInvestigations.dataCollection.dataPublications.id': + { + eq: 2, + }, }) ); expect(axios.get).toHaveBeenCalledWith( - '/investigations/', + '/datapublications', expect.objectContaining({ params, }) @@ -309,7 +318,7 @@ describe('ID check functions', () => { params.toString() ); }); - it('returns false on invalid study + investigation pair', async () => { + it('returns false on invalid study datapublication + investigation data publication pair', async () => { expect.assertions(1); (axios.get as jest.Mock).mockImplementation(() => Promise.resolve({ @@ -317,8 +326,63 @@ describe('ID check functions', () => { }) ); - const result = await checkStudyId(2, 3); + const result = await checkStudyDataPublicationId(2, 3); + expect(result).toBe(false); + }); + it('returns false on HTTP error', async () => { + expect.assertions(2); + (axios.get as jest.Mock).mockImplementation(() => + Promise.reject({ + message: 'Test error message', + }) + ); + + const result = await checkStudyDataPublicationId(2, 3); + expect(result).toBe(false); + expect(handleICATError).toHaveBeenCalledWith({ + message: 'Test error message', + }); + }); + }); + + describe('checkDatasetId', () => { + it('returns true on valid dataset + datafile pair', async () => { + expect.assertions(2); + (axios.get as jest.Mock).mockImplementation(() => + Promise.resolve({ + data: { id: 2, name: 'Test datafile' }, + }) + ); + + const result = await checkDatasetId(1, 2); + expect(result).toBe(true); + const params = new URLSearchParams(); + params.append( + 'where', + JSON.stringify({ + id: { + eq: 2, + }, + }) + ); + params.append('where', JSON.stringify({ 'dataset.id': { eq: 1 } })); + expect(axios.get).toHaveBeenCalledWith('/datafiles/findone', { + params, + headers: { Authorization: 'Bearer null' }, + }); + }); + it('returns false on invalid dataset + datafile pair', async () => { + expect.assertions(2); + (axios.get as jest.Mock).mockImplementation(() => + Promise.reject({ + response: { status: 404 }, + isAxiosError: true, + }) + ); + + const result = await checkDatasetId(1, 2); expect(result).toBe(false); + expect(handleICATError).not.toHaveBeenCalled(); }); it('returns false on HTTP error', async () => { expect.assertions(2); @@ -328,7 +392,7 @@ describe('ID check functions', () => { }) ); - const result = await checkStudyId(2, 3); + const result = await checkDatasetId(1, 2); expect(result).toBe(false); expect(handleICATError).toHaveBeenCalledWith({ message: 'Test error message', diff --git a/packages/datagateway-dataview/src/page/idCheckFunctions.ts b/packages/datagateway-dataview/src/page/idCheckFunctions.ts index c6550e0a8..23b5a605b 100644 --- a/packages/datagateway-dataview/src/page/idCheckFunctions.ts +++ b/packages/datagateway-dataview/src/page/idCheckFunctions.ts @@ -1,4 +1,4 @@ -import axios, { AxiosError, AxiosResponse } from 'axios'; +import axios, { AxiosResponse } from 'axios'; import { handleICATError, Investigation, @@ -11,15 +11,15 @@ import memoize from 'lodash.memoize'; let apiUrl = ''; // this is so that idCheckFunctions have access to the apiUrl -export const saveApiUrlMiddleware: Middleware = (() => ( - next: Dispatch -) => (action: AnyAction): AnyAction => { - if (action.type === ConfigureURLsType) { - apiUrl = action.payload.urls.apiUrl; - } +export const saveApiUrlMiddleware: Middleware = (() => + (next: Dispatch) => + (action: AnyAction): AnyAction => { + if (action.type === ConfigureURLsType) { + apiUrl = action.payload.urls.apiUrl; + } - return next(action); -}) as Middleware; + return next(action); + }) as Middleware; const unmemoizedCheckInvestigationId = ( investigationId: number, @@ -50,7 +50,8 @@ const unmemoizedCheckInvestigationId = ( }) .catch((error) => { // 404 is valid response from API saying the investigation id is invalid - if ((error as AxiosError).response?.status === 404) return false; + if (axios.isAxiosError(error) && error.response?.status === 404) + return false; // handle other API errors handleICATError(error); return false; @@ -73,21 +74,22 @@ const unmemoizedCheckInstrumentAndFacilityCycleId = ( investigationId: number ): Promise => { return axios - .get( - `${apiUrl}/instruments/${instrumentId}/facilitycycles/${facilityCycleId}/investigations/`, - { - params: { - where: { - id: { - eq: investigationId, - }, + .get(`${apiUrl}/investigations`, { + params: { + where: JSON.stringify({ + id: { + eq: investigationId, }, - }, - headers: { - Authorization: `Bearer ${readSciGatewayToken().sessionId}`, - }, - } - ) + investigationInstrument: { instrument: { id: { eq: instrumentId } } }, + investigationFacilityCycle: { + facilityCycle: { id: { eq: facilityCycleId } }, + }, + }), + }, + headers: { + Authorization: `Bearer ${readSciGatewayToken().sessionId}`, + }, + }) .then((response: AxiosResponse) => { return response.data.length > 0; }) @@ -102,27 +104,28 @@ export const checkInstrumentAndFacilityCycleId = memoize( (...args) => JSON.stringify(args) ); -const unmemoizedCheckStudyId = ( - studyId: number, - investigationId: number +const unmemoizedCheckStudyDataPublicationId = ( + studyDataPublicationId: number, + investigationDataPublicationId: number ): Promise => { const params = new URLSearchParams(); params.append( 'where', JSON.stringify({ - id: { eq: investigationId }, + id: { eq: investigationDataPublicationId }, }) ); params.append( 'where', JSON.stringify({ - 'studyInvestigations.study.id': { - eq: studyId, - }, + 'content.dataCollectionInvestigations.investigation.dataCollectionInvestigations.dataCollection.dataPublications.id': + { + eq: studyDataPublicationId, + }, }) ); return axios - .get(`${apiUrl}/investigations/`, { + .get(`${apiUrl}/datapublications`, { params, headers: { Authorization: `Bearer ${readSciGatewayToken().sessionId}`, @@ -137,31 +140,33 @@ const unmemoizedCheckStudyId = ( }); }; -export const checkStudyId = memoize(unmemoizedCheckStudyId, (...args) => - JSON.stringify(args) +export const checkStudyDataPublicationId = memoize( + unmemoizedCheckStudyDataPublicationId, + (...args) => JSON.stringify(args) ); const unmemoizedCheckInstrumentId = ( instrumentId: number, - studyId: number + dataPublicationId: number ): Promise => { const params = new URLSearchParams(); params.append( 'where', JSON.stringify({ - id: { eq: studyId }, + id: { eq: dataPublicationId }, }) ); params.append( 'where', JSON.stringify({ - 'studyInvestigations.investigation.investigationInstruments.instrument.id': { - eq: instrumentId, - }, + 'content.dataCollectionInvestigations.investigation.investigationInstruments.instrument.id': + { + eq: instrumentId, + }, }) ); return axios - .get(`${apiUrl}/studies/`, { + .get(`${apiUrl}/datapublications/`, { params, headers: { Authorization: `Bearer ${readSciGatewayToken().sessionId}`, @@ -204,3 +209,41 @@ export const checkProposalName = memoize( unmemoizedCheckProposalName, (...args) => JSON.stringify(args) ); + +const unmemoizedCheckDatasetId = ( + datasetId: number, + datafileId: number +): Promise => { + const params = new URLSearchParams(); + params.append( + 'where', + JSON.stringify({ + id: { + eq: datafileId, + }, + }) + ); + params.append('where', JSON.stringify({ 'dataset.id': { eq: datasetId } })); + return axios + .get(`${apiUrl}/datafiles/findone`, { + params, + headers: { + Authorization: `Bearer ${readSciGatewayToken().sessionId}`, + }, + }) + .then(() => { + return true; + }) + .catch((error) => { + // 404 is valid response from API saying the investigation id is invalid + if (axios.isAxiosError(error) && error.response?.status === 404) + return false; + // handle other API errors + handleICATError(error); + return false; + }); +}; + +export const checkDatasetId = memoize(unmemoizedCheckDatasetId, (...args) => + JSON.stringify(args) +); diff --git a/packages/datagateway-dataview/src/page/pageContainer.component.test.tsx b/packages/datagateway-dataview/src/page/pageContainer.component.test.tsx index 943799510..e61ade2cf 100644 --- a/packages/datagateway-dataview/src/page/pageContainer.component.test.tsx +++ b/packages/datagateway-dataview/src/page/pageContainer.component.test.tsx @@ -1,26 +1,27 @@ -import React from 'react'; -import { ReactWrapper, mount } from 'enzyme'; - +import * as React from 'react'; import thunk from 'redux-thunk'; import configureStore from 'redux-mock-store'; import { StateType } from '../state/app.types'; import { initialState as dgDataViewInitialState } from '../state/reducers/dgdataview.reducer'; import { dGCommonInitialState, + DownloadCartItem, readSciGatewayToken, - useCart, - ClearFiltersButton, } from 'datagateway-common'; - -import { LinearProgress } from '@material-ui/core'; -import { createLocation, createMemoryHistory, History } from 'history'; +import { + createLocation, + createMemoryHistory, + createPath, + History, +} from 'history'; import { Router } from 'react-router-dom'; import PageContainer, { paths } from './pageContainer.component'; -import { checkInstrumentId, checkInvestigationId } from './idCheckFunctions'; -import axios from 'axios'; -import { act } from 'react-dom/test-utils'; -import { flushPromises } from '../setupTests'; +import { + checkInstrumentId as unmockedCheckInstrumentId, + checkInvestigationId as unmockedCheckInvestigationId, +} from './idCheckFunctions'; +import axios, { AxiosResponse } from 'axios'; import { QueryClient, QueryClientProvider, @@ -28,9 +29,20 @@ import { useQueryClient, } from 'react-query'; import { Provider } from 'react-redux'; +import { + render, + type RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; +import { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; jest.mock('loglevel'); jest.mock('./idCheckFunctions'); +const checkInstrumentId = jest.mocked(unmockedCheckInstrumentId); +const checkInvestigationId = jest.mocked(unmockedCheckInvestigationId); jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -38,7 +50,6 @@ jest.mock('datagateway-common', () => { return { __esModule: true, ...originalModule, - useCart: jest.fn(() => ({ data: [] })), // mock table and cardview to opt out of rendering them in these tests as there's no need Table: jest.fn(() => 'MockedTable'), CardView: jest.fn(() => 'MockedCardView'), @@ -58,22 +69,25 @@ jest.mock('react-query', () => ({ describe('PageContainer - Tests', () => { let queryClient: QueryClient; let history: History; + let user: UserEvent; + let cartItems: DownloadCartItem[]; + let holder: HTMLElement; - const createWrapper = ( + const renderComponent = ( h: History = history, client: QueryClient = queryClient - ): ReactWrapper => { + ): RenderResult => { const state: StateType = { dgcommon: dGCommonInitialState, dgdataview: dgDataViewInitialState, router: { action: 'POP', - location: createLocation('/'), + location: { ...createLocation('/'), query: {} }, }, }; const mockStore = configureStore([thunk]); const testStore = mockStore(state); - return mount( + return render( @@ -85,218 +99,254 @@ describe('PageContainer - Tests', () => { }; beforeEach(() => { - (axios.get as jest.Mock).mockImplementation((url: string) => { - if (url.includes('count')) { - return Promise.resolve({ data: 0 }); - } else { - return Promise.resolve({ data: [] }); - } - }); queryClient = new QueryClient(); history = createMemoryHistory({ initialEntries: ['/'], }); + user = userEvent.setup(); + + // @ts-expect-error we need it this way + delete window.location; + // @ts-expect-error we need it this way + window.location = new URL(`http://localhost/`); + + // below code keeps window.location in sync with history changes + // (needed because useUpdateQueryParam uses window.location not history) + const historyReplace = history.replace; + const historyReplaceSpy = jest.spyOn(history, 'replace'); + historyReplaceSpy.mockImplementation((args) => { + historyReplace(args); + if (typeof args === 'string') { + // @ts-expect-error we need it this way + window.location = new URL(`http://localhost${args}`); + } else { + // @ts-expect-error we need it this way + window.location = new URL(`http://localhost${createPath(args)}`); + } + }); + const historyPush = history.push; + const historyPushSpy = jest.spyOn(history, 'push'); + historyPushSpy.mockImplementation((args) => { + historyPush(args); + if (typeof args === 'string') { + // @ts-expect-error we need it this way + window.location = new URL(`http://localhost${args}`); + } else { + // @ts-expect-error we need it this way + window.location = new URL(`http://localhost${createPath(args)}`); + } + }); + + holder = document.createElement('div'); + holder.setAttribute('id', 'datagateway-search'); + document.body.appendChild(holder); + (useQueryClient as jest.Mock).mockReturnValue({ getQueryData: jest.fn(() => 0), }); + + (axios.get as jest.Mock).mockImplementation( + (url: string): Promise> => { + if (url.includes('count')) { + return Promise.resolve({ data: 0 }); + } + + if (url.includes('/user/cart')) { + return Promise.resolve({ + data: { cartItems }, + }); + } + + if (/.*\/\w+\/\d+$/.test(url)) { + // fetch entity information + return Promise.resolve({ + data: { + id: 1, + name: 'Name 1', + title: 'Title 1', + visitId: '1', + }, + }); + } + + return Promise.resolve({ data: [] }); + } + ); }); afterEach(() => { - (useCart as jest.Mock).mockClear(); + document.body.removeChild(holder); }); - it('displays the correct entity count', () => { + it('displays the correct entity count', async () => { history.replace(paths.toggle.investigation); (useQueryClient as jest.Mock).mockReturnValue({ getQueryData: jest.fn(() => 101), }); - const wrapper = createWrapper(); - - expect( - wrapper.find('[aria-label="view-count"]').first().find('h3').text() - ).toBe('app.results: 101'); - }); - - it('fetches cart on mount', () => { - (useCart as jest.Mock).mockReturnValueOnce({ - data: [ - { - entityId: 1, - entityType: 'dataset', - id: 1, - name: 'Test 1', - parentEntities: [], - }, - ], - }); - - createWrapper(); + renderComponent(); - expect(useCart).toHaveBeenCalled(); + expect(await screen.findByLabelText('view-count')).toHaveTextContent( + 'app.results: 101' + ); }); - it('opens search plugin when icon clicked', () => { - const wrapper = createWrapper(); + it('opens search plugin when icon clicked', async () => { + renderComponent(); - wrapper.find('[aria-label="view-search"]').first().simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'view-search' }) + ); expect(history.location.pathname).toBe('/search/data'); history.push('/browse/instrument'); - wrapper.find('[aria-label="view-search"]').first().simulate('click'); + + await user.click( + await screen.findByRole('button', { name: 'view-search' }) + ); expect(history.location.pathname).toBe('/search/isis'); history.push('/browse/proposal'); - wrapper.find('[aria-label="view-search"]').first().simulate('click'); + + await user.click( + await screen.findByRole('button', { name: 'view-search' }) + ); expect(history.location.pathname).toBe('/search/dls'); }); - it('opens download plugin when Download Cart clicked', () => { - const wrapper = createWrapper(); + it('opens download plugin when Download Cart clicked', async () => { + renderComponent(); - wrapper.find('[aria-label="app.cart_arialabel"]').first().simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'app.cart_arialabel' }) + ); expect(history.length).toBe(2); expect(history.location.pathname).toBe('/download'); }); - it('do not display loading bar loading false', () => { - const wrapper = createWrapper(); - - expect(wrapper.exists(LinearProgress)).toBeFalsy(); + it('do not display loading bar loading false', async () => { + renderComponent(); + await waitFor(() => { + expect(screen.queryByRole('progressbar')).toBeNull(); + }); }); - it('display loading bar when loading true', () => { - (useIsFetching as jest.Mock).mockReturnValueOnce(1); - const wrapper = createWrapper(); - - expect(wrapper.exists(LinearProgress)).toBeTruthy(); + it('display loading bar when loading true', async () => { + (useIsFetching as jest.Mock).mockReturnValue(1); + renderComponent(); + expect(await screen.findByRole('progressbar')).toBeInTheDocument(); + (useIsFetching as jest.Mock).mockReturnValue(0); }); - it('display clear filters button and clear for filters onClick', () => { + it('display clear filters button and clear for filters onClick', async () => { history.replace( '/browse/investigation?filters=%7B"title"%3A%7B"value"%3A"spend"%2C"type"%3A"include"%7D%7D' ); - const wrapper = createWrapper(); - - expect(wrapper.find(ClearFiltersButton).prop('disabled')).toEqual(false); + renderComponent(); - wrapper - .find('[data-testid="clear-filters-button"]') - .first() - .simulate('click'); - - wrapper.update(); + await user.click( + await screen.findByRole('button', { name: 'app.clear_filters' }) + ); - expect(wrapper.find(ClearFiltersButton).prop('disabled')).toEqual(true); + expect( + await screen.findByRole('button', { name: 'app.clear_filters' }) + ).toBeDisabled(); expect(history.location.search).toEqual('?'); }); - it('display clear filters button and clear for filters onClick (/my-data/DLS)', () => { + it('display clear filters button and clear for filters onClick (/my-data/DLS)', async () => { const dateNow = `${new Date(Date.now()).toISOString().split('T')[0]}`; history.replace( '/my-data/DLS?filters=%7B"startDate"%3A%7B"endDate"%3A" ' + dateNow + - '"%7D%2C"title"%3A%7B"value"%3A"test"%2C"type"%3A"include"%7D%7D&sort=%7B"startDate"%3A"desc"%7D' + '"%7D%2C"title"%3A%7B"value"%3A"test"%2C"type"%3A"include"%7D%7D&sort=%7B%22startDate%22%3A%22desc%22%7D' ); const response = { username: 'SomePerson' }; (readSciGatewayToken as jest.Mock).mockReturnValue(response); - const wrapper = createWrapper(); - - expect(wrapper.find(ClearFiltersButton).prop('disabled')).toEqual(false); - - wrapper - .find('[data-testid="clear-filters-button"]') - .first() - .simulate('click'); - - wrapper.update(); - - expect(wrapper.find(ClearFiltersButton).prop('disabled')).toEqual(true); + renderComponent(); + await user.click( + await screen.findByRole('button', { name: 'app.clear_filters' }) + ); + expect( + await screen.findByRole('button', { name: 'app.clear_filters' }) + ).toBeDisabled(); expect(history.location.search).toEqual( '?filters=%7B%22startDate%22%3A%7B%22endDate%22%3A%22' + dateNow + - '%22%7D%7D' + '%22%7D%7D&sort=%7B%22startDate%22%3A%22desc%22%7D' ); (readSciGatewayToken as jest.Mock).mockClear(); }); - it('display disabled clear filters button', () => { + it('display disabled clear filters button', async () => { history.replace(paths.toggle.investigation); - const wrapper = createWrapper(); + renderComponent(); - expect(wrapper.find(ClearFiltersButton).prop('disabled')).toEqual(true); + expect( + await screen.findByRole('button', { name: 'app.clear_filters' }) + ).toBeDisabled(); }); it('display filter warning on datafile table', async () => { history.replace('/browse/investigation/1/dataset/25/datafile'); (checkInvestigationId as jest.Mock).mockResolvedValueOnce(true); - const wrapper = createWrapper(); + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); expect( - wrapper.find('[aria-label="filter-message"]').first().text() - ).toEqual('loading.filter_message'); + await screen.findByText('loading.filter_message') + ).toBeInTheDocument(); }); - it('switches view button display name when clicked', () => { + it('switches view button display name when clicked', async () => { history.replace(paths.toggle.investigation); - const wrapper = createWrapper(); + renderComponent(); - expect( - wrapper.find('[aria-label="page view app.view_cards"]').exists() - ).toBeTruthy(); - expect( - wrapper.find('[aria-label="page view app.view_cards"]').first().text() - ).toEqual('app.view_cards'); - - // Click view button - wrapper - .find('[aria-label="page view app.view_cards"]') - .first() - .simulate('click'); - wrapper.update(); + await user.click( + await screen.findByRole('button', { name: 'page view app.view_cards' }) + ); // Check that the text on the button has changed expect( - wrapper.find('[aria-label="page view app.view_table"]').first().text() - ).toEqual('app.view_table'); + await screen.findByRole('button', { name: 'page view app.view_table' }) + ).toBeInTheDocument(); }); - it('displays role selector when on My Data route', () => { + it('displays role selector when on My Data route', async () => { history.replace(paths.myData.root); - const wrapper = createWrapper(); + renderComponent(); - expect(wrapper.find('#role-selector').exists()).toBeTruthy(); + expect( + await screen.findByRole('button', { name: 'my_data_table.role_selector' }) + ).toBeInTheDocument(); }); - it('display filter warning on toggle table', () => { + it('display filter warning on toggle table', async () => { history.replace(`${paths.toggle.investigation}?view=table`); - const wrapper = createWrapper(); + renderComponent(); - expect( - wrapper.find('[aria-label="filter-message"]').first().text() - ).toEqual('loading.filter_message'); + expect(await screen.findByLabelText('filter-message')).toHaveTextContent( + 'loading.filter_message' + ); }); - it('do not display filter warning on toggle card', () => { + it('do not display filter warning on toggle card', async () => { history.replace(`${paths.toggle.investigation}?view=card`); - const wrapper = createWrapper(); + renderComponent(); - expect(wrapper.exists('[aria-label="filter-message"]')).toBeFalsy(); + await waitFor(() => { + expect(screen.queryByLabelText('filter-message')).toBeNull(); + }); }); it('do not use StyledRouting component on landing pages', async () => { @@ -304,131 +354,135 @@ describe('PageContainer - Tests', () => { (useQueryClient as jest.Mock).mockReturnValue({ getQueryData: jest.fn(), }); - history.replace(`${paths.studyHierarchy.landing.isisStudyLanding}`); + history.replace( + `${paths.dataPublications.landing.isisDataPublicationLanding}` + ); - const wrapper = createWrapper(); + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - - expect(wrapper.exists('StyledRouting')).toBeFalsy(); + expect( + await screen.findByTestId('isis-dataPublication-landing') + ).toBeInTheDocument(); + expect(screen.queryByTestId('styled-routing')).toBeNull(); }); it('set view to card if cardview stored in localstorage', () => { localStorage.setItem('dataView', 'card'); history.replace(paths.toggle.investigation); - createWrapper(); + renderComponent(); expect(history.location.search).toBe('?view=card'); + + localStorage.removeItem('dataView'); }); - it('displays warning label when browsing data anonymously', () => { + it('displays warning label when browsing data anonymously', async () => { const response = { username: 'anon/anon' }; - (readSciGatewayToken as jest.Mock).mockReturnValueOnce(response); + (readSciGatewayToken as jest.Mock).mockReturnValue(response); - const wrapper = createWrapper(); + renderComponent(); expect( - wrapper.find('[aria-label="open-data-warning"]').exists() - ).toBeTruthy(); + await screen.findByLabelText('open-data-warning') + ).toBeInTheDocument(); }); - it('displays warning label when browsing study hierarchy', () => { - history.replace(paths.studyHierarchy.toggle.isisStudy); + it('displays warning label when browsing study hierarchy', async () => { + history.replace(paths.dataPublications.toggle.isisDataPublication); const response = { username: 'SomePerson' }; (readSciGatewayToken as jest.Mock).mockReturnValueOnce(response); - const wrapper = createWrapper(); + renderComponent(); expect( - wrapper.find('[aria-label="open-data-warning"]').exists() - ).toBeTruthy(); + await screen.findByLabelText('open-data-warning') + ).toBeInTheDocument(); }); - it('does not display warning label when logged in', () => { + it('does not display warning label when logged in', async () => { const response = { username: 'SomePerson' }; (readSciGatewayToken as jest.Mock).mockReturnValueOnce(response); - const wrapper = createWrapper(); + renderComponent(); - expect( - wrapper.find('[aria-label="open-data-warning"]').exists() - ).toBeFalsy(); + await waitFor(() => { + expect(screen.queryByLabelText('open-data-warning')).toBeNull(); + }); }); - it('shows SelectionAlert banner when item selected', () => { + it('shows SelectionAlert banner when item selected', async () => { // Supply data to make SelectionAlert display - (useCart as jest.Mock).mockReturnValueOnce({ - data: [ - { - entityId: 1, - entityType: 'dataset', - id: 1, - name: 'Test 1', - parentEntities: [], - }, - ], - }); - const wrapper = createWrapper(); + cartItems = [ + { + entityId: 1, + entityType: 'dataset', + id: 1, + name: 'Test 1', + parentEntities: [], + }, + ]; + renderComponent(); - expect(wrapper.exists('[aria-label="selection-alert"]')).toBeTruthy(); + expect(await screen.findByLabelText('selection-alert')).toBeInTheDocument(); }); - it('does not show SelectionAlert banner when no items are selected', () => { - (useCart as jest.Mock).mockReturnValueOnce({ - data: [], - }); - const wrapper = createWrapper(); + it('does not show SelectionAlert banner when no items are selected', async () => { + renderComponent(); - expect(wrapper.exists('[aria-label="selection-alert"]')).toBeFalsy(); + await waitFor(() => { + expect(screen.queryByLabelText('selection-alert')).toBeNull(); + }); }); - it('opens download plugin when link in SelectionAlert clicked', () => { + it('opens download plugin when link in SelectionAlert clicked', async () => { // Supply data to make SelectionAlert display - (useCart as jest.Mock).mockReturnValueOnce({ - data: [ - { - entityId: 1, - entityType: 'dataset', - id: 1, - name: 'Test 1', - parentEntities: [], - }, - ], - }); - const wrapper = createWrapper(); + cartItems = [ + { + entityId: 1, + entityType: 'dataset', + id: 1, + name: 'Test 1', + parentEntities: [], + }, + ]; + renderComponent(); - wrapper - .find('[aria-label="selection-alert-link"]') - .first() - .simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'selection-alert-link' }) + ); expect(history.location.pathname).toBe('/download'); }); - it('passes correct landing page entities to breadcrumbs', () => { - history.replace(paths.toggle.isisInvestigation); - let wrapper = createWrapper(); + it('shows breadcrumb according to the current path', async () => { + history.replace('/browse/instrument/1/facilityCycle/1/investigation'); + renderComponent(); - expect( - wrapper.find('PageBreadcrumbs').prop('landingPageEntities') - ).toEqual(['investigation', 'dataset']); + expect(await screen.findByText('breadcrumbs.home')).toBeInTheDocument(); + const baseBreadcrumb = screen.getByTestId('Breadcrumb-base'); + expect(baseBreadcrumb).toHaveAttribute('href', '/browse/instrument'); + expect(baseBreadcrumb).toHaveTextContent('breadcrumbs.instrument'); - history.replace(paths.studyHierarchy.toggle.isisInvestigation); - wrapper = createWrapper(); + const breadcrumbs = screen.getAllByTestId(/^Breadcrumb-hierarchy-\d+$/); + expect(breadcrumbs[0]).toHaveAttribute( + 'href', + '/browse/instrument/1/facilityCycle' + ); + expect(within(breadcrumbs[0]).getByText('Name 1')).toBeInTheDocument(); + expect(within(breadcrumbs[1]).getByText('Name 1')).toBeInTheDocument(); expect( - wrapper.find('PageBreadcrumbs').prop('landingPageEntities') - ).toEqual(['study', 'investigation', 'dataset']); + within(screen.getByTestId('Breadcrumb-last')).getByText( + 'breadcrumbs.investigation' + ) + ).toBeInTheDocument(); }); it('does not fetch cart when on homepage (cart request errors when user is viewing homepage unauthenticated)', () => { history.replace(paths.homepage); - createWrapper(); + renderComponent(); - expect(useCart).not.toHaveBeenCalled(); + expect(axios.get).not.toHaveBeenCalledWith('/user/cart'); }); }); diff --git a/packages/datagateway-dataview/src/page/pageContainer.component.tsx b/packages/datagateway-dataview/src/page/pageContainer.component.tsx index 2497fbe9a..af6cbc8bb 100644 --- a/packages/datagateway-dataview/src/page/pageContainer.component.tsx +++ b/packages/datagateway-dataview/src/page/pageContainer.component.tsx @@ -4,15 +4,11 @@ import { Paper, Typography, Theme, - withStyles, - createStyles, IconButton, - makeStyles, -} from '@material-ui/core'; - -import SearchIcon from '@material-ui/icons/Search'; -import InfoIcon from '@material-ui/icons/Info'; -import { StyleRules } from '@material-ui/core/styles'; + styled, +} from '@mui/material'; +import SearchIcon from '@mui/icons-material/Search'; +import InfoIcon from '@mui/icons-material/Info'; import { Sticky, ViewsType, @@ -36,6 +32,7 @@ import { useLocation, useHistory, useRouteMatch, + matchPath, } from 'react-router-dom'; import PageBreadcrumbs from './breadcrumbs.component'; import PageRouting from './pageRouting.component'; @@ -45,62 +42,45 @@ import DoiRedirect from './doiRedirect.component'; import RoleSelector from '../views/roleSelector.component'; import { useIsFetching, useQueryClient } from 'react-query'; -const usePaperStyles = makeStyles( - (theme: Theme) => - createStyles({ - cardPaper: { backgroundColor: 'inherit' }, - tablePaper: { - height: ({ tablePaperHeight }) => tablePaperHeight, - width: '100%', - minHeight: 500, - backgroundColor: 'inherit', - overflowX: 'auto', - }, - tablePaperMessage: { - //Footer is 36px - height: 'calc(100vh - 244px - 4rem - 36px)', - width: '100%', - backgroundColor: 'inherit', - overflowX: 'auto', - }, - noResultsPaper: { - padding: theme.spacing(2), - marginTop: theme.spacing(2), - marginBottom: theme.spacing(2), - marginLeft: 'auto', - marginRight: 'auto', - maxWidth: '960px', - }, - }) -); - -const useNavBarStyles = makeStyles( - (theme: Theme): StyleRules => - createStyles({ - openDataPaper: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - backgroundColor: (theme as any).colours?.warning, - display: 'flex', - flexDirection: 'column', - paddingLeft: 0, - paddingRight: 20, - justifyContent: 'center', - }, - openDataInfoIcon: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - color: (theme as any).colours?.information, - }, - }) -); - -const gridStyles = (theme: Theme): StyleRules => - createStyles({ - root: { - backgroundColor: theme.palette.background.default, - }, - }); +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +const getTablePaperStyle = ( + displayFilterMessage: boolean, + tablePaperHeight: string +) => { + return { + height: displayFilterMessage + ? 'calc(100vh - 244px - 4rem - 36px)' // Footer is 36px + : tablePaperHeight, + width: '100%', + backgroundColor: 'inherit', + overflowX: 'auto', + }; +}; -const StyledGrid = withStyles(gridStyles)(Grid); +const cardPaperStyle = { backgroundColor: 'inherit' }; + +const NoResultsPaper = styled(Paper)(({ theme }) => ({ + padding: theme.spacing(2), + marginTop: theme.spacing(2), + marginBottom: theme.spacing(2), + marginLeft: 'auto', + marginRight: 'auto', + maxWidth: '960px', +})); + +const OpenDataPaper = styled(Paper)(({ theme }) => ({ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + backgroundColor: (theme as any).colours?.warning, + display: 'flex', + flexDirection: 'column', + paddingLeft: 0, + paddingRight: 20, + justifyContent: 'center', +})); + +const StyledGrid = styled(Grid)(({ theme }) => ({ + backgroundColor: theme.palette.background.default, +})); // Define all the supported paths for data-view. export const paths = { @@ -140,51 +120,59 @@ export const paths = { dlsDatafile: '/browse/proposal/:proposalName/investigation/:investigationId/dataset/:datasetId/datafile', }, - studyHierarchy: { - root: '/browseStudyHierarchy', + dataPublications: { + root: '/browseDataPublications', toggle: { - isisInstrument: '/browseStudyHierarchy/instrument', - isisStudy: '/browseStudyHierarchy/instrument/:instrumentId/study', - isisInvestigation: - '/browseStudyHierarchy/instrument/:instrumentId/study/:studyId/investigation', + isisInstrument: '/browseDataPublications/instrument', + isisStudyDataPublication: + '/browseDataPublications/instrument/:instrumentId/dataPublication', + isisInvestigationDataPublication: + '/browseDataPublications/instrument/:instrumentId/dataPublication/:studyDataPublicationId/investigation', + isisDataPublication: + '/browseDataPublications/instrument/:instrumentId/dataPublication', isisDataset: - '/browseStudyHierarchy/instrument/:instrumentId/study/:studyId/investigation/:investigationId/dataset', + '/browseDataPublications/instrument/:instrumentId/dataPublication/:dataPublicationId/investigation/:investigationId/dataset', }, standard: { isisDatafile: - '/browseStudyHierarchy/instrument/:instrumentId/study/:studyId/investigation/:investigationId/dataset/:datasetId/datafile', + '/browseDataPublications/instrument/:instrumentId/dataPublication/:dataPublicationId/investigation/:investigationId/dataset/:datasetId/datafile', }, landing: { - isisStudyLanding: - '/browseStudyHierarchy/instrument/:instrumentId/study/:studyId', + isisDataPublicationLanding: + '/browseDataPublications/instrument/:instrumentId/dataPublication/:dataPublicationId', isisInvestigationLanding: - '/browseStudyHierarchy/instrument/:instrumentId/study/:studyId/investigation/:investigationId', + '/browseDataPublications/instrument/:instrumentId/dataPublication/:dataPublicationId/investigation/:investigationId', isisDatasetLanding: - '/browseStudyHierarchy/instrument/:instrumentId/study/:studyId/investigation/:investigationId/dataset/:datasetId', + '/browseDataPublications/instrument/:instrumentId/dataPublication/:dataPublicationId/investigation/:investigationId/dataset/:datasetId', }, }, + // defines routes for datafile previews + preview: { + isisDatafilePreview: + '/browse/instrument/:instrumentId/facilityCycle/:facilityCycleId/investigation/:investigationId/dataset/:datasetId/datafile/:datafileId', + isisDataPublicationDatafilePreview: + '/browseDataPublications/instrument/:instrumentId/dataPublication/:dataPublicationId/investigation/:investigationId/dataset/:datasetId/datafile/:datafileId', + }, }; const togglePaths = Object.values(paths.toggle).concat( - Object.values(paths.studyHierarchy.toggle) + Object.values(paths.dataPublications.toggle) ); // ISIS base paths - required for linking to correct search view const isisPaths = [ paths.myData.isis, paths.toggle.isisInstrument, - paths.studyHierarchy.root, + paths.dataPublications.root, ]; // DLS base paths - required for linking to correct search view const dlsPaths = [paths.myData.dls, paths.toggle.dlsProposal]; -const BlackTextTypography = withStyles({ - root: { - color: '#000000', - fontSize: '16px', - }, -})(Typography); +const BlackTextTypography = styled(Typography)({ + color: '#000000', + fontSize: '16px', +}); const NavBar = React.memo( ( @@ -195,15 +183,14 @@ const NavBar = React.memo( } & CartProps ): React.ReactElement => { const [t] = useTranslation(); - const classes = useNavBarStyles(); - const isStudyHierarchy = + const isDataPublication = useRouteMatch([ - ...Object.values(paths.studyHierarchy.toggle), - ...Object.values(paths.studyHierarchy.standard), + ...Object.values(paths.dataPublications.toggle), + ...Object.values(paths.dataPublications.standard), ]) !== null; const isISISRoute = useRouteMatch(isisPaths) !== null; - const landingPages = isStudyHierarchy - ? paths.studyHierarchy.landing + const landingPages = isDataPublication + ? paths.dataPublications.landing : isISISRoute ? paths.landing : []; @@ -222,28 +209,29 @@ const NavBar = React.memo( aria-label="page-breadcrumbs" > {/* don't show breadcrumbs on /my-data - only on browse */} - + - {props.loggedInAnonymously || isStudyHierarchy ? ( + {props.loggedInAnonymously || isDataPublication ? ( - + - {isStudyHierarchy - ? t('app.open_data_warning.studies_tooltip') + {isDataPublication + ? t( + 'app.open_data_warning.datapublications_tooltip' + ) : t('app.open_data_warning.tooltip')}

@@ -260,9 +248,16 @@ const NavBar = React.memo( > - + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (theme as any).colours?.information, + }} + />
@@ -272,7 +267,7 @@ const NavBar = React.memo(
- + ) : null} @@ -283,14 +278,14 @@ const NavBar = React.memo( path={Object.values(paths.myData).concat( Object.values(paths.toggle), Object.values(paths.standard), - Object.values(paths.studyHierarchy.toggle), - Object.values(paths.studyHierarchy.standard) + Object.values(paths.dataPublications.toggle), + Object.values(paths.dataPublications.standard) )} render={() => { return ( bar to push the page down so subtract the height of this (4px if on-screen) // Additional rows of breadcrumbs also push the page down so subtract the height of the breadcrumb div - const tablePaperHeight = `calc(100vh - 180px - 36px - 1px - ${linearProgressHeight} - ${breadcrumbHeight})`; + const tablePaperHeight = `calc(100vh - 152px - 36px - 1px - ${linearProgressHeight} - ${breadcrumbHeight})`; const [t] = useTranslation(); - const paperClasses = usePaperStyles({ tablePaperHeight }); - const tableClassName = displayFilterMessage - ? paperClasses.tablePaperMessage - : paperClasses.tablePaper; + const tableClassStyle = getTablePaperStyle( + displayFilterMessage, + tablePaperHeight + ); return ( -
+
{viewStyle !== 'card' && displayFilterMessage && ( - + {t('loading.filter_message')} - + )} {/* For "landing" paths, don't use a containing Paper */} ( { const location = useLocation(); const { push } = useHistory(); const prevLocationRef = React.useRef(location); - const { view } = React.useMemo(() => parseSearchToQuery(location.search), [ - location.search, - ]); + const { view } = React.useMemo( + () => parseSearchToQuery(location.search), + [location.search] + ); const [totalDataCount, setTotalDataCount] = React.useState(0); // exclude size and count queries from showing the linear progress bar for performance @@ -625,9 +629,10 @@ const DataviewPageContainer: React.FC = () => { const username = readSciGatewayToken().username; const loggedInAnonymously = username === null || username === 'anon/anon'; - const { filters } = React.useMemo(() => parseSearchToQuery(location.search), [ - location.search, - ]); + const { filters } = React.useMemo( + () => parseSearchToQuery(location.search), + [location.search] + ); const dlsDefaultFilters = { startDate: { @@ -687,8 +692,8 @@ const DataviewPageContainer: React.FC = () => { path={Object.values(paths.myData).concat( Object.values(paths.toggle), Object.values(paths.standard), - Object.values(paths.studyHierarchy.toggle), - Object.values(paths.studyHierarchy.standard) + Object.values(paths.dataPublications.toggle), + Object.values(paths.dataPublications.standard) )} render={() => ( { - let mount; let state: StateType; let history: History; - const createTableWrapper = ( - path: string, - loggedInAnonymously?: boolean - ): ReactWrapper => { + function Wrapper({ children }: { children: React.ReactNode }): JSX.Element { const mockStore = configureStore([thunk]); - const client = new QueryClient(); - history.push(path); - return mount( - - - - - - - - ); - }; - - const createCardWrapper = (path: string): ReactWrapper => { - const mockStore = configureStore([thunk]); - const client = new QueryClient(); - history.push(path); - return mount( - - - - - - - - ); - }; - - const createLandingWrapper = (path: string): ReactWrapper => { - const mockStore = configureStore([thunk]); - const client = new QueryClient(); - history.push(path); - return mount( + const client = new QueryClient({ + defaultOptions: { + queries: { retry: false }, + }, + }); + return ( - - - + {children} ); - }; + } beforeEach(() => { - mount = createMount(); history = createMemoryHistory(); state = JSON.parse( @@ -184,23 +125,43 @@ describe('PageTable', () => { (axios.get as jest.Mock).mockImplementation((url: string) => { if (url.includes('count')) { return Promise.resolve({ data: 0 }); + } else if (url.includes('datapublications')) { + // this is so that routes can convert from data pub id -> investigation id + return Promise.resolve({ + data: [ + { + id: 1, + pid: 'pid.1', + title: 'test', + content: { + id: 2, + dataCollectionInvestigations: [ + { + id: 3, + investigation: { + id: 4, + title: 'Test', + name: 'test', + visitId: '1', + }, + }, + ], + }, + } satisfies DataPublication, + ], + }); } else { return Promise.resolve({ data: [] }); } }); - (checkInstrumentAndFacilityCycleId as jest.Mock).mockImplementation(() => - Promise.resolve(true) - ); - (checkInstrumentId as jest.Mock).mockImplementation(() => - Promise.resolve(true) - ); - (checkStudyId as jest.Mock).mockImplementation(() => Promise.resolve(true)); - (checkInvestigationId as jest.Mock).mockImplementation(() => - Promise.resolve(true) - ); - (checkProposalName as jest.Mock).mockImplementation(() => + checkInstrumentAndFacilityCycleId.mockImplementation(() => Promise.resolve(true) ); + checkInstrumentId.mockImplementation(() => Promise.resolve(true)); + checkStudyDataPublicationId.mockImplementation(() => Promise.resolve(true)); + checkInvestigationId.mockImplementation(() => Promise.resolve(true)); + checkProposalName.mockImplementation(() => Promise.resolve(true)); + checkDatasetId.mockImplementation(() => Promise.resolve(true)); }); afterEach(() => { @@ -209,506 +170,1269 @@ describe('PageTable', () => { describe('Generic', () => { it('renders PageTable correctly', () => { - const wrapper = createTableWrapper('/'); - expect(wrapper.exists(Link)).toBe(true); + history.push('/'); + + render( + , + { + wrapper: Wrapper, + } + ); + + expect( + screen.getByRole('link', { name: 'Browse investigations' }) + ).toHaveAttribute('href', '/browse/investigation'); }); it('renders PageCard correctly', () => { - const wrapper = createCardWrapper('/'); - expect(wrapper.exists(Link)).toBe(true); + history.push('/'); + + render( + , + { wrapper: Wrapper } + ); + + expect( + screen.getByRole('link', { name: 'Browse investigations' }) + ).toHaveAttribute('href', '/browse/investigation?view=card'); }); - it('renders InvestigationTable for generic investigations route', () => { - const wrapper = createTableWrapper(genericRoutes['investigations']); - expect(wrapper.exists(InvestigationTable)).toBe(true); + it('renders InvestigationTable for generic investigations route', async () => { + history.push(genericRoutes['investigations']); + + render( + , + { + wrapper: Wrapper, + } + ); + + expect( + await findColumnHeaderByName('investigations.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.visit_id') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.doi') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.instrument') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.end_date') + ).toBeInTheDocument(); }); - it('renders InvestigationCardView for generic investigations route', () => { - const wrapper = createCardWrapper(genericRoutes['investigations']); - expect(wrapper.exists(InvestigationCardView)).toBe(true); + it('renders InvestigationCardView for generic investigations route', async () => { + history.push(genericRoutes.investigations); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await screen.findByTestId('investigation-card-view') + ).toBeInTheDocument(); }); - it('renders DatasetTable for generic datasets route', () => { - const wrapper = createTableWrapper(genericRoutes['datasets']); - expect(wrapper.exists(DatasetTable)).toBe(true); + it('renders DatasetTable for generic datasets route', async () => { + history.push(genericRoutes['datasets']); + + render( + , + { + wrapper: Wrapper, + } + ); + + expect(await findColumnHeaderByName('datasets.name')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.datafile_count') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.create_time') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.modified_time') + ).toBeInTheDocument(); }); - it('renders DatasetCardView for generic datasets route', () => { - const wrapper = createCardWrapper(genericRoutes['datasets']); - expect(wrapper.exists(DatasetCardView)).toBe(true); + it('renders DatasetCardView for generic datasets route', async () => { + history.push(genericRoutes.datasets); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await screen.findByTestId('dataset-card-view') + ).toBeInTheDocument(); }); it('renders DatafileTable for generic datafiles route', async () => { - const wrapper = createTableWrapper(genericRoutes['datafiles']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(DatafileTable)).toBe(true); + history.push(genericRoutes['datafiles']); + + render( + , + { + wrapper: Wrapper, + } + ); + + expect( + await findColumnHeaderByName('datafiles.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.location') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.modified_time') + ).toBeInTheDocument(); }); it('does not render DatafileTable for incorrect generic datafiles route', async () => { - (checkInvestigationId as jest.Mock).mockImplementation(() => - Promise.resolve(false) + checkInvestigationId.mockImplementation(() => Promise.resolve(false)); + history.push(genericRoutes['datafiles']); + + render( + , + { + wrapper: Wrapper, + } ); - const wrapper = createTableWrapper(genericRoutes['datafiles']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(DatafileTable)).toBe(false); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); }); describe('ISIS', () => { - it('renders ISISMyDataTable for ISIS my data route', () => { - const wrapper = createTableWrapper(ISISRoutes['mydata'], false); - expect(wrapper.exists(ISISMyDataTable)).toBe(true); + it('renders ISISMyDataTable for ISIS my data route', async () => { + history.push(ISISRoutes['mydata']); + + render( + , + { + wrapper: Wrapper, + } + ); + + expect( + await findColumnHeaderByName('investigations.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.doi') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.visit_id') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.instrument') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.end_date') + ).toBeInTheDocument(); }); it('redirects to login page when not signed in (ISISMyDataTable) ', () => { - const wrapper = createTableWrapper(ISISRoutes['mydata'], true); - expect(wrapper.exists(ISISMyDataTable)).toBe(false); - expect(history.length).toBe(2); + history.push(ISISRoutes['mydata']); + + render( + , + { + wrapper: Wrapper, + } + ); + expect(history.location.pathname).toBe('/login'); }); - it('renders ISISInstrumentsTable for ISIS instruments route', () => { - const wrapper = createTableWrapper(ISISRoutes['instruments']); - expect(wrapper.exists(ISISInstrumentsTable)).toBe(true); + it('renders ISISInstrumentsTable for ISIS instruments route', async () => { + history.push(ISISRoutes['instruments']); + + render( + , + { + wrapper: Wrapper, + } + ); + + expect( + await findColumnHeaderByName('instruments.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('instruments.type') + ).toBeInTheDocument(); }); - it('renders ISISInstrumentsCardView for ISIS instruments route', () => { - const wrapper = createCardWrapper(ISISRoutes['instruments']); - expect(wrapper.exists(ISISInstrumentsCardView)).toBe(true); + it('renders ISISInstrumentsCardView for ISIS instruments route', async () => { + history.push(ISISRoutes.instruments); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await screen.findByTestId('isis-instruments-card-view') + ).toBeInTheDocument(); }); - it('renders ISISFacilityCyclesTable for ISIS facilityCycles route', () => { - const wrapper = createTableWrapper(ISISRoutes['facilityCycles']); - expect(wrapper.exists(ISISFacilityCyclesTable)).toBe(true); + it('renders ISISFacilityCyclesTable for ISIS facilityCycles route', async () => { + history.push(ISISRoutes['facilityCycles']); + + render( + , + { + wrapper: Wrapper, + } + ); + + expect( + await findColumnHeaderByName('facilitycycles.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('facilitycycles.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('facilitycycles.end_date') + ).toBeInTheDocument(); }); - it('renders ISISFacilityCyclesCardView for ISIS facilityCycles route', () => { - const wrapper = createCardWrapper(ISISRoutes['facilityCycles']); - expect(wrapper.exists(ISISFacilityCyclesCardView)).toBe(true); + it('renders ISISFacilityCyclesCardView for ISIS facilityCycles route', async () => { + history.push(ISISRoutes.facilityCycles); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await screen.findByTestId('isis-facility-card-view') + ).toBeInTheDocument(); }); - it('renders ISISInvestigationsTable for ISIS investigations route', () => { - const wrapper = createTableWrapper(ISISRoutes['investigations']); - expect(wrapper.exists(ISISInvestigationsTable)).toBe(true); + it('renders ISISInvestigationsTable for ISIS investigations route', async () => { + history.push(ISISRoutes['investigations']); + + render( + , + { + wrapper: Wrapper, + } + ); + + expect( + await findColumnHeaderByName('investigations.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.doi') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.principal_investigators') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.end_date') + ).toBeInTheDocument(); }); - it('renders ISISInvestigationsCardView for ISIS investigations route', () => { - const wrapper = createCardWrapper(ISISRoutes['investigations']); - expect(wrapper.exists(ISISInvestigationsCardView)).toBe(true); + it('renders ISISInvestigationsCardView for ISIS investigations route', async () => { + history.push(ISISRoutes.investigations); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await screen.findByTestId('isis-investigations-card-view') + ).toBeInTheDocument(); }); it('renders ISISInvestigationLanding for ISIS investigation route', async () => { - const wrapper = createLandingWrapper( - ISISRoutes['landing']['investigation'] + history.push(ISISRoutes['landing']['investigation']); + + render( + , + { + wrapper: Wrapper, + } ); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISInvestigationLanding)).toBe(true); + + expect( + await screen.findByLabelText('branding-title') + ).toBeInTheDocument(); }); it('does not render ISISInvestigationLanding for incorrect ISIS investigation route', async () => { - (checkInstrumentAndFacilityCycleId as jest.Mock).mockImplementation(() => + checkInstrumentAndFacilityCycleId.mockImplementation(() => Promise.resolve(false) ); - const wrapper = createLandingWrapper( - ISISRoutes['landing']['investigation'] + + history.push(ISISRoutes.landing.investigation); + + render( + , + { wrapper: Wrapper } ); + await act(async () => { await flushPromises(); - wrapper.update(); }); - expect(wrapper.exists(ISISInvestigationLanding)).toBe(false); + + expect(screen.getByText('loading.oops')).toBeInTheDocument(); }); it('renders ISISDatasetsTable for ISIS datasets route', async () => { - const wrapper = createTableWrapper(ISISRoutes['datasets']); + history.push(ISISRoutes.datasets); + + render( + , + { wrapper: Wrapper } + ); + await act(async () => { await flushPromises(); - wrapper.update(); }); - expect(wrapper.exists(ISISDatasetsTable)).toBe(true); + + expect(await findColumnHeaderByName('datasets.name')).toBeInTheDocument(); + expect(await findColumnHeaderByName('datasets.size')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.create_time') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.modified_time') + ).toBeInTheDocument(); }); it('does not render ISISDatasetsTable for incorrect ISIS datasets route', async () => { - (checkInstrumentAndFacilityCycleId as jest.Mock).mockImplementation(() => + checkInstrumentAndFacilityCycleId.mockImplementation(() => Promise.resolve(false) ); - const wrapper = createTableWrapper(ISISRoutes['datasets']); + + history.push(ISISRoutes.datasets); + + render( + , + { wrapper: Wrapper } + ); + await act(async () => { await flushPromises(); - wrapper.update(); }); - expect(wrapper.exists(ISISDatasetsTable)).toBe(false); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); it('renders ISISDatasetsCardview for ISIS datasets route', async () => { - const wrapper = createCardWrapper(ISISRoutes['datasets']); + history.push(ISISRoutes.datasets); + + render( + , + { wrapper: Wrapper } + ); + await act(async () => { await flushPromises(); - wrapper.update(); }); - expect(wrapper.exists(ISISDatasetsCardView)).toBe(true); + + expect(screen.getByTestId('isis-datasets-card-view')).toBeInTheDocument(); }); it('does not render ISISDatasetsCardView for incorrect ISIS datasets route', async () => { - (checkInstrumentAndFacilityCycleId as jest.Mock).mockImplementation(() => + checkInstrumentAndFacilityCycleId.mockImplementation(() => Promise.resolve(false) ); - const wrapper = createCardWrapper(ISISRoutes['datasets']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISDatasetsCardView)).toBe(false); + + history.push(ISISRoutes.datasets); + + render( + , + { wrapper: Wrapper } + ); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); it('renders ISISDatasetLanding for ISIS dataset route', async () => { - const wrapper = createLandingWrapper(ISISRoutes['landing']['dataset']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISDatasetLanding)).toBe(true); + history.push(ISISRoutes.landing.dataset); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await screen.findByTestId('isis-dataset-landing') + ).toBeInTheDocument(); }); it('does not render ISISDatasetLanding for incorrect ISIS dataset route', async () => { - (checkInstrumentAndFacilityCycleId as jest.Mock).mockImplementation(() => + checkInstrumentAndFacilityCycleId.mockImplementation(() => Promise.resolve(false) ); - const wrapper = createLandingWrapper(ISISRoutes['landing']['dataset']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISDatasetLanding)).toBe(false); + + history.push(ISISRoutes.landing.dataset); + + render( + , + { wrapper: Wrapper } + ); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); it('renders ISISDatafilesTable for ISIS datafiles route', async () => { - const wrapper = createTableWrapper(ISISRoutes['datafiles']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISDatafilesTable)).toBe(true); + history.push(ISISRoutes.datafiles); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await findColumnHeaderByName('datafiles.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.location') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.modified_time') + ).toBeInTheDocument(); }); it('does not render ISISDatafilesTable for incorrect ISIS datafiles route', async () => { - (checkInstrumentAndFacilityCycleId as jest.Mock).mockImplementation(() => + checkInstrumentAndFacilityCycleId.mockImplementation(() => Promise.resolve(false) ); - (checkInvestigationId as jest.Mock).mockImplementation(() => + checkInvestigationId.mockImplementation(() => Promise.resolve(false)); + + history.push(ISISRoutes.datafiles); + + render( + , + { wrapper: Wrapper } + ); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); + }); + + it('renders DatafilePreviewer for ISIS datafiles previewer route', async () => { + history.push(ISISRoutes.datafilePreview); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await screen.findByText('datafiles.preview.invalid_datafile') + ).toBeInTheDocument(); + }); + + it('does not render DatafilePreviewer for incorrect ISIS datafiles previewer route', async () => { + checkInstrumentAndFacilityCycleId.mockImplementation(() => Promise.resolve(false) ); - const wrapper = createTableWrapper(ISISRoutes['datafiles']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISDatafilesTable)).toBe(false); + checkInvestigationId.mockImplementation(() => Promise.resolve(false)); + checkDatasetId.mockImplementation(() => Promise.resolve(false)); + + history.push(ISISRoutes.datafilePreview); + + render( + , + { wrapper: Wrapper } + ); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); }); - describe('ISIS Study Hierarchy', () => { - it('renders ISISInstrumentsTable for ISIS instruments route in Study Hierarchy', () => { - const wrapper = createTableWrapper( - ISISStudyHierarchyRoutes['instruments'] + describe('ISIS Data Publication Hierarchy', () => { + it('renders ISISInstrumentsTable for ISIS instruments route in Data Publication Hierarchy', async () => { + history.push(ISISDataPublicationsRoutes.instruments); + + render( + , + { wrapper: Wrapper } ); - expect(wrapper.exists(ISISInstrumentsTable)).toBe(true); + + expect( + await findColumnHeaderByName('instruments.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('instruments.type') + ).toBeInTheDocument(); }); - it('renders ISISInstrumentsCardView for ISIS instruments route in Study Hierarchy', () => { - const wrapper = createCardWrapper( - ISISStudyHierarchyRoutes['instruments'] + it('renders ISISInstrumentsCardView for ISIS instruments route in Data Publication Hierarchy', async () => { + history.push(ISISDataPublicationsRoutes.instruments); + + render( + , + { wrapper: Wrapper } ); - expect(wrapper.exists(ISISInstrumentsCardView)).toBe(true); - }); - it('renders ISISStudiesTable for ISIS studies route in Study Hierarchy', () => { - const wrapper = createTableWrapper(ISISStudyHierarchyRoutes['studies']); - expect(wrapper.exists(ISISStudiesTable)).toBe(true); + expect( + await screen.findByTestId('isis-instruments-card-view') + ).toBeInTheDocument(); }); - it('renders ISISStudiesCardView for ISIS studies route in Study Hierarchy', () => { - const wrapper = createCardWrapper(ISISStudyHierarchyRoutes['studies']); - expect(wrapper.exists(ISISStudiesCardView)).toBe(true); + it('renders ISISDataPublicationsTable for ISIS dataPublications route in Data Publication Hierarchy', async () => { + history.push(ISISDataPublicationsRoutes['dataPublications']); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await findColumnHeaderByName('datapublications.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datapublications.pid') + ).toBeInTheDocument(); }); - it('renders ISISStudyLanding for ISIS study route for studyHierarchy', async () => { - const wrapper = createLandingWrapper( - ISISStudyHierarchyRoutes['landing']['study'] + it('renders ISISDataPublicationsCardView for ISIS dataPublications route in Data Publication Hierarchy', async () => { + history.push(ISISDataPublicationsRoutes.dataPublications); + + render( + , + { wrapper: Wrapper } ); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISStudyLanding)).toBe(true); + + expect( + await screen.findByTestId('isis-dataPublications-card-view') + ).toBeInTheDocument(); }); - it('does not render ISISStudyLanding for incorrect ISIS study route for studyHierarchy', async () => { - (checkInstrumentId as jest.Mock).mockImplementation(() => - Promise.resolve(false) + it('renders ISISDataPublicationLanding for ISIS dataPublications route for Data Publication Hierarchy', async () => { + history.push(ISISDataPublicationsRoutes.landing.dataPublication); + + render( + , + { wrapper: Wrapper } ); - const wrapper = createLandingWrapper( - ISISStudyHierarchyRoutes['landing']['study'] + + expect( + await screen.findByTestId('isis-dataPublication-landing') + ).toBeInTheDocument(); + }); + + it('does not render ISISDataPublicationLanding for incorrect ISIS dataPublications route for Data Publication Hierarchy', async () => { + checkInstrumentId.mockImplementation(() => Promise.resolve(false)); + + history.push(ISISDataPublicationsRoutes.landing.dataPublication); + + render( + , + { wrapper: Wrapper } ); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISStudyLanding)).toBe(false); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); - it('renders ISISInvestigationsTable for ISIS investigations route in Study Hierarchy', () => { - const wrapper = createTableWrapper( - ISISStudyHierarchyRoutes['investigations'] + it('renders ISISInvestigationsTable for ISIS investigations route in Data Publication Hierarchy', async () => { + history.push(ISISDataPublicationsRoutes.investigations); + + render( + , + { wrapper: Wrapper } ); - expect(wrapper.exists(ISISInvestigationsTable)).toBe(true); + + expect( + await findColumnHeaderByName('datapublications.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datapublications.pid') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datapublications.publication_date') + ).toBeInTheDocument(); }); - it('renders ISISInvestigationsCardView for ISIS investigations route in Study Hierarchy', () => { - const wrapper = createCardWrapper( - ISISStudyHierarchyRoutes['investigations'] + it('renders ISISInvestigationsCardView for ISIS investigations route in Data Publication Hierarchy', async () => { + history.push(ISISDataPublicationsRoutes.investigations); + + render( + , + { wrapper: Wrapper } ); - expect(wrapper.exists(ISISInvestigationsCardView)).toBe(true); + + expect( + await screen.findByTestId('isis-dataPublications-card-view') + ).toBeInTheDocument(); }); - it('renders ISISDatasetsTable for ISIS datasets route in Study Hierarchy', async () => { - const wrapper = createTableWrapper(ISISStudyHierarchyRoutes['datasets']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISDatasetsTable)).toBe(true); + it('renders ISISDatasetsTable for ISIS datasets route in Data Publication Hierarchy', async () => { + history.push(ISISDataPublicationsRoutes.datasets); + + render( + , + { wrapper: Wrapper } + ); + + expect(await findColumnHeaderByName('datasets.name')).toBeInTheDocument(); + expect(await findColumnHeaderByName('datasets.size')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.create_time') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.modified_time') + ).toBeInTheDocument(); }); - it('does not render ISISDatasetsTable for incorrect ISIS datasets route in Study Hierarchy', async () => { - (checkInstrumentId as jest.Mock).mockImplementation(() => + it('does not render ISISDatasetsTable for incorrect ISIS datasets route in Data Publication Hierarchy', async () => { + checkInstrumentId.mockImplementation(() => Promise.resolve(false)); + checkStudyDataPublicationId.mockImplementation(() => Promise.resolve(false) ); - (checkStudyId as jest.Mock).mockImplementation(() => - Promise.resolve(false) + + history.push(ISISDataPublicationsRoutes.datasets); + + render( + , + { wrapper: Wrapper } ); - const wrapper = createTableWrapper(ISISStudyHierarchyRoutes['datasets']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISDatasetsTable)).toBe(false); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); - it('renders ISISInvestigationLanding for ISIS investigation route for studyHierarchy', async () => { - const wrapper = createLandingWrapper( - ISISStudyHierarchyRoutes['landing']['investigation'] + it('renders ISISInvestigationLanding for ISIS investigation route for Data Publication Hierarchy', async () => { + history.push(ISISDataPublicationsRoutes.landing.investigation); + + render( + , + { wrapper: Wrapper } ); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISInvestigationLanding)).toBe(true); + + expect( + await screen.findByTestId('isis-investigation-landing') + ).toBeInTheDocument(); }); - it('does not render ISISInvestigationLanding for incorrect ISIS investigation route for studyHierarchy', async () => { - (checkInstrumentId as jest.Mock).mockImplementation(() => - Promise.resolve(false) - ); - (checkStudyId as jest.Mock).mockImplementation(() => + it('does not render ISISInvestigationLanding for incorrect ISIS investigation route for Data Publication Hierarchy', async () => { + checkInstrumentId.mockImplementation(() => Promise.resolve(false)); + checkStudyDataPublicationId.mockImplementation(() => Promise.resolve(false) ); - const wrapper = createLandingWrapper( - ISISStudyHierarchyRoutes['landing']['investigation'] + + history.push(ISISDataPublicationsRoutes.landing.investigation); + + render( + , + { wrapper: Wrapper } ); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISInvestigationLanding)).toBe(false); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); - it('renders ISISDatasetsCardView for ISIS datasets route in Study Hierarchy', async () => { - const wrapper = createCardWrapper(ISISStudyHierarchyRoutes['datasets']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISDatasetsCardView)).toBe(true); + it('renders ISISDatasetsCardView for ISIS datasets route in Data Publication Hierarchy', async () => { + history.push(ISISDataPublicationsRoutes.datasets); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await screen.findByTestId('isis-datasets-card-view') + ).toBeInTheDocument(); }); - it('does not render ISISDatasetsCardView for incorrect ISIS datasets route in Study Hierarchy', async () => { - (checkInstrumentId as jest.Mock).mockImplementation(() => + it('does not render ISISDatasetsCardView for incorrect ISIS datasets route in Data Publication Hierarchy', async () => { + checkInstrumentId.mockImplementation(() => Promise.resolve(false)); + checkStudyDataPublicationId.mockImplementation(() => Promise.resolve(false) ); - (checkStudyId as jest.Mock).mockImplementation(() => - Promise.resolve(false) + + history.push(ISISDataPublicationsRoutes.datasets); + + render( + , + { wrapper: Wrapper } ); - const wrapper = createCardWrapper(ISISStudyHierarchyRoutes['datasets']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISDatasetsCardView)).toBe(false); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); - it('renders ISISDatasetLanding for ISIS dataset route for studyHierarchy', async () => { - const wrapper = createLandingWrapper( - ISISStudyHierarchyRoutes['landing']['dataset'] + it('renders ISISDatasetLanding for ISIS dataset route for Data Publication Hierarchy', async () => { + history.push(ISISDataPublicationsRoutes.landing.dataset); + + render( + , + { wrapper: Wrapper } ); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISDatasetLanding)).toBe(true); + + expect( + await screen.findByTestId('isis-dataset-landing') + ).toBeInTheDocument(); }); - it('does not render ISISDatasetLanding for incorrect ISIS dataset route for studyHierarchy', async () => { - (checkInstrumentId as jest.Mock).mockImplementation(() => - Promise.resolve(false) - ); - (checkStudyId as jest.Mock).mockImplementation(() => + it('does not render ISISDatasetLanding for incorrect ISIS dataset route for Data Publication Hierarchy', async () => { + checkInstrumentId.mockImplementation(() => Promise.resolve(false)); + checkStudyDataPublicationId.mockImplementation(() => Promise.resolve(false) ); - const wrapper = createLandingWrapper( - ISISStudyHierarchyRoutes['landing']['dataset'] + + history.push(ISISDataPublicationsRoutes.landing.dataset); + + render( + , + { wrapper: Wrapper } ); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISDatasetLanding)).toBe(false); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); - it('renders ISISDatafilesTable for ISIS datafiles route in Study Hierarchy', async () => { - const wrapper = createTableWrapper(ISISStudyHierarchyRoutes['datafiles']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISDatafilesTable)).toBe(true); + it('renders ISISDatafilesTable for ISIS datafiles route in Data Publication Hierarchy', async () => { + history.push(ISISDataPublicationsRoutes.datafiles); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await findColumnHeaderByName('datafiles.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.location') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.modified_time') + ).toBeInTheDocument(); }); - it('does not render ISISDatafilesTable for incorrect ISIS datafiles route in Study Hierarchy', async () => { - (checkInstrumentId as jest.Mock).mockImplementation(() => + it('does not render ISISDatafilesTable for incorrect ISIS datafiles route in Data Publication Hierarchy', async () => { + checkInstrumentId.mockImplementation(() => Promise.resolve(false)); + checkStudyDataPublicationId.mockImplementation(() => Promise.resolve(false) ); - (checkStudyId as jest.Mock).mockImplementation(() => - Promise.resolve(false) + checkInvestigationId.mockImplementation(() => Promise.resolve(false)); + + history.push(ISISDataPublicationsRoutes.datafiles); + + render( + , + { wrapper: Wrapper } ); - (checkInvestigationId as jest.Mock).mockImplementation(() => + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); + }); + + it('renders DatafilePreviewer for ISIS datafile preview route in Data Publication Hierarchy', async () => { + history.push(ISISDataPublicationsRoutes.datafilePreview); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await screen.findByText('datafiles.preview.invalid_datafile') + ).toBeInTheDocument(); + }); + + it('does not render DatafilePreviewer for incorrect ISIS datafile preview route in Data Publication Hierarchy', async () => { + checkInstrumentId.mockImplementation(() => Promise.resolve(false)); + checkStudyDataPublicationId.mockImplementation(() => Promise.resolve(false) ); - const wrapper = createTableWrapper(ISISStudyHierarchyRoutes['datafiles']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(ISISDatafilesTable)).toBe(false); + checkInvestigationId.mockImplementation(() => Promise.resolve(false)); + checkDatasetId.mockImplementation(() => Promise.resolve(false)); + + history.push(ISISDataPublicationsRoutes.datafilePreview); + + render( + , + { wrapper: Wrapper } + ); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); }); describe('DLS', () => { - it('renders DLSMyDataTable for DLS my data route', () => { - const wrapper = createTableWrapper(DLSRoutes['mydata'], false); - expect(wrapper.exists(DLSMyDataTable)).toBe(true); + it('renders DLSMyDataTable for DLS my data route', async () => { + history.push(DLSRoutes.mydata); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await findColumnHeaderByName('investigations.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.visit_id') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.instrument') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.end_date') + ).toBeInTheDocument(); }); it('redirects to login page when not signed in (DLSMyDataTable) ', () => { - const wrapper = createTableWrapper(DLSRoutes['mydata'], true); - expect(wrapper.exists(DLSMyDataTable)).toBe(false); - expect(history.length).toBe(2); + history.push(DLSRoutes.mydata); + + render( + , + { wrapper: Wrapper } + ); + expect(history.location.pathname).toBe('/login'); }); - it('renders DLSProposalTable for DLS proposal route', () => { - const wrapper = createTableWrapper(DLSRoutes['proposals']); - expect(wrapper.exists(DLSProposalsTable)).toBe(true); + it('renders DLSProposalTable for DLS proposal route', async () => { + history.push(DLSRoutes.proposals); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await findColumnHeaderByName('investigations.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.name') + ).toBeInTheDocument(); }); - it('renders DLSProposalCardView for DLS proposal route', () => { - const wrapper = createCardWrapper(DLSRoutes['proposals']); - expect(wrapper.exists(DLSProposalsCardView)).toBe(true); + it('renders DLSProposalCardView for DLS proposal route', async () => { + history.push(DLSRoutes.proposals); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await screen.findByTestId('dls-proposals-card-view') + ).toBeInTheDocument(); }); - it('renders DLSVisitsTable for DLS investigations route', () => { - const wrapper = createTableWrapper(DLSRoutes['investigations']); - expect(wrapper.exists(DLSVisitsTable)).toBe(true); + it('renders DLSVisitsTable for DLS investigations route', async () => { + history.push(DLSRoutes.investigations); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await findColumnHeaderByName('investigations.visit_id') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.instrument') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.end_date') + ).toBeInTheDocument(); }); - it('renders DLSVisitsCardView for DLS investigations route', () => { - const wrapper = createCardWrapper(DLSRoutes['investigations']); - expect(wrapper.exists(DLSVisitsCardView)).toBe(true); + it('renders DLSVisitsCardView for DLS investigations route', async () => { + history.push(DLSRoutes.investigations); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await screen.findByTestId('dls-visits-card-view') + ).toBeInTheDocument(); }); it('renders DLSDatasetsTable for DLS datasets route', async () => { - const wrapper = createTableWrapper(DLSRoutes['datasets']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(DLSDatasetsTable)).toBe(true); + history.push(DLSRoutes.datasets); + + render( + , + { wrapper: Wrapper } + ); + + expect(await findColumnHeaderByName('datasets.name')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.datafile_count') + ).toBeInTheDocument(); + expect(await findColumnHeaderByName('datasets.size')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.create_time') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.modified_time') + ).toBeInTheDocument(); }); it('does not render DLSDatasetsTable for incorrect DLS datasets route', async () => { - (checkProposalName as jest.Mock).mockImplementation(() => - Promise.resolve(false) + checkProposalName.mockImplementation(() => Promise.resolve(false)); + + history.push(DLSRoutes.datasets); + + render( + , + { wrapper: Wrapper } ); - const wrapper = createTableWrapper(DLSRoutes['datasets']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(DLSDatasetsTable)).toBe(false); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); it('renders DLSDatasetsCardView for DLS datasets route', async () => { - const wrapper = createCardWrapper(DLSRoutes['datasets']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(DLSDatasetsCardView)).toBe(true); + history.push(DLSRoutes.datasets); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await screen.findByTestId('dls-datasets-card-view') + ).toBeInTheDocument(); }); it('does not render DLSDatasetsCardView for incorrect DLS datasets route', async () => { - (checkProposalName as jest.Mock).mockImplementation(() => - Promise.resolve(false) + checkProposalName.mockImplementation(() => Promise.resolve(false)); + + history.push(DLSRoutes.datasets); + + render( + , + { wrapper: Wrapper } ); - const wrapper = createCardWrapper(DLSRoutes['datasets']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(DLSDatasetsCardView)).toBe(false); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); it('renders DLSDatafilesTable for DLS datafiles route', async () => { - const wrapper = createTableWrapper(DLSRoutes['datafiles']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(DLSDatafilesTable)).toBe(true); + history.push(DLSRoutes.datafiles); + + render( + , + { wrapper: Wrapper } + ); + + expect( + await findColumnHeaderByName('datafiles.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.location') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.create_time') + ).toBeInTheDocument(); }); it('does not render DLSDatafilesTable for incorrect DLS datafiles route', async () => { - (checkProposalName as jest.Mock).mockImplementation(() => - Promise.resolve(false) - ); - (checkInvestigationId as jest.Mock).mockImplementation(() => - Promise.resolve(false) + checkProposalName.mockImplementation(() => Promise.resolve(false)); + checkInvestigationId.mockImplementation(() => Promise.resolve(false)); + + history.push(DLSRoutes.datafiles); + + render( + , + { wrapper: Wrapper } ); - const wrapper = createTableWrapper(DLSRoutes['datafiles']); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - expect(wrapper.exists(DLSDatafilesTable)).toBe(false); + + expect(await screen.findByText('loading.oops')).toBeInTheDocument(); }); }); }); diff --git a/packages/datagateway-dataview/src/page/pageRouting.component.tsx b/packages/datagateway-dataview/src/page/pageRouting.component.tsx index bcbb63c9a..fec453efc 100644 --- a/packages/datagateway-dataview/src/page/pageRouting.component.tsx +++ b/packages/datagateway-dataview/src/page/pageRouting.component.tsx @@ -1,7 +1,13 @@ import React from 'react'; -import { Location as LocationType } from 'history'; -import { Switch, Route, RouteComponentProps, Redirect } from 'react-router'; -import { Link } from 'react-router-dom'; +import type { Location as LocationType } from 'history'; +import { + Switch, + Route, + type RouteComponentProps, + Redirect, + Link, +} from 'react-router-dom'; +import DatafilePreviewer from '../views/datafilePreview/datafilePreviewer.component'; import InvestigationTable from '../views/table/investigationTable.component'; import DatasetTable from '../views/table/datasetTable.component'; @@ -13,7 +19,7 @@ import DLSDatasetsTable from '../views/table/dls/dlsDatasetsTable.component'; import DLSDatafilesTable from '../views/table/dls/dlsDatafilesTable.component'; import ISISInstrumentsTable from '../views/table/isis/isisInstrumentsTable.component'; -import ISISStudiesTable from '../views/table/isis/isisStudiesTable.component'; +import ISISDataPublicationsTable from '../views/table/isis/isisDataPublicationsTable.component'; import ISISFacilityCyclesTable from '../views/table/isis/isisFacilityCyclesTable.component'; import ISISInvestigationsTable from '../views/table/isis/isisInvestigationsTable.component'; import ISISDatasetsTable from '../views/table/isis/isisDatasetsTable.component'; @@ -26,8 +32,8 @@ import InvestigationCardView from '../views/card/investigationCardView.component import DatasetCardView from '../views/card/datasetCardView.component'; import ISISInstrumentsCardView from '../views/card/isis/isisInstrumentsCardView.component'; -import ISISStudiesCardView from '../views/card/isis/isisStudiesCardView.component'; -import ISISStudyLanding from '../views/landing/isis/isisStudyLanding.component'; +import ISISDataPublicationsCardView from '../views/card/isis/isisDataPublicationsCardView.component'; +import ISISDataPublicationLanding from '../views/landing/isis/isisDataPublicationLanding.component'; import ISISFacilityCyclesCardView from '../views/card/isis/isisFacilityCyclesCardView.component'; import ISISInvestigationsCardView from '../views/card/isis/isisInvestigationsCardView.component'; import ISISInvestigationLanding from '../views/landing/isis/isisInvestigationLanding.component'; @@ -44,11 +50,12 @@ import { checkInvestigationId, checkInstrumentAndFacilityCycleId, checkInstrumentId, - checkStudyId, + checkStudyDataPublicationId, + checkDatasetId, } from './idCheckFunctions'; import { paths } from './pageContainer.component'; -import { ViewsType } from 'datagateway-common'; +import { useDataPublication, ViewsType } from 'datagateway-common'; const SafeDatafileTable = React.memo( (props: { @@ -61,180 +68,284 @@ const SafeDatafileTable = React.memo( parseInt(props.datasetId) ) )(DatafileTable); - return ; + return ( + + ); } ); SafeDatafileTable.displayName = 'SafeDatafileTable'; -const SafeISISDatafilesTable = React.memo( - (props: { - instrumentId: string; - instrumentChildId: string; - investigationId: string; - datasetId: string; - studyHierarchy: boolean; - }): React.ReactElement => { - const SafeISISDatafilesTable = props.studyHierarchy - ? withIdCheck( - Promise.all([ - checkInstrumentId( - parseInt(props.instrumentId), - parseInt(props.instrumentChildId) - ), - checkStudyId( - parseInt(props.instrumentChildId), - parseInt(props.investigationId) - ), - checkInvestigationId( - parseInt(props.investigationId), - parseInt(props.datasetId) - ), - ]).then((values) => !values.includes(false)) - )(ISISDatafilesTable) - : withIdCheck( - Promise.all([ +const SafeISISDatafilesTable = (props: { + instrumentId: string; + instrumentChildId: string; + investigationId: string; + datasetId: string; + dataPublication: boolean; +}): React.ReactElement => { + const { data, isLoading } = useDataPublication( + parseInt(props.investigationId), + { + enabled: props.dataPublication, + } + ); + const dataPublicationInvestigationId = + data?.content?.dataCollectionInvestigations?.[0]?.investigation?.id; + + const SafeISISDatafilesTable = React.useMemo( + () => + props.dataPublication + ? withIdCheck( + Promise.all([ + checkInstrumentId( + parseInt(props.instrumentId), + parseInt(props.instrumentChildId) + ), + checkStudyDataPublicationId( + parseInt(props.instrumentChildId), + parseInt(props.investigationId) + ), + checkInvestigationId( + dataPublicationInvestigationId ?? -1, + parseInt(props.datasetId) + ), + ...(isLoading ? [new Promise(() => undefined)] : []), + ]).then((values) => !values.includes(false)) + )(ISISDatafilesTable) + : withIdCheck( + Promise.all([ + checkInstrumentAndFacilityCycleId( + parseInt(props.instrumentId), + parseInt(props.instrumentChildId), + parseInt(props.investigationId) + ), + checkInvestigationId( + parseInt(props.investigationId), + parseInt(props.datasetId) + ), + ]).then((values) => !values.includes(false)) + )(ISISDatafilesTable), + [ + dataPublicationInvestigationId, + isLoading, + props.dataPublication, + props.datasetId, + props.instrumentChildId, + props.instrumentId, + props.investigationId, + ] + ); + + return ( + + ); +}; + +const SafeISISDatasetLanding = (props: { + instrumentId: string; + instrumentChildId: string; + investigationId: string; + datasetId: string; + dataPublication: boolean; +}): React.ReactElement => { + const { data, isLoading } = useDataPublication( + parseInt(props.investigationId), + { + enabled: props.dataPublication, + } + ); + const dataPublicationInvestigationId = + data?.content?.dataCollectionInvestigations?.[0]?.investigation?.id; + + const SafeISISDatasetLanding = React.useMemo( + () => + props.dataPublication + ? withIdCheck( + Promise.all([ + checkInstrumentId( + parseInt(props.instrumentId), + parseInt(props.instrumentChildId) + ), + checkStudyDataPublicationId( + parseInt(props.instrumentChildId), + parseInt(props.investigationId) + ), + checkInvestigationId( + dataPublicationInvestigationId ?? -1, + parseInt(props.datasetId) + ), + ...(isLoading ? [new Promise(() => undefined)] : []), + ]).then((values) => !values.includes(false)) + )(ISISDatasetLanding) + : withIdCheck( + Promise.all([ + checkInstrumentAndFacilityCycleId( + parseInt(props.instrumentId), + parseInt(props.instrumentChildId), + parseInt(props.investigationId) + ), + checkInvestigationId( + parseInt(props.investigationId), + parseInt(props.datasetId) + ), + ]).then((values) => !values.includes(false)) + )(ISISDatasetLanding), + [ + dataPublicationInvestigationId, + isLoading, + props.dataPublication, + props.datasetId, + props.instrumentChildId, + props.instrumentId, + props.investigationId, + ] + ); + + return ; +}; + +const SafeISISDatasetsTable = (props: { + instrumentId: string; + instrumentChildId: string; + investigationId: string; + dataPublication: boolean; +}): React.ReactElement => { + const { data, isLoading } = useDataPublication( + parseInt(props.investigationId), + { + enabled: props.dataPublication, + } + ); + + const dataPublicationInvestigationId = + data?.content?.dataCollectionInvestigations?.[0]?.investigation?.id; + + const SafeISISDatasetsTable = React.useMemo( + () => + props.dataPublication + ? withIdCheck( + Promise.all([ + checkInstrumentId( + parseInt(props.instrumentId), + parseInt(props.instrumentChildId) + ), + checkStudyDataPublicationId( + parseInt(props.instrumentChildId), + parseInt(props.investigationId) + ), + ...(isLoading ? [new Promise(() => undefined)] : []), + ]).then((values) => !values.includes(false)) + )(ISISDatasetsTable) + : withIdCheck( checkInstrumentAndFacilityCycleId( parseInt(props.instrumentId), parseInt(props.instrumentChildId), parseInt(props.investigationId) - ), - checkInvestigationId( - parseInt(props.investigationId), - parseInt(props.datasetId) - ), - ]).then((values) => !values.includes(false)) - )(ISISDatafilesTable); - - return ; - } -); -SafeISISDatafilesTable.displayName = 'SafeISISDatafilesTable'; - -const SafeISISDatasetLanding = React.memo( - (props: { - instrumentId: string; - instrumentChildId: string; - investigationId: string; - datasetId: string; - studyHierarchy: boolean; - }): React.ReactElement => { - const SafeISISDatasetLanding = props.studyHierarchy - ? withIdCheck( - Promise.all([ - checkInstrumentId( - parseInt(props.instrumentId), - parseInt(props.instrumentChildId) - ), - checkStudyId( - parseInt(props.instrumentChildId), - parseInt(props.investigationId) - ), - checkInvestigationId( - parseInt(props.investigationId), - parseInt(props.datasetId) - ), - ]).then((values) => !values.includes(false)) - )(ISISDatasetLanding) - : withIdCheck( - Promise.all([ + ) + )(ISISDatasetsTable), + [ + isLoading, + props.dataPublication, + props.instrumentChildId, + props.instrumentId, + props.investigationId, + ] + ); + + return ( + + ); +}; + +const SafeISISDatasetsCardView = (props: { + instrumentId: string; + instrumentChildId: string; + investigationId: string; + dataPublication: boolean; +}): React.ReactElement => { + const { data, isLoading } = useDataPublication( + parseInt(props.investigationId), + { + enabled: props.dataPublication, + } + ); + + const dataPublicationInvestigationId = + data?.content?.dataCollectionInvestigations?.[0]?.investigation?.id; + + const SafeISISDatasetsCardView = React.useMemo( + () => + props.dataPublication + ? withIdCheck( + Promise.all([ + checkInstrumentId( + parseInt(props.instrumentId), + parseInt(props.instrumentChildId) + ), + checkStudyDataPublicationId( + parseInt(props.instrumentChildId), + parseInt(props.investigationId) + ), + ...(isLoading ? [new Promise(() => undefined)] : []), + ]).then((values) => !values.includes(false)) + )(ISISDatasetsCardView) + : withIdCheck( checkInstrumentAndFacilityCycleId( parseInt(props.instrumentId), parseInt(props.instrumentChildId), parseInt(props.investigationId) - ), - checkInvestigationId( - parseInt(props.investigationId), - parseInt(props.datasetId) - ), - ]).then((values) => !values.includes(false)) - )(ISISDatasetLanding); - - return ; - } -); -SafeISISDatasetLanding.displayName = 'SafeISISDatasetLanding'; - -const SafeISISDatasetsTable = React.memo( - (props: { - instrumentId: string; - instrumentChildId: string; - investigationId: string; - studyHierarchy: boolean; - }): React.ReactElement => { - const SafeISISDatasetsTable = props.studyHierarchy - ? withIdCheck( - Promise.all([ - checkInstrumentId( - parseInt(props.instrumentId), - parseInt(props.instrumentChildId) - ), - checkStudyId( - parseInt(props.instrumentChildId), - parseInt(props.investigationId) - ), - ]).then((values) => !values.includes(false)) - )(ISISDatasetsTable) - : withIdCheck( - checkInstrumentAndFacilityCycleId( - parseInt(props.instrumentId), - parseInt(props.instrumentChildId), - parseInt(props.investigationId) - ) - )(ISISDatasetsTable); - - return ; - } -); -SafeISISDatasetsTable.displayName = 'SafeISISDatasetsTable'; - -const SafeISISDatasetsCardView = React.memo( - (props: { - instrumentId: string; - instrumentChildId: string; - investigationId: string; - studyHierarchy: boolean; - }): React.ReactElement => { - const SafeISISDatasetsCardView = props.studyHierarchy - ? withIdCheck( - Promise.all([ - checkInstrumentId( - parseInt(props.instrumentId), - parseInt(props.instrumentChildId) - ), - checkStudyId( - parseInt(props.instrumentChildId), - parseInt(props.investigationId) - ), - ]).then((values) => !values.includes(false)) - )(ISISDatasetsCardView) - : withIdCheck( - checkInstrumentAndFacilityCycleId( - parseInt(props.instrumentId), - parseInt(props.instrumentChildId), - parseInt(props.investigationId) - ) - )(ISISDatasetsCardView); - - return ; - } -); -SafeISISDatasetsCardView.displayName = 'SafeISISDatasetsCardView'; + ) + )(ISISDatasetsCardView), + [ + isLoading, + props.dataPublication, + props.instrumentChildId, + props.instrumentId, + props.investigationId, + ] + ); + + return ( + + ); +}; const SafeISISInvestigationLanding = React.memo( (props: { instrumentId: string; instrumentChildId: string; investigationId: string; - studyHierarchy: boolean; + dataPublication: boolean; }): React.ReactElement => { - const SafeISISInvestigationLanding = props.studyHierarchy + const SafeISISInvestigationLanding = props.dataPublication ? withIdCheck( Promise.all([ checkInstrumentId( parseInt(props.instrumentId), parseInt(props.instrumentChildId) ), - checkStudyId( + checkStudyDataPublicationId( parseInt(props.instrumentChildId), parseInt(props.investigationId) ), @@ -248,21 +359,33 @@ const SafeISISInvestigationLanding = React.memo( ) )(ISISInvestigationLanding); - return ; + return ( + + ); } ); SafeISISInvestigationLanding.displayName = 'SafeISISInvestigationLanding'; -const SafeISISStudyLanding = React.memo( - (props: { instrumentId: string; studyId: string }): React.ReactElement => { - const SafeISISStudyLanding = withIdCheck( - checkInstrumentId(parseInt(props.instrumentId), parseInt(props.studyId)) - )(ISISStudyLanding); +const SafeISISDataPublicationLanding = React.memo( + (props: { + instrumentId: string; + dataPublicationId: string; + }): React.ReactElement => { + const SafeISISDataPublicationLanding = withIdCheck( + checkInstrumentId( + parseInt(props.instrumentId), + parseInt(props.dataPublicationId) + ) + )(ISISDataPublicationLanding); - return ; + return ; } ); -SafeISISStudyLanding.displayName = 'SafeISISStudyLanding'; +SafeISISDataPublicationLanding.displayName = 'SafeISISDataPublicationLanding'; const SafeDLSDatafilesTable = React.memo( (props: { @@ -280,7 +403,12 @@ const SafeDLSDatafilesTable = React.memo( ]).then((values) => !values.includes(false)) )(DLSDatafilesTable); - return ; + return ( + + ); } ); SafeDLSDatafilesTable.displayName = 'SafeDLSDatafilesTable'; @@ -323,6 +451,80 @@ const SafeDLSDatasetsCardView = React.memo( ); SafeDLSDatasetsCardView.displayName = 'SafeDLSDatasetsCardView'; +const SafeDatafilePreviewer = (props: { + dataPublication: boolean; + instrumentId: string; + instrumentChildId: string; + investigationId: string; + datasetId: string; + datafileId: string; +}): React.ReactElement => { + const { data, isLoading } = useDataPublication( + parseInt(props.investigationId), + { + enabled: props.dataPublication, + } + ); + + const dataPublicationInvestigationId = + data?.content?.dataCollectionInvestigations?.[0]?.investigation?.id; + + const SafeDatafilePreviewer = React.useMemo( + () => + props.dataPublication + ? withIdCheck( + Promise.all([ + checkInstrumentId( + parseInt(props.instrumentId), + parseInt(props.instrumentChildId) + ), + checkStudyDataPublicationId( + parseInt(props.instrumentChildId), + parseInt(props.investigationId) + ), + checkInvestigationId( + dataPublicationInvestigationId ?? -1, + parseInt(props.datasetId) + ), + checkDatasetId( + parseInt(props.datasetId), + parseInt(props.datafileId) + ), + ...(isLoading ? [new Promise(() => undefined)] : []), + ]).then((values) => !values.includes(false)) + )(DatafilePreviewer) + : withIdCheck( + Promise.all([ + checkInstrumentAndFacilityCycleId( + parseInt(props.instrumentId), + parseInt(props.instrumentChildId), + parseInt(props.investigationId) + ), + checkInvestigationId( + parseInt(props.investigationId), + parseInt(props.datasetId) + ), + checkDatasetId( + parseInt(props.datasetId), + parseInt(props.datafileId) + ), + ]).then((checks) => checks.every((passes) => passes)) + )(DatafilePreviewer), + [ + dataPublicationInvestigationId, + isLoading, + props.dataPublication, + props.datafileId, + props.datasetId, + props.instrumentChildId, + props.instrumentId, + props.investigationId, + ] + ); + + return ; +}; + interface PageRoutingProps { view: ViewsType; location: LocationType; @@ -423,28 +625,28 @@ class PageRouting extends React.PureComponent { )} /> - {/* ISIS studyHierarchy routes */} + {/* ISIS dataPublications routes */} this.props.view === 'card' ? ( - + ) : ( - + ) } /> this.props.view === 'card' ? ( - ) : ( - ) @@ -452,61 +654,63 @@ class PageRouting extends React.PureComponent { /> ( - )} /> this.props.view === 'card' ? ( - ) : ( - ) } /> ( )} /> this.props.view === 'card' ? ( ) : ( ) @@ -514,12 +718,12 @@ class PageRouting extends React.PureComponent { /> ( @@ -527,14 +731,28 @@ class PageRouting extends React.PureComponent { /> ( + )} + /> + ( + )} /> @@ -545,9 +763,9 @@ class PageRouting extends React.PureComponent { path={paths.toggle.isisInstrument} render={() => this.props.view === 'card' ? ( - + ) : ( - + ) } /> @@ -572,15 +790,13 @@ class PageRouting extends React.PureComponent { render={({ match }) => this.props.view === 'card' ? ( ) : ( ) } @@ -590,7 +806,7 @@ class PageRouting extends React.PureComponent { path={paths.landing.isisInvestigationLanding} render={({ match }) => ( { render={({ match }) => this.props.view === 'card' ? ( ) : ( { path={paths.landing.isisDatasetLanding} render={({ match }) => ( { path={paths.standard.isisDatafile} render={({ match }) => ( + )} + /> + ( + )} /> diff --git a/packages/datagateway-dataview/src/page/pageSearch.component.tsx b/packages/datagateway-dataview/src/page/pageSearch.component.tsx deleted file mode 100644 index 7d191d225..000000000 --- a/packages/datagateway-dataview/src/page/pageSearch.component.tsx +++ /dev/null @@ -1,84 +0,0 @@ -/* Currently unused, commented out to bypass codecov -import React from 'react'; -import { TextField, InputAdornment } from '@material-ui/core'; -import SearchIcon from '@material-ui/icons/Search'; -import { ThunkDispatch } from 'redux-thunk'; -import { StateType, pushPageSearch } from 'datagateway-common'; -import { AnyAction } from 'redux'; -import { connect } from 'react-redux'; - -import debounce from 'lodash.debounce'; - -interface PageSearchDispatchProps { - pushSearch: (search: string | null) => Promise; -} - -interface PageSearchStateProps { - search: string | null; -} - -type PageSearchCombinedProps = PageSearchDispatchProps & PageSearchStateProps; - -// TODO: This will need to use data-search components from -// datagateway-common when added. -class PageSearch extends React.Component< - PageSearchCombinedProps, - { value: string } -> { - public constructor(props: PageSearchCombinedProps) { - super(props); - - // Add internal state value to prevent debounce from blocking user input. - this.state = { - value: this.props.search ? this.props.search : '', - }; - } - - // Debounce by 500 ms. - private updateValue = debounce((value: string) => { - this.props.pushSearch(value); - }, 500); - - private handleChange = (event: React.ChangeEvent): void => { - this.updateValue(event.target.value); - this.setState({ - value: event.target.value, - }); - }; - - public render(): React.ReactElement { - return ( - - - - ), - }} - /> - ); - } -} - -const mapDispatchToProps = ( - dispatch: ThunkDispatch -): PageSearchDispatchProps => ({ - pushSearch: (search: string | null) => dispatch(pushPageSearch(search)), -}); - -const mapStateToProps = (state: StateType): PageSearchStateProps => ({ - search: state.dgcommon.query.search, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(PageSearch); -*/ -export {}; diff --git a/packages/datagateway-dataview/src/page/translatedHomePage.component.test.tsx b/packages/datagateway-dataview/src/page/translatedHomePage.component.test.tsx index 832f45f6d..3437aa8a3 100644 --- a/packages/datagateway-dataview/src/page/translatedHomePage.component.test.tsx +++ b/packages/datagateway-dataview/src/page/translatedHomePage.component.test.tsx @@ -1,24 +1,26 @@ import React from 'react'; -import { createShallow } from '@material-ui/core/test-utils'; import { TranslatedHomePage as HomePage, TranslatedHomePageStateProps, } from './translatedHomePage.component'; +import { render } from '@testing-library/react'; +import { MemoryRouter } from 'react-router-dom'; describe('HomePage', () => { - let shallow; let props: TranslatedHomePageStateProps; beforeEach(() => { - shallow = createShallow({ untilSelector: 'div' }); - props = { pluginHost: 'test', }; }); it('translated homepage renders correctly', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const { asFragment } = render( + + + + ); + expect(asFragment()).toMatchSnapshot(); }); }); diff --git a/packages/datagateway-dataview/src/page/withIdCheck.test.tsx b/packages/datagateway-dataview/src/page/withIdCheck.test.tsx index c27957053..468810f9e 100644 --- a/packages/datagateway-dataview/src/page/withIdCheck.test.tsx +++ b/packages/datagateway-dataview/src/page/withIdCheck.test.tsx @@ -1,14 +1,11 @@ import React from 'react'; import withIdCheck from './withIdCheck'; -import { createShallow } from '@material-ui/core/test-utils'; -import { shallow as enzymeShallow } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { flushPromises } from '../setupTests'; -/* eslint-disable-next-line import/no-extraneous-dependencies */ -import { createLocation } from 'history'; +import { MemoryRouter } from 'react-router-dom'; +import { render, RenderResult } from '@testing-library/react'; describe('withIdCheck', () => { - let shallow: typeof enzymeShallow; let useEffect: jest.SpyInstance; const Test: React.FC<{ message: string }> = (props: { message: string }) => ( @@ -23,8 +20,18 @@ describe('withIdCheck', () => { useEffect.mockImplementationOnce((f) => f()); }; + const createWrapper = ( + Component: React.ComponentType<{ message: string }>, + locationPath: string + ): RenderResult => { + return render( + + + + ); + }; + beforeEach(() => { - shallow = createShallow({ untilSelector: 'WithIdCheckComponent' }); useEffect = jest.spyOn(React, 'useEffect'); pendingPromiseMock = jest.fn().mockImplementation( () => @@ -43,54 +50,47 @@ describe('withIdCheck', () => { it('renders loading indicator when loading', () => { const SafeComponent = withIdCheck(pendingPromiseMock())(Test); - const wrapper = shallow(); + const wrapper = createWrapper(SafeComponent, '/'); - expect(wrapper).toMatchSnapshot(); + expect(wrapper.asFragment()).toMatchSnapshot(); }); it('renders component when checkingPromise resolves to be true', async () => { const SafeComponent = withIdCheck(resolvedTruePromiseMock())(Test); - const wrapper = shallow(); + const wrapper = createWrapper(SafeComponent, '/'); await act(async () => { await flushPromises(); - wrapper.update(); }); - expect(wrapper).toMatchSnapshot(); + expect(wrapper.asFragment()).toMatchSnapshot(); }); it('renders error when checkingPromise is rejected', async () => { const SafeComponent = withIdCheck(rejectedPromiseMock())(Test); - const wrapper = shallow( - + const wrapper = createWrapper( + SafeComponent, + '/browse/investigation/2/dataset/1/datafile' ); await act(async () => { await flushPromises(); - wrapper.update(); }); - expect(wrapper).toMatchSnapshot(); + expect(wrapper.asFragment()).toMatchSnapshot(); }); it('renders error when checkingPromise does not resolve to be true', async () => { const SafeComponent = withIdCheck(resolvedFalsePromiseMock())(Test); - const wrapper = shallow( - + const wrapper = createWrapper( + SafeComponent, + '/browse/investigation/2/dataset/1/datafile' ); await act(async () => { await flushPromises(); - wrapper.update(); }); - expect(wrapper).toMatchSnapshot(); + expect(wrapper.asFragment()).toMatchSnapshot(); }); }); diff --git a/packages/datagateway-dataview/src/page/withIdCheck.tsx b/packages/datagateway-dataview/src/page/withIdCheck.tsx index 0ae9e73dc..6e1b1dadd 100644 --- a/packages/datagateway-dataview/src/page/withIdCheck.tsx +++ b/packages/datagateway-dataview/src/page/withIdCheck.tsx @@ -1,49 +1,18 @@ import React from 'react'; -import { BugReport } from '@material-ui/icons'; -import { - Typography, - withStyles, - WithStyles, - Theme, - createStyles, - Grid, - CircularProgress, - Link, -} from '@material-ui/core'; -import { StyleRules } from '@material-ui/core/styles'; -import { withRouter, RouteComponentProps } from 'react-router'; +import { BugReport } from '@mui/icons-material'; +import { Typography, Grid, CircularProgress, Link } from '@mui/material'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; import { Link as RouterLink } from 'react-router-dom'; import { compose } from 'redux'; import { useTranslation, Trans } from 'react-i18next'; -const styles = (theme: Theme): StyleRules => - createStyles({ - container: { - height: '100%', - }, - bugIcon: { - width: '5rem', - height: '5rem', - color: theme.palette.primary.main, - }, - titleText: { - fontWeight: 'bold', - fontSize: '3rem', - color: theme.palette.primary.main, - }, - message: { - maxWidth: 600, - textAlign: 'center', - }, - }); +const containerStyle = { height: '100%' }; function withIdCheck(checkingPromise: Promise) { return function WithIdCheck( Component: React.ComponentType ): React.ComponentType { - const WithIdCheckComponent: React.FC< - T & WithStyles & RouteComponentProps - > = (props) => { + const WithIdCheckComponent: React.FC = (props) => { const [loading, setLoading] = React.useState(true); const [valid, setValid] = React.useState(false); const [t] = useTranslation(); @@ -61,14 +30,8 @@ function withIdCheck(checkingPromise: Promise) { }); }, []); - const { - classes, - history, - location, - match, - staticContext, - ...componentProps - } = props; + const { history, location, match, staticContext, ...componentProps } = + props; if (loading) { return ( @@ -76,9 +39,9 @@ function withIdCheck(checkingPromise: Promise) { container item direction="column" - justify="center" + justifyContent="center" alignItems="center" - className={classes.container} + sx={containerStyle} > {t('loading.verifying')} @@ -86,24 +49,40 @@ function withIdCheck(checkingPromise: Promise) { ); } else { if (valid) { - return ; + return ( + + ); } else { return ( - - - + + + {t('loading.oops')} - - + + We're sorry, it seems as though the URL you requested is attempting to fetch incorrect data. Please double check your @@ -127,10 +106,7 @@ function withIdCheck(checkingPromise: Promise) { } }; - return compose>( - withRouter, - withStyles(styles) - )(WithIdCheckComponent); + return compose>(withRouter)(WithIdCheckComponent); }; } diff --git a/packages/datagateway-dataview/src/settings.ts b/packages/datagateway-dataview/src/settings.ts index 9e10a42ae..1f183b890 100644 --- a/packages/datagateway-dataview/src/settings.ts +++ b/packages/datagateway-dataview/src/settings.ts @@ -6,10 +6,11 @@ export interface DataviewSettings { apiUrl: string; downloadApiUrl: string; idsUrl: string; + icatUrl: string; selectAllSetting?: boolean; facilityImageURL?: string; features?: never; - breadcrumbs?: BreadcrumbSettings; + breadcrumbs?: BreadcrumbSettings[]; routes: PluginRoute[]; helpSteps?: { target: string; content: string }[]; pluginHost?: string; diff --git a/packages/datagateway-dataview/src/setupTests.ts b/packages/datagateway-dataview/src/setupTests.ts index 9022d0493..47b07f987 100644 --- a/packages/datagateway-dataview/src/setupTests.ts +++ b/packages/datagateway-dataview/src/setupTests.ts @@ -1,12 +1,20 @@ -import Enzyme from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; -import { Action } from 'redux'; +/* eslint-disable @typescript-eslint/no-empty-function */ +import '@testing-library/jest-dom'; +// Blob implementation in jsdom is not complete (https://github.com/jsdom/jsdom/issues/2555) +// blob-polyfill fills in the gap +import 'blob-polyfill'; +import { Action, AnyAction } from 'redux'; import { StateType } from './state/app.types'; import { initialState as dgDataViewInitialState } from './state/reducers/dgdataview.reducer'; import { dGCommonInitialState } from 'datagateway-common'; +import { screen, within } from '@testing-library/react'; +import failOnConsole from 'jest-fail-on-console'; +import { createLocation } from 'history'; +import { ThunkDispatch, ThunkAction } from 'redux-thunk'; -// React 16 Enzyme adapter -Enzyme.configure({ adapter: new Adapter() }); +failOnConsole(); + +jest.setTimeout(20000); function noOp(): void { // required as work-around for enzyme/jest environment not implementing window.URL.createObjectURL method @@ -21,13 +29,16 @@ export let actions: Action[] = []; export const resetActions = (): void => { actions = []; }; -export const getState = (): Partial => ({ +export const getState = (): StateType => ({ dgdataview: dgDataViewInitialState, dgcommon: dGCommonInitialState, + router: { location: { ...createLocation('/'), query: {} }, action: 'POP' }, }); -export const dispatch = (action: Action): void | Promise => { +export const dispatch: ThunkDispatch = ( + action: Action | ThunkAction +) => { if (typeof action === 'function') { - action(dispatch, getState); + action(dispatch, getState, null); return Promise.resolve(); } else { actions.push(action); @@ -39,3 +50,94 @@ export const flushPromises = (): Promise => // Mock lodash.debounce to return the function we want to call. jest.mock('lodash.debounce', () => (fn: (args: unknown) => unknown) => fn); + +// MUI date pickers default to mobile versions during testing and so functions +// like .simulate('change') will not work, this workaround ensures desktop +// datepickers are used in tests instead +// https://github.com/mui/material-ui-pickers/issues/2073 +export const applyDatePickerWorkaround = (): void => { + // add window.matchMedia + // this is necessary for the date picker to be rendered in desktop mode. + // if this is not provided, the mobile mode is rendered, which might lead to unexpected behavior + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: (query: string) => ({ + media: query, + // this is the media query that @material-ui/pickers uses to determine if a device is a desktop device + matches: query === '(pointer: fine)', + onchange: () => {}, + addEventListener: () => {}, + removeEventListener: () => {}, + addListener: () => {}, + removeListener: () => {}, + dispatchEvent: () => false, + }), + }); +}; + +export const cleanupDatePickerWorkaround = (): void => { + // @ts-expect-error it's a workaround + delete window.matchMedia; +}; + +/** + * Finds the index of the column with the given name. + */ +export const findColumnIndexByName = async ( + columnName: string +): Promise => { + const columnHeaders = await screen.findAllByRole('columnheader'); + return columnHeaders.findIndex( + (header) => within(header).queryByText(columnName) !== null + ); +}; + +/** + * Find the header row of the table currently rendered. + * This assumes that the first row is always the header row. + */ +export const findColumnHeaderByName = async ( + name: string +): Promise => { + const columnHeaders = await screen.findAllByRole('columnheader'); + const header = columnHeaders.find( + (header) => within(header).queryByText(name) !== null + ); + if (!header) { + throw new Error(`Cannot find column header by name: ${name}`); + } + return header; +}; + +/** + * Finds all table rows except the header row. + */ +export const findAllRows = async (): Promise => + (await screen.findAllByRole('row')).slice(1); + +/** + * Find the table row at the given index. This assumes the first table row is always the header row. + * + * @param index The index of the table row, igoring the header row. For example, if the table has 2 rows and the first row is the header row, + * the actual row that contains the data is considered the first row, and has an index of 0. + */ +export const findRowAt = async (index: number): Promise => { + const rows = await screen.findAllByRole('row'); + const row = rows[index + 1]; + if (!row) { + throw new Error(`Cannot find row at index ${index}`); + } + return row; +}; + +export const findCellInRow = ( + row: HTMLElement, + { columnIndex }: { columnIndex: number } +): HTMLElement => { + const cells = within(row).getAllByRole('gridcell'); + const cell = cells[columnIndex]; + if (!cell) { + throw new Error(`Cannot find cell in row.`); + } + return cell; +}; diff --git a/packages/datagateway-dataview/src/state/actions/actions.test.tsx b/packages/datagateway-dataview/src/state/actions/actions.test.tsx index c9bfdfd7f..c1f1f6967 100644 --- a/packages/datagateway-dataview/src/state/actions/actions.test.tsx +++ b/packages/datagateway-dataview/src/state/actions/actions.test.tsx @@ -47,20 +47,22 @@ describe('Actions', () => { }); it('given JSON loadBreadcrumbSettings returns a ConfigureBreadcrumbSettingsType with ConfigureBreadcrumbSettingsPayload', () => { - const action = loadBreadcrumbSettings({ - test: { + const action = loadBreadcrumbSettings([ + { + matchEntity: 'test', replaceEntity: 'testEntity', replaceEntityField: 'testField', }, - }); + ]); expect(action.type).toEqual(ConfigureBreadcrumbSettingsType); expect(action.payload).toEqual({ - settings: { - test: { + settings: [ + { + matchEntity: 'test', replaceEntity: 'testEntity', replaceEntityField: 'testField', }, - }, + ], }); }); @@ -95,11 +97,12 @@ describe('Actions', () => { features: {}, idsUrl: 'ids', apiUrl: 'api', - breadcrumbs: { - test: { + breadcrumbs: [ + { + matchEntity: 'test', replaceEntityField: 'title', }, - }, + ], downloadApiUrl: 'download-api', selectAllSetting: false, routes: [ @@ -112,7 +115,7 @@ describe('Actions', () => { pluginHost: 'http://localhost:3000/', }); const asyncAction = configureApp(); - await asyncAction(dispatch, getState); + await asyncAction(dispatch, getState, null); expect(actions.length).toEqual(8); expect(actions).toContainEqual(loadFacilityName('Generic')); @@ -127,11 +130,12 @@ describe('Actions', () => { }) ); expect(actions).toContainEqual( - loadBreadcrumbSettings({ - test: { + loadBreadcrumbSettings([ + { + matchEntity: 'test', replaceEntityField: 'title', }, - }) + ]) ); expect(actions).toContainEqual(settingsLoaded()); expect(actions).toContainEqual(loadSelectAllSetting(false)); @@ -149,7 +153,7 @@ describe('Actions', () => { }); const asyncAction = configureApp(); - await asyncAction(dispatch, getState); + await asyncAction(dispatch, getState, null); expect(actions.length).toEqual(3); expect( @@ -174,7 +178,7 @@ describe('Actions', () => { it("doesn't send any actions when settings are undefined", async () => { mockSettingsGetter.mockReturnValue(undefined); const asyncAction = configureApp(); - await asyncAction(dispatch, getState); + await asyncAction(dispatch, getState, null); expect(actions.length).toEqual(0); }); diff --git a/packages/datagateway-dataview/src/state/actions/actions.types.tsx b/packages/datagateway-dataview/src/state/actions/actions.types.tsx index 8670f3ae8..b3b04ddf1 100644 --- a/packages/datagateway-dataview/src/state/actions/actions.types.tsx +++ b/packages/datagateway-dataview/src/state/actions/actions.types.tsx @@ -19,11 +19,13 @@ export interface FeatureSwitchesPayload { export interface FeatureSwitches {} export interface ConfigureBreadcrumbSettingsPayload { - settings: BreadcrumbSettings; + settings: BreadcrumbSettings[]; } + export interface ConfigureSelectAllSettingPayload { settings: boolean; } + export interface ConfigurePluginHostSettingPayload { settings: string; } @@ -33,9 +35,9 @@ export interface ConfigureFacilityImageSettingPayload { } export interface BreadcrumbSettings { - [matchEntity: string]: { - replaceEntityField: string; - replaceEntity?: string; - parentEntity?: string; - }; + matchEntity: string; + replaceEntityField: string; + replaceEntityQueryField?: string; + replaceEntity?: string; + parentEntity?: string; } diff --git a/packages/datagateway-dataview/src/state/actions/index.tsx b/packages/datagateway-dataview/src/state/actions/index.tsx index fa8bb63b9..0e93bee90 100644 --- a/packages/datagateway-dataview/src/state/actions/index.tsx +++ b/packages/datagateway-dataview/src/state/actions/index.tsx @@ -32,7 +32,7 @@ export const loadFeatureSwitches = ( }); export const loadBreadcrumbSettings = ( - breadcrumbSettings: BreadcrumbSettings + breadcrumbSettings: BreadcrumbSettings[] ): ActionType => ({ type: ConfigureBreadcrumbSettingsType, payload: { diff --git a/packages/datagateway-dataview/src/state/app.types.tsx b/packages/datagateway-dataview/src/state/app.types.tsx index 5ffc8adf1..8fcfaed39 100644 --- a/packages/datagateway-dataview/src/state/app.types.tsx +++ b/packages/datagateway-dataview/src/state/app.types.tsx @@ -1,15 +1,20 @@ -import { ThunkAction } from 'redux-thunk'; -import { AnyAction } from 'redux'; -import { DGCommonState } from 'datagateway-common'; -import { FeatureSwitches, BreadcrumbSettings } from './actions/actions.types'; +import type { ThunkAction } from 'redux-thunk'; +import type { AnyAction } from 'redux'; +import type { DGCommonState } from 'datagateway-common'; +import type { DatafilePreviewerState } from '../views/datafilePreview/state/reducer'; +import type { + FeatureSwitches, + BreadcrumbSettings, +} from './actions/actions.types'; export interface DGDataViewState { facilityImageURL: string; features: FeatureSwitches; - breadcrumbSettings: BreadcrumbSettings; + breadcrumbSettings: BreadcrumbSettings[]; settingsLoaded: boolean; selectAllSetting: boolean; pluginHost: string; + datafilePreviewer: DatafilePreviewerState; } export interface EntityCache { diff --git a/packages/datagateway-dataview/src/state/reducers/dgdataview.reducer.test.tsx b/packages/datagateway-dataview/src/state/reducers/dgdataview.reducer.test.tsx index bbad966e7..01b8b7940 100644 --- a/packages/datagateway-dataview/src/state/reducers/dgdataview.reducer.test.tsx +++ b/packages/datagateway-dataview/src/state/reducers/dgdataview.reducer.test.tsx @@ -1,5 +1,5 @@ import DGDataViewReducer, { initialState } from './dgdataview.reducer'; -import { StateType } from '../app.types'; +import { DGDataViewState } from '../app.types'; import { loadFeatureSwitches, loadBreadcrumbSettings, @@ -10,15 +10,10 @@ import { } from '../actions'; describe('dgdataview reducer', () => { - let state: StateType; + let state: DGDataViewState; beforeEach(() => { - // state = { ...dgdataviewInitialState }; - state = JSON.parse( - JSON.stringify({ - dgdataview: initialState, - }) - ); + state = JSON.parse(JSON.stringify(initialState)); }); it('should return state for actions it does not care about', () => { @@ -30,7 +25,7 @@ describe('dgdataview reducer', () => { }); it('should set settingsLoaded to true when SettingsLoaded action is sent', () => { - expect(state.dgdataview.settingsLoaded).toBe(false); + expect(state.settingsLoaded).toBe(false); const updatedState = DGDataViewReducer(state, settingsLoaded()); @@ -38,7 +33,7 @@ describe('dgdataview reducer', () => { }); it('should set feature switches property when configure feature switches action is sent', () => { - expect(state.dgdataview.features).toEqual({}); + expect(state.features).toEqual({}); const updatedState = DGDataViewReducer(state, loadFeatureSwitches({})); @@ -46,26 +41,28 @@ describe('dgdataview reducer', () => { }); it('should set breadcrumb settings property when configure breadcrumb settings action is sent', () => { - expect(state.dgdataview.breadcrumbSettings).toEqual({}); + expect(state.breadcrumbSettings).toEqual([]); const updatedState = DGDataViewReducer( state, - loadBreadcrumbSettings({ - test: { + loadBreadcrumbSettings([ + { + matchEntity: 'test', replaceEntityField: 'title', }, - }) + ]) ); - expect(updatedState.breadcrumbSettings).toEqual({ - test: { + expect(updatedState.breadcrumbSettings).toEqual([ + { + matchEntity: 'test', replaceEntityField: 'title', }, - }); + ]); }); it('should set selectAllSetting when configuring action is sent', () => { - expect(state.dgdataview.selectAllSetting).toEqual(true); + expect(state.selectAllSetting).toEqual(true); const updatedState = DGDataViewReducer(state, loadSelectAllSetting(false)); @@ -73,7 +70,7 @@ describe('dgdataview reducer', () => { }); it('should set pluginHostSetting when configuring action is sent', () => { - expect(state.dgdataview.pluginHost).toEqual(''); + expect(state.pluginHost).toEqual(''); const updatedState = DGDataViewReducer( state, @@ -84,7 +81,7 @@ describe('dgdataview reducer', () => { }); it('should set facilityImageSetting when configuring action is sent', () => { - expect(state.dgdataview.facilityImageURL).toEqual(''); + expect(state.facilityImageURL).toEqual(''); const updatedState = DGDataViewReducer( state, diff --git a/packages/datagateway-dataview/src/state/reducers/dgdataview.reducer.tsx b/packages/datagateway-dataview/src/state/reducers/dgdataview.reducer.tsx index d6b589827..d7d3099b0 100644 --- a/packages/datagateway-dataview/src/state/reducers/dgdataview.reducer.tsx +++ b/packages/datagateway-dataview/src/state/reducers/dgdataview.reducer.tsx @@ -1,5 +1,9 @@ -import { DGDataViewState } from '../app.types'; import { createReducer } from 'datagateway-common'; +import { + datafilePreviewerInitialState, + datafilePreviewerReducer, +} from '../../views/datafilePreview/state/reducer'; +import { DGDataViewState } from '../app.types'; import { FeatureSwitchesPayload, ConfigureFeatureSwitchesType, @@ -16,11 +20,12 @@ import { export const initialState: DGDataViewState = { features: {}, - breadcrumbSettings: {}, + breadcrumbSettings: [], settingsLoaded: false, selectAllSetting: true, pluginHost: '', facilityImageURL: '', + datafilePreviewer: datafilePreviewerInitialState, }; export function handleSettingsLoaded(state: DGDataViewState): DGDataViewState { @@ -89,6 +94,7 @@ const DGDataViewReducer = createReducer(initialState, { [ConfigureSelectAllSettingType]: handleConfigureSelectAllSetting, [ConfigurePluginHostSettingType]: handleConfigurePluginHostSetting, [ConfigureFacilityImageSettingType]: handleConfigureFacilityImageSetting, + ...datafilePreviewerReducer, }); export default DGDataViewReducer; diff --git a/packages/datagateway-dataview/src/utils.test.tsx b/packages/datagateway-dataview/src/utils.test.tsx index 635dc1c81..20e5e5c8e 100644 --- a/packages/datagateway-dataview/src/utils.test.tsx +++ b/packages/datagateway-dataview/src/utils.test.tsx @@ -1,15 +1,5 @@ -import React from 'react'; import useAfterMountEffect from './utils'; -import { mount } from 'enzyme'; - -const TestHook = (props: { - callback: () => void; - triggerProp: number; - nonTriggerProp?: number; -}): React.ReactElement => { - props.callback(); - return
; -}; +import { renderHook } from '@testing-library/react-hooks'; describe('Utils', () => { describe('useAfterMountEffect', () => { @@ -20,38 +10,33 @@ describe('Utils', () => { }); it('calls effect only upon prop changes, not on mount', () => { - const wrapper = mount( - useAfterMountEffect(mockFunction)} - /> - ); + const callback = jest.fn(); - expect(mockFunction).not.toHaveBeenCalled(); + const { rerender } = renderHook(() => useAfterMountEffect(callback)); - wrapper.setProps({ triggerProp: 2 }); - expect(mockFunction).toHaveBeenCalled(); + expect(callback).not.toHaveBeenCalled(); + + rerender(); + expect(callback).toHaveBeenCalled(); }); it('respects dependency array', () => { - let triggerProp = 1; - - const wrapper = mount( - useAfterMountEffect(mockFunction, [triggerProp])} - /> + const callback = jest.fn(); + + const { rerender } = renderHook( + (testProp) => useAfterMountEffect(callback, [testProp]), + { + initialProps: 1, + } ); - expect(mockFunction).not.toHaveBeenCalled(); + expect(callback).not.toHaveBeenCalled(); - wrapper.setProps({ nonTriggerProp: 2 }); - expect(mockFunction).not.toHaveBeenCalled(); + rerender(1); + expect(callback).not.toHaveBeenCalled(); - triggerProp = 2; - wrapper.setProps({}); - expect(mockFunction).toHaveBeenCalled(); + rerender(2); + expect(callback).toHaveBeenCalled(); }); }); }); diff --git a/packages/datagateway-dataview/src/views/card/__snapshots__/datasetCardView.component.test.tsx.snap b/packages/datagateway-dataview/src/views/card/__snapshots__/datasetCardView.component.test.tsx.snap deleted file mode 100644 index bb82d5942..000000000 --- a/packages/datagateway-dataview/src/views/card/__snapshots__/datasetCardView.component.test.tsx.snap +++ /dev/null @@ -1,81 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Dataset - Card View renders correctly 1`] = ` -Object { - "buttons": Array [ - [Function], - ], - "data": Array [ - Object { - "createTime": "2019-07-23", - "id": 1, - "modTime": "2019-07-23", - "name": "Test 1", - "size": 1, - }, - ], - "description": Object { - "dataKey": "description", - "filterComponent": [Function], - "label": "datasets.details.description", - }, - "filters": Object {}, - "information": Array [ - Object { - "dataKey": "datafileCount", - "disableSort": true, - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.datafile_count", - }, - Object { - "dataKey": "createTime", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.create_time", - }, - Object { - "dataKey": "modTime", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.modified_time", - }, - ], - "loadedCount": true, - "loadedData": true, - "onFilter": [Function], - "onPageChange": [Function], - "onResultsChange": [Function], - "onSort": [Function], - "page": null, - "results": null, - "sort": Object {}, - "title": Object { - "content": [Function], - "dataKey": "name", - "filterComponent": [Function], - "label": "datasets.name", - }, - "totalDataCount": 1, -} -`; diff --git a/packages/datagateway-dataview/src/views/card/__snapshots__/investigationCardView.component.test.tsx.snap b/packages/datagateway-dataview/src/views/card/__snapshots__/investigationCardView.component.test.tsx.snap deleted file mode 100644 index 6cc06e810..000000000 --- a/packages/datagateway-dataview/src/views/card/__snapshots__/investigationCardView.component.test.tsx.snap +++ /dev/null @@ -1,137 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Investigation - Card View renders correctly 1`] = ` -Object { - "buttons": Array [ - [Function], - ], - "customFilters": Array [ - Object { - "dataKey": "type.id", - "filterItems": Array [], - "label": "investigations.type.id", - "prefixLabel": true, - }, - Object { - "dataKey": "facility.id", - "filterItems": Array [], - "label": "investigations.facility.id", - "prefixLabel": true, - }, - ], - "data": Array [ - Object { - "doi": "doi 1", - "id": 1, - "name": "Test 1", - "title": "Test 1", - "visitId": "1", - }, - ], - "description": Object { - "dataKey": "summary", - "filterComponent": [Function], - "label": "investigations.details.summary", - }, - "filters": Object {}, - "information": Array [ - Object { - "content": [Function], - "dataKey": "doi", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.doi", - }, - Object { - "dataKey": "visitId", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.visit_id", - }, - Object { - "dataKey": "name", - "disableSort": true, - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.details.name", - }, - Object { - "content": [Function], - "dataKey": "datasetCount", - "disableSort": true, - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.dataset_count", - }, - Object { - "dataKey": "startDate", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.details.start_date", - }, - Object { - "dataKey": "endDate", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.details.end_date", - }, - ], - "loadedCount": true, - "loadedData": true, - "onFilter": [Function], - "onPageChange": [Function], - "onResultsChange": [Function], - "onSort": [Function], - "page": null, - "results": null, - "sort": Object {}, - "title": Object { - "content": [Function], - "dataKey": "title", - "filterComponent": [Function], - "label": "investigations.title", - }, - "totalDataCount": 1, -} -`; diff --git a/packages/datagateway-dataview/src/views/card/datasetCardView.component.test.tsx b/packages/datagateway-dataview/src/views/card/datasetCardView.component.test.tsx index 88f702090..5bbab8537 100644 --- a/packages/datagateway-dataview/src/views/card/datasetCardView.component.test.tsx +++ b/packages/datagateway-dataview/src/views/card/datasetCardView.component.test.tsx @@ -1,24 +1,31 @@ -import { Link, ListItemText } from '@material-ui/core'; -import { createMount } from '@material-ui/core/test-utils'; import { - AdvancedFilter, + type Dataset, dGCommonInitialState, - useDatasetsPaginated, useDatasetCount, - Dataset, - AddToCartButton, + useDatasetsPaginated, } from 'datagateway-common'; -import { ReactWrapper } from 'enzyme'; -import React from 'react'; +import * as React from 'react'; import { Provider } from 'react-redux'; -import { Router } from 'react-router'; +import { Router } from 'react-router-dom'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; -import { StateType } from '../../state/app.types'; +import type { StateType } from '../../state/app.types'; import DatasetCardView from './datasetCardView.component'; import { QueryClient, QueryClientProvider } from 'react-query'; -import { createMemoryHistory, History } from 'history'; +import { createMemoryHistory, type History } from 'history'; import { initialState as dgDataViewInitialState } from '../../state/reducers/dgdataview.reducer'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, +} from '../../setupTests'; +import { + render, + type RenderResult, + screen, + within, +} from '@testing-library/react'; +import { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -32,16 +39,15 @@ jest.mock('datagateway-common', () => { }); describe('Dataset - Card View', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let cardData: Dataset[]; let history: History; + let user: UserEvent; - const createWrapper = (): ReactWrapper => { - const store = mockStore(state); - return mount( - + const renderComponent = (): RenderResult => + render( + @@ -49,22 +55,22 @@ describe('Dataset - Card View', () => { ); - }; beforeEach(() => { - mount = createMount(); cardData = [ { id: 1, name: 'Test 1', + description: 'Test description', size: 1, modTime: '2019-07-23', createTime: '2019-07-23', + datafileCount: 1, }, ]; history = createMemoryHistory(); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -85,45 +91,103 @@ describe('Dataset - Card View', () => { }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('CardView').props()).toMatchSnapshot(); - }); + it('renders datasets as cards', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - const investigationId = '1'; - createWrapper(); - expect(useDatasetCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: investigationId }, - }), - }, - ]); - expect(useDatasetsPaginated).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: investigationId }, - }), - }, - ]); + const cards = await screen.findAllByTestId('card'); + expect(cards).toHaveLength(1); + + const card = within(cards[0]); + + // check that title & description is displayed correctly + expect( + within(card.getByLabelText('card-title')).getByRole('link', { + name: 'Test 1', + }) + ).toHaveAttribute('href', '/browse/investigation/1/dataset/1/datafile'); + expect( + within(card.getByLabelText('card-description')).getByText( + 'Test description' + ) + ).toBeInTheDocument(); + + // check that datafile count is displayed correctly + expect( + card.getByTestId('card-info-datasets.datafile_count') + ).toBeInTheDocument(); + expect( + within(card.getByTestId('card-info-datasets.datafile_count')).getByTestId( + 'ConfirmationNumberIcon' + ) + ).toBeInTheDocument(); + expect( + card.getByTestId('card-info-datasets.datafile_count') + ).toHaveTextContent('datasets.datafile_count'); + expect( + within( + card.getByTestId('card-info-data-datasets.datafile_count') + ).getByText('1') + ).toBeInTheDocument(); + + // check that datafile create time is displayed correctly + expect( + card.getByTestId('card-info-datasets.create_time') + ).toBeInTheDocument(); + expect( + card.getByTestId('card-info-datasets.create_time') + ).toHaveTextContent('datasets.create_time'); + expect( + within(card.getByTestId('card-info-datasets.create_time')).getByTestId( + 'CalendarTodayIcon' + ) + ).toBeInTheDocument(); + expect( + within(card.getByTestId('card-info-data-datasets.create_time')).getByText( + '2019-07-23' + ) + ).toBeInTheDocument(); + + // check that datafile modified time is displayed correctly + expect( + card.getByTestId('card-info-datasets.modified_time') + ).toBeInTheDocument(); + expect( + card.getByTestId('card-info-datasets.modified_time') + ).toHaveTextContent('datasets.modified_time'); + expect( + within(card.getByTestId('card-info-datasets.modified_time')).getByTestId( + 'CalendarTodayIcon' + ) + ).toBeInTheDocument(); + expect( + within( + card.getByTestId('card-info-data-datasets.modified_time') + ).getByText('2019-07-23') + ).toBeInTheDocument(); + + // check that buttons are displayed correctly + expect( + card.getByRole('button', { name: 'buttons.add_to_cart' }) + ).toBeInTheDocument(); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: 'test' } }); + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); + + const filter = await screen.findByRole('textbox', { + name: 'Filter by datasets.name', + hidden: true, + }); + + await user.type(filter, 'test'); expect(history.location.search).toBe( `?filters=${encodeURIComponent( @@ -131,58 +195,57 @@ describe('Dataset - Card View', () => { )}` ); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: '' } }); + await user.clear(filter); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '2019-08-06' } }); + renderComponent(); + + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); + + const filter = await screen.findByRole('textbox', { + name: 'datasets.modified_time filter to', + }); + + await user.type(filter, '2019-08-06'); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"modTime":{"endDate":"2019-08-06"}}')}` ); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '' } }); + // await user.clear(filter); + await user.click(filter); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - const button = wrapper.find(ListItemText).first(); - expect(button.text()).toEqual('datasets.name'); - button.simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'Sort by DATASETS.NAME' }) + ); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"name":"asc"}')}` ); }); - it('renders buttons correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find(AddToCartButton).exists()).toBeTruthy(); - expect(wrapper.find(AddToCartButton).text()).toEqual('buttons.add_to_cart'); - }); - it('renders fine with incomplete data', () => { (useDatasetCount as jest.Mock).mockReturnValue({}); (useDatasetsPaginated as jest.Mock).mockReturnValue({}); - expect(() => createWrapper()).not.toThrowError(); + expect(() => renderComponent()).not.toThrowError(); }); }); diff --git a/packages/datagateway-dataview/src/views/card/datasetCardView.component.tsx b/packages/datagateway-dataview/src/views/card/datasetCardView.component.tsx index 8f8c01018..71ede5e86 100644 --- a/packages/datagateway-dataview/src/views/card/datasetCardView.component.tsx +++ b/packages/datagateway-dataview/src/views/card/datasetCardView.component.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { ConfirmationNumber, CalendarToday } from '@material-ui/icons'; +import { ConfirmationNumber, CalendarToday } from '@mui/icons-material'; import { CardView, Dataset, @@ -111,14 +111,16 @@ const DatasetCardView = (props: DatasetCardViewProps): React.ReactElement => { entityType="dataset" allIds={data?.map((dataset) => dataset.id) ?? []} entityId={dataset.id} + parentId={investigationId} /> ), ], - [data] + [data, investigationId] ); return ( { const originalModule = jest.requireActual('datagateway-common'); @@ -33,16 +34,15 @@ jest.mock('datagateway-common', () => { }); describe('DLS Datasets - Card View', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let cardData: Dataset[]; let history: History; + let user: UserEvent; - const createWrapper = (): ReactWrapper => { - const store = mockStore(state); - return mount( - + const renderComponent = (): RenderResult => + render( + @@ -50,21 +50,21 @@ describe('DLS Datasets - Card View', () => { ); - }; beforeEach(() => { - mount = createMount(); cardData = [ { id: 1, name: 'Test 1', modTime: '2019-07-23', createTime: '2019-07-23', + fileSize: 1, + fileCount: 1, }, ]; history = createMemoryHistory(); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -86,48 +86,23 @@ describe('DLS Datasets - Card View', () => { }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('CardView').props()).toMatchSnapshot(); - }); + it('updates filter query params on text filter', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - const investigationId = '1'; - createWrapper(); - expect(useDatasetCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: investigationId }, - }), - }, - ]); - expect(useDatasetsPaginated).toHaveBeenCalledWith( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: investigationId }, - }), - }, - ], - expect.any(Boolean) + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) ); - }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + const filter = await screen.findByRole('textbox', { + name: 'Filter by datasets.name', + hidden: true, + }); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: 'test' } }); + await user.type(filter, 'test'); expect(history.location.search).toBe( `?filters=${encodeURIComponent( @@ -135,40 +110,43 @@ describe('DLS Datasets - Card View', () => { )}` ); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: '' } }); + await user.clear(filter); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '2019-08-06' } }); + renderComponent(); + + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); + + const filter = await screen.findByRole('textbox', { + name: 'datasets.details.end_date filter to', + }); + + await user.type(filter, '2019-08-06'); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"endDate":{"endDate":"2019-08-06"}}')}` ); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '' } }); + // await user.clear(filter); + await user.click(filter); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"createTime":"desc"}')}` @@ -183,39 +161,37 @@ describe('DLS Datasets - Card View', () => { ); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - const button = wrapper.find(ListItemText).first(); - expect(button.text()).toEqual('datasets.name'); - button.simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'Sort by DATASETS.NAME' }) + ); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"name":"asc"}')}` ); - }); + }, 10000); - it('displays details panel when more information is expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(DLSDatasetDetailsPanel).exists()).toBeFalsy(); - wrapper - .find('[aria-label="card-more-info-expand"]') - .first() - .simulate('click'); - - expect(wrapper.find(DLSDatasetDetailsPanel).exists()).toBeTruthy(); + it('displays details panel when more information is expanded', async () => { + renderComponent(); + await user.click( + await screen.findByRole('button', { name: 'card-more-info-expand' }) + ); + expect(screen.findByTestId('dataset-details-panel')).toBeTruthy(); }); - it('renders buttons correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find(AddToCartButton).exists()).toBeTruthy(); - expect(wrapper.find(AddToCartButton).text()).toEqual('buttons.add_to_cart'); + it('renders buttons correctly', async () => { + renderComponent(); + expect( + await screen.findByRole('button', { name: 'buttons.add_to_cart' }) + ).toBeInTheDocument(); }); it('renders fine with incomplete data', () => { (useDatasetCount as jest.Mock).mockReturnValueOnce({}); (useDatasetsPaginated as jest.Mock).mockReturnValueOnce({}); - expect(() => createWrapper()).not.toThrowError(); + expect(() => renderComponent()).not.toThrowError(); }); }); diff --git a/packages/datagateway-dataview/src/views/card/dls/dlsDatasetsCardView.component.tsx b/packages/datagateway-dataview/src/views/card/dls/dlsDatasetsCardView.component.tsx index 40d17caed..d13b455ea 100644 --- a/packages/datagateway-dataview/src/views/card/dls/dlsDatasetsCardView.component.tsx +++ b/packages/datagateway-dataview/src/views/card/dls/dlsDatasetsCardView.component.tsx @@ -3,7 +3,6 @@ import { CardView, CardViewDetails, Dataset, - formatCountOrSize, tableLink, parseSearchToQuery, useDateFilter, @@ -14,14 +13,14 @@ import { usePushResults, useSort, useTextFilter, - useDatasetsDatafileCount, AddToCartButton, DLSDatasetDetailsPanel, + formatBytes, } from 'datagateway-common'; -import { CalendarToday } from '@material-ui/icons'; -import ConfirmationNumberIcon from '@material-ui/icons/ConfirmationNumber'; +import { CalendarToday, Save } from '@mui/icons-material'; +import ConfirmationNumberIcon from '@mui/icons-material/ConfirmationNumber'; import { useTranslation } from 'react-i18next'; -import { useLocation } from 'react-router'; +import { useLocation } from 'react-router-dom'; interface DLSDatasetsCVProps { proposalName: string; @@ -74,8 +73,6 @@ const DLSDatasetsCardView = (props: DLSDatasetsCVProps): React.ReactElement => { isMounted ); - const datafileCountQueries = useDatasetsDatafileCount(data); - const title: CardViewDetails = React.useMemo( () => ({ // Provide label for filter component. @@ -107,13 +104,14 @@ const DLSDatasetsCardView = (props: DLSDatasetsCVProps): React.ReactElement => { { icon: ConfirmationNumberIcon, label: t('datasets.datafile_count'), - dataKey: 'datafileCount', - content: (dataset: Dataset): string => { - const index = data?.findIndex((item) => item.id === dataset.id); - if (typeof index === 'undefined') return 'Unknown'; - return formatCountOrSize(datafileCountQueries[index]); - }, - disableSort: true, + dataKey: 'fileCount', + }, + { + icon: Save, + label: t('datasets.size'), + dataKey: 'fileSize', + cellContentRenderer: (dataset: Dataset): string => + formatBytes(dataset.fileSize), }, { icon: CalendarToday, @@ -141,7 +139,7 @@ const DLSDatasetsCardView = (props: DLSDatasetsCVProps): React.ReactElement => { filterComponent: dateFilter, }, ], - [data, datafileCountQueries, dateFilter, t] + [dateFilter, t] ); const buttons = React.useMemo( @@ -151,14 +149,16 @@ const DLSDatasetsCardView = (props: DLSDatasetsCVProps): React.ReactElement => { entityType="dataset" allIds={data?.map((dataset) => dataset.id) ?? []} entityId={dataset.id} + parentId={investigationId} /> ), ], - [data] + [data, investigationId] ); return ( { const originalModule = jest.requireActual('datagateway-common'); @@ -31,16 +30,15 @@ jest.mock('datagateway-common', () => { }); describe('DLS Proposals - Card View', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let cardData: Investigation[]; let history: History; + let user: UserEvent; - const createWrapper = (): ReactWrapper => { - const store = mockStore(state); - return mount( - + const renderComponent = (): RenderResult => + render( + @@ -48,10 +46,8 @@ describe('DLS Proposals - Card View', () => { ); - }; beforeEach(() => { - mount = createMount(); cardData = [ { id: 1, @@ -61,8 +57,8 @@ describe('DLS Proposals - Card View', () => { }, ]; history = createMemoryHistory(); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -84,44 +80,23 @@ describe('DLS Proposals - Card View', () => { }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('CardView').props()).toMatchSnapshot(); - }); + it('updates filter query params on text filter', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - createWrapper(); - expect(useInvestigationCount).toHaveBeenCalledWith([ - { - filterType: 'distinct', - filterValue: JSON.stringify(['name', 'title']), - }, - ]); - expect(useInvestigationsPaginated).toHaveBeenCalledWith( - [ - { - filterType: 'distinct', - filterValue: JSON.stringify(['name', 'title']), - }, - ], - true, - expect.any(Boolean) + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) ); - }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + const filter = await screen.findByRole('textbox', { + name: 'Filter by investigations.title', + hidden: true, + }); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: 'test' } }); + await user.type(filter, 'test'); expect(history.location.search).toBe( `?filters=${encodeURIComponent( @@ -129,18 +104,13 @@ describe('DLS Proposals - Card View', () => { )}` ); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: '' } }); + await user.clear(filter); expect(history.location.search).toBe('?'); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"title":"asc"}')}` @@ -164,6 +134,6 @@ describe('DLS Proposals - Card View', () => { (useInvestigationCount as jest.Mock).mockReturnValueOnce({}); (useInvestigationsPaginated as jest.Mock).mockReturnValueOnce({}); - expect(() => createWrapper()).not.toThrowError(); + expect(() => renderComponent()).not.toThrowError(); }); }); diff --git a/packages/datagateway-dataview/src/views/card/dls/dlsProposalsCardView.component.tsx b/packages/datagateway-dataview/src/views/card/dls/dlsProposalsCardView.component.tsx index 6830e1ffa..33cb01cd9 100644 --- a/packages/datagateway-dataview/src/views/card/dls/dlsProposalsCardView.component.tsx +++ b/packages/datagateway-dataview/src/views/card/dls/dlsProposalsCardView.component.tsx @@ -39,15 +39,13 @@ const DLSProposalsCardView = (): React.ReactElement => { setIsMounted(true); }, []); - const { - data: totalDataCount, - isLoading: countLoading, - } = useInvestigationCount([ - { - filterType: 'distinct', - filterValue: JSON.stringify(['name', 'title']), - }, - ]); + const { data: totalDataCount, isLoading: countLoading } = + useInvestigationCount([ + { + filterType: 'distinct', + filterValue: JSON.stringify(['name', 'title']), + }, + ]); const { isLoading: dataLoading, data } = useInvestigationsPaginated( [ { @@ -93,6 +91,7 @@ const DLSProposalsCardView = (): React.ReactElement => { return ( { const originalModule = jest.requireActual('datagateway-common'); @@ -29,21 +30,19 @@ jest.mock('datagateway-common', () => { ...originalModule, useInvestigationCount: jest.fn(), useInvestigationsPaginated: jest.fn(), - useInvestigationsDatasetCount: jest.fn(), }; }); describe('DLS Visits - Card View', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let cardData: Investigation[]; let history: History; + let user: UserEvent; - const createWrapper = (): ReactWrapper => { - const store = mockStore(state); - return mount( - + const renderComponent = (): RenderResult => + render( + @@ -51,21 +50,21 @@ describe('DLS Visits - Card View', () => { ); - }; beforeEach(() => { - mount = createMount(); cardData = [ { id: 1, title: 'Test 1', name: 'Test 1', visitId: '1', + fileSize: 1, + fileCount: 1, }, ]; history = createMemoryHistory(); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -81,100 +80,73 @@ describe('DLS Visits - Card View', () => { data: cardData, isLoading: false, }); - (useInvestigationsDatasetCount as jest.Mock).mockReturnValue({ data: 1 }); // Prevent error logging window.scrollTo = jest.fn(); }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('CardView').props()).toMatchSnapshot(); - }); + it('updates filter query params on text filter', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - const proposalName = 'test'; - createWrapper(); - expect(useInvestigationCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ name: { eq: proposalName } }), - }, - ]); - expect(useInvestigationsPaginated).toHaveBeenCalledWith( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ name: { eq: proposalName } }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - investigationInstruments: 'instrument', - }), - }, - ], - undefined, - expect.any(Boolean) + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) ); - expect(useInvestigationsDatasetCount).toHaveBeenCalledWith(cardData); - }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + const filter = await screen.findByRole('textbox', { + name: 'Filter by investigations.visit_id', + hidden: true, + }); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '2019-08-06' } }); + await user.type(filter, 'test'); expect(history.location.search).toBe( - `?filters=${encodeURIComponent('{"endDate":{"endDate":"2019-08-06"}}')}` + `?filters=${encodeURIComponent( + '{"visitId":{"value":"test","type":"include"}}' + )}` ); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '' } }); + await user.clear(filter); expect(history.location.search).toBe('?'); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: 'test' } }); + renderComponent(); + + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); + + const filter = await screen.findByRole('textbox', { + name: 'investigations.end_date filter to', + }); + + await user.type(filter, '2019-08-06'); expect(history.location.search).toBe( - `?filters=${encodeURIComponent( - '{"visitId":{"value":"test","type":"include"}}' - )}` + `?filters=${encodeURIComponent('{"endDate":{"endDate":"2019-08-06"}}')}` ); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: '' } }); + // await user.clear(filter); + await user.click(filter); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"startDate":"desc"}')}` @@ -194,34 +166,32 @@ describe('DLS Visits - Card View', () => { ); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - const button = wrapper.find(ListItemText).first(); - expect(button.text()).toEqual('investigations.visit_id'); - button.simulate('click'); + await user.click( + await screen.findByRole('button', { + name: 'Sort by INVESTIGATIONS.VISIT_ID', + }) + ); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"visitId":"asc"}')}` ); }); - it('displays details panel when more information is expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(DLSVisitDetailsPanel).exists()).toBeFalsy(); - wrapper - .find('[aria-label="card-more-info-expand"]') - .first() - .simulate('click'); - - expect(wrapper.find(DLSVisitDetailsPanel).exists()).toBeTruthy(); + it('displays details panel when more information is expanded', async () => { + renderComponent(); + await user.click(await screen.findByLabelText('card-more-info-expand')); + expect( + await screen.findByTestId('dls-visit-details-panel') + ).toBeInTheDocument(); }); it('renders fine with incomplete data', () => { (useInvestigationCount as jest.Mock).mockReturnValueOnce({}); (useInvestigationsPaginated as jest.Mock).mockReturnValueOnce({}); - (useInvestigationsDatasetCount as jest.Mock).mockReturnValueOnce([]); - expect(() => createWrapper()).not.toThrowError(); + expect(() => renderComponent()).not.toThrowError(); }); }); diff --git a/packages/datagateway-dataview/src/views/card/dls/dlsVisitsCardView.component.tsx b/packages/datagateway-dataview/src/views/card/dls/dlsVisitsCardView.component.tsx index a442f51b6..b11fc2d07 100644 --- a/packages/datagateway-dataview/src/views/card/dls/dlsVisitsCardView.component.tsx +++ b/packages/datagateway-dataview/src/views/card/dls/dlsVisitsCardView.component.tsx @@ -3,7 +3,6 @@ import React from 'react'; import { CardView, CardViewDetails, - formatCountOrSize, Investigation, tableLink, parseSearchToQuery, @@ -15,19 +14,15 @@ import { usePushResults, useSort, useTextFilter, - useInvestigationsDatasetCount, nestedValue, ArrowTooltip, DLSVisitDetailsPanel, + formatBytes, } from 'datagateway-common'; -import { - Assessment, - CalendarToday, - ConfirmationNumber, -} from '@material-ui/icons'; +import { Assessment, CalendarToday, Save } from '@mui/icons-material'; import { useTranslation } from 'react-i18next'; import { useLocation } from 'react-router-dom'; -import { Typography } from '@material-ui/core'; +import { Typography } from '@mui/material'; interface DLSVisitsCVProps { proposalName: string; @@ -59,15 +54,13 @@ const DLSVisitsCardView = (props: DLSVisitsCVProps): React.ReactElement => { setIsMounted(true); }, []); - const { - data: totalDataCount, - isLoading: countLoading, - } = useInvestigationCount([ - { - filterType: 'where', - filterValue: JSON.stringify({ name: { eq: proposalName } }), - }, - ]); + const { data: totalDataCount, isLoading: countLoading } = + useInvestigationCount([ + { + filterType: 'where', + filterValue: JSON.stringify({ name: { eq: proposalName } }), + }, + ]); const { isLoading: dataLoading, data } = useInvestigationsPaginated( [ { @@ -84,7 +77,6 @@ const DLSVisitsCardView = (props: DLSVisitsCVProps): React.ReactElement => { undefined, isMounted ); - const countQueries = useInvestigationsDatasetCount(data); const title = React.useMemo( () => ({ @@ -131,15 +123,11 @@ const DLSVisitsCardView = (props: DLSVisitsCVProps): React.ReactElement => { filterComponent: textFilter, }, { - icon: ConfirmationNumber, - label: t('investigations.dataset_count'), - dataKey: 'datasetCount', - content: (investigation: Investigation): string => { - const index = data?.findIndex((item) => item.id === investigation.id); - if (typeof index === 'undefined') return 'Unknown'; - return formatCountOrSize(countQueries[index]); - }, - disableSort: true, + icon: Save, + label: t('investigations.details.size'), + dataKey: 'fileSize', + content: (investigation: Investigation): number | string => + formatBytes(investigation.fileSize), }, { icon: CalendarToday, @@ -155,11 +143,12 @@ const DLSVisitsCardView = (props: DLSVisitsCVProps): React.ReactElement => { filterComponent: dateFilter, }, ], - [countQueries, data, dateFilter, t, textFilter] + [dateFilter, t, textFilter] ); return ( { - const originalModule = jest.requireActual('datagateway-common'); - - return { - __esModule: true, - ...originalModule, - useInvestigationCount: jest.fn(), - useInvestigationsPaginated: jest.fn(), - useInvestigationsDatasetCount: jest.fn(), - }; -}); +import { createMemoryHistory, type History } from 'history'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, +} from '../../setupTests'; +import { + render, + type RenderResult, + screen, + within, +} from '@testing-library/react'; +import type { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; +import axios, { AxiosResponse } from 'axios'; describe('Investigation - Card View', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let cardData: Investigation[]; let history: History; + let user: UserEvent; + let cartItems: DownloadCartItem[]; - const createWrapper = (): ReactWrapper => { - const store = mockStore(state); - return mount( - + const renderComponent = (): RenderResult => + render( + @@ -58,22 +45,26 @@ describe('Investigation - Card View', () => { ); - }; beforeEach(() => { - mount = createMount(); + cartItems = []; cardData = [ { id: 1, - title: 'Test 1', - name: 'Test 1', - visitId: '1', + fileSize: 1, + fileCount: 1, + title: 'Test title 1', + summary: 'Test summary', + name: 'Test name 1', + visitId: 'visit id 1', doi: 'doi 1', + startDate: '2020-01-01', + endDate: '2020-01-02', }, ]; history = createMemoryHistory(); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -81,46 +72,166 @@ describe('Investigation - Card View', () => { }) ); - (useInvestigationCount as jest.Mock).mockReturnValue({ - data: 1, - isLoading: false, - }); - (useInvestigationsPaginated as jest.Mock).mockReturnValue({ - data: cardData, - isLoading: false, - }); - (useInvestigationsDatasetCount as jest.Mock).mockReturnValue({ data: 1 }); + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + if (url.includes('/investigations/count')) { + return Promise.resolve({ + data: 1, + }); + } + + if (url.includes('/investigations')) { + return Promise.resolve({ + data: cardData, + }); + } + + if (url.includes('/user/cart')) { + return Promise.resolve({ + data: { cartItems }, + }); + } + + return Promise.reject(`Endpoint not mocked: ${url}`); + }); // Prevent error logging window.scrollTo = jest.fn(); }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('CardView').props()).toMatchSnapshot(); - }); + it('renders investigations as cards', async () => { + renderComponent(); + + const cards = await screen.findAllByTestId('card'); + expect(cards).toHaveLength(1); + + const card = within(cards[0]); + + // check that title & description is displayed correctly + expect( + within(card.getByLabelText('card-title')).getByRole('link', { + name: 'Test title 1', + }) + ).toHaveAttribute('href', '/browse/investigation/1/dataset'); + expect( + within(card.getByLabelText('card-description')).getByText('Test summary') + ).toBeInTheDocument(); - it('calls the correct data fetching hooks on load', () => { - createWrapper(); - expect(useInvestigationCount).toHaveBeenCalled(); - expect(useInvestigationsPaginated).toHaveBeenCalled(); - expect(useInvestigationsDatasetCount).toHaveBeenCalledWith(cardData); + // check that investigation doi is displayed correctly + expect( + within(card.getByTestId('card-info-investigations.doi')).getByTestId( + 'PublicIcon' + ) + ).toBeInTheDocument(); + expect(card.getByTestId('card-info-investigations.doi')).toHaveTextContent( + 'investigations.doi' + ); + expect( + within(card.getByTestId('card-info-data-investigations.doi')).getByRole( + 'link', + { name: 'doi 1' } + ) + ).toHaveAttribute('href', 'https://doi.org/doi 1'); + + // check that visit id is displayed correctly + expect( + card.getByTestId('card-info-investigations.visit_id') + ).toHaveTextContent('investigations.visit_id'); + expect( + within(card.getByTestId('card-info-investigations.visit_id')).getByTestId( + 'FingerprintIcon' + ) + ).toBeInTheDocument(); + expect( + within( + card.getByTestId('card-info-data-investigations.visit_id') + ).getByText('visit id 1') + ).toBeInTheDocument(); + + // check that investigation name is displayed correctly + expect( + card.getByTestId('card-info-investigations.details.name') + ).toHaveTextContent('investigations.details.name'); + expect( + within( + card.getByTestId('card-info-investigations.details.name') + ).getByTestId('FingerprintIcon') + ).toBeInTheDocument(); + expect( + within( + card.getByTestId('card-info-data-investigations.details.name') + ).getByText('Test name 1') + ).toBeInTheDocument(); + + // check that investigation size is displayed correctly + expect( + card.getByTestId('card-info-investigations.details.size') + ).toHaveTextContent('investigations.details.size'); + expect( + within( + card.getByTestId('card-info-investigations.details.size') + ).getByTestId('SaveIcon') + ).toBeInTheDocument(); + expect( + within( + card.getByTestId('card-info-data-investigations.details.size') + ).getByText('1 B') + ).toBeInTheDocument(); + + // check that investigation start date is displayed correctly + expect( + card.getByTestId('card-info-investigations.details.start_date') + ).toHaveTextContent('investigations.details.start_date'); + expect( + within( + card.getByTestId('card-info-investigations.details.start_date') + ).getByTestId('CalendarTodayIcon') + ).toBeInTheDocument(); + expect( + within( + card.getByTestId('card-info-data-investigations.details.start_date') + ).getByText('2020-01-01') + ).toBeInTheDocument(); + + // check that investigation start date is displayed correctly + expect( + card.getByTestId('card-info-investigations.details.end_date') + ).toHaveTextContent('investigations.details.end_date'); + expect( + within( + card.getByTestId('card-info-investigations.details.end_date') + ).getByTestId('CalendarTodayIcon') + ).toBeInTheDocument(); + expect( + within( + card.getByTestId('card-info-data-investigations.details.end_date') + ).getByText('2020-01-02') + ).toBeInTheDocument(); + + // check that card buttons are displayed correctly + expect( + card.getByRole('button', { name: 'buttons.add_to_cart' }) + ).toBeInTheDocument(); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: 'test' } }); + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); + + const filter = await screen.findByRole('textbox', { + name: 'Filter by investigations.title', + hidden: true, + }); + + await user.type(filter, 'test'); expect(history.location.search).toBe( `?filters=${encodeURIComponent( @@ -128,75 +239,51 @@ describe('Investigation - Card View', () => { )}` ); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: '' } }); + await user.clear(filter); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); + + renderComponent(); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '2019-08-06' } }); + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); + + const filter = await screen.findByRole('textbox', { + name: 'investigations.details.end_date filter to', + }); + + await user.type(filter, '2019-08-06'); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"endDate":{"endDate":"2019-08-06"}}')}` ); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '' } }); + // await user.clear(filter); + await user.click(filter); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.location.search).toBe('?'); - }); - - it('displays DOI and renders the expected Link ', () => { - const wrapper = createWrapper(); - expect( - wrapper.find('[data-testid="investigation-card-doi-link"]').first().text() - ).toEqual('doi 1'); - expect( - wrapper - .find('[data-testid="investigation-card-doi-link"]') - .first() - .prop('href') - ).toEqual('https://doi.org/doi 1'); + cleanupDatePickerWorkaround(); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - const button = wrapper.find(ListItemText).first(); - expect(button.text()).toEqual('investigations.title'); - button.simulate('click'); + await user.click( + await screen.findByRole('button', { + name: 'Sort by INVESTIGATIONS.TITLE', + }) + ); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"title":"asc"}')}` ); }); - - it('renders buttons correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find(AddToCartButton).exists()).toBeTruthy(); - expect(wrapper.find(AddToCartButton).text()).toEqual('buttons.add_to_cart'); - }); - - it('renders fine with incomplete data', () => { - (useInvestigationCount as jest.Mock).mockReturnValueOnce({}); - (useInvestigationsPaginated as jest.Mock).mockReturnValueOnce({}); - (useInvestigationsDatasetCount as jest.Mock).mockReturnValueOnce([ - { data: 0 }, - ]); - - expect(() => createWrapper()).not.toThrowError(); - }); }); diff --git a/packages/datagateway-dataview/src/views/card/investigationCardView.component.tsx b/packages/datagateway-dataview/src/views/card/investigationCardView.component.tsx index 600b93c22..6088f7200 100644 --- a/packages/datagateway-dataview/src/views/card/investigationCardView.component.tsx +++ b/packages/datagateway-dataview/src/views/card/investigationCardView.component.tsx @@ -1,13 +1,7 @@ -import { - CalendarToday, - ConfirmationNumber, - Fingerprint, - Public, -} from '@material-ui/icons'; -import { Link as MuiLink } from '@material-ui/core'; +import { CalendarToday, Save, Fingerprint, Public } from '@mui/icons-material'; +import { Link as MuiLink } from '@mui/material'; import { CardView, - formatCountOrSize, formatFilterCount, Investigation, investigationLink, @@ -16,7 +10,6 @@ import { useCustomFilter, useCustomFilterCount, useInvestigationCount, - useInvestigationsDatasetCount, useInvestigationsPaginated, usePushFilter, usePushPage, @@ -24,6 +17,7 @@ import { useSort, useTextFilter, AddToCartButton, + formatBytes, } from 'datagateway-common'; import React from 'react'; import { useTranslation } from 'react-i18next'; @@ -45,10 +39,8 @@ const InvestigationCardView = (): React.ReactElement => { const pushPage = usePushPage(); const pushResults = usePushResults(); - const { - data: totalDataCount, - isLoading: countLoading, - } = useInvestigationCount(); + const { data: totalDataCount, isLoading: countLoading } = + useInvestigationCount(); const { isLoading: dataLoading, data } = useInvestigationsPaginated([ { @@ -60,7 +52,6 @@ const InvestigationCardView = (): React.ReactElement => { filterValue: JSON.stringify('facility'), }, ]); - const countQueries = useInvestigationsDatasetCount(data); const { data: typeIds } = useCustomFilter('investigation', 'type.id'); const { data: facilityIds } = useCustomFilter('investigation', 'facility.id'); @@ -137,14 +128,11 @@ const InvestigationCardView = (): React.ReactElement => { disableSort: true, }, { - icon: ConfirmationNumber, - label: t('investigations.dataset_count'), - dataKey: 'datasetCount', - content: (investigation: Investigation): string => { - const index = data?.findIndex((item) => item.id === investigation.id); - if (typeof index === 'undefined') return 'Unknown'; - return formatCountOrSize(countQueries[index]); - }, + icon: Save, + label: t('investigations.details.size'), + dataKey: 'size', + content: (investigation: Investigation): number | string => + formatBytes(investigation.fileSize), disableSort: true, }, { @@ -160,7 +148,7 @@ const InvestigationCardView = (): React.ReactElement => { filterComponent: dateFilter, }, ], - [countQueries, data, dateFilter, t, textFilter] + [dateFilter, t, textFilter] ); const buttons = React.useMemo( @@ -206,6 +194,7 @@ const InvestigationCardView = (): React.ReactElement => { return ( { + const mockStore = configureStore([thunk]); + let state: StateType; + let cardData: DataPublication[]; + let history: History; + + const renderComponent = (studyDataPublicationId?: string): RenderResult => { + if (studyDataPublicationId) + history.replace( + generatePath( + paths.dataPublications.toggle.isisInvestigationDataPublication, + { + instrumentId: 1, + studyDataPublicationId, + } + ) + ); + return render( + + + + + + + + ); + }; + + beforeEach(() => { + cardData = [ + { + id: 14, + pid: 'doi', + title: 'Test 1', + description: 'Data Publication Description', + publicationDate: '2001-01-01', + content: { + id: 1, + dataCollectionInvestigations: [ + { + id: 1, + investigation: { + id: 711, + title: 'investigation title', + name: 'investigation name', + visitId: 'IPim0', + startDate: '1999-01-01', + endDate: '1999-01-02', + }, + }, + ], + }, + }, + ]; + history = createMemoryHistory({ + initialEntries: [ + generatePath(paths.dataPublications.toggle.isisStudyDataPublication, { + instrumentId: 1, + }), + ], + }); + + state = JSON.parse( + JSON.stringify({ + dgcommon: dGCommonInitialState, + dgdataview: dgDataViewInitialState, + }) + ); + + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + switch (url) { + case '/datapublications': + return Promise.resolve({ + data: cardData, + }); + + case '/datapublications/count': + return Promise.resolve({ + data: 1, + }); + default: + return Promise.reject(`Endpoint not mocked: ${url}`); + } + }); + + // Prevent error logging + window.scrollTo = jest.fn(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('Study Data Publication', () => { + it('renders correctly', async () => { + renderComponent(); + + const cards = await screen.findAllByTestId( + 'isis-dataPublications-card-view' + ); + expect(cards).toHaveLength(1); + + const card = cards[0]; + // card id should be rendered as link to data publication + expect( + within(card).getByRole('link', { name: 'Test 1' }) + ).toHaveAttribute( + 'href', + '/browseDataPublications/instrument/1/dataPublication/14' + ); + expect(within(card).getByLabelText('card-description')).toHaveTextContent( + 'Data Publication Description' + ); + expect(within(card).getByRole('link', { name: 'doi' })).toHaveAttribute( + 'href', + 'https://doi.org/doi' + ); + }); + + it('uses default sort', () => { + renderComponent(); + expect(history.length).toBe(1); + expect(history.location.search).toBe( + `?sort=${encodeURIComponent('{"title":"desc"}')}` + ); + + // check that the data request is sent only once after mounting + const datafilesCalls = (axios.get as jest.Mock).mock.calls.filter( + (call) => call[0] === '/datapublications' + ); + expect(datafilesCalls).toHaveLength(1); + }); + + it('updates filter query params on text filter', async () => { + jest.useFakeTimers(); + const user = userEvent.setup({ + advanceTimers: jest.advanceTimersByTime, + }); + + renderComponent(); + + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); + + const filter = await screen.findByRole('textbox', { + name: 'Filter by datapublications.title', + hidden: true, + }); + + await user.type(filter, 'Test'); + + expect(history.location.search).toBe( + `?filters=${encodeURIComponent( + '{"title":{"value":"Test","type":"include"}}' + )}` + ); + + await user.clear(filter); + + expect(history.location.search).toBe('?'); + + jest.useRealTimers(); + }); + + it('updates sort query params on sort', async () => { + const user = userEvent.setup(); + + renderComponent(); + + await user.click( + await screen.findByRole('button', { + name: 'Sort by DATAPUBLICATIONS.PID', + }) + ); + + expect(history.location.search).toBe( + `?sort=${encodeURIComponent('{"pid":"asc"}')}` + ); + }); + }); + + describe('Investigation Data Publication', () => { + it('renders correctly', async () => { + renderComponent('2'); + + const cards = await screen.findAllByTestId( + 'isis-dataPublications-card-view' + ); + expect(cards).toHaveLength(1); + + const card = cards[0]; + // card id should be rendered as link to data publication + expect( + within(card).getByRole('link', { name: 'Test 1' }) + ).toHaveAttribute( + 'href', + '/browseDataPublications/instrument/1/dataPublication/2/investigation/14' + ); + expect(within(card).getByLabelText('card-description')).toHaveTextContent( + 'Data Publication Description' + ); + expect(within(card).getByRole('link', { name: 'doi' })).toHaveAttribute( + 'href', + 'https://doi.org/doi' + ); + expect(within(card).getByText('2001-01-01')).toBeInTheDocument(); + }); + + it('uses default sort', () => { + renderComponent('2'); + expect(history.length).toBe(1); + expect(history.location.search).toBe( + `?sort=${encodeURIComponent('{"publicationDate":"desc"}')}` + ); + + // check that the data request is sent only once after mounting + const datafilesCalls = (axios.get as jest.Mock).mock.calls.filter( + (call) => call[0] === '/datapublications' + ); + expect(datafilesCalls).toHaveLength(1); + }); + + it('updates filter query params on date filter', async () => { + const user = userEvent.setup(); + applyDatePickerWorkaround(); + + renderComponent('2'); + + // open advanced filter + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); + + const filterInput = screen.getByRole('textbox', { + name: 'datapublications.publication_date filter to', + }); + + await user.type(filterInput, '2019-08-06'); + expect(history.location.search).toBe( + `?filters=${encodeURIComponent( + '{"publicationDate":{"endDate":"2019-08-06"}}' + )}` + ); + + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); + + expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); + }); + }); +}); diff --git a/packages/datagateway-dataview/src/views/card/isis/isisDataPublicationsCardView.component.tsx b/packages/datagateway-dataview/src/views/card/isis/isisDataPublicationsCardView.component.tsx new file mode 100644 index 000000000..3024fefbd --- /dev/null +++ b/packages/datagateway-dataview/src/views/card/isis/isisDataPublicationsCardView.component.tsx @@ -0,0 +1,226 @@ +import React from 'react'; +import { + CardView, + CardViewDetails, + parseSearchToQuery, + DataPublication, + tableLink, + useDateFilter, + usePushFilter, + usePushPage, + usePushResults, + useSort, + useDataPublicationsPaginated, + useDataPublicationCount, + useTextFilter, +} from 'datagateway-common'; +import { Public, CalendarToday } from '@mui/icons-material'; +import { useTranslation } from 'react-i18next'; +import { useLocation } from 'react-router-dom'; +import { Link as MuiLink } from '@mui/material'; + +interface ISISDataPublicationsCVProps { + instrumentId: string; + studyDataPublicationId?: string; +} + +const ISISDataPublicationsCardView = ( + props: ISISDataPublicationsCVProps +): React.ReactElement => { + const { instrumentId, studyDataPublicationId } = props; + + const [t] = useTranslation(); + const location = useLocation(); + + const { filters, view, sort, page, results } = React.useMemo( + () => parseSearchToQuery(location.search), + [location.search] + ); + + const textFilter = useTextFilter(filters); + const dateFilter = useDateFilter(filters); + const handleSort = useSort(); + const pushFilter = usePushFilter(); + const pushPage = usePushPage(); + const pushResults = usePushResults(); + + // isMounted is used to disable queries when the component isn't fully mounted. + // It prevents the request being sent twice if default sort is set. + // It is not needed for cards/tables that don't have default sort. + const [isMounted, setIsMounted] = React.useState(false); + React.useEffect(() => { + setIsMounted(true); + }, []); + + const { data: totalDataCount, isLoading: countLoading } = + useDataPublicationCount([ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'content.dataCollectionInvestigations.investigation.investigationInstruments.instrument.id': + { + eq: instrumentId, + }, + }), + }, + ...(studyDataPublicationId + ? [ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'content.dataCollectionInvestigations.investigation.dataCollectionInvestigations.dataCollection.dataPublications.id': + { + eq: studyDataPublicationId, + }, + }), + }, + { + filterType: 'where', + filterValue: JSON.stringify({ + 'type.name': { eq: 'investigation' }, + }), + }, + ] + : [ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'type.name': { eq: 'study' }, + }), + }, + { + filterType: 'distinct', + filterValue: JSON.stringify(['id', 'title', 'pid']), + }, + ]), + ]); + + const { isLoading: dataLoading, data } = useDataPublicationsPaginated( + [ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'content.dataCollectionInvestigations.investigation.investigationInstruments.instrument.id': + { + eq: instrumentId, + }, + }), + }, + ...(studyDataPublicationId + ? [ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'content.dataCollectionInvestigations.investigation.dataCollectionInvestigations.dataCollection.dataPublications.id': + { + eq: studyDataPublicationId, + }, + }), + }, + { + filterType: 'where', + filterValue: JSON.stringify({ + 'type.name': { eq: 'investigation' }, + }), + }, + ] + : [ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'type.name': { eq: 'study' }, + }), + }, + { + filterType: 'distinct', + filterValue: JSON.stringify(['id', 'title', 'pid']), + }, + ]), + ], + isMounted + ); + + const title: CardViewDetails = React.useMemo(() => { + return { + label: t('datapublications.title'), + dataKey: 'title', + content: (dataPublication: DataPublication) => + tableLink( + `${location.pathname}/${dataPublication.id}`, + dataPublication.title, + view + ), + filterComponent: textFilter, + defaultSort: studyDataPublicationId ? undefined : 'desc', + }; + }, [t, textFilter, studyDataPublicationId, location.pathname, view]); + + const description: CardViewDetails = React.useMemo( + () => ({ + label: t('datapublications.description'), + dataKey: 'description', + filterComponent: textFilter, + }), + [t, textFilter] + ); + + const information: CardViewDetails[] = React.useMemo( + () => [ + { + content: function dataPublicationPidFormat(entity: DataPublication) { + return ( + entity?.pid && ( + + {entity.pid} + + ) + ); + }, + icon: Public, + label: t('datapublications.pid'), + dataKey: 'pid', + filterComponent: textFilter, + }, + ...(studyDataPublicationId + ? ([ + { + icon: CalendarToday, + label: t('datapublications.publication_date'), + dataKey: 'publicationDate', + content: (dataPublication: DataPublication) => + dataPublication.publicationDate?.slice(0, 10) ?? '', + filterComponent: dateFilter, + defaultSort: 'desc', + }, + ] as CardViewDetails[]) + : []), + ], + [dateFilter, studyDataPublicationId, t, textFilter] + ); + + return ( + + ); +}; + +export default ISISDataPublicationsCardView; diff --git a/packages/datagateway-dataview/src/views/card/isis/isisDatasetsCardView.component.test.tsx b/packages/datagateway-dataview/src/views/card/isis/isisDatasetsCardView.component.test.tsx index 9a9c75735..2c8e7e364 100644 --- a/packages/datagateway-dataview/src/views/card/isis/isisDatasetsCardView.component.test.tsx +++ b/packages/datagateway-dataview/src/views/card/isis/isisDatasetsCardView.component.test.tsx @@ -1,26 +1,27 @@ -import { Link, ListItemText } from '@material-ui/core'; -import { createMount } from '@material-ui/core/test-utils'; import { - AdvancedFilter, + type Dataset, dGCommonInitialState, - useDatasetsPaginated, useDatasetCount, - Dataset, - AddToCartButton, - DownloadButton, - ISISDatasetDetailsPanel, + useDatasetsPaginated, } from 'datagateway-common'; -import { ReactWrapper } from 'enzyme'; -import React from 'react'; +import * as React from 'react'; import { Provider } from 'react-redux'; -import { Router } from 'react-router'; +import { generatePath, Router } from 'react-router-dom'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; -import { StateType } from '../../../state/app.types'; +import type { StateType } from '../../../state/app.types'; import { initialState as dgDataViewInitialState } from '../../../state/reducers/dgdataview.reducer'; import ISISDatasetsCardView from './isisDatasetsCardView.component'; import { QueryClient, QueryClientProvider } from 'react-query'; -import { createMemoryHistory, History } from 'history'; +import { createMemoryHistory, type History } from 'history'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, +} from '../../../setupTests'; +import { render, type RenderResult, screen } from '@testing-library/react'; +import type { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; +import { paths } from '../../../page/pageContainer.component'; jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -34,32 +35,24 @@ jest.mock('datagateway-common', () => { }); describe('ISIS Datasets - Card View', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let cardData: Dataset[]; let history: History; + let user: UserEvent; - const createWrapper = (): ReactWrapper => { - const store = mockStore(state); - return mount( - + const renderComponent = (): RenderResult => + render( + - + ); - }; beforeEach(() => { - mount = createMount(); cardData = [ { id: 1, @@ -69,9 +62,17 @@ describe('ISIS Datasets - Card View', () => { createTime: '2019-07-23', }, ]; - history = createMemoryHistory(); + history = createMemoryHistory({ + initialEntries: [ + generatePath(paths.toggle.isisDataset, { + instrumentId: '1', + investigationId: '1', + facilityCycleId: '1', + }), + ], + }); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -93,78 +94,48 @@ describe('ISIS Datasets - Card View', () => { }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('CardView').props()).toMatchSnapshot(); + it('correct link used when NOT in dataPublication hierarchy', async () => { + renderComponent(); + expect(await screen.findByRole('link', { name: 'Test 1' })).toHaveAttribute( + 'href', + '/browse/instrument/1/facilityCycle/1/investigation/1/dataset/1' + ); }); - it('calls the correct data fetching hooks on load', () => { - const investigationId = '1'; - createWrapper(); - expect(useDatasetCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: investigationId }, - }), - }, - ]); - expect(useDatasetsPaginated).toHaveBeenCalledWith( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: investigationId }, - }), - }, - ], - expect.any(Boolean) + it('correct link used for dataPublication hierarchy', async () => { + history.replace( + generatePath(paths.dataPublications.toggle.isisDataset, { + instrumentId: '1', + investigationId: '1', + dataPublicationId: '1', + }) ); - }); - it('correct link used when NOT in studyHierarchy', () => { - const wrapper = createWrapper(); - expect( - wrapper.find('[aria-label="card-title"]').childAt(0).prop('to') - ).toEqual('/browse/instrument/1/facilityCycle/1/investigation/1/dataset/1'); - }); + renderComponent(); - it('correct link used for studyHierarchy', () => { - const store = mockStore(state); - const wrapper = mount( - - - - - - - - ); - expect( - wrapper.find('[aria-label="card-title"]').childAt(0).prop('to') - ).toEqual( - '/browseStudyHierarchy/instrument/1/study/1/investigation/1/dataset/1' + expect(await screen.findByRole('link', { name: 'Test 1' })).toHaveAttribute( + 'href', + '/browseDataPublications/instrument/1/dataPublication/1/investigation/1/dataset/1' ); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); + + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); + + const filter = await screen.findByRole('textbox', { + name: 'Filter by datasets.name', + hidden: true, + }); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: 'test' } }); + await user.type(filter, 'test'); expect(history.location.search).toBe( `?filters=${encodeURIComponent( @@ -172,40 +143,43 @@ describe('ISIS Datasets - Card View', () => { )}` ); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: '' } }); + await user.clear(filter); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); + + renderComponent(); + + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); + + const filter = await screen.findByRole('textbox', { + name: 'datasets.modified_time filter to', + }); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '2019-08-06' } }); + await user.type(filter, '2019-08-06'); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"modTime":{"endDate":"2019-08-06"}}')}` ); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '' } }); + // await user.clear(filter); + await user.click(filter); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"createTime":"desc"}')}` @@ -220,38 +194,41 @@ describe('ISIS Datasets - Card View', () => { ); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - const button = wrapper.find(ListItemText).first(); - expect(button.text()).toEqual('datasets.name'); - button.simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'Sort by DATASETS.NAME' }) + ); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"name":"asc"}')}` ); }); - it('renders buttons correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find(AddToCartButton).exists()).toBeTruthy(); - expect(wrapper.find(AddToCartButton).text()).toEqual('buttons.add_to_cart'); - - expect(wrapper.find(DownloadButton).exists()).toBeTruthy(); - expect(wrapper.find(DownloadButton).text()).toEqual('buttons.download'); + it('renders buttons correctly', async () => { + renderComponent(); + expect( + await screen.findByRole('button', { name: 'buttons.add_to_cart' }) + ).toBeInTheDocument(); + expect( + await screen.findByRole('button', { name: 'buttons.download' }) + ).toBeInTheDocument(); }); - it('displays details panel when more information is expanded and navigates to datafiles view when tab clicked', () => { - const wrapper = createWrapper(); - expect(wrapper.find(ISISDatasetDetailsPanel).exists()).toBeFalsy(); - wrapper - .find('[aria-label="card-more-info-expand"]') - .first() - .simulate('click'); + it('displays details panel when more information is expanded and navigates to datafiles view when tab clicked', async () => { + renderComponent(); + + await user.click(await screen.findByLabelText('card-more-info-expand')); - expect(wrapper.find(ISISDatasetDetailsPanel).exists()).toBeTruthy(); + expect( + await screen.findByTestId('isis-dataset-details-panel') + ).toBeInTheDocument(); + + await user.click( + await screen.findByRole('tab', { name: 'datasets.details.datafiles' }) + ); - wrapper.find('#dataset-datafiles-tab').first().simulate('click'); expect(history.location.pathname).toBe( '/browse/instrument/1/facilityCycle/1/investigation/1/dataset/1/datafile' ); @@ -261,6 +238,6 @@ describe('ISIS Datasets - Card View', () => { (useDatasetCount as jest.Mock).mockReturnValueOnce({}); (useDatasetsPaginated as jest.Mock).mockReturnValueOnce({}); - expect(() => createWrapper()).not.toThrowError(); + expect(() => renderComponent()).not.toThrowError(); }); }); diff --git a/packages/datagateway-dataview/src/views/card/isis/isisDatasetsCardView.component.tsx b/packages/datagateway-dataview/src/views/card/isis/isisDatasetsCardView.component.tsx index 26e13aa48..8e0dad841 100644 --- a/packages/datagateway-dataview/src/views/card/isis/isisDatasetsCardView.component.tsx +++ b/packages/datagateway-dataview/src/views/card/isis/isisDatasetsCardView.component.tsx @@ -4,8 +4,7 @@ import { CardViewDetails, Dataset, tableLink, - formatCountOrSize, - useDatasetSizes, + formatBytes, parseSearchToQuery, useDateFilter, useDatasetCount, @@ -19,40 +18,28 @@ import { DownloadButton, ISISDatasetDetailsPanel, } from 'datagateway-common'; -import { Save, CalendarToday } from '@material-ui/icons'; +import { Save, CalendarToday } from '@mui/icons-material'; import { useTranslation } from 'react-i18next'; -import { useHistory, useLocation } from 'react-router'; -import { Theme, createStyles, makeStyles } from '@material-ui/core'; - -const useStyles = makeStyles((theme: Theme) => - createStyles({ - actionButtons: { - display: 'flex', - flexDirection: 'column', - '& button': { - marginTop: theme.spacing(1), - margin: 'auto', - }, - }, - }) -); +import { useHistory, useLocation } from 'react-router-dom'; +import { styled } from '@mui/material'; + +const ActionButtonsContainer = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + '& button': { + margin: 'auto', + marginTop: theme.spacing(1), + }, +})); interface ISISDatasetCardViewProps { - instrumentId: string; - instrumentChildId: string; investigationId: string; - studyHierarchy: boolean; } const ISISDatasetsCardView = ( props: ISISDatasetCardViewProps ): React.ReactElement => { - const { - instrumentId, - instrumentChildId, - investigationId, - studyHierarchy, - } = props; + const { investigationId } = props; const [t] = useTranslation(); const location = useLocation(); @@ -97,11 +84,6 @@ const ISISDatasetsCardView = ( ], isMounted ); - const sizeQueries = useDatasetSizes(data); - - const pathRoot = studyHierarchy ? 'browseStudyHierarchy' : 'browse'; - const instrumentChild = studyHierarchy ? 'study' : 'facilityCycle'; - const urlPrefix = `/${pathRoot}/instrument/${instrumentId}/${instrumentChild}/${instrumentChildId}/investigation/${investigationId}/dataset`; const title: CardViewDetails = React.useMemo( () => ({ @@ -110,10 +92,10 @@ const ISISDatasetsCardView = ( // Provide both the dataKey (for tooltip) and content to render. dataKey: 'name', content: (dataset: Dataset) => - tableLink(`${urlPrefix}/${dataset.id}`, dataset.name, view), + tableLink(`${location.pathname}/${dataset.id}`, dataset.name, view), filterComponent: textFilter, }), - [t, textFilter, urlPrefix, view] + [t, textFilter, location.pathname, view] ); const description: CardViewDetails = React.useMemo( @@ -134,7 +116,7 @@ const ISISDatasetsCardView = ( content: (dataset: Dataset): string => { const index = data?.findIndex((item) => item.id === dataset.id); if (typeof index === 'undefined') return 'Unknown'; - return formatCountOrSize(sizeQueries[index], true); + return formatBytes(dataset.fileSize); }, disableSort: true, }, @@ -152,15 +134,13 @@ const ISISDatasetsCardView = ( filterComponent: dateFilter, }, ], - [data, dateFilter, sizeQueries, t] + [data, dateFilter, t] ); - const classes = useStyles(); - const buttons = React.useMemo( () => [ (dataset: Dataset) => ( -
+ dataset.id) ?? []} @@ -170,14 +150,12 @@ const ISISDatasetsCardView = ( entityType="dataset" entityId={dataset.id} entityName={dataset.name} - entitySize={ - data ? sizeQueries[data.indexOf(dataset)]?.data ?? -1 : -1 - } + entitySize={dataset.fileSize ?? -1} /> -
+ ), ], - [classes.actionButtons, data, sizeQueries] + [data] ); const moreInformation = React.useCallback( @@ -186,17 +164,18 @@ const ISISDatasetsCardView = ( rowData={dataset} viewDatafiles={(id: number) => { const url = view - ? `${urlPrefix}/${id}/datafile?view=${view}` - : `${urlPrefix}/${id}/datafile`; + ? `${location.pathname}/${id}/datafile?view=${view}` + : `${location.pathname}/${id}/datafile`; push(url); }} /> ), - [push, urlPrefix, view] + [push, location.pathname, view] ); return ( { const originalModule = jest.requireActual('datagateway-common'); @@ -31,17 +34,16 @@ jest.mock('datagateway-common', () => { }); describe('ISIS Facility Cycles - Card View', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let cardData: FacilityCycle[]; let history: History; let replaceSpy: jest.SpyInstance; + let user: UserEvent; - const createWrapper = (): ReactWrapper => { - const store = mockStore(state); - return mount( - + const renderComponent = (): RenderResult => + render( + @@ -49,11 +51,9 @@ describe('ISIS Facility Cycles - Card View', () => { ); - }; beforeEach(() => { - mount = createMount(); - mockStore = configureStore([thunk]); + user = userEvent.setup(); state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -84,34 +84,23 @@ describe('ISIS Facility Cycles - Card View', () => { }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('CardView').props()).toMatchSnapshot(); - }); + it('updates filter query params on text filter', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - const instrumentId = '1'; - createWrapper(); - expect(useFacilityCycleCount).toHaveBeenCalledWith(parseInt(instrumentId)); - expect(useFacilityCyclesPaginated).toHaveBeenCalledWith( - parseInt(instrumentId), - expect.any(Boolean) + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) ); - }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + const filter = await screen.findByRole('textbox', { + name: 'Filter by facilitycycles.name', + hidden: true, + }); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: 'test' } }); + await user.type(filter, 'test'); expect(history.location.search).toBe( `?filters=${encodeURIComponent( @@ -119,40 +108,43 @@ describe('ISIS Facility Cycles - Card View', () => { )}` ); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: '' } }); + await user.clear(filter); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '2019-08-06' } }); + renderComponent(); + + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); + + const filter = await screen.findByRole('textbox', { + name: 'facilitycycles.end_date filter to', + }); + + await user.type(filter, '2019-08-06'); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"endDate":{"endDate":"2019-08-06"}}')}` ); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '' } }); + // await user.clear(filter); + await user.click(filter); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(replaceSpy).toHaveBeenCalledWith({ search: `?sort=${encodeURIComponent('{"startDate":"desc"}')}`, @@ -170,12 +162,12 @@ describe('ISIS Facility Cycles - Card View', () => { ); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - const button = wrapper.find(ListItemText).first(); - expect(button.text()).toEqual('facilitycycles.name'); - button.simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'Sort by FACILITYCYCLES.NAME' }) + ); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"name":"asc"}')}` @@ -186,6 +178,6 @@ describe('ISIS Facility Cycles - Card View', () => { (useFacilityCycleCount as jest.Mock).mockReturnValueOnce({}); (useFacilityCyclesPaginated as jest.Mock).mockReturnValueOnce({}); - expect(() => createWrapper()).not.toThrowError(); + expect(() => renderComponent()).not.toThrowError(); }); }); diff --git a/packages/datagateway-dataview/src/views/card/isis/isisFacilityCyclesCardView.component.tsx b/packages/datagateway-dataview/src/views/card/isis/isisFacilityCyclesCardView.component.tsx index d9f55752e..956e5ffc0 100644 --- a/packages/datagateway-dataview/src/views/card/isis/isisFacilityCyclesCardView.component.tsx +++ b/packages/datagateway-dataview/src/views/card/isis/isisFacilityCyclesCardView.component.tsx @@ -14,9 +14,9 @@ import { useSort, useTextFilter, } from 'datagateway-common'; -import { CalendarToday } from '@material-ui/icons'; +import { CalendarToday } from '@mui/icons-material'; import { useTranslation } from 'react-i18next'; -import { useLocation } from 'react-router'; +import { useLocation } from 'react-router-dom'; interface ISISFacilityCyclesCVProps { instrumentId: string; @@ -49,10 +49,8 @@ const ISISFacilityCyclesCardView = ( setIsMounted(true); }, []); - const { - data: totalDataCount, - isLoading: countLoading, - } = useFacilityCycleCount(parseInt(instrumentId)); + const { data: totalDataCount, isLoading: countLoading } = + useFacilityCycleCount(parseInt(instrumentId)); const { isLoading: dataLoading, data } = useFacilityCyclesPaginated( parseInt(instrumentId), isMounted @@ -103,6 +101,7 @@ const ISISFacilityCyclesCardView = ( return ( { const originalModule = jest.requireActual('datagateway-common'); @@ -32,27 +30,25 @@ jest.mock('datagateway-common', () => { }); describe('ISIS Instruments - Card View', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let cardData: Instrument[]; let history: History; + let user: UserEvent; - const createWrapper = (): ReactWrapper => { - const store = mockStore(state); - return mount( - + const renderComponent = (): RenderResult => + render( + - + ); - }; beforeEach(() => { - mount = createMount(); + user = userEvent.setup(); cardData = [ { id: 1, @@ -61,7 +57,6 @@ describe('ISIS Instruments - Card View', () => { ]; history = createMemoryHistory(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -83,53 +78,47 @@ describe('ISIS Instruments - Card View', () => { }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('CardView').props()).toMatchSnapshot(); - }); - - it('calls the correct data fetching hooks on load', () => { - createWrapper(); - expect(useInstrumentCount).toHaveBeenCalled(); - expect(useInstrumentsPaginated).toHaveBeenCalled(); - }); - - it('correct link used when NOT in studyHierarchy', () => { - const wrapper = createWrapper(); - expect( - wrapper.find('[aria-label="card-title"]').childAt(0).prop('to') - ).toEqual('/browse/instrument/1/facilityCycle'); + it('correct link used when NOT in studyHierarchy', async () => { + renderComponent(); + expect(await screen.findByRole('link', { name: 'Test 1' })).toHaveAttribute( + 'href', + '/browse/instrument/1/facilityCycle' + ); }); - it('correct link used for studyHierarchy', () => { - const store = mockStore(state); - const wrapper = mount( - + it('correct link used for studyHierarchy', async () => { + render( + - + ); - expect( - wrapper.find('[aria-label="card-title"]').childAt(0).prop('to') - ).toEqual('/browseStudyHierarchy/instrument/1/study'); + expect(await screen.findByRole('link', { name: 'Test 1' })).toHaveAttribute( + 'href', + '/browseDataPublications/instrument/1/dataPublication' + ); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); + + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); + + const filter = await screen.findByRole('textbox', { + name: 'Filter by instruments.name', + hidden: true, + }); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: 'test' } }); + await user.type(filter, 'test'); expect(history.location.search).toBe( `?filters=${encodeURIComponent( @@ -137,18 +126,13 @@ describe('ISIS Instruments - Card View', () => { )}` ); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: '' } }); + await user.clear(filter); expect(history.location.search).toBe('?'); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"fullName":"asc"}')}` @@ -160,33 +144,28 @@ describe('ISIS Instruments - Card View', () => { expect(useInstrumentsPaginated).toHaveBeenLastCalledWith(undefined, true); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - const button = wrapper.find(ListItemText).first(); - expect(button.text()).toEqual('instruments.name'); - button.simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'Sort by INSTRUMENTS.NAME' }) + ); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"fullName":"desc"}')}` ); }); - it('displays details panel when more information is expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(ISISInstrumentDetailsPanel).exists()).toBeFalsy(); - wrapper - .find('[aria-label="card-more-info-expand"]') - .first() - .simulate('click'); - - expect(wrapper.find(ISISInstrumentDetailsPanel).exists()).toBeTruthy(); + it('displays details panel when more information is expanded', async () => { + renderComponent(); + await user.click(await screen.findByLabelText('card-more-info-expand')); + expect(await screen.findByTestId('instrument-details-panel')); }); it('renders fine with incomplete data', () => { (useInstrumentCount as jest.Mock).mockReturnValueOnce({}); (useInstrumentsPaginated as jest.Mock).mockReturnValueOnce({}); - expect(() => createWrapper()).not.toThrowError(); + expect(() => renderComponent()).not.toThrowError(); }); }); diff --git a/packages/datagateway-dataview/src/views/card/isis/isisInstrumentsCardView.component.tsx b/packages/datagateway-dataview/src/views/card/isis/isisInstrumentsCardView.component.tsx index cc3dd2c4b..7e5b81920 100644 --- a/packages/datagateway-dataview/src/views/card/isis/isisInstrumentsCardView.component.tsx +++ b/packages/datagateway-dataview/src/views/card/isis/isisInstrumentsCardView.component.tsx @@ -1,5 +1,5 @@ -import { Link } from '@material-ui/core'; -import { Title, Link as LinkIcon } from '@material-ui/icons'; +import { Link } from '@mui/material'; +import { Title, Link as LinkIcon } from '@mui/icons-material'; import { CardView, CardViewDetails, @@ -17,16 +17,16 @@ import { } from 'datagateway-common'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { useLocation } from 'react-router'; +import { useLocation } from 'react-router-dom'; interface ISISInstrumentsCVProps { - studyHierarchy: boolean; + dataPublication: boolean; } const ISISInstrumentsCardView = ( props: ISISInstrumentsCVProps ): React.ReactElement => { - const { studyHierarchy } = props; + const { dataPublication } = props; const [t] = useTranslation(); const location = useLocation(); @@ -49,18 +49,18 @@ const ISISInstrumentsCardView = ( setIsMounted(true); }, []); - const { - data: totalDataCount, - isLoading: countLoading, - } = useInstrumentCount(); + const { data: totalDataCount, isLoading: countLoading } = + useInstrumentCount(); const { isLoading: dataLoading, data } = useInstrumentsPaginated( undefined, isMounted ); const title: CardViewDetails = React.useMemo(() => { - const pathRoot = studyHierarchy ? 'browseStudyHierarchy' : 'browse'; - const instrumentChild = studyHierarchy ? 'study' : 'facilityCycle'; + const pathRoot = dataPublication ? 'browseDataPublications' : 'browse'; + const instrumentChild = dataPublication + ? 'dataPublication' + : 'facilityCycle'; return { label: t('instruments.name'), dataKey: 'fullName', @@ -74,7 +74,7 @@ const ISISInstrumentsCardView = ( filterComponent: textFilter, defaultSort: 'asc', }; - }, [t, textFilter, view, studyHierarchy]); + }, [t, textFilter, view, dataPublication]); const description: CardViewDetails = React.useMemo( () => ({ @@ -112,6 +112,7 @@ const ISISInstrumentsCardView = ( return ( { - const originalModule = jest.requireActual('datagateway-common'); - - return { - __esModule: true, - ...originalModule, - useISISInvestigationCount: jest.fn(), - useISISInvestigationsPaginated: jest.fn(), - useInvestigationSizes: jest.fn(), - }; -}); +import { createMemoryHistory, type History } from 'history'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, + flushPromises, +} from '../../../setupTests'; +import { + render, + type RenderResult, + screen, + within, +} from '@testing-library/react'; +import type { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; +import axios, { type AxiosResponse } from 'axios'; +import { paths } from '../../../page/pageContainer.component'; describe('ISIS Investigations - Card View', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let cardData: Investigation[]; let history: History; let replaceSpy: jest.SpyInstance; + let user: UserEvent; - const createWrapper = (studyHierarchy = false): ReactWrapper => { - const store = mockStore(state); - return mount( - + const renderComponent = (): RenderResult => + render( + - - + + ); - }; beforeEach(() => { - mount = createMount(); cardData = [ { id: 1, - title: 'Test 1', + title: 'Test title 1', name: 'Test 1', + fileSize: 123, + fileCount: 1, visitId: '1', - studyInvestigations: [ - { id: 1, study: { id: 1, pid: 'study pid' }, name: 'study 1' }, + startDate: '2022-01-01', + endDate: '2022-01-03', + dataCollectionInvestigations: [ + { + id: 1, + dataCollection: { + id: 14, + dataPublications: [ + { + id: 15, + pid: 'Investigation.Data.Publication.Pid', + description: 'Investigation Data Publication description', + title: 'Investigation Data Publication', + type: { + id: 16, + name: 'investigation', + }, + }, + ], + }, + }, + { + id: 1, + dataCollection: { + id: 11, + dataPublications: [ + { + id: 12, + pid: 'Data.Publication.Pid', + description: 'Data Publication description', + title: 'Data Publication', + type: { + id: 13, + name: 'study', + }, + }, + ], + }, + }, ], investigationUsers: [ { @@ -85,10 +113,17 @@ describe('ISIS Investigations - Card View', () => { ], }, ]; - history = createMemoryHistory(); + history = createMemoryHistory({ + initialEntries: [ + generatePath(paths.toggle.isisInvestigation, { + instrumentId: '1', + facilityCycleId: '1', + }), + ], + }); replaceSpy = jest.spyOn(history, 'replace'); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -96,73 +131,138 @@ describe('ISIS Investigations - Card View', () => { }) ); - (useISISInvestigationCount as jest.Mock).mockReturnValue({ - data: 1, - isLoading: false, - }); - (useISISInvestigationsPaginated as jest.Mock).mockReturnValue({ - data: cardData, - isLoading: false, - }); - (useInvestigationSizes as jest.Mock).mockReturnValue([{ data: 1 }]); + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + if (/\/investigations\/count$/.test(url)) { + // investigation count query + return Promise.resolve({ + data: 1, + }); + } + + if (/\/investigations$/.test(url)) { + // investigations query + return Promise.resolve({ + data: cardData, + }); + } + + if (/\/user\/getSize$/.test(url)) { + // investigation size query + return Promise.resolve({ + data: 123, + }); + } + + return Promise.reject({ + response: { status: 403 }, + message: `Endpoint not mocked: ${url}`, + }); + }); // Prevent error logging window.scrollTo = jest.fn(); }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('CardView').props()).toMatchSnapshot(); - }); + it('renders investigations as cards', async () => { + renderComponent(); - it('calls required query, filter and sort functions on page load', () => { - const instrumentId = '1'; - const instrumentChildId = '1'; - const studyHierarchy = false; - createWrapper(); - expect(useISISInvestigationCount).toHaveBeenCalledWith( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy - ); - expect(useISISInvestigationsPaginated).toHaveBeenCalledWith( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy, - expect.any(Boolean) - ); - expect(useInvestigationSizes).toHaveBeenCalledWith(cardData); - }); + const allCards = await screen.findAllByTestId('card'); + expect(allCards).toHaveLength(1); - it('correct link used when NOT in studyHierarchy', () => { - const wrapper = createWrapper(); + const firstCard = within(allCards[0]); + expect( + firstCard.getByRole('link', { name: 'Test title 1' }) + ).toBeInTheDocument(); + expect(firstCard.getByText('investigations.name:')).toBeInTheDocument(); + expect(firstCard.getByText('Test 1')).toBeInTheDocument(); + expect( + firstCard.getByRole('link', { name: 'Data.Publication.Pid' }) + ).toHaveAttribute('href', 'https://doi.org/Data.Publication.Pid'); + expect( + firstCard.getByText('investigations.details.size:') + ).toBeInTheDocument(); + expect(firstCard.getByText('123 B')).toBeInTheDocument(); expect( - wrapper.find('[aria-label="card-title"]').childAt(0).prop('to') - ).toEqual('/browse/instrument/1/facilityCycle/1/investigation/1'); + firstCard.getByText('investigations.principal_investigators:') + ).toBeInTheDocument(); + expect(firstCard.getByText('Test PI')).toBeInTheDocument(); + expect( + firstCard.getByText('investigations.details.start_date:') + ).toBeInTheDocument(); + expect(firstCard.getByText('2022-01-01')).toBeInTheDocument(); + expect( + firstCard.getByText('investigations.details.end_date:') + ).toBeInTheDocument(); + expect(firstCard.getByText('2022-01-03')).toBeInTheDocument(); }); - it('correct link used for studyHierarchy', () => { - const wrapper = createWrapper(true); + it('renders no card if no investigation is returned', async () => { + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + if (/\/investigations\/count$/.test(url)) { + // investigation count query + return Promise.resolve({ + data: 0, + }); + } + + if (/\/investigations$/.test(url)) { + // investigations query + return Promise.resolve({ + data: [], + }); + } + + if (/\/user\/getSize$/.test(url)) { + // investigation size query + return Promise.resolve({ + data: 123, + }); + } + + return Promise.reject({ + response: { status: 403 }, + message: `Endpoint not mocked: ${url}`, + }); + }); + + renderComponent(); + await flushPromises(); + + expect(screen.queryAllByTestId('card')).toHaveLength(0); + }); + it('correct link used when NOT in studyHierarchy', async () => { + renderComponent(); expect( - wrapper.find('[aria-label="card-title"]').childAt(0).prop('to') - ).toEqual('/browseStudyHierarchy/instrument/1/study/1/investigation/1'); + await screen.findByRole('link', { name: 'Test title 1' }) + ).toHaveAttribute( + 'href', + '/browse/instrument/1/facilityCycle/1/investigation/1' + ); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); + + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: 'test' } }); + const filter = await screen.findByRole('textbox', { + name: 'Filter by investigations.title', + hidden: true, + }); + + await user.type(filter, 'test'); expect(history.location.search).toBe( `?filters=${encodeURIComponent( @@ -170,136 +270,95 @@ describe('ISIS Investigations - Card View', () => { )}` ); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: '' } }); + await user.clear(filter); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); + + renderComponent(); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '2019-08-06' } }); + // click on button to show advanced filters + await user.click( + await screen.findByRole('button', { name: 'advanced_filters.show' }) + ); + + const filter = await screen.findByRole('textbox', { + name: 'investigations.details.end_date filter to', + }); + + await user.type(filter, '2019-08-06'); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"endDate":{"endDate":"2019-08-06"}}')}` ); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '' } }); + // await user.clear(filter); + await user.click(filter); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.location.search).toBe('?'); - }); - it('displays DOI and renders the expected Link ', () => { - const wrapper = createWrapper(); - expect( - wrapper - .find('[data-testid="isis-investigations-card-doi-link"]') - .first() - .text() - ).toEqual('study pid'); - - expect( - wrapper - .find('[data-testid="isis-investigations-card-doi-link"]') - .first() - .prop('href') - ).toEqual('https://doi.org/study pid'); + cleanupDatePickerWorkaround(); }); - it('displays the correct user as the PI ', () => { - const wrapper = createWrapper(); - - expect( - wrapper - .find( - '[data-testid="card-info-data-investigations.principal_investigators"]' - ) - .text() - ).toEqual('Test PI'); + it('displays the correct user as the PI ', async () => { + renderComponent(); + expect(await screen.findByText('Test PI')).toBeInTheDocument(); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(replaceSpy).toHaveBeenCalledWith({ search: `?sort=${encodeURIComponent('{"startDate":"desc"}')}`, }); - const instrumentId = '1'; - const instrumentChildId = '1'; - const studyHierarchy = false; - // check that the data request is sent only once after mounting - expect(useISISInvestigationsPaginated).toHaveBeenCalledTimes(2); - expect(useISISInvestigationsPaginated).toHaveBeenCalledWith( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy, - false - ); - expect(useISISInvestigationsPaginated).toHaveBeenCalledWith( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy, - true + const datafilesCalls = (axios.get as jest.Mock).mock.calls.filter( + (call) => call[0] === '/investigations' ); + expect(datafilesCalls).toHaveLength(1); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); - - const button = wrapper.find(ListItemText).first(); - expect(button.text()).toEqual('investigations.title'); - button.simulate('click'); - + it('updates sort query params on sort', async () => { + renderComponent(); + await user.click( + await screen.findByRole('button', { + name: 'Sort by INVESTIGATIONS.TITLE', + }) + ); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"title":"asc"}')}` ); }); - it('renders buttons correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find(AddToCartButton).exists()).toBeTruthy(); - expect(wrapper.find(AddToCartButton).text()).toEqual('buttons.add_to_cart'); - - expect(wrapper.find(DownloadButton).exists()).toBeTruthy(); - expect(wrapper.find(DownloadButton).text()).toEqual('buttons.download'); + it('renders buttons correctly', async () => { + renderComponent(); + expect( + await screen.findByRole('button', { name: 'buttons.add_to_cart' }) + ).toBeInTheDocument(); + expect( + await screen.findByRole('button', { name: 'buttons.download' }) + ).toBeInTheDocument(); }); - it('displays details panel when more information is expanded and navigates to datasets view when tab clicked', () => { - const wrapper = createWrapper(); - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeFalsy(); - wrapper - .find('[aria-label="card-more-info-expand"]') - .first() - .simulate('click'); - - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeTruthy(); - - wrapper.find('#investigation-datasets-tab').first().simulate('click'); + it('displays details panel when more information is expanded and navigates to datasets view when tab clicked', async () => { + renderComponent(); + await user.click(await screen.findByLabelText('card-more-info-expand')); + expect( + await screen.findByTestId('isis-investigation-details-panel') + ).toBeTruthy(); + await user.click( + await screen.findByRole('tab', { + name: 'investigations.details.datasets', + }) + ); expect(history.location.pathname).toBe( '/browse/instrument/1/facilityCycle/1/investigation/1/dataset' ); }); - - it('renders fine with incomplete data', () => { - (useISISInvestigationCount as jest.Mock).mockReturnValueOnce({}); - (useISISInvestigationsPaginated as jest.Mock).mockReturnValueOnce({}); - (useInvestigationSizes as jest.Mock).mockReturnValueOnce([{ data: 0 }]); - - expect(() => createWrapper()).not.toThrowError(); - }); }); diff --git a/packages/datagateway-dataview/src/views/card/isis/isisInvestigationsCardView.component.tsx b/packages/datagateway-dataview/src/views/card/isis/isisInvestigationsCardView.component.tsx index 1497801b3..f73770e4a 100644 --- a/packages/datagateway-dataview/src/views/card/isis/isisInvestigationsCardView.component.tsx +++ b/packages/datagateway-dataview/src/views/card/isis/isisInvestigationsCardView.component.tsx @@ -1,60 +1,55 @@ -import { Link as MuiLink } from '@material-ui/core'; import { + CalendarToday, Fingerprint, + Person, Public, Save, - Person, - CalendarToday, -} from '@material-ui/icons'; +} from '@mui/icons-material'; +import { styled } from '@mui/material'; import { + AdditionalFilters, + AddToCartButton, CardView, CardViewDetails, - formatCountOrSize, Investigation, tableLink, - useInvestigationSizes, + DownloadButton, + externalSiteLink, + ISISInvestigationDetailsPanel, parseSearchToQuery, useDateFilter, - useISISInvestigationCount, - useISISInvestigationsPaginated, + useInvestigationCount, + useInvestigationsPaginated, usePrincipalExperimenterFilter, usePushFilter, usePushPage, usePushResults, useSort, useTextFilter, - AddToCartButton, - DownloadButton, - ISISInvestigationDetailsPanel, + formatBytes, } from 'datagateway-common'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { useHistory, useLocation } from 'react-router'; -import { Theme, createStyles, makeStyles } from '@material-ui/core'; +import { useHistory, useLocation } from 'react-router-dom'; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - actionButtons: { - display: 'flex', - flexDirection: 'column', - '& button': { - marginTop: theme.spacing(1), - margin: 'auto', - }, - }, - }) -); +const ActionButtonsContainer = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + '& button': { + margin: 'auto', + marginTop: theme.spacing(1), + }, +})); interface ISISInvestigationsCardViewProps { instrumentId: string; - instrumentChildId: string; - studyHierarchy: boolean; + facilityCycleId: string; } const ISISInvestigationsCardView = ( props: ISISInvestigationsCardViewProps ): React.ReactElement => { - const { instrumentId, instrumentChildId, studyHierarchy } = props; + const { instrumentId, facilityCycleId } = props; const [t] = useTranslation(); const location = useLocation(); @@ -73,6 +68,25 @@ const ISISInvestigationsCardView = ( const pushPage = usePushPage(); const pushResults = usePushResults(); + const investigationQueryFilters: AdditionalFilters = [ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'investigationInstruments.instrument.id': { + eq: parseInt(instrumentId), + }, + }), + }, + { + filterType: 'where', + filterValue: JSON.stringify({ + 'investigationFacilityCycles.facilityCycle.id': { + eq: parseInt(facilityCycleId), + }, + }), + }, + ]; + // isMounted is used to disable queries when the component isn't fully mounted. // It prevents the request being sent twice if default sort is set. // It is not needed for cards/tables that don't have default sort. @@ -81,25 +95,31 @@ const ISISInvestigationsCardView = ( setIsMounted(true); }, []); - const { - data: totalDataCount, - isLoading: countLoading, - } = useISISInvestigationCount( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy - ); - const { data, isLoading: dataLoading } = useISISInvestigationsPaginated( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy, + const { data: totalDataCount, isLoading: countLoading } = + useInvestigationCount(investigationQueryFilters); + const { data, isLoading: dataLoading } = useInvestigationsPaginated( + [ + ...investigationQueryFilters, + { + filterType: 'include', + filterValue: JSON.stringify([ + { + investigationInstruments: 'instrument', + }, + { + dataCollectionInvestigations: { + dataCollection: { dataPublications: 'type' }, + }, + }, + { + investigationUsers: 'user', + }, + ]), + }, + ], + undefined, isMounted ); - const sizeQueries = useInvestigationSizes(data); - - const pathRoot = studyHierarchy ? 'browseStudyHierarchy' : 'browse'; - const instrumentChild = studyHierarchy ? 'study' : 'facilityCycle'; - const urlPrefix = `/${pathRoot}/instrument/${instrumentId}/${instrumentChild}/${instrumentChildId}/investigation`; const title: CardViewDetails = React.useMemo( () => ({ @@ -107,14 +127,14 @@ const ISISInvestigationsCardView = ( dataKey: 'title', content: (investigation: Investigation) => tableLink( - `${urlPrefix}/${investigation.id}`, + `${location.pathname}/${investigation.id}`, investigation.title, view, 'isis-investigations-card-title' ), filterComponent: textFilter, }), - [t, textFilter, urlPrefix, view] + [location.pathname, t, textFilter, view] ); const description: CardViewDetails = React.useMemo( @@ -136,31 +156,34 @@ const ISISInvestigationsCardView = ( }, { content: function doiFormat(entity: Investigation) { - return ( - entity?.studyInvestigations?.[0]?.study?.pid && ( - - {entity.studyInvestigations[0].study?.pid} - - ) - ); + const studyDataPublication = + entity.dataCollectionInvestigations?.filter( + (dci) => + dci.dataCollection?.dataPublications?.[0]?.type?.name === + 'study' + )?.[0]?.dataCollection?.dataPublications?.[0]; + if (studyDataPublication) { + return externalSiteLink( + `https://doi.org/${studyDataPublication.pid}`, + studyDataPublication.pid, + 'isis-investigations-card-doi-link' + ); + } else { + return ''; + } }, icon: Public, label: t('investigations.doi'), - dataKey: 'studyInvestigations[0].study.pid', + dataKey: + 'dataCollectionInvestigations.dataCollection.dataPublications.pid', filterComponent: textFilter, }, { icon: Save, label: t('investigations.details.size'), dataKey: 'size', - content: (investigation: Investigation): number | string => { - const index = data?.findIndex((item) => item.id === investigation.id); - if (typeof index === 'undefined') return 'Unknown'; - return formatCountOrSize(sizeQueries[index], true); - }, + content: (investigation: Investigation): number | string => + formatBytes(investigation.fileSize), disableSort: true, }, { @@ -169,9 +192,10 @@ const ISISInvestigationsCardView = ( dataKey: 'investigationUsers.user.fullName', disableSort: true, content: function Content(investigation: Investigation) { - const principal_investigators = investigation?.investigationUsers?.filter( - (iu) => iu.role === 'principal_experimenter' - ); + const principal_investigators = + investigation?.investigationUsers?.filter( + (iu) => iu.role === 'principal_experimenter' + ); let principal_investigator = ''; if (principal_investigators && principal_investigators.length !== 0) { principal_investigator = @@ -196,15 +220,13 @@ const ISISInvestigationsCardView = ( filterComponent: dateFilter, }, ], - [data, dateFilter, principalExperimenterFilter, sizeQueries, t, textFilter] + [dateFilter, principalExperimenterFilter, t, textFilter] ); - const classes = useStyles(); - const buttons = React.useMemo( () => [ (investigation: Investigation) => ( -
+ investigation.id) ?? []} @@ -214,14 +236,12 @@ const ISISInvestigationsCardView = ( entityType="investigation" entityId={investigation.id} entityName={investigation.name} - entitySize={ - data ? sizeQueries[data.indexOf(investigation)]?.data ?? -1 : -1 - } + entitySize={investigation.fileSize ?? -1} /> -
+ ), ], - [classes.actionButtons, data, sizeQueries] + [data] ); const moreInformation = React.useCallback( @@ -230,17 +250,18 @@ const ISISInvestigationsCardView = ( rowData={investigation} viewDatasets={(id: number) => { const url = view - ? `${urlPrefix}/${id}/dataset?view=${view}` - : `${urlPrefix}/${id}/dataset`; + ? `${location.pathname}/${id}/dataset?view=${view}` + : `${location.pathname}/${id}/dataset`; push(url); }} /> ), - [push, urlPrefix, view] + [location.pathname, push, view] ); return ( { - const originalModule = jest.requireActual('datagateway-common'); - - return { - __esModule: true, - ...originalModule, - useStudyCount: jest.fn(), - useStudiesPaginated: jest.fn(), - }; -}); - -describe('ISIS Studies - Card View', () => { - let mount; - let mockStore; - let state: StateType; - let cardData: Study[]; - let history: History; - - const createWrapper = (): ReactWrapper => { - const store = mockStore(state); - return mount( - - - - - - - - ); - }; - - beforeEach(() => { - mount = createMount(); - cardData = [ - { - id: 1, - pid: 'doi', - name: 'Test 1', - modTime: '2000-01-01', - createTime: '2000-01-01', - }, - ]; - history = createMemoryHistory(); - - mockStore = configureStore([thunk]); - state = JSON.parse( - JSON.stringify({ - dgcommon: dGCommonInitialState, - dgdataview: dgDataViewInitialState, - }) - ); - - (useStudyCount as jest.Mock).mockReturnValue({ - data: 1, - isLoading: false, - }); - (useStudiesPaginated as jest.Mock).mockReturnValue({ - data: cardData, - isLoading: false, - }); - - // Prevent error logging - window.scrollTo = jest.fn(); - }); - - afterEach(() => { - mount.cleanUp(); - jest.clearAllMocks(); - }); - - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('CardView').props()).toMatchSnapshot(); - }); - - it('calls the correct data fetching hooks on load', () => { - const instrumentId = '1'; - createWrapper(); - expect(useStudyCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'studyInvestigations.investigation.investigationInstruments.instrument.id': { - eq: instrumentId, - }, - }), - }, - { - filterType: 'where', - filterValue: JSON.stringify({ - 'studyInvestigations.investigation.releaseDate': { - lt: '2021-10-27 00:00:00', - }, - }), - }, - ]); - expect(useStudiesPaginated).toHaveBeenCalledWith( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'studyInvestigations.investigation.investigationInstruments.instrument.id': { - eq: instrumentId, - }, - }), - }, - { - filterType: 'where', - filterValue: JSON.stringify({ - 'studyInvestigations.investigation.releaseDate': { - lt: '2021-10-27 00:00:00', - }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - studyInvestigations: 'investigation', - }), - }, - ], - expect.any(Boolean) - ); - }); - - it('displays Experiment DOI (PID) and renders the expected Link ', () => { - const wrapper = createWrapper(); - expect( - wrapper.find('[data-testid="landing-study-card-pid-link"]').first().text() - ).toEqual('doi'); - - expect( - wrapper - .find('[data-testid="landing-study-card-pid-link"]') - .first() - .prop('href') - ).toEqual('https://doi.org/doi'); - }); - - it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - - expect(history.length).toBe(1); - expect(history.location.search).toBe( - `?sort=${encodeURIComponent( - '{"studyInvestigations.investigation.startDate":"desc"}' - )}` - ); - - // check that the data request is sent only once after mounting - expect(useStudiesPaginated).toHaveBeenCalledTimes(2); - expect(useStudiesPaginated).toHaveBeenCalledWith(expect.anything(), false); - expect(useStudiesPaginated).toHaveBeenLastCalledWith( - expect.anything(), - true - ); - }); - - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); - - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: 'test' } }); - - expect(history.location.search).toBe( - `?filters=${encodeURIComponent( - '{"name":{"value":"test","type":"include"}}' - )}` - ); - - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: '' } }); - - expect(history.location.search).toBe('?'); - }); - - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); - - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '2019-08-06' } }); - - expect(history.location.search).toBe( - `?filters=${encodeURIComponent( - '{"studyInvestigations.investigation.endDate":{"endDate":"2019-08-06"}}' - )}` - ); - - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '' } }); - - expect(history.location.search).toBe('?'); - }); - - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); - - const button = wrapper.find(ListItemText).first(); - expect(button.text()).toEqual('studies.name'); - button.simulate('click'); - - expect(history.location.search).toBe( - `?sort=${encodeURIComponent('{"name":"asc"}')}` - ); - }); - - it('displays information from investigation when investigation present', () => { - cardData = [ - { - ...cardData[0], - studyInvestigations: [ - { - id: 2, - study: { - ...cardData[0], - }, - investigation: { - id: 3, - name: 'Test', - title: 'Test investigation', - visitId: '3', - startDate: '2021-08-19', - endDate: '2021-08-20', - }, - }, - ], - }, - ]; - (useStudiesPaginated as jest.Mock).mockReturnValue({ - data: cardData, - }); - - const wrapper = createWrapper(); - - expect( - wrapper.find('[aria-label="card-description"]').first().text() - ).toEqual('Test investigation'); - }); - - it('renders fine with incomplete data', () => { - (useStudyCount as jest.Mock).mockReturnValueOnce({}); - (useStudiesPaginated as jest.Mock).mockReturnValueOnce({}); - - expect(() => createWrapper()).not.toThrowError(); - - cardData = [ - { - ...cardData[0], - studyInvestigations: [ - { - id: 2, - study: { - ...cardData[0], - }, - }, - ], - }, - ]; - (useStudiesPaginated as jest.Mock).mockReturnValue({ - data: cardData, - }); - - expect(() => createWrapper()).not.toThrowError(); - }); -}); diff --git a/packages/datagateway-dataview/src/views/card/isis/isisStudiesCardView.component.tsx b/packages/datagateway-dataview/src/views/card/isis/isisStudiesCardView.component.tsx deleted file mode 100644 index 366ebb7ca..000000000 --- a/packages/datagateway-dataview/src/views/card/isis/isisStudiesCardView.component.tsx +++ /dev/null @@ -1,200 +0,0 @@ -import React from 'react'; -import { - CardView, - CardViewDetails, - getStudyInfoInvestigation, - parseSearchToQuery, - Study, - tableLink, - useDateFilter, - usePushFilter, - usePushPage, - usePushResults, - useSort, - useStudiesPaginated, - useStudyCount, - useTextFilter, -} from 'datagateway-common'; -import PublicIcon from '@material-ui/icons/Public'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; -import { useTranslation } from 'react-i18next'; -import { useLocation } from 'react-router'; -import { format, set } from 'date-fns'; -import { Link as MuiLink } from '@material-ui/core'; - -interface ISISStudiesCVProps { - instrumentId: string; -} - -const ISISStudiesCardView = (props: ISISStudiesCVProps): React.ReactElement => { - const { instrumentId } = props; - - const [t] = useTranslation(); - const location = useLocation(); - - const { filters, view, sort, page, results } = React.useMemo( - () => parseSearchToQuery(location.search), - [location.search] - ); - - const textFilter = useTextFilter(filters); - const dateFilter = useDateFilter(filters); - const handleSort = useSort(); - const pushFilter = usePushFilter(); - const pushPage = usePushPage(); - const pushResults = usePushResults(); - - // isMounted is used to disable queries when the component isn't fully mounted. - // It prevents the request being sent twice if default sort is set. - // It is not needed for cards/tables that don't have default sort. - const [isMounted, setIsMounted] = React.useState(false); - React.useEffect(() => { - setIsMounted(true); - }, []); - - const unembargoDate = format( - // set s and ms to 0 to escape recursive loop of fetching data every time they change - set(new Date(), { seconds: 0, milliseconds: 0 }), - 'yyyy-MM-dd HH:mm:ss' - ); - - const { data: totalDataCount, isLoading: countLoading } = useStudyCount([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'studyInvestigations.investigation.investigationInstruments.instrument.id': { - eq: instrumentId, - }, - }), - }, - { - filterType: 'where', - filterValue: JSON.stringify({ - // this matches the ISIS ICAT rule - 'studyInvestigations.investigation.releaseDate': { - lt: unembargoDate, - }, - }), - }, - ]); - const { isLoading: dataLoading, data } = useStudiesPaginated( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'studyInvestigations.investigation.investigationInstruments.instrument.id': { - eq: instrumentId, - }, - }), - }, - { - filterType: 'where', - filterValue: JSON.stringify({ - // this matches the ISIS ICAT rule - 'studyInvestigations.investigation.releaseDate': { - lt: unembargoDate, - }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - studyInvestigations: 'investigation', - }), - }, - ], - isMounted - ); - - const title = React.useMemo(() => { - const pathRoot = 'browseStudyHierarchy'; - const instrumentChild = 'study'; - - return { - label: t('studies.name'), - dataKey: 'name', - content: (study: Study) => - tableLink( - `/${pathRoot}/instrument/${instrumentId}/${instrumentChild}/${study.id}`, - study.name, - view - ), - filterComponent: textFilter, - }; - }, [t, textFilter, instrumentId, view]); - - const description: CardViewDetails = React.useMemo( - () => ({ - label: t('studies.title'), - dataKey: 'studyInvestigations.investigation.title', - content: (study: Study) => { - return getStudyInfoInvestigation(study)?.title ?? ''; - }, - filterComponent: textFilter, - }), - [t, textFilter] - ); - - const information: CardViewDetails[] = React.useMemo( - () => [ - { - content: function studyPidFormat(entity: Study) { - return ( - entity?.pid && ( - - {entity.pid} - - ) - ); - }, - icon: PublicIcon, - label: t('studies.pid'), - dataKey: 'pid', - filterComponent: textFilter, - }, - { - icon: CalendarTodayIcon, - label: t('studies.start_date'), - dataKey: 'studyInvestigations.investigation.startDate', - content: (study: Study) => - getStudyInfoInvestigation(study)?.startDate ?? '', - filterComponent: dateFilter, - defaultSort: 'desc', - }, - { - icon: CalendarTodayIcon, - label: t('studies.end_date'), - dataKey: 'studyInvestigations.investigation.endDate', - content: (study: Study) => - getStudyInfoInvestigation(study)?.endDate ?? '', - filterComponent: dateFilter, - }, - ], - [dateFilter, t, textFilter] - ); - - return ( - - ); -}; - -export default ISISStudiesCardView; diff --git a/packages/datagateway-dataview/src/views/citationFormatter.component.test.tsx b/packages/datagateway-dataview/src/views/citationFormatter.component.test.tsx index 45822fa57..c483604b9 100644 --- a/packages/datagateway-dataview/src/views/citationFormatter.component.test.tsx +++ b/packages/datagateway-dataview/src/views/citationFormatter.component.test.tsx @@ -1,15 +1,20 @@ import React from 'react'; -import { createMount } from '@material-ui/core/test-utils'; import CitationFormatter from './citationFormatter.component'; import axios from 'axios'; -import { flushPromises } from '../setupTests'; -import { act } from 'react-dom/test-utils'; -import { ReactWrapper } from 'enzyme'; +import { + render, + type RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; import { QueryClient, QueryClientProvider } from 'react-query'; +import { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; describe('Citation formatter component tests', () => { - let mount; - let queryClient; + let queryClient: QueryClient; + let user: UserEvent; const props = { doi: 'test', @@ -20,16 +25,17 @@ describe('Citation formatter component tests', () => { startDate: '2019-04-03', }; - const createWrapper = (props): ReactWrapper => { - return mount( + const renderComponent = ( + componentProps: React.ComponentProps + ): RenderResult => + render( - + ); - }; beforeEach(() => { - mount = createMount(); + user = userEvent.setup(); queryClient = new QueryClient({ defaultOptions: { queries: { @@ -44,134 +50,87 @@ describe('Citation formatter component tests', () => { }); it('renders correctly', async () => { - const wrapper = createWrapper(props); - await act(async () => flushPromises()); - wrapper.update(); + renderComponent(props); expect( - wrapper.find('[data-testid="citation-formatter-title"]').first().text() - ).toEqual('studies.details.citation_formatter.label'); - expect( - wrapper.find('[data-testid="citation-formatter-details"]').first().text() - ).toEqual( - 'studies.details.citation_formatter.details studies.details.citation_formatter.details_select_format' - ); + await screen.findByText( + 'datapublications.details.citation_formatter.label' + ) + ).toBeInTheDocument(); expect( - wrapper - .find( - '[aria-label="studies.details.citation_formatter.select_arialabel"]' - ) - .first() - .prop('defaultValue') - ).toEqual('default'); + await screen.findByText( + 'datapublications.details.citation_formatter.details datapublications.details.citation_formatter.details_select_format' + ) + ).toBeInTheDocument(); expect( - wrapper - .find( - '[aria-label="studies.details.citation_formatter.select_arialabel"]' - ) - .first() - .text() - ).toEqual('studies.details.citation_formatter.default_format'); + await screen.findByText( + 'datapublications.details.citation_formatter.default_format' + ) + ).toBeInTheDocument(); expect( - wrapper.find('[data-testid="citation-formatter-citation"]').first().text() - ).toEqual( - 'John Smith; 2019: title, doi_constants.publisher.name, https://doi.org/test' - ); + await screen.findByText( + 'John Smith; 2019: title, doi_constants.publisher.name, https://doi.org/test' + ) + ).toBeInTheDocument(); expect( - wrapper.find('#citation-formatter-copy-citation').first().prop('disabled') - ).toEqual(false); + await screen.findByRole('button', { + name: 'datapublications.details.citation_formatter.copy_citation_arialabel', + }) + ).toBeEnabled(); }); it('renders correctly without a doi', async () => { const newProps = { ...props, doi: undefined }; - const wrapper = createWrapper(newProps); - await act(async () => flushPromises()); - wrapper.update(); - - expect( - wrapper.find('[data-testid="citation-formatter-title"]').first().text() - ).toEqual('studies.details.citation_formatter.label'); - expect( - wrapper.find('[data-testid="citation-formatter-details"]').first().text() - ).toEqual('studies.details.citation_formatter.details'); - expect( - wrapper - .find( - '[aria-label="studies.details.citation_formatter.select_arialabel"]' - ) - .exists() - ).toEqual(false); - expect( - wrapper.find('[data-testid="citation-formatter-citation"]').first().text() - ).toEqual('John Smith; 2019: title, doi_constants.publisher.name'); - expect( - wrapper.find('#citation-formatter-copy-citation').first().prop('disabled') - ).toEqual(false); - }); - - it('formats citation on load', async () => { - const wrapper = createWrapper(props); - await act(async () => flushPromises()); - wrapper.update(); + renderComponent(newProps); expect( - wrapper - .find( - '[aria-label="studies.details.citation_formatter.select_arialabel"]' - ) - .first() - .prop('defaultValue') - ).toEqual('default'); - + await screen.findByText( + 'datapublications.details.citation_formatter.label' + ) + ).toBeInTheDocument(); expect( - wrapper.find('[data-testid="citation-formatter-citation"]').first().text() - ).toEqual( - 'John Smith; 2019: title, doi_constants.publisher.name, https://doi.org/test' - ); + await screen.findByText( + 'datapublications.details.citation_formatter.details' + ) + ).toBeInTheDocument(); expect( - wrapper.find('#citation-formatter-copy-citation').first().prop('disabled') - ).toEqual(false); - }); - - it('formats citation on load without a doi', async () => { - const newProps = { ...props, doi: undefined }; - const wrapper = createWrapper(newProps); - await act(async () => flushPromises()); - wrapper.update(); - + screen.queryByLabelText( + 'datapublications.details.citation_formatter.select_arialabel' + ) + ).toBeNull(); expect( - wrapper - .find( - '[aria-label="studies.details.citation_formatter.select_arialabel"]' - ) - .exists() - ).toBeFalsy(); - + await screen.findByText( + 'John Smith; 2019: title, doi_constants.publisher.name' + ) + ).toBeInTheDocument(); expect( - wrapper.find('[data-testid="citation-formatter-citation"]').first().text() - ).toEqual('John Smith; 2019: title, doi_constants.publisher.name'); - expect( - wrapper.find('#citation-formatter-copy-citation').first().prop('disabled') - ).toEqual(false); + await screen.findByRole('button', { + name: 'datapublications.details.citation_formatter.copy_citation_arialabel', + }) + ).toBeEnabled(); }); it('sends axios request to fetch a formatted citation when a format is selected', async () => { - const wrapper = createWrapper(props); - (axios.get as jest.Mock).mockResolvedValue({ data: 'This is a test', }); - wrapper - .find('input') - .first() - .simulate('change', { target: { value: 'format2' } }); - await act(async () => flushPromises()); - wrapper.update(); + renderComponent(props); + + // click on the format dropdown + await user.click( + within( + await screen.findByLabelText( + 'datapublications.details.citation_formatter.select_arialabel' + ) + ).getByRole('button') + ); + // then select the format2 option + await user.click(await screen.findByRole('option', { name: 'format2' })); const params = new URLSearchParams({ style: 'format2', - locale: 'studies.details.citation_formatter.locale', + locale: 'datapublications.details.citation_formatter.locale', }); expect(axios.get).toHaveBeenCalledWith( @@ -184,42 +143,40 @@ describe('Citation formatter component tests', () => { params.toString() ); + expect(await screen.findByText('This is a test')).toBeInTheDocument(); expect( - wrapper.find('[data-testid="citation-formatter-citation"]').first().text() - ).toEqual('This is a test'); - expect( - wrapper.find('#citation-formatter-copy-citation').first().prop('disabled') - ).toEqual(false); + await screen.findByRole('button', { + name: 'datapublications.details.citation_formatter.copy_citation_arialabel', + }) + ).toBeEnabled(); }); it('copies data citation to clipboard', async () => { - const wrapper = createWrapper(props); - await act(async () => flushPromises()); - wrapper.update(); + renderComponent(props); // Mock the clipboard object - const testWriteText = jest.fn(); - Object.assign(navigator, { - clipboard: { - writeText: testWriteText, - }, - }); + const testWriteText = jest.spyOn(navigator.clipboard, 'writeText'); expect( - wrapper.find('[data-testid="citation-formatter-citation"]').first().text() - ).toEqual( - 'John Smith; 2019: title, doi_constants.publisher.name, https://doi.org/test' + await screen.findByText( + 'John Smith; 2019: title, doi_constants.publisher.name, https://doi.org/test' + ) + ).toBeInTheDocument(); + + await user.click( + await screen.findByRole('button', { + name: 'datapublications.details.citation_formatter.copy_citation_arialabel', + }) ); - wrapper.find('#citation-formatter-copy-citation').first().simulate('click'); - expect(testWriteText).toHaveBeenCalledWith( 'John Smith; 2019: title, doi_constants.publisher.name, https://doi.org/test' ); - expect( - wrapper.find('#citation-formatter-copied-citation').first().text() - ).toEqual('studies.details.citation_formatter.copied_citation'); + await screen.findByRole('button', { + name: 'datapublications.details.citation_formatter.copied_citation', + }) + ).toBeInTheDocument(); }); it('displays error message when axios request to fetch a formatted citation fails', async () => { @@ -229,17 +186,22 @@ describe('Citation formatter component tests', () => { message: 'error', }); - const wrapper = createWrapper(props); - wrapper - .find('input') - .first() - .simulate('change', { target: { value: 'format2' } }); - await act(async () => flushPromises()); - wrapper.update(); + renderComponent(props); + + // click on the format dropdown + await user.click( + within( + await screen.findByLabelText( + 'datapublications.details.citation_formatter.select_arialabel' + ) + ).getByRole('button') + ); + // then select the format2 option + await user.click(await screen.findByRole('option', { name: 'format2' })); const params = new URLSearchParams({ style: 'format2', - locale: 'studies.details.citation_formatter.locale', + locale: 'datapublications.details.citation_formatter.locale', }); expect(axios.get).toHaveBeenCalledWith( @@ -253,35 +215,47 @@ describe('Citation formatter component tests', () => { ); expect( - wrapper.find('#citation-formatter-error-message').first().text() - ).toEqual('studies.details.citation_formatter.error'); - + await screen.findByText( + 'datapublications.details.citation_formatter.error' + ) + ).toBeInTheDocument(); expect( - wrapper.find('#citation-formatter-copy-citation').first().prop('disabled') - ).toEqual(true); + await screen.findByRole('button', { + name: 'datapublications.details.citation_formatter.copy_citation_arialabel', + }) + ).toBeDisabled(); }); it('displays loading spinner while waiting for a response from DataCite', async () => { - (axios.get as jest.Mock).mockRejectedValueOnce({ - message: 'error', - }); + console.error = jest.fn(); + + let reject = (): void => { + // no-op + }; + (axios.get as jest.Mock).mockReturnValueOnce( + new Promise((_, _reject) => { + reject = _reject; + }) + ); - const wrapper = createWrapper(props); - wrapper - .find('input') - .first() - .simulate('change', { target: { value: 'format2' } }); - wrapper.update(); + renderComponent(props); - expect( - wrapper.find('[data-testid="loading-spinner"]').exists() - ).toBeTruthy(); + // click on the format dropdown + await user.click( + within( + await screen.findByLabelText( + 'datapublications.details.citation_formatter.select_arialabel' + ) + ).getByRole('button') + ); + // then select the format2 option + await user.click(await screen.findByRole('option', { name: 'format2' })); - await act(async () => flushPromises()); - wrapper.update(); + expect(await screen.findByRole('progressbar')).toBeInTheDocument(); - expect( - wrapper.find('[data-testid="loading-spinner"]').exists() - ).toBeFalsy(); + reject(); + await waitFor(() => { + expect(screen.queryByRole('progressbar')).toBeNull(); + }); }); }); diff --git a/packages/datagateway-dataview/src/views/citationFormatter.component.tsx b/packages/datagateway-dataview/src/views/citationFormatter.component.tsx index 3a66e3a38..feb2896ba 100644 --- a/packages/datagateway-dataview/src/views/citationFormatter.component.tsx +++ b/packages/datagateway-dataview/src/views/citationFormatter.component.tsx @@ -1,37 +1,25 @@ import { Box, CircularProgress, - createStyles, FormControl, FormHelperText, - makeStyles, MenuItem, Select, - Theme, + SelectChangeEvent, + styled, Typography, -} from '@material-ui/core'; + Button, +} from '@mui/material'; import { Mark } from 'datagateway-common'; import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; -import Button from '@material-ui/core/Button'; import axios, { AxiosError } from 'axios'; -import { FormattedUser } from './landing/isis/isisStudyLanding.component'; +import { FormattedUser } from './landing/isis/isisDataPublicationLanding.component'; import { useQuery, UseQueryResult } from 'react-query'; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - subHeading: { - marginTop: theme.spacing(1), - }, - formatSelect: { - marginTop: theme.spacing(1), - marginBottom: theme.spacing(1), - }, - spinner: { - marginLeft: theme.spacing(1), - }, - }) -); +const Subheading = styled(Typography)(({ theme }) => ({ + marginTop: theme.spacing(1), +})); const fetchCitation = ( doi: string, @@ -101,23 +89,26 @@ const CitationFormatter = ( const { doi } = props; const [t] = useTranslation(); - const classes = useStyles(); const [copiedCitation, setCopiedCitation] = React.useState(false); const [format, setFormat] = React.useState('default'); - const { data: citation, isFetching: fetching, isError: error } = useCitation( + const { + data: citation, + isFetching: fetching, + isError: error, + } = useCitation( props, t('doi_constants.publisher.name'), format, - t('studies.details.citation_formatter.locale') + t('datapublications.details.citation_formatter.locale') ); - const handleChange = (event: React.ChangeEvent<{ value: unknown }>): void => { + const handleChange = (event: SelectChangeEvent): void => { setFormat(event.target.value as string); }; //Information on available formats can be found here: https://citationstyles.org/developers/ let citationFormats: string[] = t( - 'studies.details.citation_formatter.formats', + 'datapublications.details.citation_formatter.formats', { returnObjects: true } ); //When testing can't easily mock i18next data, but citationFormats.map will fail if @@ -127,36 +118,34 @@ const CitationFormatter = ( return ( - - {t('studies.details.citation_formatter.label')} - + + {t('datapublications.details.citation_formatter.label')} + - {t('studies.details.citation_formatter.details') + + {t('datapublications.details.citation_formatter.details') + (doi ? ` ${t( - 'studies.details.citation_formatter.details_select_format' + 'datapublications.details.citation_formatter.details_select_format' )}` : '')} {doi && ( - +
{t('my_data_table.all_roles')} @@ -127,7 +116,7 @@ const RoleSelector: React.FC = () => { {role.replace('_', ' ').toLowerCase()} ))} - + ); }; diff --git a/packages/datagateway-dataview/src/views/table/__snapshots__/datafileTable.component.test.tsx.snap b/packages/datagateway-dataview/src/views/table/__snapshots__/datafileTable.component.test.tsx.snap deleted file mode 100644 index e24cdf474..000000000 --- a/packages/datagateway-dataview/src/views/table/__snapshots__/datafileTable.component.test.tsx.snap +++ /dev/null @@ -1,96 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Datafile table component renders correctly 1`] = ` -Object { - "actions": Array [ - [Function], - ], - "allIds": Array [ - 1, - ], - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "dataKey": "name", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datafiles.name", - }, - Object { - "dataKey": "location", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datafiles.location", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "fileSize", - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datafiles.size", - }, - Object { - "dataKey": "modTime", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datafiles.modified_time", - }, - ], - "data": Array [ - Object { - "createTime": "2019-07-23", - "fileSize": 1, - "id": 1, - "location": "/test1", - "modTime": "2019-07-23", - "name": "Test 1", - }, - ], - "detailsPanel": [Function], - "disableSelectAll": false, - "loadMoreRows": [Function], - "loading": false, - "onCheck": [MockFunction], - "onSort": [Function], - "onUncheck": [MockFunction], - "selectedRows": Array [], - "sort": Object {}, - "totalRowCount": 0, -} -`; diff --git a/packages/datagateway-dataview/src/views/table/__snapshots__/datasetTable.component.test.tsx.snap b/packages/datagateway-dataview/src/views/table/__snapshots__/datasetTable.component.test.tsx.snap deleted file mode 100644 index 8a326aaff..000000000 --- a/packages/datagateway-dataview/src/views/table/__snapshots__/datasetTable.component.test.tsx.snap +++ /dev/null @@ -1,247 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Dataset table component renders Dataset title as a link 1`] = ` - - - - - - - - Test 1 - - - - - - - -`; - -exports[`Dataset table component renders correctly 1`] = ` -Object { - "allIds": Array [ - 1, - ], - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "name", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.name", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "datafileCount", - "disableSort": true, - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.datafile_count", - }, - Object { - "dataKey": "createTime", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.create_time", - }, - Object { - "dataKey": "modTime", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.modified_time", - }, - ], - "data": Array [ - Object { - "createTime": "2019-07-23", - "id": 1, - "modTime": "2019-07-23", - "name": "Test 1", - "size": 1, - }, - ], - "detailsPanel": [Function], - "disableSelectAll": false, - "loadMoreRows": [Function], - "loading": false, - "onCheck": [MockFunction], - "onSort": [Function], - "onUncheck": [MockFunction], - "selectedRows": Array [], - "sort": Object {}, - "totalRowCount": 0, -} -`; diff --git a/packages/datagateway-dataview/src/views/table/__snapshots__/investigationTable.component.test.tsx.snap b/packages/datagateway-dataview/src/views/table/__snapshots__/investigationTable.component.test.tsx.snap deleted file mode 100644 index 5a9598faa..000000000 --- a/packages/datagateway-dataview/src/views/table/__snapshots__/investigationTable.component.test.tsx.snap +++ /dev/null @@ -1,392 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Investigation table component renders correctly 1`] = ` -Object { - "allIds": Array [ - 1, - ], - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "title", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.title", - }, - Object { - "dataKey": "visitId", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.visit_id", - }, - Object { - "dataKey": "name", - "disableSort": true, - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.name", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "doi", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.doi", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "size", - "disableSort": true, - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.size", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "investigationInstruments.instrument.name", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.instrument", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "startDate", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.start_date", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "endDate", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.end_date", - }, - ], - "data": Array [ - Object { - "doi": "doi 1", - "endDate": "2019-07-24", - "id": 1, - "investigationInstruments": Array [ - Object { - "id": 3, - "instrument": Object { - "id": 4, - "name": "LARMOR", - }, - }, - ], - "name": "Test 1", - "startDate": "2019-07-23", - "title": "Test 1", - "visitId": "1", - }, - ], - "detailsPanel": [Function], - "disableSelectAll": false, - "loadMoreRows": [Function], - "loading": false, - "onCheck": [MockFunction], - "onSort": [Function], - "onUncheck": [MockFunction], - "selectedRows": Array [], - "sort": Object {}, - "totalRowCount": 0, -} -`; - -exports[`Investigation table component renders details panel correctly 1`] = ` - - - - - Test 1 - - - - - - - investigations.details.name - - - - Test 1 - - - - - - investigations.details.start_date - - - - 2019-07-23 - - - - - - investigations.details.end_date - - - - 2019-07-24 - - - - -`; - -exports[`Investigation table component renders investigation title as a link 1`] = ` - - - - - - - - Test 1 - - - - - - - -`; diff --git a/packages/datagateway-dataview/src/views/table/datafileTable.component.test.tsx b/packages/datagateway-dataview/src/views/table/datafileTable.component.test.tsx index dc546f655..19e458114 100644 --- a/packages/datagateway-dataview/src/views/table/datafileTable.component.test.tsx +++ b/packages/datagateway-dataview/src/views/table/datafileTable.component.test.tsx @@ -1,65 +1,62 @@ -import { createMount } from '@material-ui/core/test-utils'; import { - Datafile, + type Datafile, + type DownloadCartItem, dGCommonInitialState, - useDatafileCount, - useIds, - useCart, - useAddToCart, - useRemoveFromCart, - useDatafilesInfinite, - DownloadButton, - DatafileDetailsPanel, } from 'datagateway-common'; -import React from 'react'; +import * as React from 'react'; import { Provider } from 'react-redux'; -import { Router } from 'react-router'; +import { Router } from 'react-router-dom'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; -import { StateType } from '../../state/app.types'; +import type { StateType } from '../../state/app.types'; import { initialState as dgDataViewInitialState } from '../../state/reducers/dgdataview.reducer'; import DatafileTable from './datafileTable.component'; import { QueryClient, QueryClientProvider } from 'react-query'; -import { ReactWrapper } from 'enzyme'; -import { createMemoryHistory, History } from 'history'; - -jest.mock('datagateway-common', () => { - const originalModule = jest.requireActual('datagateway-common'); - - return { - __esModule: true, - ...originalModule, - useDatafileCount: jest.fn(), - useDatafilesInfinite: jest.fn(), - useIds: jest.fn(), - useCart: jest.fn(), - useAddToCart: jest.fn(), - useRemoveFromCart: jest.fn(), - }; -}); +import { createMemoryHistory, type History } from 'history'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, + findAllRows, + findColumnHeaderByName, +} from '../../setupTests'; +import { + render, + type RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; +import type { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; +import { + findCellInRow, + findColumnIndexByName, +} from 'datagateway-search/src/setupTests'; +import axios, { type AxiosResponse } from 'axios'; describe('Datafile table component', () => { - let mount; const mockStore = configureStore([thunk]); let state: StateType; let rowData: Datafile[]; + let cartItems: DownloadCartItem[]; let history: History; + let user: UserEvent; + let holder: HTMLElement; - const createWrapper = (): ReactWrapper => { - const store = mockStore(state); - return mount( - + const renderComponent = (): RenderResult => + render( + - + ); - }; beforeEach(() => { - mount = createMount(); + user = userEvent.setup(); + cartItems = []; rowData = [ { id: 1, @@ -72,6 +69,10 @@ describe('Datafile table component', () => { ]; history = createMemoryHistory(); + holder = document.createElement('div'); + holder.setAttribute('id', 'datagateway-dataview'); + document.body.appendChild(holder); + state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -79,138 +80,189 @@ describe('Datafile table component', () => { }) ); - (useCart as jest.Mock).mockReturnValue({ - data: [], - }); - (useDatafileCount as jest.Mock).mockReturnValue({ - data: 0, - }); - (useDatafilesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - (useIds as jest.Mock).mockReturnValue({ - data: [1], - }); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + if (/\/user\/cart\/$/.test(url)) { + // fetch download cart + return Promise.resolve({ + data: { cartItems }, + }); + } + + if (/\/datafiles\/count$/.test(url)) { + // fetch datafile count + return Promise.resolve({ + data: rowData.length, + }); + } + + if (/\/datafiles$/.test(url)) { + // datafiles infinite + return Promise.resolve({ + data: rowData, + }); + } + + return Promise.reject(`Endpoint not mocked: ${url}`); + }); + + axios.post = jest + .fn() + .mockImplementation( + (url: string, data: unknown): Promise> => { + if (/\/user\/cart\/\/cartItems$/.test(url)) { + const isRemove: boolean = JSON.parse( + (data as URLSearchParams).get('remove') ?? 'false' + ); + + if (isRemove) { + cartItems = []; + + return Promise.resolve({ + data: { + cartItems: [], + }, + }); + } + + cartItems = [ + ...cartItems, + { + id: 123, + entityId: 1, + entityType: 'datafile', + name: 'download cart item name', + parentEntities: [], + }, + ]; + + return Promise.resolve({ + data: { cartItems }, + }); + } + + return Promise.reject(`Endpoint not mocked: ${url}`); + } + ); }); afterEach(() => { - mount.cleanUp(); + document.body.removeChild(holder); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); + it('renders correctly', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - const datasetId = '1'; - createWrapper(); - expect(useDatafileCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ 'dataset.id': { eq: datasetId } }), - }, - ]); - expect(useDatafilesInfinite).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ 'dataset.id': { eq: datasetId } }), - }, - ]); - expect(useIds).toHaveBeenCalledWith( - 'datafile', - [ - { - filterType: 'where', - filterValue: JSON.stringify({ 'dataset.id': { eq: datasetId } }), - }, - ], - true - ); - expect(useCart).toHaveBeenCalled(); - expect(useAddToCart).toHaveBeenCalledWith('datafile'); - expect(useRemoveFromCart).toHaveBeenCalledWith('datafile'); - }); - - it('calls useDatafilesInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useDatafilesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, + let rows: HTMLElement[] = []; + await waitFor(async () => { + rows = await findAllRows(); + // should have 1 row in the table + expect(rows).toHaveLength(1); }); - const wrapper = createWrapper(); - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); - - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, - }); + const row = rows[0]; + + // check that column headers are shown correctly. + expect(await findColumnHeaderByName('datafiles.name')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.location') + ).toBeInTheDocument(); + expect(await findColumnHeaderByName('datafiles.size')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.modified_time') + ).toBeInTheDocument(); + + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.name'), + }) + ).getByText('Test 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.location'), + }) + ).getByText('/test1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.size'), + }) + ).getByText('1 B') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.modified_time'), + }) + ).getByText('2019-07-23') + ).toBeInTheDocument(); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); - const filterInput = wrapper - .find('[aria-label="Filter by datafiles.name"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by datafiles.name', + hidden: true, + }); - expect(history.length).toBe(2); + await user.type(filterInput, 'test'); + + // user.type inputs the given string character by character to simulate user typing + // each keystroke of user.type creates a new entry in the history stack + // so the initial entry + 4 characters in "test" = 5 entries + expect(history.length).toBe(5); expect(history.location.search).toBe( `?filters=${encodeURIComponent( '{"name":{"value":"test","type":"include"}}' )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); - expect(history.length).toBe(3); + expect(history.length).toBe(6); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const filterInput = wrapper.find( - 'input[id="datafiles.modified_time filter to"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'datafiles.modified_time filter to', + }); + + await user.type(filterInput, '2019-08-06'); expect(history.length).toBe(2); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"modTime":{"endDate":"2019-08-06"}}')}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.length).toBe(3); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'datafiles.name' }) + ); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -218,100 +270,114 @@ describe('Datafile table component', () => { ); }); - it('calls addToCart mutate function on unchecked checkbox click', () => { - const addToCart = jest.fn(); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: addToCart, - loading: false, - }); - const wrapper = createWrapper(); - - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); - - expect(addToCart).toHaveBeenCalledWith([1]); - }); + it('adds selected row to cart if unselected; removes it from cart otherwise', async () => { + renderComponent(); - it('calls removeFromCart mutate function on checked checkbox click', () => { - (useCart as jest.Mock).mockReturnValue({ - data: [ - { - entityId: 1, - entityType: 'datafile', - id: 1, - name: 'test', - parentEntities: [], - }, - ], - }); + // row should not be selected initially as the cart is empty + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).not.toBeChecked(); - const removeFromCart = jest.fn(); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: removeFromCart, - loading: false, - }); + // select the row + await user.click( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ); - const wrapper = createWrapper(); + // datafile should be added to the cart + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).toBeChecked(); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + // unselect the row + await user.click(screen.getByRole('checkbox', { name: 'select row 0' })); - expect(removeFromCart).toHaveBeenCalledWith([1]); + // datafile should be removed from the cart + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).not.toBeChecked(); }); - it('selected rows only considers relevant cart items', () => { - (useCart as jest.Mock).mockReturnValueOnce({ - data: [ - { - entityId: 1, - entityType: 'dataset', - id: 1, - name: 'test', - parentEntities: [], - }, - { - entityId: 2, - entityType: 'datafile', - id: 2, - name: 'test', - parentEntities: [], - }, - ], - }); + it('selected rows only considers relevant cart items', async () => { + cartItems = [ + { + entityId: 1, + entityType: 'dataset', + id: 1, + name: 'test', + parentEntities: [], + }, + { + entityId: 2, + entityType: 'datafile', + id: 2, + name: 'test', + parentEntities: [], + }, + ]; - const wrapper = createWrapper(); + renderComponent(); + // wait for rows to show up + await waitFor(async () => { + expect(await findAllRows()).toHaveLength(1); + }); - const selectAllCheckbox = wrapper - .find('[aria-label="select all rows"]') - .first(); + const selectAllCheckbox = await screen.findByRole('checkbox', { + name: 'select all rows', + }); - expect(selectAllCheckbox.prop('checked')).toEqual(false); - expect(selectAllCheckbox.prop('data-indeterminate')).toEqual(false); + expect(selectAllCheckbox).not.toBeChecked(); + expect(selectAllCheckbox).toHaveAttribute('data-indeterminate', 'false'); }); - it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', () => { + it('no select all checkbox appears if selectAllSetting is false', async () => { state.dgdataview.selectAllSetting = false; - const wrapper = createWrapper(); + renderComponent(); + // wait for rows to show up + await waitFor(async () => { + expect(await findAllRows()).toHaveLength(1); + }); - expect(useIds).toHaveBeenCalledWith('datafile', expect.anything(), false); - expect(useIds).not.toHaveBeenCalledWith( - 'datafile', - expect.anything(), - true - ); - expect(wrapper.exists('[aria-label="select all rows"]')).toBe(false); + await waitFor(() => { + expect( + screen.queryByRole('checkbox', { name: 'select all rows' }) + ).toBeNull(); + }); }); - it('renders actions correctly', () => { - const wrapper = createWrapper(); + it('renders actions correctly', async () => { + renderComponent(); - expect(wrapper.find(DownloadButton).exists()).toBeTruthy(); + // wait for rows to show up + let rows: HTMLElement[] = []; + await waitFor(async () => { + rows = await findAllRows(); + expect(rows).toHaveLength(1); + }); + + expect( + within(rows[0]).getByRole('button', { name: 'buttons.download' }) + ).toBeInTheDocument(); }); - it('displays details panel when expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(DatafileDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); + it('displays details panel when expanded', async () => { + renderComponent(); + + // wait for rows to show up + let rows: HTMLElement[] = []; + await waitFor(async () => { + rows = await findAllRows(); + expect(rows).toHaveLength(1); + }); + + expect(screen.queryByTestId('datafile-details-panel')).toBeNull(); + + await user.click( + within(rows[0]).getByRole('button', { name: 'Show details' }) + ); - expect(wrapper.find(DatafileDetailsPanel).exists()).toBeTruthy(); + expect( + await screen.findByTestId('datafile-details-panel') + ).toBeInTheDocument(); }); }); diff --git a/packages/datagateway-dataview/src/views/table/datafileTable.component.tsx b/packages/datagateway-dataview/src/views/table/datafileTable.component.tsx index 644fba2ba..2936db152 100644 --- a/packages/datagateway-dataview/src/views/table/datafileTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/datafileTable.component.tsx @@ -1,39 +1,37 @@ -import React from 'react'; -import SubjectIcon from '@material-ui/icons/Subject'; -import ExploreIcon from '@material-ui/icons/Explore'; -import SaveIcon from '@material-ui/icons/Save'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; +import { CalendarToday, Explore, Save, Subject } from '@mui/icons-material'; import { + ColumnType, + Datafile, + DatafileDetailsPanel, + DownloadButton, + formatBytes, + parseSearchToQuery, Table, TableActionProps, - formatBytes, - Datafile, + useAddToCart, + useCart, useDatafileCount, useDatafilesInfinite, - parseSearchToQuery, - useTextFilter, useDateFilter, - ColumnType, - useSort, useIds, - useCart, - useAddToCart, useRemoveFromCart, - DatafileDetailsPanel, - DownloadButton, + useSort, + useTextFilter, } from 'datagateway-common'; +import React from 'react'; import { useTranslation } from 'react-i18next'; -import { useLocation } from 'react-router'; import { useSelector } from 'react-redux'; -import { StateType } from '../../state/app.types'; +import { useLocation } from 'react-router-dom'; import { IndexRange } from 'react-virtualized'; +import type { StateType } from '../../state/app.types'; interface DatafileTableProps { datasetId: string; + investigationId: string; } const DatafileTable = (props: DatafileTableProps): React.ReactElement => { - const { datasetId } = props; + const { datasetId, investigationId } = props; const [t] = useTranslation(); @@ -51,7 +49,7 @@ const DatafileTable = (props: DatafileTableProps): React.ReactElement => { const textFilter = useTextFilter(filters); const dateFilter = useDateFilter(filters); const handleSort = useSort(); - const { data: allIds } = useIds( + const { data: allIds, isLoading: allIdsLoading } = useIds( 'datafile', [ { @@ -61,14 +59,11 @@ const DatafileTable = (props: DatafileTableProps): React.ReactElement => { ], selectAllSetting ); - const { data: cartItems } = useCart(); - const { mutate: addToCart, isLoading: addToCartLoading } = useAddToCart( - 'datafile' - ); - const { - mutate: removeFromCart, - isLoading: removeFromCartLoading, - } = useRemoveFromCart('datafile'); + const { data: cartItems, isLoading: cartLoading } = useCart(); + const { mutate: addToCart, isLoading: addToCartLoading } = + useAddToCart('datafile'); + const { mutate: removeFromCart, isLoading: removeFromCartLoading } = + useRemoveFromCart('datafile'); const { data: totalDataCount } = useDatafileCount([ { @@ -89,27 +84,35 @@ const DatafileTable = (props: DatafileTableProps): React.ReactElement => { [fetchNextPage] ); - const aggregatedData: Datafile[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + /* istanbul ignore next */ + const aggregatedData: Datafile[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } + + return []; + }, [data]); const columns: ColumnType[] = React.useMemo( () => [ { - icon: SubjectIcon, + icon: Subject, label: t('datafiles.name'), dataKey: 'name', filterComponent: textFilter, }, { - icon: ExploreIcon, + icon: Explore, label: t('datafiles.location'), dataKey: 'location', filterComponent: textFilter, }, { - icon: SaveIcon, + icon: Save, label: t('datafiles.size'), dataKey: 'fileSize', cellContentRenderer: (cellProps) => { @@ -117,7 +120,7 @@ const DatafileTable = (props: DatafileTableProps): React.ReactElement => { }, }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('datafiles.modified_time'), dataKey: 'modTime', filterComponent: dateFilter, @@ -140,9 +143,25 @@ const DatafileTable = (props: DatafileTableProps): React.ReactElement => { [cartItems, selectAllSetting, allIds] ); + const isParentSelected = React.useMemo(() => { + return cartItems?.some( + (cartItem) => + (cartItem.entityType === 'dataset' && + cartItem.entityId.toString() === datasetId) || + (cartItem.entityType === 'investigation' && + cartItem.entityId.toString() === investigationId) + ); + }, [cartItems, datasetId, investigationId]); + return ( { - const originalModule = jest.requireActual('datagateway-common'); - - return { - __esModule: true, - ...originalModule, - useDatasetCount: jest.fn(), - useDatasetsInfinite: jest.fn(), - useDatasetsDatafileCount: jest.fn(), - useIds: jest.fn(), - useCart: jest.fn(), - useAddToCart: jest.fn(), - useRemoveFromCart: jest.fn(), - }; -}); +import { createMemoryHistory, type History } from 'history'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, + findAllRows, + findColumnHeaderByName, +} from '../../setupTests'; +import { + render, + type RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; +import type { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; +import { + findCellInRow, + findColumnIndexByName, +} from 'datagateway-search/src/setupTests'; +import axios, { type AxiosResponse } from 'axios'; describe('Dataset table component', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let rowData: Dataset[]; + let cartItems: DownloadCartItem[]; let history: History; + let user: UserEvent; + let holder: HTMLElement; - const createWrapper = (): ReactWrapper => { + const renderComponent = (): RenderResult => { const store = mockStore(state); - return mount( + return render( @@ -60,11 +57,14 @@ describe('Dataset table component', () => { }; beforeEach(() => { - mount = createMount(); + user = userEvent.setup(); + cartItems = []; rowData = [ { id: 1, name: 'Test 1', + fileSize: 1, + fileCount: 1, size: 1, modTime: '2019-07-23', createTime: '2019-07-23', @@ -72,7 +72,10 @@ describe('Dataset table component', () => { ]; history = createMemoryHistory(); - mockStore = configureStore([thunk]); + holder = document.createElement('div'); + holder.setAttribute('id', 'datagateway-dataview'); + document.body.appendChild(holder); + state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -80,148 +83,195 @@ describe('Dataset table component', () => { }) ); - (useCart as jest.Mock).mockReturnValue({ - data: [], - }); - (useDatasetCount as jest.Mock).mockReturnValue({ - data: 0, - }); - (useDatasetsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - (useDatasetsDatafileCount as jest.Mock).mockReturnValue([{ data: 1 }]); - (useIds as jest.Mock).mockReturnValue({ - data: [1], - }); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + if (/\/user\/cart\/$/.test(url)) { + // fetch download cart + return Promise.resolve({ + data: { cartItems }, + }); + } + + if (/\/datafiles\/count$/.test(url)) { + // fetch datafile count + return Promise.resolve({ + data: 1, + }); + } + + if (/\/datasets\/count$/.test(url)) { + // fetch dataset count + return Promise.resolve({ + data: rowData.length, + }); + } + + if (/\/datasets$/.test(url)) { + // datafiles infinite + return Promise.resolve({ + data: rowData, + }); + } + + return Promise.reject(`Endpoint not mocked: ${url}`); + }); + + axios.post = jest + .fn() + .mockImplementation( + (url: string, data: unknown): Promise> => { + if (/\/user\/cart\/\/cartItems$/.test(url)) { + const isRemove: boolean = JSON.parse( + (data as URLSearchParams).get('remove') ?? 'false' + ); + + if (isRemove) { + cartItems = []; + + return Promise.resolve({ + data: { + cartItems: [], + }, + }); + } + + cartItems = [ + ...cartItems, + { + id: 123, + entityId: 1, + entityType: 'dataset', + name: 'download cart item name', + parentEntities: [], + }, + ]; + + return Promise.resolve({ + data: { cartItems }, + }); + } + + return Promise.reject(`Endpoint not mocked: ${url}`); + } + ); }); afterEach(() => { - mount.cleanUp(); + document.body.removeChild(holder); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); + it('renders correctly', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - const investigationId = '1'; - createWrapper(); - expect(useDatasetCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: investigationId }, - }), - }, - ]); - expect(useDatasetsInfinite).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: investigationId }, - }), - }, - ]); - expect(useDatasetsDatafileCount).toHaveBeenCalledWith({ - pages: [rowData], + let rows: HTMLElement[] = []; + await waitFor(async () => { + rows = await findAllRows(); + // should have 1 row in the table + expect(rows).toHaveLength(1); }); - expect(useIds).toHaveBeenCalledWith( - 'dataset', - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: parseInt(investigationId) }, - }), - }, - ], - true - ); - expect(useCart).toHaveBeenCalled(); - expect(useAddToCart).toHaveBeenCalledWith('dataset'); - expect(useRemoveFromCart).toHaveBeenCalledWith('dataset'); - }); - it('sends fetchDatasets action when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useDatasetsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); + const row = rows[0]; - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); + // check that column headers are shown correctly. + expect(await findColumnHeaderByName('datasets.name')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.datafile_count') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.create_time') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.modified_time') + ).toBeInTheDocument(); - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, - }); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.name'), + }) + ).getByRole('link', { name: 'Test 1' }) + ).toHaveAttribute('href', '/browse/investigation/1/dataset/1/datafile'); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.datafile_count'), + }) + ).getByText('1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.create_time'), + }) + ).getByText('2019-07-23') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.modified_time'), + }) + ).getByText('2019-07-23') + ).toBeInTheDocument(); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by datasets.name', + hidden: true, + }); - const filterInput = wrapper - .find('[aria-label="Filter by datasets.name"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + await user.type(filterInput, 'test'); - expect(history.length).toBe(2); + expect(history.length).toBe(5); expect(history.location.search).toBe( `?filters=${encodeURIComponent( '{"name":{"value":"test","type":"include"}}' )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); - expect(history.length).toBe(3); + expect(history.length).toBe(6); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const filterInput = wrapper.find( - 'input[id="datasets.modified_time filter to"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'datasets.modified_time filter to', + }); + + await user.type(filterInput, '2019-08-06'); expect(history.length).toBe(2); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"modTime":{"endDate":"2019-08-06"}}')}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.length).toBe(3); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'datasets.name' }) + ); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -229,98 +279,104 @@ describe('Dataset table component', () => { ); }); - it('calls addToCart mutate function on unchecked checkbox click', () => { - const addToCart = jest.fn(); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: addToCart, - loading: false, - }); - const wrapper = createWrapper(); - - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); - - expect(addToCart).toHaveBeenCalledWith([1]); - }); + it('adds selected row to cart if unselected; removes it from cart otherwise', async () => { + renderComponent(); - it('calls removeFromCart mutate function on checked checkbox click', () => { - (useCart as jest.Mock).mockReturnValue({ - data: [ - { - entityId: 1, - entityType: 'dataset', - id: 1, - name: 'test', - parentEntities: [], - }, - ], + // wait for rows to show up + await waitFor(async () => { + expect(await findAllRows()).toHaveLength(1); }); - const removeFromCart = jest.fn(); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: removeFromCart, - loading: false, - }); + // row should not be selected initially as the cart is empty + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).not.toBeChecked(); + + // select the row + await user.click( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ); - const wrapper = createWrapper(); + // datafile should be added to the cart + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).toBeChecked(); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + // unselect the row + await user.click(screen.getByRole('checkbox', { name: 'select row 0' })); - expect(removeFromCart).toHaveBeenCalledWith([1]); + // datafile should be removed from the cart + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).not.toBeChecked(); }); - it('selected rows only considers relevant cart items', () => { - (useCart as jest.Mock).mockReturnValueOnce({ - data: [ - { - entityId: 1, - entityType: 'investigation', - id: 1, - name: 'test', - parentEntities: [], - }, - { - entityId: 2, - entityType: 'dataset', - id: 2, - name: 'test', - parentEntities: [], - }, - ], - }); + it('selected rows only considers relevant cart items', async () => { + cartItems = [ + { + entityId: 1, + entityType: 'investigation', + id: 1, + name: 'test', + parentEntities: [], + }, + { + entityId: 2, + entityType: 'dataset', + id: 2, + name: 'test', + parentEntities: [], + }, + ]; - const wrapper = createWrapper(); + renderComponent(); + // wait for rows to show up + await waitFor(async () => { + expect(await findAllRows()).toHaveLength(1); + }); - const selectAllCheckbox = wrapper - .find('[aria-label="select all rows"]') - .first(); + const selectAllCheckbox = await screen.findByRole('checkbox', { + name: 'select all rows', + }); - expect(selectAllCheckbox.prop('checked')).toEqual(false); - expect(selectAllCheckbox.prop('data-indeterminate')).toEqual(false); + expect(selectAllCheckbox).not.toBeChecked(); + expect(selectAllCheckbox).toHaveAttribute('data-indeterminate', 'false'); }); - it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', () => { + it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', async () => { state.dgdataview.selectAllSetting = false; - const wrapper = createWrapper(); + renderComponent(); + // wait for rows to show up + await waitFor(async () => { + expect(await findAllRows()).toHaveLength(1); + }); - expect(useIds).toHaveBeenCalledWith('dataset', expect.anything(), false); - expect(useIds).not.toHaveBeenCalledWith('dataset', expect.anything(), true); - expect(wrapper.exists('[aria-label="select all rows"]')).toBe(false); + await waitFor(() => { + expect( + screen.queryByRole('checkbox', { name: 'select all rows' }) + ).toBeNull(); + }); }); - it('displays details panel when expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(DatasetDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); + it('displays details panel when expanded', async () => { + renderComponent(); - expect(wrapper.find(DatasetDetailsPanel).exists()).toBeTruthy(); - }); + // wait for rows to show up + let rows: HTMLElement[] = []; + await waitFor(async () => { + rows = await findAllRows(); + expect(rows).toHaveLength(1); + }); - it('renders Dataset title as a link', () => { - const wrapper = createWrapper(); + expect(screen.queryByTestId('dataset-details-panel')).toBeNull(); + + await user.click( + within(rows[0]).getByRole('button', { name: 'Show details' }) + ); expect( - wrapper.find('[aria-colindex=3]').find('p').children() - ).toMatchSnapshot(); + await screen.findByTestId('dataset-details-panel') + ).toBeInTheDocument(); }); }); diff --git a/packages/datagateway-dataview/src/views/table/datasetTable.component.tsx b/packages/datagateway-dataview/src/views/table/datasetTable.component.tsx index 8357a5a52..4389912f8 100644 --- a/packages/datagateway-dataview/src/views/table/datasetTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/datasetTable.component.tsx @@ -1,12 +1,13 @@ import React from 'react'; -import SubjectIcon from '@material-ui/icons/Subject'; -import ConfirmationNumberIcon from '@material-ui/icons/ConfirmationNumber'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; +import { + Subject, + ConfirmationNumber, + CalendarToday, +} from '@mui/icons-material'; import { Table, datasetLink, Dataset, - formatCountOrSize, useDatasetCount, useDatasetsInfinite, parseSearchToQuery, @@ -19,13 +20,12 @@ import { useAddToCart, useRemoveFromCart, DatasetDetailsPanel, - useDatasetsDatafileCount, } from 'datagateway-common'; import { useTranslation } from 'react-i18next'; -import { useLocation } from 'react-router'; +import { useLocation } from 'react-router-dom'; import { useSelector } from 'react-redux'; import { StateType } from '../../state/app.types'; -import { TableCellProps, IndexRange } from 'react-virtualized'; +import { IndexRange } from 'react-virtualized'; interface DatasetTableProps { investigationId: string; @@ -51,7 +51,7 @@ const DatasetTable = (props: DatasetTableProps): React.ReactElement => { const dateFilter = useDateFilter(filters); const handleSort = useSort(); - const { data: allIds } = useIds( + const { data: allIds, isLoading: allIdsLoading } = useIds( 'dataset', [ { @@ -63,14 +63,11 @@ const DatasetTable = (props: DatasetTableProps): React.ReactElement => { ], selectAllSetting ); - const { data: cartItems } = useCart(); - const { mutate: addToCart, isLoading: addToCartLoading } = useAddToCart( - 'dataset' - ); - const { - mutate: removeFromCart, - isLoading: removeFromCartLoading, - } = useRemoveFromCart('dataset'); + const { data: cartItems, isLoading: cartLoading } = useCart(); + const { mutate: addToCart, isLoading: addToCartLoading } = + useAddToCart('dataset'); + const { mutate: removeFromCart, isLoading: removeFromCartLoading } = + useRemoveFromCart('dataset'); const { data: totalDataCount } = useDatasetCount([ { @@ -95,17 +92,23 @@ const DatasetTable = (props: DatasetTableProps): React.ReactElement => { [fetchNextPage] ); - const datafileCountQueries = useDatasetsDatafileCount(data); + /* istanbul ignore next */ + const aggregatedData: Dataset[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } - const aggregatedData: Dataset[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + return []; + }, [data]); const columns: ColumnType[] = React.useMemo( () => [ { - icon: SubjectIcon, + icon: Subject, label: t('datasets.name'), dataKey: 'name', cellContentRenderer: (cellProps) => { @@ -120,27 +123,25 @@ const DatasetTable = (props: DatasetTableProps): React.ReactElement => { filterComponent: textFilter, }, { - icon: ConfirmationNumberIcon, + icon: ConfirmationNumber, label: t('datasets.datafile_count'), - dataKey: 'datafileCount', - cellContentRenderer: (cellProps: TableCellProps): number | string => - formatCountOrSize(datafileCountQueries[cellProps.rowIndex]), + dataKey: 'fileCount', disableSort: true, }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('datasets.create_time'), dataKey: 'createTime', filterComponent: dateFilter, }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('datasets.modified_time'), dataKey: 'modTime', filterComponent: dateFilter, }, ], - [t, textFilter, dateFilter, investigationId, view, datafileCountQueries] + [t, textFilter, dateFilter, investigationId, view] ); const selectedRows = React.useMemo( @@ -157,9 +158,23 @@ const DatasetTable = (props: DatasetTableProps): React.ReactElement => { [cartItems, selectAllSetting, allIds] ); + const isParentSelected = React.useMemo(() => { + return cartItems?.some( + (cartItem) => + cartItem.entityType === 'investigation' && + cartItem.entityId.toString() === investigationId + ); + }, [cartItems, investigationId]); + return (
- - - - - - - Test 1 - - - - - - - -`; - -exports[`DLS Dataset table component renders correctly 1`] = ` -Object { - "allIds": Array [ - 1, - ], - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "name", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.name", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "datafileCount", - "disableSort": true, - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.datafile_count", - }, - Object { - "dataKey": "createTime", - "defaultSort": "desc", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.create_time", - }, - Object { - "dataKey": "modTime", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.modified_time", - }, - ], - "data": Array [ - Object { - "createTime": "2019-07-23", - "id": 1, - "modTime": "2019-07-23", - "name": "Test 1", - "size": 1, - }, - ], - "detailsPanel": [Function], - "disableSelectAll": false, - "loadMoreRows": [Function], - "loading": false, - "onCheck": [MockFunction], - "onSort": [Function], - "onUncheck": [MockFunction], - "selectedRows": Array [], - "sort": Object { - "createTime": "desc", - }, - "totalRowCount": 0, -} -`; diff --git a/packages/datagateway-dataview/src/views/table/dls/__snapshots__/dlsMyDataTable.component.test.tsx.snap b/packages/datagateway-dataview/src/views/table/dls/__snapshots__/dlsMyDataTable.component.test.tsx.snap deleted file mode 100644 index 9cdc35e36..000000000 --- a/packages/datagateway-dataview/src/views/table/dls/__snapshots__/dlsMyDataTable.component.test.tsx.snap +++ /dev/null @@ -1,441 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DLS MyData table component renders correctly 1`] = ` -Object { - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "title", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.title", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "visitId", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.visit_id", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "datasetCount", - "disableSort": true, - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.dataset_count", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "investigationInstruments.instrument.fullName", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.instrument", - }, - Object { - "dataKey": "startDate", - "defaultSort": "desc", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.start_date", - }, - Object { - "dataKey": "endDate", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.end_date", - }, - ], - "data": Array [ - Object { - "doi": "doi 1", - "endDate": "2019-06-11", - "id": 1, - "investigationInstruments": Array [ - Object { - "id": 1, - "instrument": Object { - "id": 3, - "name": "LARMOR", - }, - }, - ], - "name": "Test 1", - "size": 1, - "startDate": "2019-06-10", - "summary": "foo bar", - "title": "Test 1", - "visitId": "1", - }, - ], - "detailsPanel": [Function], - "loadMoreRows": [Function], - "onSort": [Function], - "sort": Object {}, - "totalRowCount": 0, -} -`; - -exports[`DLS MyData table component renders title and visit ID as a links 1`] = ` - - - - - - - - Test 1 - - - - - - - -`; - -exports[`DLS MyData table component renders title and visit ID as a links 2`] = ` - - - - - - - - 1 - - - - - - - -`; diff --git a/packages/datagateway-dataview/src/views/table/dls/__snapshots__/dlsProposalsTable.component.test.tsx.snap b/packages/datagateway-dataview/src/views/table/dls/__snapshots__/dlsProposalsTable.component.test.tsx.snap deleted file mode 100644 index df5e05d3c..000000000 --- a/packages/datagateway-dataview/src/views/table/dls/__snapshots__/dlsProposalsTable.component.test.tsx.snap +++ /dev/null @@ -1,232 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DLS Proposals table component renders correctly 1`] = ` -Object { - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "title", - "defaultSort": "asc", - "disableSort": true, - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.title", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "name", - "disableSort": true, - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.name", - }, - ], - "data": Array [ - Object { - "doi": "doi 1", - "endDate": "2019-06-11", - "id": 1, - "investigationInstruments": Array [ - Object { - "id": 1, - "instrument": Object { - "id": 3, - "name": "LARMOR", - }, - }, - ], - "name": "Test 1", - "size": 1, - "startDate": "2019-06-10", - "summary": "foo bar", - "title": "Test 1", - "visitId": "1", - }, - ], - "loadMoreRows": [Function], - "onSort": [Function], - "sort": Object { - "title": "asc", - }, - "totalRowCount": 1, -} -`; - -exports[`DLS Proposals table component renders title and name as links 1`] = ` - - - - - - - - Test 1 - - - - - - - -`; - -exports[`DLS Proposals table component renders title and name as links 2`] = `null`; diff --git a/packages/datagateway-dataview/src/views/table/dls/__snapshots__/dlsVisitsTable.component.test.tsx.snap b/packages/datagateway-dataview/src/views/table/dls/__snapshots__/dlsVisitsTable.component.test.tsx.snap deleted file mode 100644 index 1476bf933..000000000 --- a/packages/datagateway-dataview/src/views/table/dls/__snapshots__/dlsVisitsTable.component.test.tsx.snap +++ /dev/null @@ -1,269 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DLS Visits table component renders correctly 1`] = ` -Object { - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "visitId", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.visit_id", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "datasetCount", - "disableSort": true, - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.dataset_count", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "investigationInstruments.instrument.name", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.instrument", - }, - Object { - "dataKey": "startDate", - "defaultSort": "desc", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.start_date", - }, - Object { - "dataKey": "endDate", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.end_date", - }, - ], - "data": Array [ - Object { - "doi": "doi 1", - "endDate": "2019-06-11", - "id": 1, - "investigationInstruments": Array [ - Object { - "id": 1, - "instrument": Object { - "id": 3, - "name": "LARMOR", - }, - }, - ], - "name": "Test 1", - "size": 1, - "startDate": "2019-06-10", - "summary": "foo bar", - "title": "Test 1", - "visitId": "1", - }, - ], - "detailsPanel": [Function], - "loadMoreRows": [Function], - "onSort": [Function], - "sort": Object { - "startDate": "desc", - }, - "totalRowCount": 1, -} -`; - -exports[`DLS Visits table component renders visit ID as links 1`] = ` - - - - - - - - 1 - - - - - - - -`; diff --git a/packages/datagateway-dataview/src/views/table/dls/dlsDatafilesTable.component.test.tsx b/packages/datagateway-dataview/src/views/table/dls/dlsDatafilesTable.component.test.tsx index 78c7b943c..7ff367e8f 100644 --- a/packages/datagateway-dataview/src/views/table/dls/dlsDatafilesTable.component.test.tsx +++ b/packages/datagateway-dataview/src/views/table/dls/dlsDatafilesTable.component.test.tsx @@ -1,25 +1,41 @@ -import { createMount } from '@material-ui/core/test-utils'; import { + Datafile, dGCommonInitialState, + useAddToCart, + useCart, useDatafileCount, + useDatafilesInfinite, useIds, - useCart, - useAddToCart, useRemoveFromCart, - useDatafilesInfinite, - Datafile, } from 'datagateway-common'; -import React from 'react'; +import * as React from 'react'; import { Provider } from 'react-redux'; -import { Router } from 'react-router'; +import { Router } from 'react-router-dom'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { StateType } from '../../../state/app.types'; import { initialState as dgDataViewInitialState } from '../../../state/reducers/dgdataview.reducer'; import DLSDatafilesTable from './dlsDatafilesTable.component'; import { QueryClient, QueryClientProvider } from 'react-query'; -import { ReactWrapper } from 'enzyme'; -import { createMemoryHistory, History } from 'history'; +import { createMemoryHistory, type History } from 'history'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, + findAllRows, + findCellInRow, + findColumnHeaderByName, + findColumnIndexByName, + findRowAt, +} from '../../../setupTests'; +import { + render, + type RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; +import { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -38,27 +54,24 @@ jest.mock('datagateway-common', () => { }); describe('DLS datafiles table component', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let rowData: Datafile[]; let history: History; + let user: UserEvent; - const createWrapper = (): ReactWrapper => { - const store = mockStore(state); - return mount( - + const renderComponent = (): RenderResult => + render( + - + ); - }; beforeEach(() => { - mount = createMount(); rowData = [ { id: 1, @@ -70,8 +83,8 @@ describe('DLS datafiles table component', () => { }, ]; history = createMemoryHistory(); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgdataview: dgDataViewInitialState, @@ -81,6 +94,7 @@ describe('DLS datafiles table component', () => { (useCart as jest.Mock).mockReturnValue({ data: [], + isLoading: false, }); (useDatafileCount as jest.Mock).mockReturnValue({ data: 0, @@ -91,6 +105,7 @@ describe('DLS datafiles table component', () => { }); (useIds as jest.Mock).mockReturnValue({ data: [1], + isLoading: false, }); (useAddToCart as jest.Mock).mockReturnValue({ mutate: jest.fn(), @@ -103,97 +118,93 @@ describe('DLS datafiles table component', () => { }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); + it('renders correctly', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - const datasetId = '1'; - createWrapper(); - expect(useDatafileCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ 'dataset.id': { eq: datasetId } }), - }, - ]); - expect(useDatafilesInfinite).toHaveBeenCalledWith( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ 'dataset.id': { eq: datasetId } }), - }, - ], - expect.any(Boolean) - ); - expect(useIds).toHaveBeenCalledWith( - 'datafile', - [ - { - filterType: 'where', - filterValue: JSON.stringify({ 'dataset.id': { eq: datasetId } }), - }, - ], - true - ); - expect(useCart).toHaveBeenCalled(); - expect(useAddToCart).toHaveBeenCalledWith('datafile'); - expect(useRemoveFromCart).toHaveBeenCalledWith('datafile'); - }); - - it('calls useDatafilesInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useDatafilesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); + const rows = await findAllRows(); + // should have 1 row in the table + expect(rows).toHaveLength(1); - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); + expect(await findColumnHeaderByName('datafiles.name')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.location') + ).toBeInTheDocument(); + expect(await findColumnHeaderByName('datafiles.size')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.create_time') + ).toBeInTheDocument(); - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, - }); + const row = rows[0]; + // check that every cell contains the correct values + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.name'), + }) + ).getByText('Test 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.location'), + }) + ).getByText('/test1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.size'), + }) + ).getByText('1 B') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.create_time'), + }) + ).getByText('2019-07-23') + ).toBeInTheDocument(); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by datafiles.name', + hidden: true, + }); - const filterInput = wrapper - .find('[aria-label="Filter by datafiles.name"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + await user.type(filterInput, 'test'); - expect(history.length).toBe(2); + // user.type inputs the given string character by character to simulate user typing + // each keystroke of user.type creates a new entry in the history stack + // so the initial entry + 4 characters in "test" = 5 entries + expect(history.length).toBe(5); expect(history.location.search).toBe( `?filters=${encodeURIComponent( '{"name":{"value":"test","type":"include"}}' )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); - expect(history.length).toBe(3); + expect(history.length).toBe(6); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const filterInput = wrapper.find( - 'input[id="datafiles.create_time filter to"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'datafiles.create_time filter to', + }); + + await user.type(filterInput, '2019-08-06'); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -202,17 +213,19 @@ describe('DLS datafiles table component', () => { )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.length).toBe(3); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"createTime":"desc"}')}` @@ -227,13 +240,12 @@ describe('DLS datafiles table component', () => { ); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'datafiles.name' }) + ); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -241,20 +253,22 @@ describe('DLS datafiles table component', () => { ); }); - it('calls addToCart mutate function on unchecked checkbox click', () => { + it('calls addToCart mutate function on unchecked checkbox click', async () => { const addToCart = jest.fn(); (useAddToCart as jest.Mock).mockReturnValue({ mutate: addToCart, loading: false, }); - const wrapper = createWrapper(); + renderComponent(); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + await user.click( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ); expect(addToCart).toHaveBeenCalledWith([1]); }); - it('calls removeFromCart mutate function on checked checkbox click', () => { + it('calls removeFromCart mutate function on checked checkbox click', async () => { (useCart as jest.Mock).mockReturnValue({ data: [ { @@ -265,6 +279,7 @@ describe('DLS datafiles table component', () => { parentEntities: [], }, ], + isLoading: false, }); const removeFromCart = jest.fn(); @@ -273,14 +288,16 @@ describe('DLS datafiles table component', () => { loading: false, }); - const wrapper = createWrapper(); + renderComponent(); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + await user.click( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ); expect(removeFromCart).toHaveBeenCalledWith([1]); }); - it('selected rows only considers relevant cart items', () => { + it('selected rows only considers relevant cart items', async () => { (useCart as jest.Mock).mockReturnValueOnce({ data: [ { @@ -298,33 +315,32 @@ describe('DLS datafiles table component', () => { parentEntities: [], }, ], + isLoading: false, }); - const wrapper = createWrapper(); + renderComponent(); - const selectAllCheckbox = wrapper - .find('[aria-label="select all rows"]') - .first(); + const selectAllCheckbox = await screen.findByRole('checkbox', { + name: 'select all rows', + }); - expect(selectAllCheckbox.prop('checked')).toEqual(false); - expect(selectAllCheckbox.prop('data-indeterminate')).toEqual(false); + expect(selectAllCheckbox).not.toBeChecked(); + expect(selectAllCheckbox).toHaveAttribute('data-indeterminate', 'false'); }); - it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', () => { + it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', async () => { state.dgdataview.selectAllSetting = false; - const wrapper = createWrapper(); + renderComponent(); - expect(useIds).toHaveBeenCalledWith('datafile', expect.anything(), false); - expect(useIds).not.toHaveBeenCalledWith( - 'datafile', - expect.anything(), - true - ); - expect(wrapper.exists('[aria-label="select all rows"]')).toBe(false); + await waitFor(() => { + expect( + screen.queryByRole('checkbox', { name: 'select all rows' }) + ).toBeNull(); + }); }); - it("doesn't display download button for datafiles with no location", () => { + it("doesn't display download button for datafiles with no location", async () => { (useDatafilesInfinite as jest.Mock).mockReturnValueOnce([ { id: 1, @@ -335,10 +351,26 @@ describe('DLS datafiles table component', () => { }, ]); - const wrapper = createWrapper(); + renderComponent(); + + const row = await findRowAt(0); + + await waitFor(() => { + expect( + within(row).queryByRole('button', { name: 'datafiles.download' }) + ).toBeNull(); + }); + }); + + it('displays details panel when expanded', async () => { + renderComponent(); + + await user.click( + await screen.findByRole('button', { name: 'Show details' }) + ); expect( - wrapper.find('button[aria-label="datafiles.download"]') - ).toHaveLength(0); + await screen.findByTestId('dls-datafile-details-panel') + ).toBeTruthy(); }); }); diff --git a/packages/datagateway-dataview/src/views/table/dls/dlsDatafilesTable.component.tsx b/packages/datagateway-dataview/src/views/table/dls/dlsDatafilesTable.component.tsx index c9a7c1b55..b0bcfc224 100644 --- a/packages/datagateway-dataview/src/views/table/dls/dlsDatafilesTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/dls/dlsDatafilesTable.component.tsx @@ -1,8 +1,5 @@ import React from 'react'; -import SubjectIcon from '@material-ui/icons/Subject'; -import ExploreIcon from '@material-ui/icons/Explore'; -import SaveIcon from '@material-ui/icons/Save'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; +import { Subject, Explore, Save, CalendarToday } from '@mui/icons-material'; import { Table, formatBytes, @@ -21,19 +18,20 @@ import { DLSDatafileDetailsPanel, } from 'datagateway-common'; import { useTranslation } from 'react-i18next'; -import { useLocation } from 'react-router'; +import { useLocation } from 'react-router-dom'; import { useSelector } from 'react-redux'; import { StateType } from '../../../state/app.types'; import { IndexRange } from 'react-virtualized'; interface DLSDatafilesTableProps { datasetId: string; + investigationId: string; } const DLSDatafilesTable = ( props: DLSDatafilesTableProps ): React.ReactElement => { - const { datasetId } = props; + const { datasetId, investigationId } = props; const [t] = useTranslation(); @@ -52,7 +50,7 @@ const DLSDatafilesTable = ( const dateFilter = useDateFilter(filters); const handleSort = useSort(); - const { data: allIds } = useIds( + const { data: allIds, isLoading: allIdsLoading } = useIds( 'datafile', [ { @@ -62,14 +60,11 @@ const DLSDatafilesTable = ( ], selectAllSetting ); - const { data: cartItems } = useCart(); - const { mutate: addToCart, isLoading: addToCartLoading } = useAddToCart( - 'datafile' - ); - const { - mutate: removeFromCart, - isLoading: removeFromCartLoading, - } = useRemoveFromCart('datafile'); + const { data: cartItems, isLoading: cartLoading } = useCart(); + const { mutate: addToCart, isLoading: addToCartLoading } = + useAddToCart('datafile'); + const { mutate: removeFromCart, isLoading: removeFromCartLoading } = + useRemoveFromCart('datafile'); const { data: totalDataCount } = useDatafileCount([ { @@ -101,36 +96,43 @@ const DLSDatafilesTable = ( [fetchNextPage] ); - const aggregatedData: Datafile[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + /* istanbul ignore next */ + const aggregatedData: Datafile[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } + + return []; + }, [data]); const columns: ColumnType[] = React.useMemo( () => [ { - icon: SubjectIcon, + icon: Subject, label: t('datafiles.name'), dataKey: 'name', filterComponent: textFilter, }, { - icon: ExploreIcon, + icon: Explore, label: t('datafiles.location'), dataKey: 'location', filterComponent: textFilter, }, { - icon: SaveIcon, + icon: Save, label: t('datafiles.size'), dataKey: 'fileSize', cellContentRenderer: (cellProps) => { return formatBytes(cellProps.cellData); }, - filterComponent: textFilter, }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('datafiles.create_time'), dataKey: 'createTime', filterComponent: dateFilter, @@ -154,9 +156,25 @@ const DLSDatafilesTable = ( [cartItems, selectAllSetting, allIds] ); + const isParentSelected = React.useMemo(() => { + return cartItems?.some( + (cartItem) => + (cartItem.entityType === 'dataset' && + cartItem.entityId.toString() === datasetId) || + (cartItem.entityType === 'investigation' && + cartItem.entityId.toString() === investigationId) + ); + }, [cartItems, datasetId, investigationId]); + return (
{ const originalModule = jest.requireActual('datagateway-common'); @@ -40,15 +56,15 @@ jest.mock('datagateway-common', () => { }); describe('DLS Dataset table component', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let rowData: Dataset[]; let history: History; + let user: UserEvent; - const createWrapper = (): ReactWrapper => { + const renderComponent = (): RenderResult => { const store = mockStore(state); - return mount( + return render( @@ -60,10 +76,11 @@ describe('DLS Dataset table component', () => { }; beforeEach(() => { - mount = createMount(); rowData = [ { id: 1, + fileSize: 1, + fileCount: 1, name: 'Test 1', size: 1, modTime: '2019-07-23', @@ -71,8 +88,8 @@ describe('DLS Dataset table component', () => { }, ]; history = createMemoryHistory(); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgdataview: dgDataViewInitialState, @@ -82,9 +99,11 @@ describe('DLS Dataset table component', () => { (useCart as jest.Mock).mockReturnValue({ data: [], + isLoading: false, }); (useDatasetCount as jest.Mock).mockReturnValue({ data: 0, + isSuccess: true, }); (useDatasetsInfinite as jest.Mock).mockReturnValue({ data: { pages: [rowData] }, @@ -92,6 +111,7 @@ describe('DLS Dataset table component', () => { }); (useIds as jest.Mock).mockReturnValue({ data: [1], + isLoading: false, }); (useAddToCart as jest.Mock).mockReturnValue({ mutate: jest.fn(), @@ -101,127 +121,112 @@ describe('DLS Dataset table component', () => { mutate: jest.fn(), isLoading: false, }); - (useDatasetsDatafileCount as jest.Mock).mockReturnValue([{ data: 1 }]); }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); - - it('calls the correct data fetching hooks on load', () => { - const investigationId = '1'; - createWrapper(); - expect(useDatasetCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: investigationId }, - }), - }, - ]); - expect(useDatasetsInfinite).toHaveBeenCalledWith( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: investigationId }, - }), - }, - ], - expect.any(Boolean) - ); - expect(useDatasetsDatafileCount).toHaveBeenCalledWith({ - pages: [rowData], - }); - expect(useIds).toHaveBeenCalledWith( - 'dataset', - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: parseInt(investigationId) }, - }), - }, - ], - true - ); - expect(useCart).toHaveBeenCalled(); - expect(useAddToCart).toHaveBeenCalledWith('dataset'); - expect(useRemoveFromCart).toHaveBeenCalledWith('dataset'); - }); + it('renders correctly', async () => { + renderComponent(); - it('sends fetchDatasets action when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useDatasetsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); + const rows = await findAllRows(); + expect(rows).toHaveLength(1); - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); + expect(await findColumnHeaderByName('datasets.name')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.datafile_count') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.create_time') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.modified_time') + ).toBeInTheDocument(); - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, - }); + const row = rows[0]; + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.name'), + }) + ).getByText('Test 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.datafile_count'), + }) + ).getByText('1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.create_time'), + }) + ).getByText('2019-07-23') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.modified_time'), + }) + ).getByText('2019-07-23') + ).toBeInTheDocument(); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by datasets.name', + hidden: true, + }); - const filterInput = wrapper - .find('[aria-label="Filter by datasets.name"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + await user.type(filterInput, 'test'); - expect(history.length).toBe(2); + expect(history.length).toBe(5); expect(history.location.search).toBe( `?filters=${encodeURIComponent( '{"name":{"value":"test","type":"include"}}' )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); - expect(history.length).toBe(3); + expect(history.length).toBe(6); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const filterInput = wrapper.find( - 'input[id="datasets.modified_time filter to"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'datasets.modified_time filter to', + }); + + await user.type(filterInput, '2019-08-06'); expect(history.length).toBe(2); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"modTime":{"endDate":"2019-08-06"}}')}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.length).toBe(3); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"createTime":"desc"}')}` @@ -236,13 +241,12 @@ describe('DLS Dataset table component', () => { ); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'datasets.name' }) + ); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -250,20 +254,22 @@ describe('DLS Dataset table component', () => { ); }); - it('calls addToCart mutate function on unchecked checkbox click', () => { + it('calls addToCart mutate function on unchecked checkbox click', async () => { const addToCart = jest.fn(); (useAddToCart as jest.Mock).mockReturnValue({ mutate: addToCart, loading: false, }); - const wrapper = createWrapper(); + renderComponent(); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + await user.click( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ); expect(addToCart).toHaveBeenCalledWith([1]); }); - it('calls removeFromCart mutate function on checked checkbox click', () => { + it('calls removeFromCart mutate function on checked checkbox click', async () => { (useCart as jest.Mock).mockReturnValue({ data: [ { @@ -274,6 +280,7 @@ describe('DLS Dataset table component', () => { parentEntities: [], }, ], + isLoading: false, }); const removeFromCart = jest.fn(); @@ -282,14 +289,16 @@ describe('DLS Dataset table component', () => { loading: false, }); - const wrapper = createWrapper(); + renderComponent(); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + await user.click( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ); expect(removeFromCart).toHaveBeenCalledWith([1]); }); - it('selected rows only considers relevant cart items', () => { + it('selected rows only considers relevant cart items', async () => { (useCart as jest.Mock).mockReturnValueOnce({ data: [ { @@ -307,33 +316,46 @@ describe('DLS Dataset table component', () => { parentEntities: [], }, ], + isLoading: false, }); - const wrapper = createWrapper(); + renderComponent(); - const selectAllCheckbox = wrapper - .find('[aria-label="select all rows"]') - .first(); + const selectAllCheckbox = await screen.findByRole('checkbox', { + name: 'select all rows', + }); - expect(selectAllCheckbox.prop('checked')).toEqual(false); - expect(selectAllCheckbox.prop('data-indeterminate')).toEqual(false); + expect(selectAllCheckbox).not.toBeChecked(); + expect(selectAllCheckbox).toHaveAttribute('data-indeterminate', 'false'); }); - it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', () => { + it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', async () => { state.dgdataview.selectAllSetting = false; + renderComponent(); + await waitFor(() => { + expect( + screen.queryByRole('checkbox', { name: 'select all rows' }) + ).toBeNull(); + }); + }); - const wrapper = createWrapper(); - - expect(useIds).toHaveBeenCalledWith('dataset', expect.anything(), false); - expect(useIds).not.toHaveBeenCalledWith('dataset', expect.anything(), true); - expect(wrapper.exists('[aria-label="select all rows"]')).toBe(false); + it('renders Dataset title as a link', async () => { + renderComponent(); + expect(await screen.findByRole('link', { name: 'Test 1' })).toHaveAttribute( + 'href', + '/browse/proposal/Proposal 1/investigation/1/dataset/1/datafile' + ); }); - it('renders Dataset title as a link', () => { - const wrapper = createWrapper(); + it('displays details panel when expanded', async () => { + renderComponent(); - expect( - wrapper.find('[aria-colindex=3]').find('p').children() - ).toMatchSnapshot(); + const row = await findRowAt(0); + + await user.click( + await within(row).findByRole('button', { name: 'Show details' }) + ); + + expect(await screen.findByTestId('dls-dataset-details-panel')).toBeTruthy(); }); }); diff --git a/packages/datagateway-dataview/src/views/table/dls/dlsDatasetsTable.component.tsx b/packages/datagateway-dataview/src/views/table/dls/dlsDatasetsTable.component.tsx index 1a917f13b..445d059ee 100644 --- a/packages/datagateway-dataview/src/views/table/dls/dlsDatasetsTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/dls/dlsDatasetsTable.component.tsx @@ -1,12 +1,14 @@ import React from 'react'; -import SubjectIcon from '@material-ui/icons/Subject'; -import ConfirmationNumberIcon from '@material-ui/icons/ConfirmationNumber'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; +import { + Subject, + ConfirmationNumber, + CalendarToday, + Save, +} from '@mui/icons-material'; import { Table, tableLink, Dataset, - formatCountOrSize, useDatasetCount, useDatasetsInfinite, parseSearchToQuery, @@ -18,12 +20,12 @@ import { useCart, useAddToCart, useRemoveFromCart, - useDatasetsDatafileCount, DLSDatasetDetailsPanel, + formatBytes, } from 'datagateway-common'; import { IndexRange, TableCellProps } from 'react-virtualized'; import { useTranslation } from 'react-i18next'; -import { useLocation } from 'react-router'; +import { useLocation } from 'react-router-dom'; import { useSelector } from 'react-redux'; import { StateType } from '../../../state/app.types'; @@ -52,7 +54,7 @@ const DLSDatasetsTable = (props: DLSDatasetsTableProps): React.ReactElement => { const dateFilter = useDateFilter(filters); const handleSort = useSort(); - const { data: allIds } = useIds( + const { data: allIds, isLoading: allIdsLoading } = useIds( 'dataset', [ { @@ -64,14 +66,11 @@ const DLSDatasetsTable = (props: DLSDatasetsTableProps): React.ReactElement => { ], selectAllSetting ); - const { data: cartItems } = useCart(); - const { mutate: addToCart, isLoading: addToCartLoading } = useAddToCart( - 'dataset' - ); - const { - mutate: removeFromCart, - isLoading: removeFromCartLoading, - } = useRemoveFromCart('dataset'); + const { data: cartItems, isLoading: cartLoading } = useCart(); + const { mutate: addToCart, isLoading: addToCartLoading } = + useAddToCart('dataset'); + const { mutate: removeFromCart, isLoading: removeFromCartLoading } = + useRemoveFromCart('dataset'); const { data: totalDataCount } = useDatasetCount([ { @@ -107,59 +106,62 @@ const DLSDatasetsTable = (props: DLSDatasetsTableProps): React.ReactElement => { [fetchNextPage] ); - const datafileCountQueries = useDatasetsDatafileCount(data); + /* istanbul ignore next */ + const aggregatedData: Dataset[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } - const aggregatedData: Dataset[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + return []; + }, [data]); const columns: ColumnType[] = React.useMemo( () => [ { - icon: SubjectIcon, + icon: Subject, label: t('datasets.name'), dataKey: 'name', cellContentRenderer: (cellProps: TableCellProps) => tableLink( `/browse/proposal/${proposalName}/investigation/${investigationId}/dataset/${cellProps.rowData.id}/datafile`, cellProps.rowData.name, - view + view, + 'dls-datasets-table-title' ), filterComponent: textFilter, }, { - icon: ConfirmationNumberIcon, + icon: ConfirmationNumber, label: t('datasets.datafile_count'), - dataKey: 'datafileCount', + dataKey: 'fileCount', + }, + { + icon: Save, + label: t('datasets.size'), + dataKey: 'fileSize', cellContentRenderer: (cellProps: TableCellProps): number | string => - formatCountOrSize(datafileCountQueries[cellProps.rowIndex]), - disableSort: true, + formatBytes(cellProps.rowData.fileSize), }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('datasets.create_time'), dataKey: 'createTime', filterComponent: dateFilter, defaultSort: 'desc', }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('datasets.modified_time'), dataKey: 'modTime', filterComponent: dateFilter, }, ], - [ - t, - textFilter, - dateFilter, - proposalName, - investigationId, - view, - datafileCountQueries, - ] + [t, textFilter, dateFilter, proposalName, investigationId, view] ); const selectedRows = React.useMemo( @@ -176,9 +178,23 @@ const DLSDatasetsTable = (props: DLSDatasetsTableProps): React.ReactElement => { [cartItems, selectAllSetting, allIds] ); + const isParentSelected = React.useMemo(() => { + return cartItems?.some( + (cartItem) => + cartItem.entityType === 'investigation' && + cartItem.entityId.toString() === investigationId + ); + }, [cartItems, investigationId]); + return (
{ const originalModule = jest.requireActual('datagateway-common'); @@ -28,22 +41,20 @@ jest.mock('datagateway-common', () => { ...originalModule, useInvestigationCount: jest.fn(), useInvestigationsInfinite: jest.fn(), - useInvestigationsDatasetCount: jest.fn(), readSciGatewayToken: jest.fn(), }; }); describe('DLS MyData table component', () => { - let mount; const mockStore = configureStore([thunk]); let state: StateType; let rowData: Investigation[]; let history: MemoryHistory; - let events: CustomEvent[] = []; + let user: UserEvent; - const createWrapper = (): ReactWrapper => { + const renderComponent = (): RenderResult => { const store = mockStore(state); - return mount( + return render( @@ -55,14 +66,8 @@ describe('DLS MyData table component', () => { }; beforeEach(() => { - mount = createMount(); - events = []; history = createMemoryHistory(); - - document.dispatchEvent = (e: Event) => { - events.push(e as CustomEvent); - return true; - }; + user = userEvent.setup(); state = JSON.parse( JSON.stringify({ @@ -79,12 +84,15 @@ describe('DLS MyData table component', () => { visitId: '1', doi: 'doi 1', size: 1, + fileSize: 1, + fileCount: 1, investigationInstruments: [ { id: 1, instrument: { id: 3, name: 'LARMOR', + fullName: 'LARMORLARMOR', }, }, ], @@ -100,7 +108,6 @@ describe('DLS MyData table component', () => { data: { pages: [rowData] }, fetchNextPage: jest.fn(), }); - (useInvestigationsDatasetCount as jest.Mock).mockReturnValue([{ data: 1 }]); (readSciGatewayToken as jest.Mock).mockReturnValue({ username: 'testUser', }); @@ -108,52 +115,82 @@ describe('DLS MyData table component', () => { }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); + it('renders correctly', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - createWrapper(); - expect(useInvestigationCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigationUsers.user.name': { eq: 'testUser' }, - }), - }, - ]); - expect(useInvestigationsInfinite).toHaveBeenCalledWith( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigationUsers.user.name': { eq: 'testUser' }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify([ - { - investigationInstruments: 'instrument', - }, - ]), - }, - ], - undefined, - expect.any(Boolean) - ); - expect(useInvestigationsDatasetCount).toHaveBeenCalledWith({ - pages: [rowData], - }); + const rows = await findAllRows(); + expect(rows).toHaveLength(1); + + expect( + await findColumnHeaderByName('investigations.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.visit_id') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.instrument') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.end_date') + ).toBeInTheDocument(); + + const row = rows[0]; + + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.title'), + }) + ).getByText('Test 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.visit_id'), + }) + ).getByText('1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.size'), + }) + ).getByText('1 B') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.instrument'), + }) + ).getByText('LARMORLARMOR') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.start_date'), + }) + ).getByText('2019-06-10') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.end_date'), + }) + ).getByText('2019-06-11') + ).toBeInTheDocument(); }); it('sorts by startDate desc and filters startDate to be before the current date on load', () => { - createWrapper(); + renderComponent(); expect(history.length).toBe(2); expect(history.entries[0].search).toBe( @@ -166,32 +203,15 @@ describe('DLS MyData table component', () => { ); }); - it('calls useInvestigationsInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useInvestigationsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); - - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); + it('updates filter query params on text filter', async () => { + renderComponent(); - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by investigations.visit_id', + hidden: true, }); - }); - - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); - const filterInput = wrapper - .find('[aria-label="Filter by investigations.visit_id"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + await user.type(filterInput, 'test'); expect(history.location.search).toBe( `?filters=${encodeURIComponent( @@ -199,57 +219,66 @@ describe('DLS MyData table component', () => { )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const filterInput = wrapper.find( - 'input[id="investigations.end_date filter to"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'investigations.end_date filter to', + }); + + await user.type(filterInput, '2019-08-06'); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"endDate":{"endDate":"2019-08-06"}}')}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'investigations.title' }) + ); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"title":"asc"}')}` ); }); - it('renders title and visit ID as a links', () => { - const wrapper = createWrapper(); + it('renders title and visit ID as a links', async () => { + renderComponent(); - expect( - wrapper.find('[aria-colindex=2]').find('p').children() - ).toMatchSnapshot(); + const row = await findRowAt(0); expect( - wrapper.find('[aria-colindex=3]').find('p').children() - ).toMatchSnapshot(); + await within(row).findByRole('link', { name: 'Test 1' }) + ).toHaveAttribute( + 'href', + '/browse/proposal/Test 1/investigation/1/dataset' + ); + expect(await within(row).findByRole('link', { name: '1' })).toHaveAttribute( + 'href', + '/browse/proposal/Test 1/investigation/1/dataset' + ); }); - it('gracefully handles empty InvestigationInstrument and missing Instrument from InvestigationInstrument object', () => { + it('gracefully handles empty InvestigationInstrument', async () => { rowData[0] = { ...rowData[0], investigationInstruments: [], @@ -259,10 +288,12 @@ describe('DLS MyData table component', () => { fetchNextPage: jest.fn(), }); - let wrapper = createWrapper(); + renderComponent(); - expect(() => wrapper).not.toThrowError(); + expect(await findAllRows()).toHaveLength(1); + }); + it('gracefully handles missing Instrument from InvestigationInstrument object', async () => { rowData[0] = { ...rowData[0], investigationInstruments: [ @@ -276,8 +307,30 @@ describe('DLS MyData table component', () => { fetchNextPage: jest.fn(), }); - wrapper = createWrapper(); + renderComponent(); + + const investigationInstrumentColIndex = await findColumnIndexByName( + 'investigations.instrument' + ); + + const row = await findRowAt(0); + + expect( + await findCellInRow(row, { columnIndex: investigationInstrumentColIndex }) + ).toHaveTextContent(''); + }); + + it('displays details panel when expanded', async () => { + renderComponent(); + + const row = await findRowAt(0); - expect(wrapper.find('[aria-colindex=5]').find('p').text()).toEqual(''); + await user.click( + await within(row).findByRole('button', { name: 'Show details' }) + ); + + expect( + await screen.findByTestId('dls-visit-details-panel') + ).toBeInTheDocument(); }); }); diff --git a/packages/datagateway-dataview/src/views/table/dls/dlsMyDataTable.component.tsx b/packages/datagateway-dataview/src/views/table/dls/dlsMyDataTable.component.tsx index 9f8279884..7ef5d4be5 100644 --- a/packages/datagateway-dataview/src/views/table/dls/dlsMyDataTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/dls/dlsMyDataTable.component.tsx @@ -1,6 +1,5 @@ import { ColumnType, - formatCountOrSize, Investigation, parseSearchToQuery, readSciGatewayToken, @@ -8,23 +7,25 @@ import { tableLink, useDateFilter, useInvestigationCount, - useInvestigationsDatasetCount, useInvestigationsInfinite, usePushFilter, useSort, useTextFilter, DLSVisitDetailsPanel, + formatBytes, } from 'datagateway-common'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { IndexRange, TableCellProps } from 'react-virtualized'; -import SubjectIcon from '@material-ui/icons/Subject'; -import FingerprintIcon from '@material-ui/icons/Fingerprint'; -import ConfirmationNumberIcon from '@material-ui/icons/ConfirmationNumber'; -import AssessmentIcon from '@material-ui/icons/Assessment'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; -import { useLocation } from 'react-router'; +import { + Subject, + Fingerprint, + Assessment, + CalendarToday, + Save, +} from '@mui/icons-material'; +import { useLocation } from 'react-router-dom'; const DLSMyDataTable = (): React.ReactElement => { const [t] = useTranslation(); @@ -74,12 +75,18 @@ const DLSMyDataTable = (): React.ReactElement => { isMounted ); - const datasetCountQueries = useInvestigationsDatasetCount(data); + /* istanbul ignore next */ + const aggregatedData: Investigation[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } - const aggregatedData: Investigation[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + return []; + }, [data]); const textFilter = useTextFilter(filters); const dateFilter = useDateFilter(filters); @@ -94,7 +101,7 @@ const DLSMyDataTable = (): React.ReactElement => { const columns: ColumnType[] = React.useMemo( () => [ { - icon: SubjectIcon, + icon: Subject, label: t('investigations.title'), dataKey: 'title', cellContentRenderer: (cellProps: TableCellProps) => { @@ -109,7 +116,7 @@ const DLSMyDataTable = (): React.ReactElement => { filterComponent: textFilter, }, { - icon: FingerprintIcon, + icon: Fingerprint, label: t('investigations.visit_id'), dataKey: 'visitId', cellContentRenderer: (cellProps: TableCellProps) => { @@ -117,21 +124,21 @@ const DLSMyDataTable = (): React.ReactElement => { return tableLink( `/browse/proposal/${investigationData.name}/investigation/${investigationData.id}/dataset`, investigationData.visitId, - view + view, + 'dls-mydata-table-visitId' ); }, filterComponent: textFilter, }, { - icon: ConfirmationNumberIcon, - label: t('investigations.dataset_count'), - dataKey: 'datasetCount', + icon: Save, + label: t('investigations.size'), + dataKey: 'fileSize', cellContentRenderer: (cellProps: TableCellProps): number | string => - formatCountOrSize(datasetCountQueries[cellProps.rowIndex]), - disableSort: true, + formatBytes(cellProps.rowData.fileSize), }, { - icon: AssessmentIcon, + icon: Assessment, label: t('investigations.instrument'), dataKey: 'investigationInstruments.instrument.fullName', cellContentRenderer: (cellProps: TableCellProps) => { @@ -146,21 +153,21 @@ const DLSMyDataTable = (): React.ReactElement => { filterComponent: textFilter, }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('investigations.start_date'), dataKey: 'startDate', filterComponent: dateFilter, defaultSort: 'desc', }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('investigations.end_date'), dataKey: 'endDate', filterComponent: dateFilter, }, ], - [t, dateFilter, textFilter, view, datasetCountQueries] + [t, dateFilter, textFilter, view] ); React.useEffect(() => { diff --git a/packages/datagateway-dataview/src/views/table/dls/dlsProposalsTable.component.test.tsx b/packages/datagateway-dataview/src/views/table/dls/dlsProposalsTable.component.test.tsx index 7ccdf2058..11e83f017 100644 --- a/packages/datagateway-dataview/src/views/table/dls/dlsProposalsTable.component.test.tsx +++ b/packages/datagateway-dataview/src/views/table/dls/dlsProposalsTable.component.test.tsx @@ -1,21 +1,34 @@ -import React from 'react'; -import { createMount } from '@material-ui/core/test-utils'; +import * as React from 'react'; import DLSProposalsTable from './dlsProposalsTable.component'; -import { StateType } from '../../../state/app.types'; +import type { StateType } from '../../../state/app.types'; import { initialState as dgDataViewInitialState } from '../../../state/reducers/dgdataview.reducer'; import { - Investigation, + dGCommonInitialState, + type Investigation, useInvestigationCount, useInvestigationsInfinite, - dGCommonInitialState, } from 'datagateway-common'; -import { ReactWrapper } from 'enzyme'; import configureStore from 'redux-mock-store'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; import { QueryClient, QueryClientProvider } from 'react-query'; -import { Router } from 'react-router'; +import { Router } from 'react-router-dom'; import { createMemoryHistory, History } from 'history'; +import { + render, + type RenderResult, + screen, + within, +} from '@testing-library/react'; +import type { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; +import { + findAllRows, + findCellInRow, + findColumnHeaderByName, + findColumnIndexByName, + findRowAt, +} from '../../../setupTests'; jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -29,15 +42,15 @@ jest.mock('datagateway-common', () => { }); describe('DLS Proposals table component', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let rowData: Investigation[]; let history: History; + let user: UserEvent; - const createWrapper = (): ReactWrapper => { + const renderComponent = (): RenderResult => { const store = mockStore(state); - return mount( + return render( @@ -49,7 +62,6 @@ describe('DLS Proposals table component', () => { }; beforeEach(() => { - mount = createMount(); rowData = [ { id: 1, @@ -73,8 +85,8 @@ describe('DLS Proposals table component', () => { }, ]; history = createMemoryHistory(); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgdataview: dgDataViewInitialState, @@ -93,78 +105,68 @@ describe('DLS Proposals table component', () => { }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); + it('renders correctly', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - createWrapper(); - expect(useInvestigationCount).toHaveBeenCalledWith([ - { - filterType: 'distinct', - filterValue: JSON.stringify(['name', 'title']), - }, - ]); - expect(useInvestigationsInfinite).toHaveBeenCalledWith( - [ - { - filterType: 'distinct', - filterValue: JSON.stringify(['name', 'title']), - }, - ], - true, - expect.any(Boolean) - ); - }); + const rows = await findAllRows(); + expect(rows).toHaveLength(1); - it('calls useInvestigationsInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useInvestigationsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); + expect( + await findColumnHeaderByName('investigations.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.name') + ).toBeInTheDocument(); - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); + const row = rows[0]; - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, - }); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.title'), + }) + ).getByText('Test 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.name'), + }) + ).getByText('Test 1') + ).toBeInTheDocument(); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by investigations.title', + hidden: true, + }); - const filterInput = wrapper.find('input').first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + await user.type(filterInput, 'test'); - expect(history.length).toBe(2); + // user.type inputs the given string character by character to simulate user typing + // each keystroke of user.type creates a new entry in the history stack + // so the initial entry + 4 characters in "test" = 5 entries + expect(history.length).toBe(5); expect(history.location.search).toBe( `?filters=${encodeURIComponent( '{"title":{"value":"test","type":"include"}}' )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); - expect(history.length).toBe(3); + expect(history.length).toBe(6); expect(history.location.search).toBe('?'); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"title":"asc"}')}` @@ -184,15 +186,27 @@ describe('DLS Proposals table component', () => { ); }); - it('renders title and name as links', () => { - const wrapper = createWrapper(); + it('renders title and name as links', async () => { + renderComponent(); + + const row = await findRowAt(0); + + const titleColIndex = await findColumnIndexByName('investigations.title'); + const investigationNameColIndex = await findColumnIndexByName( + 'investigations.name' + ); + + const titleCell = await findCellInRow(row, { columnIndex: titleColIndex }); + const nameCell = await findCellInRow(row, { + columnIndex: investigationNameColIndex, + }); expect( - wrapper.find('[aria-colindex=2]').find('p').children() - ).toMatchSnapshot(); + within(titleCell).getByRole('link', { name: 'Test 1' }) + ).toHaveAttribute('href', '/browse/proposal/Test 1/investigation'); expect( - wrapper.find('[aria-colindex=3]').find('p').children() - ).toMatchSnapshot(); + within(nameCell).getByRole('link', { name: 'Test 1' }) + ).toHaveAttribute('href', '/browse/proposal/Test 1/investigation'); }); }); diff --git a/packages/datagateway-dataview/src/views/table/dls/dlsProposalsTable.component.tsx b/packages/datagateway-dataview/src/views/table/dls/dlsProposalsTable.component.tsx index 55d6d008a..b7c9d4223 100644 --- a/packages/datagateway-dataview/src/views/table/dls/dlsProposalsTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/dls/dlsProposalsTable.component.tsx @@ -13,7 +13,7 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { IndexRange, TableCellProps } from 'react-virtualized'; import { useLocation } from 'react-router-dom'; -import SubjectIcon from '@material-ui/icons/Subject'; +import SubjectIcon from '@mui/icons-material/Subject'; const DLSProposalsTable = (): React.ReactElement => { const location = useLocation(); @@ -52,10 +52,18 @@ const DLSProposalsTable = (): React.ReactElement => { isMounted ); - const aggregatedData: Investigation[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + /* istanbul ignore next */ + const aggregatedData: Investigation[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } + + return []; + }, [data]); const textFilter = useTextFilter(filters); const handleSort = useSort(); @@ -94,7 +102,8 @@ const DLSProposalsTable = (): React.ReactElement => { return tableLink( `/browse/proposal/${cellProps.rowData.name}/investigation`, cellProps.rowData.name, - view + view, + 'dls-proposals-table-name' ); }, filterComponent: textFilter, diff --git a/packages/datagateway-dataview/src/views/table/dls/dlsVisitsTable.component.test.tsx b/packages/datagateway-dataview/src/views/table/dls/dlsVisitsTable.component.test.tsx index a2dbdaf87..c9d3c162c 100644 --- a/packages/datagateway-dataview/src/views/table/dls/dlsVisitsTable.component.test.tsx +++ b/packages/datagateway-dataview/src/views/table/dls/dlsVisitsTable.component.test.tsx @@ -1,23 +1,36 @@ -import React from 'react'; -import { createMount } from '@material-ui/core/test-utils'; +import * as React from 'react'; import DLSVisitsTable from './dlsVisitsTable.component'; import { StateType } from '../../../state/app.types'; import { initialState as dgDataViewInitialState } from '../../../state/reducers/dgdataview.reducer'; import { + dGCommonInitialState, Investigation, useInvestigationCount, useInvestigationsInfinite, - useInvestigationsDatasetCount, - dGCommonInitialState, - DLSVisitDetailsPanel, } from 'datagateway-common'; -import { ReactWrapper } from 'enzyme'; import configureStore from 'redux-mock-store'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; import { QueryClient, QueryClientProvider } from 'react-query'; -import { Router } from 'react-router'; +import { Router } from 'react-router-dom'; import { createMemoryHistory, History } from 'history'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, + findAllRows, + findCellInRow, + findColumnHeaderByName, + findColumnIndexByName, + findRowAt, +} from '../../../setupTests'; +import { + render, + type RenderResult, + screen, + within, +} from '@testing-library/react'; +import { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -27,20 +40,19 @@ jest.mock('datagateway-common', () => { ...originalModule, useInvestigationCount: jest.fn(), useInvestigationsInfinite: jest.fn(), - useInvestigationsDatasetCount: jest.fn(), }; }); describe('DLS Visits table component', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let rowData: Investigation[]; let history: History; + let user: UserEvent; - const createWrapper = (): ReactWrapper => { + const renderComponent = (): RenderResult => { const store = mockStore(state); - return mount( + return render( @@ -52,7 +64,6 @@ describe('DLS Visits table component', () => { }; beforeEach(() => { - mount = createMount(); rowData = [ { id: 1, @@ -62,6 +73,8 @@ describe('DLS Visits table component', () => { visitId: '1', doi: 'doi 1', size: 1, + fileSize: 1, + fileCount: 1, investigationInstruments: [ { id: 1, @@ -76,8 +89,8 @@ describe('DLS Visits table component', () => { }, ]; history = createMemoryHistory(); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgdataview: dgDataViewInitialState, @@ -93,113 +106,128 @@ describe('DLS Visits table component', () => { data: rowData, isLoading: false, }); - (useInvestigationsDatasetCount as jest.Mock).mockReturnValue([1]); }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); + it('renders correctly', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - const proposalName = 'Test 1'; - createWrapper(); - expect(useInvestigationCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ name: { eq: proposalName } }), - }, - ]); - expect(useInvestigationsInfinite).toHaveBeenCalledWith( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ name: { eq: proposalName } }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - investigationInstruments: 'instrument', - }), - }, - ], - undefined, - expect.any(Boolean) - ); - expect(useInvestigationsDatasetCount).toHaveBeenCalledWith(rowData); - }); + const rows = await findAllRows(); + expect(rows).toHaveLength(1); - it('calls useInvestigationsInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useInvestigationsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); + expect( + await findColumnHeaderByName('investigations.visit_id') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.instrument') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.end_date') + ).toBeInTheDocument(); - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); + const row = rows[0]; - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, - }); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.visit_id'), + }) + ).getByText('1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.size'), + }) + ).getByText('1 B') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.instrument'), + }) + ).getByText('LARMOR') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.start_date'), + }) + ).getByText('2019-06-10') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.end_date'), + }) + ).getByText('2019-06-11') + ).toBeInTheDocument(); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); - const filterInput = wrapper - .find('[aria-label="Filter by investigations.visit_id"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by investigations.visit_id', + hidden: true, + }); - expect(history.length).toBe(2); + await user.type(filterInput, 'test'); + + // user.type inputs the given string character by character to simulate user typing + // each keystroke of user.type creates a new entry in the history stack + // so the initial entry + 4 characters in "test" = 5 entries + expect(history.length).toBe(5); expect(history.location.search).toBe( `?filters=${encodeURIComponent( '{"visitId":{"value":"test","type":"include"}}' )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); - expect(history.length).toBe(3); + expect(history.length).toBe(6); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const filterInput = wrapper.find( - 'input[id="investigations.end_date filter to"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'investigations.end_date filter to', + }); + + await user.type(filterInput, '2019-08-06'); expect(history.length).toBe(2); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"endDate":{"endDate":"2019-08-06"}}')}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.length).toBe(3); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"startDate":"desc"}')}` @@ -219,13 +247,12 @@ describe('DLS Visits table component', () => { ); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'investigations.visit_id' }) + ); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -233,62 +260,87 @@ describe('DLS Visits table component', () => { ); }); - it('renders details panel correctly and it sends off an FetchInvestigationDetails action', () => { - const wrapper = createWrapper(); - expect(wrapper.find(DLSVisitDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); + it('renders details panel correctly and it sends off an FetchInvestigationDetails action', async () => { + renderComponent(); - expect(wrapper.find(DLSVisitDetailsPanel).exists()).toBeTruthy(); - }); + const row = await findRowAt(0); - it('renders visit ID as links', () => { - const wrapper = createWrapper(); + await user.click(within(row).getByRole('button', { name: 'Show details' })); - expect( - wrapper.find('[aria-colindex=2]').find('p').children() - ).toMatchSnapshot(); + expect(await screen.findByTestId('dls-visit-details-panel')).toBeTruthy(); }); - it('renders fine with incomplete data', () => { - (useInvestigationCount as jest.Mock).mockReturnValue({}); - (useInvestigationsInfinite as jest.Mock).mockReturnValue({}); - (useInvestigationsDatasetCount as jest.Mock).mockReturnValue([]); + it('renders visit ID as links', async () => { + renderComponent(); - expect(() => createWrapper()).not.toThrowError(); + const visitIdColIndex = await findColumnIndexByName( + 'investigations.visit_id' + ); - (useInvestigationCount as jest.Mock).mockReturnValue({ - data: 1, - isLoading: false, + const row = await findRowAt(0); + const visitIdCell = await findCellInRow(row, { + columnIndex: visitIdColIndex, }); - (useInvestigationsInfinite as jest.Mock).mockReturnValue({ + + expect( + within(visitIdCell).getByRole('link', { name: '1' }) + ).toHaveAttribute( + 'href', + '/browse/proposal/Test 1/investigation/1/dataset' + ); + }); + + it('renders fine with incomplete data', async () => { + (useInvestigationCount as jest.Mock).mockReturnValueOnce({}); + (useInvestigationsInfinite as jest.Mock).mockReturnValueOnce({}); + + (useInvestigationsInfinite as jest.Mock).mockReturnValueOnce({ data: [ { ...rowData[0], - investigationInstruments: [], + investigationInstruments: [ + { + id: 1, + }, + ], }, ], isLoading: false, }); - (useInvestigationsDatasetCount as jest.Mock).mockReturnValue([1]); - expect(() => createWrapper()).not.toThrowError(); + renderComponent(); + expect(await findAllRows()).toHaveLength(1); + }); + + it('renders fine if no investigation instrument is returned', async () => { + (useInvestigationCount as jest.Mock).mockReturnValue({ + data: 1, + isLoading: false, + }); (useInvestigationsInfinite as jest.Mock).mockReturnValue({ data: [ { ...rowData[0], - investigationInstruments: [ - { - id: 1, - }, - ], + investigationInstruments: [], }, ], isLoading: false, }); - const wrapper = createWrapper(); + renderComponent(); + + expect(await findAllRows()).toHaveLength(1); + + const instrumentNameColIndex = await findColumnIndexByName( + 'investigations.instrument' + ); + + const row = await findRowAt(0); + const instrumentNameCell = await findCellInRow(row, { + columnIndex: instrumentNameColIndex, + }); - expect(wrapper.find('[aria-colindex=4]').find('p').text()).toEqual(''); + expect(instrumentNameCell).toHaveTextContent(''); }); }); diff --git a/packages/datagateway-dataview/src/views/table/dls/dlsVisitsTable.component.tsx b/packages/datagateway-dataview/src/views/table/dls/dlsVisitsTable.component.tsx index a3b6832b7..42b1cb4bc 100644 --- a/packages/datagateway-dataview/src/views/table/dls/dlsVisitsTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/dls/dlsVisitsTable.component.tsx @@ -3,24 +3,25 @@ import { Table, tableLink, ColumnType, - formatCountOrSize, parseSearchToQuery, useDateFilter, useInvestigationCount, useInvestigationsInfinite, - useInvestigationsDatasetCount, useSort, useTextFilter, DLSVisitDetailsPanel, + formatBytes, } from 'datagateway-common'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { IndexRange, TableCellProps } from 'react-virtualized'; -import FingerprintIcon from '@material-ui/icons/Fingerprint'; -import ConfirmationNumberIcon from '@material-ui/icons/ConfirmationNumber'; -import AssessmentIcon from '@material-ui/icons/Assessment'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; -import { useLocation } from 'react-router'; +import { + Fingerprint, + Assessment, + CalendarToday, + Save, +} from '@mui/icons-material'; +import { useLocation } from 'react-router-dom'; interface DLSVisitsTableProps { proposalName: string; @@ -69,12 +70,18 @@ const DLSVisitsTable = (props: DLSVisitsTableProps): React.ReactElement => { isMounted ); - const datasetCountQueries = useInvestigationsDatasetCount(data); + /* istanbul ignore next */ + const aggregatedData: Investigation[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } - const aggregatedData: Investigation[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + return []; + }, [data]); const textFilter = useTextFilter(filters); const dateFilter = useDateFilter(filters); @@ -88,7 +95,7 @@ const DLSVisitsTable = (props: DLSVisitsTableProps): React.ReactElement => { const columns: ColumnType[] = React.useMemo( () => [ { - icon: FingerprintIcon, + icon: Fingerprint, label: t('investigations.visit_id'), dataKey: 'visitId', cellContentRenderer: (cellProps: TableCellProps) => { @@ -96,21 +103,21 @@ const DLSVisitsTable = (props: DLSVisitsTableProps): React.ReactElement => { return tableLink( `/browse/proposal/${proposalName}/investigation/${investigationData.id}/dataset`, investigationData.visitId, - view + view, + 'dls-visits-table-visitId' ); }, filterComponent: textFilter, }, { - icon: ConfirmationNumberIcon, - label: t('investigations.dataset_count'), - dataKey: 'datasetCount', + icon: Save, + label: t('investigations.size'), + dataKey: 'fileSize', cellContentRenderer: (cellProps: TableCellProps): number | string => - formatCountOrSize(datasetCountQueries[cellProps.rowIndex]), - disableSort: true, + formatBytes(cellProps.rowData.fileSize), }, { - icon: AssessmentIcon, + icon: Assessment, label: t('investigations.instrument'), dataKey: 'investigationInstruments.instrument.name', cellContentRenderer: (cellProps: TableCellProps) => { @@ -125,20 +132,20 @@ const DLSVisitsTable = (props: DLSVisitsTableProps): React.ReactElement => { filterComponent: textFilter, }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('investigations.start_date'), dataKey: 'startDate', filterComponent: dateFilter, defaultSort: 'desc', }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('investigations.end_date'), dataKey: 'endDate', filterComponent: dateFilter, }, ], - [t, dateFilter, textFilter, view, proposalName, datasetCountQueries] + [t, dateFilter, textFilter, view, proposalName] ); return ( diff --git a/packages/datagateway-dataview/src/views/table/investigationTable.component.test.tsx b/packages/datagateway-dataview/src/views/table/investigationTable.component.test.tsx index 204e0ce08..55be1e215 100644 --- a/packages/datagateway-dataview/src/views/table/investigationTable.component.test.tsx +++ b/packages/datagateway-dataview/src/views/table/investigationTable.component.test.tsx @@ -1,57 +1,51 @@ -import { createMount, createShallow } from '@material-ui/core/test-utils'; -// import axios from 'axios'; import { - Investigation, dGCommonInitialState, - useInvestigationCount, - useIds, - useCart, - useAddToCart, - useRemoveFromCart, - useInvestigationsInfinite, - useInvestigationSizes, + type DownloadCartItem, + type Investigation, } from 'datagateway-common'; -import React from 'react'; +import * as React from 'react'; import { Provider } from 'react-redux'; -import { Router } from 'react-router'; +import { Router } from 'react-router-dom'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; -import { StateType } from '../../state/app.types'; +import type { StateType } from '../../state/app.types'; import { initialState } from '../../state/reducers/dgdataview.reducer'; -import InvestigationTable, { - InvestigationDetailsPanel, -} from './investigationTable.component'; +import InvestigationTable from './investigationTable.component'; import { QueryClient, QueryClientProvider } from 'react-query'; -import { ReactWrapper } from 'enzyme'; -import { createMemoryHistory, History } from 'history'; - -jest.mock('datagateway-common', () => { - const originalModule = jest.requireActual('datagateway-common'); - - return { - __esModule: true, - ...originalModule, - useInvestigationCount: jest.fn(), - useInvestigationsInfinite: jest.fn(), - useInvestigationSizes: jest.fn(), - useIds: jest.fn(), - useCart: jest.fn(), - useAddToCart: jest.fn(), - useRemoveFromCart: jest.fn(), - }; -}); +import { createMemoryHistory, type History } from 'history'; +import { + render, + type RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, + findAllRows, + findColumnHeaderByName, +} from '../../setupTests'; +import type { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; +import { + findCellInRow, + findColumnIndexByName, +} from 'datagateway-search/src/setupTests'; +import axios, { type AxiosResponse } from 'axios'; describe('Investigation table component', () => { - let shallow; - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let rowData: Investigation[]; + let cartItems: DownloadCartItem[]; let history: History; + let user: UserEvent; + let holder: HTMLElement; - const createWrapper = (): ReactWrapper => { + const renderComponent = (): RenderResult => { const store = mockStore(state); - return mount( + return render( @@ -63,14 +57,16 @@ describe('Investigation table component', () => { }; beforeEach(() => { - shallow = createShallow(); - mount = createMount(); + user = userEvent.setup(); + cartItems = []; rowData = [ { id: 1, - title: 'Test 1', + fileSize: 1, + fileCount: 1, + title: 'Test title 1', name: 'Test 1', - visitId: '1', + visitId: 'visit id 1', doi: 'doi 1', investigationInstruments: [ { @@ -87,7 +83,10 @@ describe('Investigation table component', () => { ]; history = createMemoryHistory(); - mockStore = configureStore([thunk]); + holder = document.createElement('div'); + holder.setAttribute('id', 'datagateway-dataview'); + document.body.appendChild(holder); + state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -95,126 +94,214 @@ describe('Investigation table component', () => { }) ); - (useCart as jest.Mock).mockReturnValue({ - data: [], - }); - (useInvestigationCount as jest.Mock).mockReturnValue({ - data: 0, - }); - (useInvestigationsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - (useInvestigationSizes as jest.Mock).mockReturnValue({ data: 1 }); - (useIds as jest.Mock).mockReturnValue({ - data: [1], - }); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + if (/\/user\/cart\/$/.test(url)) { + // fetch download cart + return Promise.resolve({ + data: { cartItems }, + }); + } + + if (/\/user\/getSize$/.test(url)) { + // fetch investigation size + return Promise.resolve({ + data: 1, + }); + } + + if (/\/investigations\/count$/.test(url)) { + // fetch investigations count + return Promise.resolve({ + data: rowData.length, + }); + } + + if (/\/investigations$/.test(url)) { + return Promise.resolve({ + data: rowData, + }); + } + + return Promise.reject(`Endpoint not mocked: ${url}`); + }); + + axios.post = jest + .fn() + .mockImplementation( + (url: string, data: unknown): Promise> => { + if (/\/user\/cart\/\/cartItems$/.test(url)) { + const isRemove: boolean = JSON.parse( + (data as URLSearchParams).get('remove') ?? 'false' + ); + + if (isRemove) { + cartItems = []; + + return Promise.resolve({ + data: { + cartItems: [], + }, + }); + } + + cartItems = [ + ...cartItems, + { + id: 123, + entityId: 1, + entityType: 'investigation', + name: 'download cart item name', + parentEntities: [], + }, + ]; + + return Promise.resolve({ + data: { cartItems }, + }); + } + + return Promise.reject(`Endpoint not mocked: ${url}`); + } + ); }); afterEach(() => { - mount.cleanUp(); + document.body.removeChild(holder); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); + it('renders correctly', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - createWrapper(); - expect(useInvestigationCount).toHaveBeenCalled(); - expect(useInvestigationsInfinite).toHaveBeenCalledWith([ - { - filterType: 'include', - filterValue: JSON.stringify({ - investigationInstruments: 'instrument', - }), - }, - ]); - expect(useInvestigationSizes).toHaveBeenCalledWith({ - pages: [rowData], + let rows: HTMLElement[] = []; + await waitFor(async () => { + rows = await findAllRows(); + // should have 1 row in the table + expect(rows).toHaveLength(1); }); - expect(useIds).toHaveBeenCalledWith('investigation', undefined, true); - expect(useCart).toHaveBeenCalled(); - expect(useAddToCart).toHaveBeenCalledWith('investigation'); - expect(useRemoveFromCart).toHaveBeenCalledWith('investigation'); - }); - it('calls useInvestigationsInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useInvestigationsInfinite as jest.Mock).mockReturnValueOnce({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); - - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); - - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, - }); - }); + const row = rows[0]; - it('displays DOI and renders the expected Link ', () => { - const wrapper = createWrapper(); + // check that column headers are shown correctly. expect( - wrapper - .find('[data-testid="investigation-table-doi-link"]') - .first() - .text() - ).toEqual('doi 1'); + await findColumnHeaderByName('investigations.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.visit_id') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.doi') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.instrument') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.end_date') + ).toBeInTheDocument(); + // check that each cell contains the correct value + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.title'), + }) + ).getByRole('link', { name: 'Test title 1' }) + ).toHaveAttribute('href', '/browse/investigation/1/dataset'); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.visit_id'), + }) + ).getByText('visit id 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.name'), + }) + ).getByText('Test 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.doi'), + }) + ).getByRole('link', { name: 'doi 1' }) + ).toHaveAttribute('href', 'https://doi.org/doi 1'); expect( - wrapper - .find('[data-testid="investigation-table-doi-link"]') - .first() - .prop('href') - ).toEqual('https://doi.org/doi 1'); + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.size'), + }) + ).getByText('1 B') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.instrument'), + }) + ).getByText('LARMOR') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.start_date'), + }) + ).getByText('2019-07-23') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.end_date'), + }) + ).getByText('2019-07-24') + ).toBeInTheDocument(); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); - const filterInput = wrapper - .find('[aria-label="Filter by investigations.name"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by investigations.name', + hidden: true, + }); - expect(history.length).toBe(2); + await user.type(filterInput, 'test'); + + expect(history.length).toBe(5); expect(history.location.search).toBe( `?filters=${encodeURIComponent( '{"name":{"value":"test","type":"include"}}' )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); - expect(history.length).toBe(3); + expect(history.length).toBe(6); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const filterInput = wrapper.find( - 'input[id="investigations.start_date filter from"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'investigations.start_date filter from', + }); + + await user.type(filterInput, '2019-08-06'); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -223,20 +310,21 @@ describe('Investigation table component', () => { )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.length).toBe(3); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + await user.click(screen.getByText('investigations.title')); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -244,130 +332,118 @@ describe('Investigation table component', () => { ); }); - it('calls addToCart mutate function on unchecked checkbox click', () => { - const addToCart = jest.fn(); - (useAddToCart as jest.Mock).mockReturnValueOnce({ - mutate: addToCart, - loading: false, + it('adds selected row to cart if unselected; removes it from cart otherwise', async () => { + renderComponent(); + + // wait for rows to show up + await waitFor(async () => { + expect(await findAllRows()).toHaveLength(1); }); - const wrapper = createWrapper(); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + // row should not be selected initially as the cart is empty + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).not.toBeChecked(); - expect(addToCart).toHaveBeenCalledWith([1]); - }); + // select the row + await user.click( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ); - it('calls removeFromCart mutate function on checked checkbox click', () => { - (useCart as jest.Mock).mockReturnValueOnce({ - data: [ - { - entityId: 1, - entityType: 'investigation', - id: 1, - name: 'test', - parentEntities: [], - }, - ], - }); + // investigation should be added to the cart + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).toBeChecked(); - const removeFromCart = jest.fn(); - (useRemoveFromCart as jest.Mock).mockReturnValueOnce({ - mutate: removeFromCart, - loading: false, - }); + // unselect the row + await user.click(screen.getByRole('checkbox', { name: 'select row 0' })); - const wrapper = createWrapper(); + // investigation should be removed from the cart + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).not.toBeChecked(); + }); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + it('selected rows only considers relevant cart items', async () => { + cartItems = [ + { + entityId: 2, + entityType: 'investigation', + id: 1, + name: 'test', + parentEntities: [], + }, + { + entityId: 1, + entityType: 'dataset', + id: 2, + name: 'test', + parentEntities: [], + }, + ]; - expect(removeFromCart).toHaveBeenCalledWith([1]); - }); + renderComponent(); - it('selected rows only considers relevant cart items', () => { - (useCart as jest.Mock).mockReturnValueOnce({ - data: [ - { - entityId: 2, - entityType: 'investigation', - id: 1, - name: 'test', - parentEntities: [], - }, - { - entityId: 1, - entityType: 'dataset', - id: 2, - name: 'test', - parentEntities: [], - }, - ], + // wait for rows to show up + await waitFor(async () => { + expect(await findAllRows()).toHaveLength(1); }); - const wrapper = createWrapper(); - - const selectAllCheckbox = wrapper - .find('[aria-label="select all rows"]') - .first(); + const selectAllCheckbox = await screen.findByRole('checkbox', { + name: 'select all rows', + }); - expect(selectAllCheckbox.prop('checked')).toEqual(false); - expect(selectAllCheckbox.prop('data-indeterminate')).toEqual(false); + expect(selectAllCheckbox).not.toBeChecked(); + expect(selectAllCheckbox).toHaveAttribute('data-indeterminate', 'false'); }); - it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', () => { + it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', async () => { state.dgdataview.selectAllSetting = false; + renderComponent(); - const wrapper = createWrapper(); - - expect(useIds).toHaveBeenCalledWith('investigation', undefined, false); - expect(useIds).not.toHaveBeenCalledWith('investigation', undefined, true); - expect(wrapper.exists('[aria-label="select all rows"]')).toBe(false); - }); - - it('renders details panel correctly', () => { - const wrapper = shallow( - - ); - expect(wrapper).toMatchSnapshot(); - }); - - it('renders investigation title as a link', () => { - const wrapper = createWrapper(); + // wait for rows to show up + await waitFor(async () => { + expect(await findAllRows()).toHaveLength(1); + }); expect( - wrapper.find('[aria-colindex=3]').find('p').children() - ).toMatchSnapshot(); - }); - - it('renders date objects as just the date', () => { - const wrapper = createWrapper(); - - expect(wrapper.find('[aria-colindex=9]').find('p').text()).toEqual( - '2019-07-23' - ); - - expect(wrapper.find('[aria-colindex=10]').find('p').text()).toEqual( - '2019-07-24' - ); + screen.queryByRole('checkbox', { name: 'select all rows' }) + ).toBeNull(); }); it('renders fine with incomplete data', () => { // this can happen when navigating between tables and the previous table's state still exists - const incompleteData = [ + rowData = [ { id: 1, name: 'test', title: 'test', doi: 'Test 1', + visitId: '1', }, ]; - (useInvestigationsInfinite as jest.Mock).mockReturnValueOnce({ - data: { pages: [incompleteData] }, - fetchNextPage: jest.fn(), + + expect(() => renderComponent()).not.toThrowError(); + }); + + it('displays details panel when expanded', async () => { + renderComponent(); + + let rows: HTMLElement[] = []; + await waitFor(async () => { + rows = await findAllRows(); + // should have 1 row in the table + expect(rows).toHaveLength(1); }); - expect(() => createWrapper()).not.toThrowError(); + expect(screen.queryByTestId('investigation-details-panel')).toBeNull(); + + await user.click( + within(rows[0]).getByRole('button', { name: 'Show details' }) + ); + + expect( + await screen.findByTestId('investigation-details-panel') + ).toBeInTheDocument(); }); }); diff --git a/packages/datagateway-dataview/src/views/table/investigationTable.component.tsx b/packages/datagateway-dataview/src/views/table/investigationTable.component.tsx index f97295bb4..b9c9209bd 100644 --- a/packages/datagateway-dataview/src/views/table/investigationTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/investigationTable.component.tsx @@ -1,19 +1,10 @@ import React from 'react'; -import { - Typography, - Grid, - createStyles, - makeStyles, - Theme, - Divider, -} from '@material-ui/core'; import { Table, investigationLink, externalSiteLink, Investigation, ColumnType, - formatCountOrSize, useInvestigationsInfinite, useInvestigationCount, useIds, @@ -24,78 +15,22 @@ import { useSort, useTextFilter, useDateFilter, - DetailsPanelProps, - useInvestigationSizes, + InvestigationDetailsPanel, + formatBytes, } from 'datagateway-common'; import { StateType } from '../../state/app.types'; import { useSelector } from 'react-redux'; import { TableCellProps, IndexRange } from 'react-virtualized'; import { useTranslation } from 'react-i18next'; import { useLocation } from 'react-router-dom'; -import SubjectIcon from '@material-ui/icons/Subject'; -import FingerprintIcon from '@material-ui/icons/Fingerprint'; -import PublicIcon from '@material-ui/icons/Public'; -import SaveIcon from '@material-ui/icons/Save'; -import AssessmentIcon from '@material-ui/icons/Assessment'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; - -const useStyles = makeStyles((theme: Theme) => - createStyles({ - root: { - padding: theme.spacing(2), - }, - divider: { - marginBottom: theme.spacing(2), - }, - }) -); - -export const InvestigationDetailsPanel = ( - props: DetailsPanelProps -): React.ReactElement => { - const classes = useStyles(); - const [t] = useTranslation(); - const investigationData = props.rowData as Investigation; - return ( - - - - {investigationData.title} - - - - - - {t('investigations.details.name')} - - - {investigationData.name} - - - - - {t('investigations.details.start_date')} - - - {investigationData.startDate} - - - - - {t('investigations.details.end_date')} - - - {investigationData.endDate} - - - - ); -}; +import { + Subject, + Fingerprint, + Public, + Save, + Assessment, + CalendarToday, +} from '@mui/icons-material'; const InvestigationTable = (): React.ReactElement => { const selectAllSetting = useSelector( @@ -118,20 +53,29 @@ const InvestigationTable = (): React.ReactElement => { }), }, ]); - const { data: allIds } = useIds('investigation', undefined, selectAllSetting); - const { data: cartItems } = useCart(); - const { mutate: addToCart, isLoading: addToCartLoading } = useAddToCart( - 'investigation' + const { data: allIds, isLoading: allIdsLoading } = useIds( + 'investigation', + undefined, + selectAllSetting ); - const { - mutate: removeFromCart, - isLoading: removeFromCartLoading, - } = useRemoveFromCart('investigation'); + const { data: cartItems, isLoading: cartLoading } = useCart(); + const { mutate: addToCart, isLoading: addToCartLoading } = + useAddToCart('investigation'); + const { mutate: removeFromCart, isLoading: removeFromCartLoading } = + useRemoveFromCart('investigation'); - const aggregatedData: Investigation[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + /* istanbul ignore next */ + const aggregatedData: Investigation[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } + + return []; + }, [data]); const selectedRows = React.useMemo( () => @@ -156,12 +100,10 @@ const InvestigationTable = (): React.ReactElement => { [fetchNextPage] ); - const sizeQueries = useInvestigationSizes(data); - const columns: ColumnType[] = React.useMemo( () => [ { - icon: SubjectIcon, + icon: Subject, label: t('investigations.title'), dataKey: 'title', cellContentRenderer: (cellProps: TableCellProps) => { @@ -176,20 +118,20 @@ const InvestigationTable = (): React.ReactElement => { filterComponent: textFilter, }, { - icon: FingerprintIcon, + icon: Fingerprint, label: t('investigations.visit_id'), dataKey: 'visitId', filterComponent: textFilter, }, { - icon: FingerprintIcon, + icon: Fingerprint, label: t('investigations.name'), dataKey: 'name', filterComponent: textFilter, disableSort: true, }, { - icon: PublicIcon, + icon: Public, label: t('investigations.doi'), dataKey: 'doi', cellContentRenderer: (cellProps: TableCellProps) => { @@ -204,15 +146,15 @@ const InvestigationTable = (): React.ReactElement => { }, { - icon: SaveIcon, + icon: Save, label: t('investigations.size'), dataKey: 'size', cellContentRenderer: (cellProps: TableCellProps): number | string => - formatCountOrSize(sizeQueries[cellProps.rowIndex], true), + formatBytes(cellProps.rowData.fileSize), disableSort: true, }, { - icon: AssessmentIcon, + icon: Assessment, label: t('investigations.instrument'), dataKey: 'investigationInstruments.instrument.name', cellContentRenderer: (cellProps: TableCellProps) => { @@ -227,7 +169,7 @@ const InvestigationTable = (): React.ReactElement => { filterComponent: textFilter, }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('investigations.start_date'), dataKey: 'startDate', @@ -239,7 +181,7 @@ const InvestigationTable = (): React.ReactElement => { }, }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('investigations.end_date'), dataKey: 'endDate', filterComponent: dateFilter, @@ -250,12 +192,17 @@ const InvestigationTable = (): React.ReactElement => { }, }, ], - [t, textFilter, dateFilter, view, sizeQueries] + [t, textFilter, dateFilter, view] ); return (
- - - - - - - Test 1 - - - - - - - + Test 1 + `; -exports[`ISIS Dataset table component renders dataset name as a link in StudyHierarchy 1`] = ` - - - - - - - - Test 1 - - - - - - - + Test 1 + `; diff --git a/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisFacilityCyclesTable.component.test.tsx.snap b/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisFacilityCyclesTable.component.test.tsx.snap index 90d1a5da7..845a69383 100644 --- a/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisFacilityCyclesTable.component.test.tsx.snap +++ b/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisFacilityCyclesTable.component.test.tsx.snap @@ -1,227 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ISIS FacilityCycles table component renders correctly 1`] = ` -Object { - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "name", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "facilitycycles.name", - }, - Object { - "dataKey": "startDate", - "defaultSort": "desc", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "facilitycycles.start_date", - }, - Object { - "dataKey": "endDate", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "facilitycycles.end_date", - }, - ], - "data": Array [ - Object { - "description": "Test 1", - "endDate": "2019-07-04", - "id": 1, - "name": "Test 1", - "startDate": "2019-07-03", - }, - ], - "loadMoreRows": [Function], - "onSort": [Function], - "sort": Object { - "startDate": "desc", - }, - "totalRowCount": 1, -} -`; - exports[`ISIS FacilityCycles table component renders facilitycycle name as a link 1`] = ` - - - - - - - - Test 1 - - - - - - - + Test 1 + `; diff --git a/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisInstrumentsTable.component.test.tsx.snap b/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisInstrumentsTable.component.test.tsx.snap deleted file mode 100644 index 2c10d916b..000000000 --- a/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisInstrumentsTable.component.test.tsx.snap +++ /dev/null @@ -1,706 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ISIS Instruments table component renders correctly 1`] = ` -Object { - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "fullName", - "defaultSort": "asc", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "instruments.name", - }, - Object { - "dataKey": "type", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "instruments.type", - }, - ], - "data": Array [ - Object { - "description": "foo bar", - "fullName": "Test instrument 1", - "id": 1, - "name": "Test 1", - "url": "test url", - }, - Object { - "description": "foo bar", - "id": 2, - "name": "Test 2", - "url": "test url", - }, - ], - "detailsPanel": [Function], - "loadMoreRows": [Function], - "onSort": [Function], - "sort": Object { - "fullName": "asc", - }, - "totalRowCount": 1, -} -`; - -exports[`ISIS Instruments table component renders names as links in StudyHierarchy 1`] = ` -Array [ - - - - - - - - Test instrument 1 - - - - - - - , - - - - - - - - Test 2 - - - - - - - , -] -`; - -exports[`ISIS Instruments table component renders names as links when NOT in studyHierarchy 1`] = ` -Array [ - - - - - - - - Test instrument 1 - - - - - - - , - - - - - - - - Test 2 - - - - - - - , -] -`; diff --git a/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisInvestigationsTable.component.test.tsx.snap b/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisInvestigationsTable.component.test.tsx.snap deleted file mode 100644 index bcda0e42d..000000000 --- a/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisInvestigationsTable.component.test.tsx.snap +++ /dev/null @@ -1,675 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ISIS Investigations table component renders correctly 1`] = ` -Object { - "actions": Array [ - [Function], - ], - "allIds": Array [ - 1, - ], - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "title", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.title", - }, - Object { - "dataKey": "name", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.name", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "studyInvestigations.study.pid", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.doi", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "size", - "disableSort": true, - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.size", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "investigationUsers.user.fullName", - "disableSort": true, - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.principal_investigators", - }, - Object { - "dataKey": "startDate", - "defaultSort": "desc", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.start_date", - }, - Object { - "dataKey": "endDate", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.end_date", - }, - ], - "data": Array [ - Object { - "doi": "doi 1", - "endDate": "2019-06-11", - "id": 1, - "investigationUsers": Array [ - Object { - "id": 2, - "role": "experimenter", - "user": Object { - "fullName": "Test experimenter", - "id": 2, - "name": "test", - }, - }, - Object { - "id": 3, - "role": "principal_experimenter", - "user": Object { - "fullName": "Test PI", - "id": 3, - "name": "testpi", - }, - }, - ], - "name": "Test 1", - "size": 1, - "startDate": "2019-06-10", - "studyInvestigations": Array [ - Object { - "id": 6, - "study": Object { - "id": 7, - "pid": "study pid", - }, - }, - ], - "summary": "foo bar", - "title": "Test 1", - "visitId": "1", - }, - ], - "detailsPanel": [Function], - "disableSelectAll": false, - "loadMoreRows": [Function], - "loading": false, - "onCheck": [MockFunction], - "onSort": [Function], - "onUncheck": [MockFunction], - "selectedRows": Array [], - "sort": Object { - "startDate": "desc", - }, - "totalRowCount": 0, -} -`; - -exports[`ISIS Investigations table component renders title, name and DOI as links 1`] = ` - - - - - - - - Test 1 - - - - - - - -`; - -exports[`ISIS Investigations table component renders title, name and DOI as links 2`] = `"Test 1"`; - -exports[`ISIS Investigations table component renders title, name and DOI as links 3`] = ` - - - - - - study pid - - - - - -`; - -exports[`ISIS Investigations table component renders title, name and DOI as links in StudyHierarchy 1`] = ` - - - - - - - - Test 1 - - - - - - - -`; - -exports[`ISIS Investigations table component renders title, name and DOI as links in StudyHierarchy 2`] = `"Test 1"`; - -exports[`ISIS Investigations table component renders title, name and DOI as links in StudyHierarchy 3`] = ` - - - - - - study pid - - - - - -`; diff --git a/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisMyDataTable.component.test.tsx.snap b/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisMyDataTable.component.test.tsx.snap deleted file mode 100644 index 32e906571..000000000 --- a/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisMyDataTable.component.test.tsx.snap +++ /dev/null @@ -1,495 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ISIS MyData table component renders correctly 1`] = ` -Object { - "allIds": Array [ - 1, - ], - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "title", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.title", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "studyInvestigations.study.pid", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.doi", - }, - Object { - "dataKey": "visitId", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.visit_id", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "name", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.name", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "investigationInstruments.instrument.fullName", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.instrument", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "size", - "disableSort": true, - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.size", - }, - Object { - "dataKey": "startDate", - "defaultSort": "desc", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.start_date", - }, - Object { - "dataKey": "endDate", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.end_date", - }, - ], - "data": Array [ - Object { - "doi": "doi 1", - "endDate": "2019-06-11", - "id": 1, - "investigationInstruments": Array [ - Object { - "id": 1, - "instrument": Object { - "id": 3, - "name": "LARMOR", - }, - }, - ], - "name": "Test 1 name", - "startDate": "2019-06-10", - "studyInvestigations": Array [ - Object { - "id": 6, - "investigation": Object { - "id": 1, - "name": "Test 1 name", - "title": "Test 1 title", - "visitId": "1", - }, - "study": Object { - "createTime": "2019-06-10", - "id": 7, - "modTime": "2019-06-10", - "name": "study", - "pid": "study pid", - }, - }, - ], - "summary": "foo bar", - "title": "Test 1 title", - "visitId": "1", - }, - ], - "detailsPanel": [Function], - "disableSelectAll": false, - "loadMoreRows": [Function], - "loading": false, - "onCheck": [MockFunction], - "onSort": [Function], - "onUncheck": [MockFunction], - "selectedRows": Array [], - "sort": Object { - "startDate": "desc", - }, - "totalRowCount": 0, -} -`; - -exports[`ISIS MyData table component renders title and name as links 1`] = ` - - - - - - - - Test 1 title - - - - - - - -`; - -exports[`ISIS MyData table component renders title and name as links 2`] = ` - - - - - - - - Test 1 name - - - - - - - -`; diff --git a/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisStudiesTable.component.test.tsx.snap b/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisStudiesTable.component.test.tsx.snap deleted file mode 100644 index c5f746fea..000000000 --- a/packages/datagateway-dataview/src/views/table/isis/__snapshots__/isisStudiesTable.component.test.tsx.snap +++ /dev/null @@ -1,257 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ISIS Studies table component renders correctly 1`] = ` -Object { - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "name", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "studies.name", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "studyInvestigations.investigation.title", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "studies.title", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "pid", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "studies.pid", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "studyInvestigations.investigation.startDate", - "defaultSort": "desc", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "studies.start_date", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "studyInvestigations.investigation.endDate", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "studies.end_date", - }, - ], - "data": Array [ - Object { - "createTime": "2000-01-01", - "id": 1, - "modTime": "2000-01-01", - "name": "Test 1", - "pid": "doi", - }, - ], - "loadMoreRows": [Function], - "onSort": [Function], - "sort": Object { - "studyInvestigations.investigation.startDate": "desc", - }, - "totalRowCount": 1, -} -`; - -exports[`ISIS Studies table component renders studies name as a link 1`] = ` - - - - - - - - Test 1 - - - - - - - -`; diff --git a/packages/datagateway-dataview/src/views/table/isis/isisDataPublicationsTable.component.test.tsx b/packages/datagateway-dataview/src/views/table/isis/isisDataPublicationsTable.component.test.tsx new file mode 100644 index 000000000..e52b24618 --- /dev/null +++ b/packages/datagateway-dataview/src/views/table/isis/isisDataPublicationsTable.component.test.tsx @@ -0,0 +1,357 @@ +import * as React from 'react'; +import { initialState as dgDataViewInitialState } from '../../../state/reducers/dgdataview.reducer'; + +import type { StateType } from '../../../state/app.types'; +import { dGCommonInitialState, type DataPublication } from 'datagateway-common'; +import configureStore from 'redux-mock-store'; +import { QueryClient, QueryClientProvider } from 'react-query'; +import { Provider } from 'react-redux'; +import thunk from 'redux-thunk'; +import { generatePath, Router } from 'react-router-dom'; +import { createMemoryHistory, type History } from 'history'; +import { parse } from 'date-fns'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, + findCellInRow, + findColumnHeaderByName, + findColumnIndexByName, + findRowAt, +} from '../../../setupTests'; +import { + render, + type RenderResult, + screen, + within, +} from '@testing-library/react'; +import { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; +import ISISDataPublicationsTable from './isisDataPublicationsTable.component'; +import axios, { AxiosResponse } from 'axios'; +import { paths } from '../../../page/pageContainer.component'; + +jest.useFakeTimers().setSystemTime(parse('2021-10-27', 'yyyy-MM-dd', 0)); + +describe('ISIS Data Publication table component', () => { + const mockStore = configureStore([thunk]); + let state: StateType; + let rowData: DataPublication[]; + let history: History; + let user: UserEvent; + + const renderComponent = (studyDataPublicationId?: string): RenderResult => { + if (studyDataPublicationId) + history.replace( + generatePath( + paths.dataPublications.toggle.isisInvestigationDataPublication, + { + instrumentId: 1, + studyDataPublicationId, + } + ) + ); + const store = mockStore(state); + return render( + + + + + + + + ); + }; + + beforeEach(() => { + rowData = [ + { + id: 1, + pid: 'doi', + title: 'Test 1', + description: 'Data Publication Description', + publicationDate: '2001-01-01', + content: { + id: 1, + dataCollectionInvestigations: [ + { + id: 1, + investigation: { + id: 711, + title: 'investigation title', + name: 'investigation name', + visitId: 'IPim0', + startDate: '1999-01-01', + endDate: '1999-01-02', + }, + }, + ], + }, + }, + ]; + history = createMemoryHistory({ + initialEntries: [ + generatePath(paths.dataPublications.toggle.isisStudyDataPublication, { + instrumentId: 1, + }), + ], + }); + user = userEvent.setup({ + delay: null, + }); + + state = JSON.parse( + JSON.stringify({ + dgdataview: dgDataViewInitialState, + dgcommon: dGCommonInitialState, + }) + ); + + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + switch (url) { + case '/datapublications': + return Promise.resolve({ + data: rowData, + }); + + case '/datapublications/count': + return Promise.resolve({ + data: 1, + isLoading: false, + }); + default: + return Promise.reject(`Endpoint not mocked: ${url}`); + } + }); + + // Prevent error logging + window.scrollTo = jest.fn(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('Study Data Publication', () => { + it('renders correctly', async () => { + renderComponent(); + + const rows = await screen.findAllByRole('row'); + //should have 1 row in the table + expect(rows).toHaveLength(1); + + expect( + await findColumnHeaderByName('datapublications.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datapublications.pid') + ).toBeInTheDocument(); + + const row = await findRowAt(0); + + // check that every cell contains the correct values + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datapublications.title'), + }) + ).getByText('Test 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datapublications.pid'), + }) + ).getByText('doi') + ).toBeInTheDocument(); + }); + + it('updates filter query params on text filter', async () => { + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by datapublications.title', + hidden: true, + }); + + await user.type(filterInput, 'test'); + + // user.type inputs the given string character by character to simulate user typing + // each keystroke of user.type creates a new entry in the history stack + // so the initial entry + 4 characters in "test" = 5 entries + expect(history.length).toBe(5); + expect(history.location.search).toBe( + `?filters=${encodeURIComponent( + '{"title":{"value":"test","type":"include"}}' + )}` + ); + + await user.clear(filterInput); + + expect(history.length).toBe(6); + expect(history.location.search).toBe('?'); + }); + + it('uses default sort', () => { + renderComponent(); + expect(history.length).toBe(1); + expect(history.location.search).toBe( + `?sort=${encodeURIComponent('{"title":"desc"}')}` + ); + + // check that the data request is sent only once after mounting + const datafilesCalls = (axios.get as jest.Mock).mock.calls.filter( + (call) => call[0] === '/datapublications' + ); + expect(datafilesCalls).toHaveLength(1); + }); + + it('updates sort query params on sort', async () => { + renderComponent(); + + await user.click( + await screen.findByRole('button', { name: 'datapublications.pid' }) + ); + + expect(history.length).toBe(2); + expect(history.location.search).toBe( + `?sort=${encodeURIComponent('{"pid":"asc"}')}` + ); + }); + + it('renders data publication name as a link', async () => { + renderComponent(); + + const dataPublicationIdColIndex = await findColumnIndexByName( + 'datapublications.title' + ); + const row = await findRowAt(0); + const dataPublicationIdCell = findCellInRow(row, { + columnIndex: dataPublicationIdColIndex, + }); + + expect( + within(dataPublicationIdCell).getByRole('link', { name: 'Test 1' }) + ).toHaveAttribute( + 'href', + '/browseDataPublications/instrument/1/dataPublication/1' + ); + }); + + it('displays Experiment DOI (PID) and renders the expected Link ', async () => { + renderComponent(); + + const pidColIndex = await findColumnIndexByName('datapublications.pid'); + const row = await findRowAt(0); + const pidCell = findCellInRow(row, { columnIndex: pidColIndex }); + + expect( + within(pidCell).getByRole('link', { name: 'doi' }) + ).toHaveAttribute('href', 'https://doi.org/doi'); + }); + }); + + describe('Investigation Data Publication', () => { + it('renders correctly', async () => { + renderComponent('2'); + + const rows = await screen.findAllByRole('row'); + //should have 1 row in the table + expect(rows).toHaveLength(1); + + expect( + await findColumnHeaderByName('datapublications.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datapublications.pid') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datapublications.publication_date') + ).toBeInTheDocument(); + + const row = await findRowAt(0); + + // check that every cell contains the correct values + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datapublications.title'), + }) + ).getByText('Test 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datapublications.pid'), + }) + ).getByText('doi') + ).toBeInTheDocument(); + }); + + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); + + renderComponent('2'); + + const filterInput = await screen.findByRole('textbox', { + name: 'datapublications.publication_date filter to', + }); + + await user.type(filterInput, '2019-08-06'); + + expect(history.length).toBe(2); + expect(history.location.search).toBe( + `?filters=${encodeURIComponent( + '{"publicationDate":{"endDate":"2019-08-06"}}' + )}` + ); + + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); + + expect(history.length).toBe(3); + expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); + }); + + it('uses default sort', () => { + renderComponent('2'); + expect(history.length).toBe(1); + expect(history.location.search).toBe( + `?sort=${encodeURIComponent('{"publicationDate":"desc"}')}` + ); + + // check that the data request is sent only once after mounting + const datafilesCalls = (axios.get as jest.Mock).mock.calls.filter( + (call) => call[0] === '/datapublications' + ); + expect(datafilesCalls).toHaveLength(1); + }); + + it('renders data publication name as a link', async () => { + renderComponent('2'); + + const dataPublicationIdColIndex = await findColumnIndexByName( + 'datapublications.title' + ); + const row = await findRowAt(0); + const dataPublicationIdCell = findCellInRow(row, { + columnIndex: dataPublicationIdColIndex, + }); + + expect( + within(dataPublicationIdCell).getByRole('link', { name: 'Test 1' }) + ).toHaveAttribute( + 'href', + '/browseDataPublications/instrument/1/dataPublication/2/investigation/1' + ); + }); + }); +}); diff --git a/packages/datagateway-dataview/src/views/table/isis/isisDataPublicationsTable.component.tsx b/packages/datagateway-dataview/src/views/table/isis/isisDataPublicationsTable.component.tsx new file mode 100644 index 000000000..1f82260ea --- /dev/null +++ b/packages/datagateway-dataview/src/views/table/isis/isisDataPublicationsTable.component.tsx @@ -0,0 +1,227 @@ +import { + ColumnType, + externalSiteLink, + parseSearchToQuery, + DataPublication, + Table, + tableLink, + useDateFilter, + useSort, + useDataPublicationsInfinite, + useTextFilter, + useDataPublicationCount, +} from 'datagateway-common'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { IndexRange, TableCellProps } from 'react-virtualized'; + +import { CalendarToday, Fingerprint, Public } from '@mui/icons-material'; +import { useLocation } from 'react-router-dom'; + +interface ISISDataPublicationsTableProps { + instrumentId: string; + studyDataPublicationId?: string; +} + +const ISISDataPublicationsTable = ( + props: ISISDataPublicationsTableProps +): React.ReactElement => { + const { instrumentId, studyDataPublicationId } = props; + + const location = useLocation(); + const [t] = useTranslation(); + + const { filters, view, sort } = React.useMemo( + () => parseSearchToQuery(location.search), + [location.search] + ); + + const { data: totalDataCount } = useDataPublicationCount([ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'content.dataCollectionInvestigations.investigation.investigationInstruments.instrument.id': + { + eq: instrumentId, + }, + }), + }, + ...(studyDataPublicationId + ? [ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'content.dataCollectionInvestigations.investigation.dataCollectionInvestigations.dataCollection.dataPublications.id': + { + eq: studyDataPublicationId, + }, + }), + }, + { + filterType: 'where', + filterValue: JSON.stringify({ + 'type.name': { eq: 'investigation' }, + }), + }, + ] + : [ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'type.name': { eq: 'study' }, + }), + }, + { + filterType: 'distinct', + filterValue: JSON.stringify(['id', 'title', 'pid']), + }, + ]), + ]); + + // isMounted is used to disable queries when the component isn't fully mounted. + // It prevents the request being sent twice if default sort is set. + // It is not needed for cards/tables that don't have default sort. + const [isMounted, setIsMounted] = React.useState(false); + React.useEffect(() => { + setIsMounted(true); + }, []); + + const { fetchNextPage, data } = useDataPublicationsInfinite( + [ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'content.dataCollectionInvestigations.investigation.investigationInstruments.instrument.id': + { + eq: instrumentId, + }, + }), + }, + ...(studyDataPublicationId + ? [ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'content.dataCollectionInvestigations.investigation.dataCollectionInvestigations.dataCollection.dataPublications.id': + { + eq: studyDataPublicationId, + }, + }), + }, + { + filterType: 'where', + filterValue: JSON.stringify({ + 'type.name': { eq: 'investigation' }, + }), + }, + ] + : [ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'type.name': { eq: 'study' }, + }), + }, + { + filterType: 'distinct', + filterValue: JSON.stringify(['id', 'title', 'pid']), + }, + ]), + ], + isMounted + ); + + /* istanbul ignore next */ + const aggregatedData: DataPublication[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } + + return []; + }, [data]); + + const textFilter = useTextFilter(filters); + const dateFilter = useDateFilter(filters); + const handleSort = useSort(); + + const loadMoreRows = React.useCallback( + (offsetParams: IndexRange) => fetchNextPage({ pageParam: offsetParams }), + [fetchNextPage] + ); + + const columns: ColumnType[] = React.useMemo(() => { + return [ + { + icon: Fingerprint, + label: t('datapublications.title'), + dataKey: 'title', + cellContentRenderer: (cellProps: TableCellProps) => + tableLink( + `${location.pathname}/${cellProps.rowData.id}`, + cellProps.rowData.title, + view, + 'isis-datapublication-table-id' + ), + + filterComponent: textFilter, + defaultSort: studyDataPublicationId ? undefined : 'desc', + }, + { + icon: Public, + label: t('datapublications.pid'), + dataKey: 'pid', + cellContentRenderer: (cellProps: TableCellProps) => { + const dataPublicationData = cellProps.rowData as DataPublication; + if (dataPublicationData?.pid) { + return externalSiteLink( + `https://doi.org/${dataPublicationData.pid}`, + dataPublicationData.pid, + 'isis-datapublication-table-doi-link' + ); + } + }, + filterComponent: textFilter, + }, + ...(studyDataPublicationId + ? ([ + { + icon: CalendarToday, + label: t('datapublications.publication_date'), + dataKey: 'publicationDate', + cellContentRenderer: (cellProps: TableCellProps) => + (cellProps.rowData as DataPublication).publicationDate?.slice( + 0, + 10 + ) ?? '', + filterComponent: dateFilter, + defaultSort: 'desc', + }, + ] as ColumnType[]) + : []), + ]; + }, [ + t, + textFilter, + studyDataPublicationId, + dateFilter, + location.pathname, + view, + ]); + + return ( + + ); +}; + +export default ISISDataPublicationsTable; diff --git a/packages/datagateway-dataview/src/views/table/isis/isisDatafilesTable.component.test.tsx b/packages/datagateway-dataview/src/views/table/isis/isisDatafilesTable.component.test.tsx index 7eabab819..0c68b3a33 100644 --- a/packages/datagateway-dataview/src/views/table/isis/isisDatafilesTable.component.test.tsx +++ b/packages/datagateway-dataview/src/views/table/isis/isisDatafilesTable.component.test.tsx @@ -1,64 +1,60 @@ -import React from 'react'; -import { createMount } from '@material-ui/core/test-utils'; +import * as React from 'react'; import ISISDatafilesTable from './isisDatafilesTable.component'; import { initialState as dgDataViewInitialState } from '../../../state/reducers/dgdataview.reducer'; import configureStore from 'redux-mock-store'; -import { StateType } from '../../../state/app.types'; +import type { StateType } from '../../../state/app.types'; import { + type Datafile, dGCommonInitialState, - Datafile, - useDatafileCount, - useIds, - useCart, - useAddToCart, - useRemoveFromCart, - useDatafilesInfinite, - DownloadButton, + DownloadCartItem, } from 'datagateway-common'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; -import { Router } from 'react-router'; +import { Router } from 'react-router-dom'; import { QueryClient, QueryClientProvider } from 'react-query'; -import { ReactWrapper } from 'enzyme'; -import { createMemoryHistory, History } from 'history'; - -jest.mock('datagateway-common', () => { - const originalModule = jest.requireActual('datagateway-common'); - - return { - __esModule: true, - ...originalModule, - useDatafileCount: jest.fn(), - useDatafilesInfinite: jest.fn(), - useIds: jest.fn(), - useCart: jest.fn(), - useAddToCart: jest.fn(), - useRemoveFromCart: jest.fn(), - }; -}); +import { createMemoryHistory, type History } from 'history'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, + findAllRows, + findColumnHeaderByName, +} from '../../../setupTests'; +import { + render, + type RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; +import type { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; +import { + findCellInRow, + findColumnIndexByName, +} from 'datagateway-search/src/setupTests'; +import axios, { AxiosResponse } from 'axios'; describe('ISIS datafiles table component', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let rowData: Datafile[]; + let cartItems: DownloadCartItem[]; let history: History; + let user: UserEvent; + let holder: HTMLElement; - const createWrapper = (): ReactWrapper => { - const store = mockStore(state); - return mount( - + const renderComponent = (): RenderResult => + render( + - + ); - }; beforeEach(() => { - mount = createMount(); rowData = [ { id: 1, @@ -69,9 +65,14 @@ describe('ISIS datafiles table component', () => { createTime: '2019-07-23', }, ]; + cartItems = []; history = createMemoryHistory(); + user = userEvent.setup(); + + holder = document.createElement('div'); + holder.setAttribute('id', 'datagateway-dataview'); + document.body.appendChild(holder); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgdataview: dgDataViewInitialState, @@ -79,159 +80,204 @@ describe('ISIS datafiles table component', () => { }) ); - (useCart as jest.Mock).mockReturnValue({ - data: [], - }); - (useDatafileCount as jest.Mock).mockReturnValue({ - data: 0, - }); - (useDatafilesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - (useIds as jest.Mock).mockReturnValue({ - data: [1], - }); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + if (/\/user\/cart\/$/.test(url)) { + // fetch download cart + return Promise.resolve({ + data: { cartItems }, + }); + } + + if (/\/datafiles\/count$/.test(url)) { + // fetch datafile count + return Promise.resolve({ + data: rowData.length, + }); + } + + if (/\/datafiles$/.test(url)) { + // datafiles infinite + return Promise.resolve({ + data: rowData, + }); + } + + return Promise.reject(`Endpoint not mocked: ${url}`); + }); + + axios.post = jest + .fn() + .mockImplementation( + (url: string, data: unknown): Promise> => { + if (/\/user\/cart\/\/cartItems$/.test(url)) { + const isRemove: boolean = JSON.parse( + (data as URLSearchParams).get('remove') ?? 'false' + ); + + if (isRemove) { + cartItems = []; + + return Promise.resolve({ + data: { + cartItems: [], + }, + }); + } + + cartItems = [ + ...cartItems, + { + id: 123, + entityId: 1, + entityType: 'datafile', + name: 'download cart item name', + parentEntities: [], + }, + ]; + + return Promise.resolve({ + data: { cartItems }, + }); + } + + return Promise.reject(`Endpoint not mocked: ${url}`); + } + ); }); afterEach(() => { - mount.cleanUp(); + document.body.removeChild(holder); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); - - it('calls the correct data fetching hooks on load', () => { - const datasetId = '1'; - createWrapper(); - expect(useDatafileCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ 'dataset.id': { eq: datasetId } }), - }, - ]); - expect(useDatafilesInfinite).toHaveBeenCalledWith( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ 'dataset.id': { eq: datasetId } }), - }, - ], - expect.any(Boolean) - ); - expect(useIds).toHaveBeenCalledWith( - 'datafile', - [ - { - filterType: 'where', - filterValue: JSON.stringify({ 'dataset.id': { eq: datasetId } }), - }, - ], - true - ); - expect(useCart).toHaveBeenCalled(); - expect(useAddToCart).toHaveBeenCalledWith('datafile'); - expect(useRemoveFromCart).toHaveBeenCalledWith('datafile'); - }); - - it('calls useDatafilesInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useDatafilesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); + it('renders correctly', async () => { + renderComponent(); - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, + let rows: HTMLElement[] = []; + await waitFor(async () => { + rows = await findAllRows(); + // should have 1 row in the table + expect(rows).toHaveLength(1); }); - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, - }); + // check that column headers are shown correctly + expect(await findColumnHeaderByName('datafiles.name')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.location') + ).toBeInTheDocument(); + expect(await findColumnHeaderByName('datafiles.size')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.modified_time') + ).toBeInTheDocument(); + + const row = rows[0]; + + // check that every cell contains the correct values + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.name'), + }) + ).getByText('Test 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.location'), + }) + ).getByText('/test1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.size'), + }) + ).getByText('1 B') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.modified_time'), + }) + ).getByText('2019-07-23') + ).toBeInTheDocument(); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); - const filterInput = wrapper - .find('[aria-label="Filter by datafiles.name"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by datafiles.name', + hidden: true, + }); - expect(history.length).toBe(2); + await user.type(filterInput, 'test'); + + // user.type inputs the given string character by character to simulate user typing + // each keystroke of user.type creates a new entry in the history stack + // so the initial entry + 4 characters in "test" = 5 entries + expect(history.length).toBe(5); expect(history.location.search).toBe( `?filters=${encodeURIComponent( '{"name":{"value":"test","type":"include"}}' )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); - expect(history.length).toBe(3); + expect(history.length).toBe(6); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const filterInput = wrapper.find( - 'input[id="datafiles.modified_time filter to"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'datafiles.modified_time filter to', + }); + + await user.type(filterInput, '2019-08-06'); expect(history.length).toBe(2); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"modTime":{"endDate":"2019-08-06"}}')}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.length).toBe(3); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"modTime":"desc"}')}` ); // check that the data request is sent only once after mounting - expect(useDatafilesInfinite).toHaveBeenCalledTimes(2); - expect(useDatafilesInfinite).toHaveBeenCalledWith(expect.anything(), false); - expect(useDatafilesInfinite).toHaveBeenLastCalledWith( - expect.anything(), - true + const datafilesCalls = (axios.get as jest.Mock).mock.calls.filter( + (call) => call[0] === '/datafiles' ); + // 2 becasue there is also a call for ids + expect(datafilesCalls).toHaveLength(2); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + // click on the datafiles.name column header + await user.click(await screen.findByText('datafiles.name')); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -239,92 +285,88 @@ describe('ISIS datafiles table component', () => { ); }); - it('calls addToCart mutate function on unchecked checkbox click', () => { - const addToCart = jest.fn(); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: addToCart, - loading: false, - }); - const wrapper = createWrapper(); - - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + it('adds selected row to cart if unselected; removes it from cart otherwise', async () => { + renderComponent(); - expect(addToCart).toHaveBeenCalledWith([1]); - }); - - it('calls removeFromCart mutate function on checked checkbox click', () => { - (useCart as jest.Mock).mockReturnValue({ - data: [ - { - entityId: 1, - entityType: 'datafile', - id: 1, - name: 'test', - parentEntities: [], - }, - ], + // wait for rows to show up + await waitFor(async () => { + expect(await findAllRows()).toHaveLength(1); }); - const removeFromCart = jest.fn(); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: removeFromCart, - loading: false, - }); + // row should not be selected initially as the cart is empty + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).not.toBeChecked(); - const wrapper = createWrapper(); + // select the row + await user.click(screen.getByRole('checkbox', { name: 'select row 0' })); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + // datafile should be added to the cart + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).toBeChecked(); - expect(removeFromCart).toHaveBeenCalledWith([1]); + // unselect the row + await user.click(screen.getByRole('checkbox', { name: 'select row 0' })); + + // datafile should be removed from the cart + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).not.toBeChecked(); }); - it('selected rows only considers relevant cart items', () => { - (useCart as jest.Mock).mockReturnValueOnce({ - data: [ - { - entityId: 1, - entityType: 'dataset', - id: 1, - name: 'test', - parentEntities: [], - }, - { - entityId: 2, - entityType: 'datafile', - id: 2, - name: 'test', - parentEntities: [], - }, - ], - }); + it('selected rows only considers relevant cart items', async () => { + cartItems = [ + { + entityId: 1, + entityType: 'dataset', + id: 1, + name: 'test', + parentEntities: [], + }, + { + entityId: 2, + entityType: 'datafile', + id: 2, + name: 'test', + parentEntities: [], + }, + ]; - const wrapper = createWrapper(); + renderComponent(); - const selectAllCheckbox = wrapper - .find('[aria-label="select all rows"]') - .first(); + const selectAllCheckbox = await screen.findByRole('checkbox', { + name: 'select all rows', + }); - expect(selectAllCheckbox.prop('checked')).toEqual(false); - expect(selectAllCheckbox.prop('data-indeterminate')).toEqual(false); + expect(selectAllCheckbox).not.toBeChecked(); + expect(selectAllCheckbox).toHaveAttribute('data-indeterminate', 'false'); }); - it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', () => { + it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', async () => { state.dgdataview.selectAllSetting = false; - - const wrapper = createWrapper(); - - expect(useIds).toHaveBeenCalledWith('datafile', expect.anything(), false); - expect(useIds).not.toHaveBeenCalledWith( - 'datafile', - expect.anything(), - true - ); - expect(wrapper.exists('[aria-label="select all rows"]')).toBe(false); + renderComponent(); + await waitFor(() => { + expect( + screen.queryByRole('checkbox', { name: 'select all rows' }) + ).toBeNull(); + }); }); - it('renders actions correctly', () => { - const wrapper = createWrapper(); + it('renders actions correctly', async () => { + renderComponent(); + expect( + await screen.findByRole('button', { name: 'buttons.download' }) + ).toBeTruthy(); + }); - expect(wrapper.find(DownloadButton).exists()).toBeTruthy(); + it('displays details panel when expanded', async () => { + renderComponent(); + await user.click( + await screen.findByRole('button', { name: 'Show details' }) + ); + expect( + await screen.findByTestId('isis-datafile-details-panel') + ).toBeInTheDocument(); }); }); diff --git a/packages/datagateway-dataview/src/views/table/isis/isisDatafilesTable.component.tsx b/packages/datagateway-dataview/src/views/table/isis/isisDatafilesTable.component.tsx index 38a10a528..bb70f301f 100644 --- a/packages/datagateway-dataview/src/views/table/isis/isisDatafilesTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/isis/isisDatafilesTable.component.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import SubjectIcon from '@material-ui/icons/Subject'; -import ExploreIcon from '@material-ui/icons/Explore'; -import SaveIcon from '@material-ui/icons/Save'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; +import SubjectIcon from '@mui/icons-material/Subject'; +import ExploreIcon from '@mui/icons-material/Explore'; +import SaveIcon from '@mui/icons-material/Save'; +import CalendarTodayIcon from '@mui/icons-material/CalendarToday'; import { Table, TableActionProps, @@ -23,19 +23,21 @@ import { ISISDatafileDetailsPanel, } from 'datagateway-common'; import { useTranslation } from 'react-i18next'; -import { useLocation } from 'react-router'; +import { useLocation } from 'react-router-dom'; import { useSelector } from 'react-redux'; import { StateType } from '../../../state/app.types'; import { IndexRange } from 'react-virtualized'; +import PreviewDatafileButton from '../../datafilePreview/previewDatafileButton.component'; interface ISISDatafilesTableProps { datasetId: string; + investigationId: string; } const ISISDatafilesTable = ( props: ISISDatafilesTableProps ): React.ReactElement => { - const { datasetId } = props; + const { datasetId, investigationId } = props; const [t] = useTranslation(); @@ -54,7 +56,7 @@ const ISISDatafilesTable = ( const dateFilter = useDateFilter(filters); const handleSort = useSort(); - const { data: allIds } = useIds( + const { data: allIds, isLoading: allIdsLoading } = useIds( 'datafile', [ { @@ -64,14 +66,11 @@ const ISISDatafilesTable = ( ], selectAllSetting ); - const { data: cartItems } = useCart(); - const { mutate: addToCart, isLoading: addToCartLoading } = useAddToCart( - 'datafile' - ); - const { - mutate: removeFromCart, - isLoading: removeFromCartLoading, - } = useRemoveFromCart('datafile'); + const { data: cartItems, isLoading: cartLoading } = useCart(); + const { mutate: addToCart, isLoading: addToCartLoading } = + useAddToCart('datafile'); + const { mutate: removeFromCart, isLoading: removeFromCartLoading } = + useRemoveFromCart('datafile'); const { data: totalDataCount } = useDatafileCount([ { @@ -103,10 +102,28 @@ const ISISDatafilesTable = ( [fetchNextPage] ); - const aggregatedData: Datafile[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + /* istanbul ignore next */ + const aggregatedData: Datafile[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } + + return []; + }, [data]); + + const isParentSelected = React.useMemo(() => { + return cartItems?.some( + (cartItem) => + (cartItem.entityType === 'dataset' && + cartItem.entityId.toString() === datasetId) || + (cartItem.entityType === 'investigation' && + cartItem.entityId.toString() === investigationId) + ); + }, [cartItems, datasetId, investigationId]); const columns: ColumnType[] = React.useMemo( () => [ @@ -157,7 +174,13 @@ const ISISDatafilesTable = ( return (
( ), + ({ rowData }: TableActionProps) => ( + + ), ]} columns={columns} /> diff --git a/packages/datagateway-dataview/src/views/table/isis/isisDatasetsTable.component.test.tsx b/packages/datagateway-dataview/src/views/table/isis/isisDatasetsTable.component.test.tsx index 362fd33d6..bc503c5d4 100644 --- a/packages/datagateway-dataview/src/views/table/isis/isisDatasetsTable.component.test.tsx +++ b/packages/datagateway-dataview/src/views/table/isis/isisDatasetsTable.component.test.tsx @@ -1,29 +1,36 @@ -import React from 'react'; -import { createMount } from '@material-ui/core/test-utils'; +import * as React from 'react'; import ISISDatasetsTable from './isisDatasetsTable.component'; import { initialState as dgDataViewInitialState } from '../../../state/reducers/dgdataview.reducer'; import configureStore from 'redux-mock-store'; -import { StateType } from '../../../state/app.types'; +import type { StateType } from '../../../state/app.types'; import { + type Dataset, dGCommonInitialState, + useAddToCart, + useCart, useDatasetCount, + useDatasetsInfinite, useIds, - useCart, - useAddToCart, useRemoveFromCart, - useDatasetsInfinite, - Dataset, - useDatasetSizes, - DownloadButton, - ISISDatasetDetailsPanel, - Table, } from 'datagateway-common'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; -import { Router } from 'react-router'; +import { generatePath, Router } from 'react-router-dom'; import { QueryClient, QueryClientProvider } from 'react-query'; -import { ReactWrapper } from 'enzyme'; -import { createMemoryHistory, History } from 'history'; +import { + render, + type RenderResult, + screen, + waitFor, +} from '@testing-library/react'; +import { createMemoryHistory, type History } from 'history'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, +} from '../../../setupTests'; +import type { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; +import { paths } from '../../../page/pageContainer.component'; jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -37,33 +44,23 @@ jest.mock('datagateway-common', () => { useCart: jest.fn(), useAddToCart: jest.fn(), useRemoveFromCart: jest.fn(), - useDatasetSizes: jest.fn(), }; }); describe('ISIS Dataset table component', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let rowData: Dataset[]; let history: History; + let user: UserEvent; - const createWrapper = ( - element: React.ReactElement = ( - - ) - ): ReactWrapper => { + const renderComponent = (): RenderResult => { const store = mockStore(state); - return mount( + return render( - {element} + @@ -71,7 +68,6 @@ describe('ISIS Dataset table component', () => { }; beforeEach(() => { - mount = createMount(); rowData = [ { id: 1, @@ -81,9 +77,17 @@ describe('ISIS Dataset table component', () => { createTime: '2019-07-23', }, ]; - history = createMemoryHistory(); + history = createMemoryHistory({ + initialEntries: [ + generatePath(paths.toggle.isisDataset, { + instrumentId: '1', + investigationId: '3', + facilityCycleId: '2', + }), + ], + }); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgdataview: dgDataViewInitialState, @@ -93,6 +97,7 @@ describe('ISIS Dataset table component', () => { (useCart as jest.Mock).mockReturnValue({ data: [], + isLoading: false, }); (useDatasetCount as jest.Mock).mockReturnValue({ data: 0, @@ -103,6 +108,7 @@ describe('ISIS Dataset table component', () => { }); (useIds as jest.Mock).mockReturnValue({ data: [1], + isLoading: false, }); (useAddToCart as jest.Mock).mockReturnValue({ mutate: jest.fn(), @@ -112,127 +118,63 @@ describe('ISIS Dataset table component', () => { mutate: jest.fn(), isLoading: false, }); - (useDatasetSizes as jest.Mock).mockReturnValue({ data: 1 }); }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); - - it('calls the correct data fetching hooks on load', () => { - const investigationId = '3'; - createWrapper(); - expect(useDatasetCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: investigationId }, - }), - }, - ]); - expect(useDatasetsInfinite).toHaveBeenCalledWith( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: investigationId }, - }), - }, - ], - expect.any(Boolean) - ); - expect(useDatasetSizes).toHaveBeenCalledWith({ - pages: [rowData], - }); - expect(useIds).toHaveBeenCalledWith( - 'dataset', - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigation.id': { eq: parseInt(investigationId) }, - }), - }, - ], - true - ); - expect(useCart).toHaveBeenCalled(); - expect(useAddToCart).toHaveBeenCalledWith('dataset'); - expect(useRemoveFromCart).toHaveBeenCalledWith('dataset'); - }); - - it('calls useDatasetsInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useDatasetsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); - - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); + it('updates filter query params on text filter', async () => { + renderComponent(); - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by datasets.name', + hidden: true, }); - }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + await user.type(filterInput, 'test'); - const filterInput = wrapper - .find('[aria-label="Filter by datasets.name"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); - - expect(history.length).toBe(2); + expect(history.length).toBe(5); expect(history.location.search).toBe( `?filters=${encodeURIComponent( '{"name":{"value":"test","type":"include"}}' )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); - expect(history.length).toBe(3); + expect(history.length).toBe(6); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const filterInput = wrapper.find( - 'input[id="datasets.modified_time filter to"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'datasets.modified_time filter to', + }); + + await user.type(filterInput, '2019-08-06'); - expect(history.length).toBe(2); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"modTime":{"endDate":"2019-08-06"}}')}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.length).toBe(3); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"createTime":"desc"}')}` @@ -247,13 +189,10 @@ describe('ISIS Dataset table component', () => { ); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + await user.click(await screen.findByText('datasets.name')); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -261,20 +200,22 @@ describe('ISIS Dataset table component', () => { ); }); - it('calls addToCart mutate function on unchecked checkbox click', () => { + it('calls addToCart mutate function on unchecked checkbox click', async () => { const addToCart = jest.fn(); (useAddToCart as jest.Mock).mockReturnValue({ mutate: addToCart, loading: false, }); - const wrapper = createWrapper(); + renderComponent(); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + await user.click( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ); expect(addToCart).toHaveBeenCalledWith([1]); }); - it('calls removeFromCart mutate function on checked checkbox click', () => { + it('calls removeFromCart mutate function on checked checkbox click', async () => { (useCart as jest.Mock).mockReturnValue({ data: [ { @@ -285,6 +226,7 @@ describe('ISIS Dataset table component', () => { parentEntities: [], }, ], + isLoading: false, }); const removeFromCart = jest.fn(); @@ -293,14 +235,16 @@ describe('ISIS Dataset table component', () => { loading: false, }); - const wrapper = createWrapper(); + renderComponent(); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + await user.click( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ); expect(removeFromCart).toHaveBeenCalledWith([1]); }); - it('selected rows only considers relevant cart items', () => { + it('selected rows only considers relevant cart items', async () => { (useCart as jest.Mock).mockReturnValueOnce({ data: [ { @@ -318,88 +262,80 @@ describe('ISIS Dataset table component', () => { parentEntities: [], }, ], + isLoading: false, }); - const wrapper = createWrapper(); + renderComponent(); - const selectAllCheckbox = wrapper - .find('[aria-label="select all rows"]') - .first(); + const selectAllCheckbox = await screen.findByRole('checkbox', { + name: 'select all rows', + }); - expect(selectAllCheckbox.prop('checked')).toEqual(false); - expect(selectAllCheckbox.prop('data-indeterminate')).toEqual(false); + expect(selectAllCheckbox).not.toBeChecked(); + expect(selectAllCheckbox).toHaveAttribute('data-indeterminate', 'false'); }); - it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', () => { + it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', async () => { state.dgdataview.selectAllSetting = false; + renderComponent(); - const wrapper = createWrapper(); - - expect(useIds).toHaveBeenCalledWith('dataset', expect.anything(), false); - expect(useIds).not.toHaveBeenCalledWith('dataset', expect.anything(), true); - expect(wrapper.exists('[aria-label="select all rows"]')).toBe(false); + await waitFor(() => { + expect( + screen.queryByRole('checkbox', { name: 'select all rows' }) + ).toBeNull(); + }); }); - it('displays details panel when expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(ISISDatasetDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); + it('displays details panel when expanded', async () => { + renderComponent(); + + await user.click( + await screen.findByRole('button', { name: 'Show details' }) + ); - expect(wrapper.find(ISISDatasetDetailsPanel).exists()).toBeTruthy(); + expect( + await screen.findByTestId('isis-dataset-details-panel') + ).toBeInTheDocument(); }); - it('renders details panel with datasets link and can navigate', () => { - const wrapper = createWrapper(); + it('renders details panel with datasets link and can navigate', async () => { + renderComponent(); - const detailsPanelWrapper = createWrapper( - wrapper.find(Table).prop('detailsPanel')({ - rowData: rowData[0], - detailsPanelResize: jest.fn(), - }) + await user.click( + await screen.findByRole('button', { name: 'Show details' }) + ); + + await user.click( + await screen.findByRole('tab', { name: 'datasets.details.datafiles' }) ); - detailsPanelWrapper - .find('#dataset-datafiles-tab') - .first() - .simulate('click'); expect(history.location.pathname).toBe( '/browse/instrument/1/facilityCycle/2/investigation/3/dataset/1/datafile' ); }); it('renders dataset name as a link', () => { - const wrapper = createWrapper(); - - expect( - wrapper.find('[aria-colindex=3]').find('p').children() - ).toMatchSnapshot(); + renderComponent(); + expect(screen.getByText('Test 1')).toMatchSnapshot(); }); - it('renders dataset name as a link in StudyHierarchy', () => { - const store = mockStore(state); - const wrapper = mount( - - - - - - - + it('renders dataset name as a link in data publication hierarchy', () => { + history.replace( + generatePath(paths.dataPublications.toggle.isisDataset, { + instrumentId: '1', + investigationId: '3', + dataPublicationId: '2', + }) ); + renderComponent(); - expect( - wrapper.find('[aria-colindex=3]').find('p').children() - ).toMatchSnapshot(); + expect(screen.getByText('Test 1')).toMatchSnapshot(); }); - it('renders actions correctly', () => { - const wrapper = createWrapper(); - - expect(wrapper.find(DownloadButton).exists()).toBeTruthy(); + it('renders actions correctly', async () => { + renderComponent(); + expect( + await screen.findByRole('button', { name: 'buttons.download' }) + ).toBeInTheDocument(); }); }); diff --git a/packages/datagateway-dataview/src/views/table/isis/isisDatasetsTable.component.tsx b/packages/datagateway-dataview/src/views/table/isis/isisDatasetsTable.component.tsx index 02cd0fa62..498dae595 100644 --- a/packages/datagateway-dataview/src/views/table/isis/isisDatasetsTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/isis/isisDatasetsTable.component.tsx @@ -1,13 +1,13 @@ import React from 'react'; -import SubjectIcon from '@material-ui/icons/Subject'; -import SaveIcon from '@material-ui/icons/Save'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; +import SubjectIcon from '@mui/icons-material/Subject'; +import SaveIcon from '@mui/icons-material/Save'; +import CalendarTodayIcon from '@mui/icons-material/CalendarToday'; import { Table, tableLink, TableActionProps, Dataset, - formatCountOrSize, + formatBytes, useDatasetCount, useDatasetsInfinite, parseSearchToQuery, @@ -19,36 +19,23 @@ import { useCart, useAddToCart, useRemoveFromCart, - useDatasetSizes, DownloadButton, ISISDatasetDetailsPanel, } from 'datagateway-common'; import { TableCellProps, IndexRange } from 'react-virtualized'; import { useTranslation } from 'react-i18next'; -import { useLocation, useHistory } from 'react-router'; +import { useLocation, useHistory } from 'react-router-dom'; import { useSelector } from 'react-redux'; import { StateType } from '../../../state/app.types'; interface ISISDatasetsTableProps { - instrumentId: string; - instrumentChildId: string; investigationId: string; - studyHierarchy: boolean; } const ISISDatasetsTable = ( props: ISISDatasetsTableProps ): React.ReactElement => { - const { - investigationId, - instrumentChildId, - instrumentId, - studyHierarchy, - } = props; - - const pathRoot = studyHierarchy ? 'browseStudyHierarchy' : 'browse'; - const instrumentChild = studyHierarchy ? 'study' : 'facilityCycle'; - const urlPrefix = `/${pathRoot}/instrument/${instrumentId}/${instrumentChild}/${instrumentChildId}/investigation/${investigationId}/dataset`; + const { investigationId } = props; const [t] = useTranslation(); @@ -69,7 +56,7 @@ const ISISDatasetsTable = ( const dateFilter = useDateFilter(filters); const handleSort = useSort(); - const { data: allIds } = useIds( + const { data: allIds, isLoading: allIdsLoading } = useIds( 'dataset', [ { @@ -81,14 +68,11 @@ const ISISDatasetsTable = ( ], selectAllSetting ); - const { data: cartItems } = useCart(); - const { mutate: addToCart, isLoading: addToCartLoading } = useAddToCart( - 'dataset' - ); - const { - mutate: removeFromCart, - isLoading: removeFromCartLoading, - } = useRemoveFromCart('dataset'); + const { data: cartItems, isLoading: cartLoading } = useCart(); + const { mutate: addToCart, isLoading: addToCartLoading } = + useAddToCart('dataset'); + const { mutate: removeFromCart, isLoading: removeFromCartLoading } = + useRemoveFromCart('dataset'); const { data: totalDataCount } = useDatasetCount([ { @@ -124,12 +108,26 @@ const ISISDatasetsTable = ( [fetchNextPage] ); - const sizeQueries = useDatasetSizes(data); - - const aggregatedData: Dataset[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + /* istanbul ignore next */ + const aggregatedData: Dataset[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } + + return []; + }, [data]); + + const isParentSelected = React.useMemo(() => { + return cartItems?.some( + (cartItem) => + cartItem.entityType === 'investigation' && + cartItem.entityId.toString() === investigationId + ); + }, [cartItems, investigationId]); const columns: ColumnType[] = React.useMemo( () => [ @@ -139,7 +137,7 @@ const ISISDatasetsTable = ( dataKey: 'name', cellContentRenderer: (cellProps: TableCellProps) => tableLink( - `${urlPrefix}/${cellProps.rowData.id}`, + `${location.pathname}/${cellProps.rowData.id}`, cellProps.rowData.name, view ), @@ -150,7 +148,7 @@ const ISISDatasetsTable = ( label: t('datasets.size'), dataKey: 'size', cellContentRenderer: (cellProps: TableCellProps): number | string => - formatCountOrSize(sizeQueries[cellProps.rowIndex], true), + formatBytes(cellProps.rowData.fileSize), disableSort: true, }, { @@ -167,7 +165,7 @@ const ISISDatasetsTable = ( filterComponent: dateFilter, }, ], - [t, textFilter, dateFilter, urlPrefix, view, sizeQueries] + [t, textFilter, dateFilter, view, location.pathname] ); const selectedRows = React.useMemo( @@ -189,15 +187,23 @@ const ISISDatasetsTable = ( push(`${urlPrefix}/${id}/datafile`)} + viewDatafiles={(id: number) => + push(`${location.pathname}/${id}/datafile`) + } /> ), - [push, urlPrefix] + [location.pathname, push] ); return (
), ]} diff --git a/packages/datagateway-dataview/src/views/table/isis/isisFacilityCyclesTable.component.test.tsx b/packages/datagateway-dataview/src/views/table/isis/isisFacilityCyclesTable.component.test.tsx index ce2d83508..2e0096080 100644 --- a/packages/datagateway-dataview/src/views/table/isis/isisFacilityCyclesTable.component.test.tsx +++ b/packages/datagateway-dataview/src/views/table/isis/isisFacilityCyclesTable.component.test.tsx @@ -1,21 +1,35 @@ -import React from 'react'; -import { createMount } from '@material-ui/core/test-utils'; +import * as React from 'react'; import ISISFacilityCyclesTable from './isisFacilityCyclesTable.component'; import { initialState as dgDataViewInitialState } from '../../../state/reducers/dgdataview.reducer'; -import { StateType } from '../../../state/app.types'; +import type { StateType } from '../../../state/app.types'; import { - FacilityCycle, + dGCommonInitialState, + type FacilityCycle, useFacilityCycleCount, useFacilityCyclesInfinite, - dGCommonInitialState, } from 'datagateway-common'; -import { ReactWrapper } from 'enzyme'; import configureStore from 'redux-mock-store'; import { QueryClient, QueryClientProvider } from 'react-query'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; -import { Router } from 'react-router'; -import { createMemoryHistory, History } from 'history'; +import { Router } from 'react-router-dom'; +import { createMemoryHistory, type History } from 'history'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, + findAllRows, + findCellInRow, + findColumnHeaderByName, + findColumnIndexByName, +} from '../../../setupTests'; +import { + render, + type RenderResult, + screen, + within, +} from '@testing-library/react'; +import { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -29,16 +43,16 @@ jest.mock('datagateway-common', () => { }); describe('ISIS FacilityCycles table component', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let rowData: FacilityCycle[]; let history: History; let replaceSpy: jest.SpyInstance; + let user: UserEvent; - const createWrapper = (): ReactWrapper => { + const renderComponent = (): RenderResult => { const store = mockStore(state); - return mount( + return render( @@ -50,7 +64,6 @@ describe('ISIS FacilityCycles table component', () => { }; beforeEach(() => { - mount = createMount(); rowData = [ { id: 1, @@ -62,8 +75,8 @@ describe('ISIS FacilityCycles table component', () => { ]; history = createMemoryHistory(); replaceSpy = jest.spyOn(history, 'replace'); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgdataview: dgDataViewInitialState, @@ -82,91 +95,108 @@ describe('ISIS FacilityCycles table component', () => { }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); + it('renders correctly', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - const instrumentId = '1'; - createWrapper(); - expect(useFacilityCycleCount).toHaveBeenCalledWith(parseInt(instrumentId)); - expect(useFacilityCyclesInfinite).toHaveBeenCalledWith( - parseInt(instrumentId), - expect.any(Boolean) - ); - }); + const rows = await findAllRows(); + // should have 1 row in the table + expect(rows).toHaveLength(1); - it('calls useFacilityCyclesInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useFacilityCyclesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); + // check that column headers are shown correctly. + expect( + await findColumnHeaderByName('facilitycycles.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('facilitycycles.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('facilitycycles.end_date') + ).toBeInTheDocument(); - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); + const row = rows[0]; - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, - }); + // check that every cell contains the correct value + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('facilitycycles.name'), + }) + ).getByText('Test 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('facilitycycles.start_date'), + }) + ).getByText('2019-07-03') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('facilitycycles.end_date'), + }) + ).getByText('2019-07-04') + ).toBeInTheDocument(); }); - it('sends filterTable action on text filter', () => { - const wrapper = createWrapper(); + it('sends filterTable action on text filter', async () => { + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by facilitycycles.name', + hidden: true, + }); - const filterInput = wrapper - .find('[aria-label="Filter by facilitycycles.name"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + await user.type(filterInput, 'test'); - expect(history.length).toBe(2); + // user.type inputs the given string character by character to simulate user typing + // each keystroke of user.type creates a new entry in the history stack + // so the initial entry + 4 characters in "test" = 5 entries + expect(history.length).toBe(5); expect(history.location.search).toBe( `?filters=${encodeURIComponent( '{"name":{"value":"test","type":"include"}}' )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); - expect(history.length).toBe(3); + expect(history.length).toBe(6); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const filterInput = wrapper.find( - 'input[id="facilitycycles.end_date filter to"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'facilitycycles.end_date filter to', + }); + + await user.type(filterInput, '2019-08-06'); expect(history.length).toBe(2); expect(history.location.search).toBe( `?filters=${encodeURIComponent('{"endDate":{"endDate":"2019-08-06"}}')}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.length).toBe(3); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(replaceSpy).toHaveBeenCalledWith({ search: `?sort=${encodeURIComponent('{"startDate":"desc"}')}`, @@ -184,13 +214,10 @@ describe('ISIS FacilityCycles table component', () => { ); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + await user.click(await screen.findByText('facilitycycles.name')); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -198,18 +225,15 @@ describe('ISIS FacilityCycles table component', () => { ); }); - it('renders facilitycycle name as a link', () => { - const wrapper = createWrapper(); - - expect( - wrapper.find('[aria-colindex=1]').find('p').children() - ).toMatchSnapshot(); + it('renders facilitycycle name as a link', async () => { + renderComponent(); + expect(await screen.findByText('Test 1')).toMatchSnapshot(); }); it('renders fine with incomplete data', () => { (useFacilityCycleCount as jest.Mock).mockReturnValueOnce({}); (useFacilityCyclesInfinite as jest.Mock).mockReturnValueOnce({}); - expect(() => createWrapper()).not.toThrowError(); + expect(() => renderComponent()).not.toThrowError(); }); }); diff --git a/packages/datagateway-dataview/src/views/table/isis/isisFacilityCyclesTable.component.tsx b/packages/datagateway-dataview/src/views/table/isis/isisFacilityCyclesTable.component.tsx index fed442967..4162b212d 100644 --- a/packages/datagateway-dataview/src/views/table/isis/isisFacilityCyclesTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/isis/isisFacilityCyclesTable.component.tsx @@ -14,8 +14,7 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { IndexRange, TableCellProps } from 'react-virtualized'; import { useLocation } from 'react-router-dom'; -import SubjectIcon from '@material-ui/icons/Subject'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; +import { Subject, CalendarToday } from '@mui/icons-material'; interface ISISFacilityCyclesTableProps { instrumentId: string; @@ -34,10 +33,6 @@ const ISISFacilityCyclesTable = ( [location.search] ); - const { data: totalDataCount } = useFacilityCycleCount( - parseInt(instrumentId) - ); - // isMounted is used to disable queries when the component isn't fully mounted. // It prevents the request being sent twice if default sort is set. // It is not needed for cards/tables that don't have default sort. @@ -46,15 +41,26 @@ const ISISFacilityCyclesTable = ( setIsMounted(true); }, []); + const { data: totalDataCount } = useFacilityCycleCount( + parseInt(instrumentId) + ); const { fetchNextPage, data } = useFacilityCyclesInfinite( parseInt(instrumentId), isMounted ); - const aggregatedData: FacilityCycle[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + /* istanbul ignore next */ + const aggregatedData: FacilityCycle[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } + + return []; + }, [data]); const textFilter = useTextFilter(filters); const dateFilter = useDateFilter(filters); @@ -68,7 +74,7 @@ const ISISFacilityCyclesTable = ( const columns: ColumnType[] = React.useMemo( () => [ { - icon: SubjectIcon, + icon: Subject, label: t('facilitycycles.name'), dataKey: 'name', cellContentRenderer: (cellProps: TableCellProps) => @@ -80,14 +86,14 @@ const ISISFacilityCyclesTable = ( filterComponent: textFilter, }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('facilitycycles.start_date'), dataKey: 'startDate', filterComponent: dateFilter, defaultSort: 'desc', }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('facilitycycles.end_date'), dataKey: 'endDate', filterComponent: dateFilter, diff --git a/packages/datagateway-dataview/src/views/table/isis/isisInstrumentsTable.component.test.tsx b/packages/datagateway-dataview/src/views/table/isis/isisInstrumentsTable.component.test.tsx index a90f25034..219df0a25 100644 --- a/packages/datagateway-dataview/src/views/table/isis/isisInstrumentsTable.component.test.tsx +++ b/packages/datagateway-dataview/src/views/table/isis/isisInstrumentsTable.component.test.tsx @@ -1,22 +1,33 @@ -import React from 'react'; -import { createMount } from '@material-ui/core/test-utils'; +import * as React from 'react'; import ISISInstrumentsTable from './isisInstrumentsTable.component'; import { initialState as dgDataViewInitialState } from '../../../state/reducers/dgdataview.reducer'; import { StateType } from '../../../state/app.types'; import { + dGCommonInitialState, Instrument, useInstrumentCount, useInstrumentsInfinite, - dGCommonInitialState, - ISISInstrumentDetailsPanel, } from 'datagateway-common'; -import { ReactWrapper } from 'enzyme'; import configureStore from 'redux-mock-store'; import { QueryClient, QueryClientProvider } from 'react-query'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; -import { Router } from 'react-router'; +import { Router } from 'react-router-dom'; import { createMemoryHistory, History } from 'history'; +import { + render, + type RenderResult, + screen, + within, +} from '@testing-library/react'; +import { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; +import { + findAllRows, + findCellInRow, + findColumnHeaderByName, + findColumnIndexByName, +} from '../../../setupTests'; jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -30,19 +41,19 @@ jest.mock('datagateway-common', () => { }); describe('ISIS Instruments table component', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let rowData: Instrument[]; let history: History; + let user: UserEvent; - const createWrapper = (studyHierarchy = false): ReactWrapper => { + const renderComponent = (dataPublication = false): RenderResult => { const store = mockStore(state); - return mount( + return render( - + @@ -50,7 +61,6 @@ describe('ISIS Instruments table component', () => { }; beforeEach(() => { - mount = createMount(); rowData = [ { id: 1, @@ -58,17 +68,19 @@ describe('ISIS Instruments table component', () => { fullName: 'Test instrument 1', description: 'foo bar', url: 'test url', + type: 'type1', }, { id: 2, name: 'Test 2', description: 'foo bar', url: 'test url', + type: 'type2', }, ]; history = createMemoryHistory(); + user = userEvent.setup(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgdataview: dgDataViewInitialState, @@ -87,64 +99,86 @@ describe('ISIS Instruments table component', () => { }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); + it('renders correctly', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - createWrapper(); - expect(useInstrumentCount).toHaveBeenCalled(); - expect(useInstrumentsInfinite).toHaveBeenCalled(); - }); + const rows = await findAllRows(); + // should have 2 rows in the table + expect(rows).toHaveLength(2); - it('calls useInstrumentsInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useInstrumentsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); - - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); + // check that column headers are shown correctly. + expect( + await findColumnHeaderByName('instruments.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('instruments.type') + ).toBeInTheDocument(); - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, - }); + // check that every cell contains the correct value + const firstRow = rows[0]; + expect( + within( + findCellInRow(firstRow, { + columnIndex: await findColumnIndexByName('instruments.name'), + }) + ).getByText('Test instrument 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(firstRow, { + columnIndex: await findColumnIndexByName('instruments.type'), + }) + ).getByText('type1') + ).toBeInTheDocument(); + + const secondRow = rows[1]; + expect( + within( + findCellInRow(secondRow, { + columnIndex: await findColumnIndexByName('instruments.name'), + }) + ).getByText('Test 2') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(secondRow, { + columnIndex: await findColumnIndexByName('instruments.type'), + }) + ).getByText('type2') + ).toBeInTheDocument(); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); - const filterInput = wrapper.find('input').first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by instruments.name', + hidden: true, + }); - expect(history.length).toBe(2); + await user.type(filterInput, 'test'); + + // user.type inputs the given string character by character to simulate user typing + // each keystroke of user.type creates a new entry in the history stack + // so the initial entry + 4 characters in "test" = 5 entries + expect(history.length).toBe(5); expect(history.location.search).toBe( `?filters=${encodeURIComponent( '{"fullName":{"value":"test","type":"include"}}' )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); - expect(history.length).toBe(3); + expect(history.length).toBe(6); expect(history.location.search).toBe('?'); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"fullName":"asc"}')}` @@ -156,13 +190,10 @@ describe('ISIS Instruments table component', () => { expect(useInstrumentsInfinite).toHaveBeenLastCalledWith(undefined, true); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + await user.click(await screen.findByText('instruments.name')); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -170,34 +201,44 @@ describe('ISIS Instruments table component', () => { ); }); - it('displays details panel when expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(ISISInstrumentDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); + it('displays details panel when expanded', async () => { + renderComponent(); - expect(wrapper.find(ISISInstrumentDetailsPanel).exists()).toBeTruthy(); - }); - - it('renders names as links when NOT in studyHierarchy', () => { - const wrapper = createWrapper(); + await user.click( + ( + await screen.findAllByRole('button', { name: 'Show details' }) + )[0] + ); expect( - wrapper.find('[aria-colindex=2]').find('p').children() - ).toMatchSnapshot(); + await screen.findByTestId('instrument-details-panel') + ).toBeInTheDocument(); }); - it('renders names as links in StudyHierarchy', () => { - const wrapper = createWrapper(true); + it('renders names as links when NOT in studyHierarchy', async () => { + renderComponent(); + expect( + await screen.findByRole('link', { name: 'Test instrument 1' }) + ).toBeInTheDocument(); + expect( + await screen.findByRole('link', { name: 'Test 2' }) + ).toBeInTheDocument(); + }); + it('renders names as links in StudyHierarchy', async () => { + renderComponent(true); + expect( + await screen.findByRole('link', { name: 'Test instrument 1' }) + ).toBeInTheDocument(); expect( - wrapper.find('[aria-colindex=2]').find('p').children() - ).toMatchSnapshot(); + await screen.findByRole('link', { name: 'Test 2' }) + ).toBeInTheDocument(); }); it('renders fine with incomplete data', () => { (useInstrumentCount as jest.Mock).mockReturnValueOnce({}); (useInstrumentsInfinite as jest.Mock).mockReturnValueOnce({}); - expect(() => createWrapper()).not.toThrowError(); + expect(() => renderComponent()).not.toThrowError(); }); }); diff --git a/packages/datagateway-dataview/src/views/table/isis/isisInstrumentsTable.component.tsx b/packages/datagateway-dataview/src/views/table/isis/isisInstrumentsTable.component.tsx index 3d2545339..4bbcbd668 100644 --- a/packages/datagateway-dataview/src/views/table/isis/isisInstrumentsTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/isis/isisInstrumentsTable.component.tsx @@ -13,17 +13,17 @@ import { import React from 'react'; import { useTranslation } from 'react-i18next'; import { IndexRange, TableCellProps } from 'react-virtualized'; -import SubjectIcon from '@material-ui/icons/Subject'; +import SubjectIcon from '@mui/icons-material/Subject'; import { useLocation } from 'react-router-dom'; interface ISISInstrumentsTableProps { - studyHierarchy: boolean; + dataPublication: boolean; } const ISISInstrumentsTable = ( props: ISISInstrumentsTableProps ): React.ReactElement => { - const { studyHierarchy } = props; + const { dataPublication } = props; const location = useLocation(); const [t] = useTranslation(); @@ -33,8 +33,6 @@ const ISISInstrumentsTable = ( [location.search] ); - const { data: totalDataCount } = useInstrumentCount(); - // isMounted is used to disable queries when the component isn't fully mounted. // It prevents the request being sent twice if default sort is set. // It is not needed for cards/tables that don't have default sort. @@ -43,12 +41,21 @@ const ISISInstrumentsTable = ( setIsMounted(true); }, []); + const { data: totalDataCount } = useInstrumentCount(); const { fetchNextPage, data } = useInstrumentsInfinite(undefined, isMounted); - const aggregatedData: Instrument[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + /* istanbul ignore next */ + const aggregatedData: Instrument[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } + + return []; + }, [data]); const textFilter = useTextFilter(filters); const handleSort = useSort(); @@ -59,8 +66,10 @@ const ISISInstrumentsTable = ( ); const columns: ColumnType[] = React.useMemo(() => { - const pathRoot = studyHierarchy ? 'browseStudyHierarchy' : 'browse'; - const instrumentChild = studyHierarchy ? 'study' : 'facilityCycle'; + const pathRoot = dataPublication ? 'browseDataPublications' : 'browse'; + const instrumentChild = dataPublication + ? 'dataPublication' + : 'facilityCycle'; return [ { icon: SubjectIcon, @@ -85,7 +94,7 @@ const ISISInstrumentsTable = ( filterComponent: textFilter, }, ]; - }, [t, textFilter, view, studyHierarchy]); + }, [t, textFilter, view, dataPublication]); return (
{ - const originalModule = jest.requireActual('datagateway-common'); - - return { - __esModule: true, - ...originalModule, - useISISInvestigationCount: jest.fn(), - useISISInvestigationsInfinite: jest.fn(), - useInvestigationSizes: jest.fn(), - useISISInvestigationIds: jest.fn(), - useCart: jest.fn(), - useAddToCart: jest.fn(), - useRemoveFromCart: jest.fn(), - useInvestigationDetails: jest.fn(), - }; -}); +import { createMemoryHistory, type History } from 'history'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, + findAllRows, + findCellInRow, + findColumnHeaderByName, + findColumnIndexByName, + findRowAt, +} from '../../../setupTests'; +import { + render, + type RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; +import type { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; +import axios, { AxiosResponse } from 'axios'; +import { paths } from '../../../page/pageContainer.component'; describe('ISIS Investigations table component', () => { - let mount; - let mockStore; + const mockStore = configureStore([thunk]); let state: StateType; let rowData: Investigation[]; let history: History; let replaceSpy: jest.SpyInstance; + let user: UserEvent; + let cartItems: DownloadCartItem[]; + let holder: HTMLElement; - const createWrapper = ( - element: React.ReactElement = ( - - ) - ): ReactWrapper => { + const renderComponent = (): RenderResult => { const store = mockStore(state); - return mount( + return render( - {element} + @@ -73,12 +58,14 @@ describe('ISIS Investigations table component', () => { }; beforeEach(() => { - mount = createMount(); + cartItems = []; rowData = [ { id: 1, title: 'Test 1', name: 'Test 1', + fileSize: 1, + fileCount: 1, summary: 'foo bar', visitId: '1', doi: 'doi 1', @@ -95,12 +82,41 @@ describe('ISIS Investigations table component', () => { user: { id: 3, name: 'testpi', fullName: 'Test PI' }, }, ], - studyInvestigations: [ + dataCollectionInvestigations: [ { - id: 6, - study: { - id: 7, - pid: 'study pid', + id: 1, + dataCollection: { + id: 14, + dataPublications: [ + { + id: 15, + pid: 'Investigation Data Publication Pid', + description: 'Investigation Data Publication description', + title: 'Investigation Data Publication', + type: { + id: 16, + name: 'investigation', + }, + }, + ], + }, + }, + { + id: 1, + dataCollection: { + id: 11, + dataPublications: [ + { + id: 12, + pid: 'Data Publication Pid', + description: 'Data Publication description', + title: 'Data Publication', + type: { + id: 13, + name: 'study', + }, + }, + ], }, }, ], @@ -108,10 +124,21 @@ describe('ISIS Investigations table component', () => { endDate: '2019-06-11', }, ]; - history = createMemoryHistory(); + history = createMemoryHistory({ + initialEntries: [ + generatePath(paths.toggle.isisInvestigation, { + instrumentId: '4', + facilityCycleId: '5', + }), + ], + }); replaceSpy = jest.spyOn(history, 'replace'); + user = userEvent.setup(); + + holder = document.createElement('div'); + holder.setAttribute('id', 'datagateway-dataview'); + document.body.appendChild(holder); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgdataview: dgDataViewInitialState, @@ -119,143 +146,215 @@ describe('ISIS Investigations table component', () => { }) ); - (useCart as jest.Mock).mockReturnValue({ - data: [], - }); - (useISISInvestigationCount as jest.Mock).mockReturnValue({ - data: 0, - }); - (useISISInvestigationsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - (useInvestigationSizes as jest.Mock).mockReturnValue([ - { - data: 1, - }, - ]); - (useISISInvestigationIds as jest.Mock).mockReturnValue({ - data: [1], - }); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); - (useInvestigationDetails as jest.Mock).mockReturnValue({ - data: [], - }); + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + if (/\/user\/cart\/$/.test(url)) { + // fetch download cart + return Promise.resolve({ + data: { cartItems }, + }); + } + + if (/\/user\/getSize$/.test(url)) { + // fetch investigation size + return Promise.resolve({ + data: 1, + }); + } + + if (/\/investigations$/.test(url)) { + return Promise.resolve({ + data: rowData, + }); + } + + if (/\/investigations\/count$/.test(url)) { + return Promise.resolve({ + data: rowData.length, + }); + } + + return Promise.reject(`Endpoint not mocked: ${url}`); + }); + + axios.post = jest + .fn() + .mockImplementation( + (url: string, data: unknown): Promise> => { + if (/\/user\/cart\/\/cartItems$/.test(url)) { + const isRemove: boolean = JSON.parse( + (data as URLSearchParams).get('remove') ?? 'false' + ); + + if (isRemove) { + cartItems = []; + + return Promise.resolve({ + data: { + cartItems: [], + }, + }); + } + + cartItems = [ + ...cartItems, + { + id: 123, + entityId: 1, + entityType: 'investigation', + name: 'download cart item name', + parentEntities: [], + }, + ]; + + return Promise.resolve({ + data: { cartItems }, + }); + } + + return Promise.reject(`Endpoint not mocked: ${url}`); + } + ); }); afterEach(() => { - mount.cleanUp(); + document.body.removeChild(holder); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); + it('renders correctly', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - const studyHierarchy = false; - const instrumentId = '4'; - const instrumentChildId = '5'; - createWrapper(); - expect(useISISInvestigationCount).toHaveBeenCalledWith( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy - ); - expect(useISISInvestigationsInfinite).toHaveBeenCalledWith( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy, - expect.any(Boolean) - ); - expect(useInvestigationSizes).toHaveBeenCalledWith({ - pages: [rowData], - }); - expect(useISISInvestigationIds).toHaveBeenCalledWith( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy, - true - ); - expect(useCart).toHaveBeenCalled(); - expect(useAddToCart).toHaveBeenCalledWith('investigation'); - expect(useRemoveFromCart).toHaveBeenCalledWith('investigation'); - }); - - it('calls useISISInvestigationsInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useISISInvestigationsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, + let rows: HTMLElement[] = []; + await waitFor(async () => { + rows = await findAllRows(); + // should have 1 row in the table + expect(rows).toHaveLength(1); }); - const wrapper = createWrapper(); - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); + // check that column headers are shown correctly. + expect( + await findColumnHeaderByName('investigations.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.doi') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.principal_investigators') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.end_date') + ).toBeInTheDocument(); - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, - }); - }); + const row = rows[0]; - it('displays DOI and renders the expected Link ', () => { - const wrapper = createWrapper(); + // check that every cell contains the correct value + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.title'), + }) + ).getByText('Test 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.name'), + }) + ).getByText('Test 1') + ).toBeInTheDocument(); expect( - wrapper - .find('[data-testid="isis-investigation-table-doi-link"]') - .first() - .text() - ).toEqual('study pid'); + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.doi'), + }) + ).getByText('Data Publication Pid') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.size'), + }) + ).getByText('1 B') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName( + 'investigations.principal_investigators' + ), + }) + ).getByText('Test PI') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.start_date'), + }) + ).getByText('2019-06-10') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.end_date'), + }) + ).getByText('2019-06-11') + ).toBeInTheDocument(); + }); + it('displays DOI and renders the expected Link ', async () => { + renderComponent(); expect( - wrapper - .find('[data-testid="isis-investigation-table-doi-link"]') - .first() - .prop('href') - ).toEqual('https://doi.org/study pid'); + await screen.findByRole('link', { name: 'Data Publication Pid' }) + ).toHaveAttribute('href', 'https://doi.org/Data Publication Pid'); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on text filter', async () => { + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by investigations.name', + hidden: true, + }); - const filterInput = wrapper - .find('[aria-label="Filter by investigations.name"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + await user.type(filterInput, 'test'); - expect(history.length).toBe(2); + // user.type inputs the given string character by character to simulate user typing + // each keystroke of user.type creates a new entry in the history stack + // so the initial entry + 4 characters in "test" = 5 entries + expect(history.length).toBe(5); expect(history.location.search).toBe( `?filters=${encodeURIComponent( '{"name":{"value":"test","type":"include"}}' )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); - expect(history.length).toBe(3); + expect(history.length).toBe(6); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const filterInput = wrapper.find( - 'input[id="investigations.start_date filter from"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'investigations.start_date filter from', + }); + + await user.type(filterInput, '2019-08-06'); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -264,49 +363,38 @@ describe('ISIS Investigations table component', () => { )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.length).toBe(3); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(replaceSpy).toHaveBeenCalledWith({ search: `?sort=${encodeURIComponent('{"startDate":"desc"}')}`, }); - const studyHierarchy = false; - const instrumentId = '4'; - const instrumentChildId = '5'; - // check that the data request is sent only once after mounting - expect(useISISInvestigationsInfinite).toHaveBeenCalledTimes(2); - expect(useISISInvestigationsInfinite).toHaveBeenCalledWith( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy, - false - ); - expect(useISISInvestigationsInfinite).toHaveBeenCalledWith( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy, - true + const datafilesCalls = (axios.get as jest.Mock).mock.calls.filter( + (call) => call[0] === '/investigations' ); + // 2 becasue there is also a call for ids + expect(datafilesCalls).toHaveLength(2); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'investigations.title' }) + ); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -314,210 +402,180 @@ describe('ISIS Investigations table component', () => { ); }); - it('calls addToCart mutate function on unchecked checkbox click', () => { - const addToCart = jest.fn(); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: addToCart, - loading: false, - }); - const wrapper = createWrapper(); - - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); - - expect(addToCart).toHaveBeenCalledWith([1]); - }); + it('adds selected row to cart if unselected; removes it from cart otherwise', async () => { + renderComponent(); - it('calls removeFromCart mutate function on checked checkbox click', () => { - (useCart as jest.Mock).mockReturnValue({ - data: [ - { - entityId: 1, - entityType: 'investigation', - id: 1, - name: 'test', - parentEntities: [], - }, - ], + // wait for rows to show up + await waitFor(async () => { + expect(await findAllRows()).toHaveLength(1); }); - const removeFromCart = jest.fn(); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: removeFromCart, - loading: false, - }); + // row should not be selected initially as the cart is empty + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).not.toBeChecked(); - const wrapper = createWrapper(); + // select the row + await user.click( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ); + + // investigation should be added to the cart + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).toBeChecked(); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + // unselect the row + await user.click(screen.getByRole('checkbox', { name: 'select row 0' })); - expect(removeFromCart).toHaveBeenCalledWith([1]); + // investigation should be removed from the cart + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).not.toBeChecked(); }); - it('selected rows only considers relevant cart items', () => { - (useCart as jest.Mock).mockReturnValueOnce({ - data: [ - { - entityId: 2, - entityType: 'investigation', - id: 1, - name: 'test', - parentEntities: [], - }, - { - entityId: 1, - entityType: 'dataset', - id: 2, - name: 'test', - parentEntities: [], - }, - ], - }); + it('selected rows only considers relevant cart items', async () => { + cartItems = [ + { + entityId: 2, + entityType: 'investigation', + id: 1, + name: 'test', + parentEntities: [], + }, + { + entityId: 1, + entityType: 'dataset', + id: 2, + name: 'test', + parentEntities: [], + }, + ]; - const wrapper = createWrapper(); + renderComponent(); - const selectAllCheckbox = wrapper - .find('[aria-label="select all rows"]') - .first(); + const selectAllCheckbox = await screen.findByRole('checkbox', { + name: 'select all rows', + }); - expect(selectAllCheckbox.prop('checked')).toEqual(false); - expect(selectAllCheckbox.prop('data-indeterminate')).toEqual(false); + expect(selectAllCheckbox).not.toBeChecked(); + expect(selectAllCheckbox).toHaveAttribute('data-indeterminate', 'false'); }); - it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', () => { + it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', async () => { state.dgdataview.selectAllSetting = false; - - const wrapper = createWrapper(); - - expect(useISISInvestigationIds).toHaveBeenCalledWith(4, 5, false, false); - expect(useISISInvestigationIds).not.toHaveBeenCalledWith(4, 5, false, true); - expect(wrapper.exists('[aria-label="select all rows"]')).toBe(false); - }); - - it('displays details panel when expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); - - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeTruthy(); + renderComponent(); + await waitFor(() => { + expect( + screen.queryByRole('button', { name: 'select all rows' }) + ).toBeNull(); + }); }); - it('renders details panel with datasets link and can navigate', () => { - const wrapper = createWrapper(); - - const detailsPanelWrapper = createWrapper( - wrapper.find(Table).prop('detailsPanel')({ - rowData: rowData[0], - detailsPanelResize: jest.fn(), - }) + it('displays details panel when expanded', async () => { + renderComponent(); + await user.click( + await screen.findByRole('button', { name: 'Show details' }) ); + expect( + await screen.findByTestId('isis-investigation-details-panel') + ).toBeTruthy(); + }); - detailsPanelWrapper - .find('#investigation-datasets-tab') - .first() - .simulate('click'); - expect(history.location.pathname).toBe( - '/browse/instrument/4/facilityCycle/5/investigation/1/dataset' + it('renders title and DOI as links', async () => { + renderComponent(); + expect(await screen.findByRole('link', { name: 'Test 1' })).toHaveAttribute( + 'href', + '/browse/instrument/4/facilityCycle/5/investigation/1' ); + expect( + await screen.findByRole('link', { name: 'Data Publication Pid' }) + ).toHaveAttribute('href', 'https://doi.org/Data Publication Pid'); }); - it('renders title, name and DOI as links', () => { - const wrapper = createWrapper(); + it('displays the correct user as the PI ', async () => { + renderComponent(); - expect( - wrapper.find('[aria-colindex=3]').find('p').children() - ).toMatchSnapshot(); + const piColumnIndex = await findColumnIndexByName( + 'investigations.principal_investigators' + ); - expect( - wrapper.find('[aria-colindex=4]').find('p').children() - ).toMatchSnapshot(); + const row = await findRowAt(0); expect( - wrapper.find('[aria-colindex=5]').find('p').children() - ).toMatchSnapshot(); + await findCellInRow(row, { columnIndex: piColumnIndex }) + ).toHaveTextContent('Test PI'); }); - it('renders title, name and DOI as links in StudyHierarchy', () => { - const store = mockStore(state); - const wrapper = mount( - - - - - - - - ); - - expect( - wrapper.find('[aria-colindex=3]').find('p').children() - ).toMatchSnapshot(); + it('gracefully handles empty Study Investigation and investigationUsers', async () => { + rowData = [ + { + ...rowData[0], + investigationUsers: [], + dataCollectionInvestigations: [], + }, + ]; - expect( - wrapper.find('[aria-colindex=4]').find('p').children() - ).toMatchSnapshot(); + renderComponent(); - expect( - wrapper.find('[aria-colindex=5]').find('p').children() - ).toMatchSnapshot(); - }); - - it('displays the correct user as the PI ', () => { - const wrapper = createWrapper(); - expect(wrapper.find('[aria-colindex=7]').find('p').text()).toEqual( - 'Test PI' - ); + await waitFor(async () => { + expect(await findAllRows()).toHaveLength(1); + }); }); - it('gracefully handles empty Study Investigation and investigationUsers, missing Study from Study Investigation object and missing User from investigationUsers object', () => { - (useISISInvestigationsInfinite as jest.Mock).mockReturnValue({ - data: { - pages: [ + it('gracefully handles missing data collection from data collection Investigations object and missing User from investigationUsers object', async () => { + rowData = [ + { + ...rowData[0], + investigationUsers: [ { - ...rowData[0], - investigationUsers: [], - studyInvestigations: [], + id: 1, + role: '', }, ], - }, - fetchNextPage: jest.fn(), - }); - - let wrapper = createWrapper(); - expect(() => wrapper).not.toThrowError(); - - (useISISInvestigationsInfinite as jest.Mock).mockClear(); - (useISISInvestigationsInfinite as jest.Mock).mockReturnValue({ - data: { - pages: [ + dataCollectionInvestigations: [ { - ...rowData[0], - investigationUsers: [ - { - id: 1, - }, - ], - studyInvestigations: [ - { - id: 6, - }, - ], + id: 6, }, ], }, - fetchNextPage: jest.fn(), - }); + ]; + + renderComponent(); + + const doiColumnIndex = await findColumnIndexByName('investigations.doi'); + const piColumnIndex = await findColumnIndexByName( + 'investigations.principal_investigators' + ); + + // verify that the doi cell and the principal investigator cell in the row are empty + const row = await findRowAt(0); - wrapper = createWrapper(); - expect(wrapper.find('[aria-colindex=5]').find('p').text()).toEqual(''); - expect(wrapper.find('[aria-colindex=7]').find('p').text()).toEqual(''); + expect( + await findCellInRow(row, { columnIndex: doiColumnIndex }) + ).toHaveTextContent(''); + expect( + await findCellInRow(row, { columnIndex: piColumnIndex }) + ).toHaveTextContent(''); }); - it('renders actions correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find(DownloadButton).exists()).toBeTruthy(); + it('renders actions correctly', async () => { + renderComponent(); + + // find the action column + const actionsColumnIndex = await findColumnIndexByName('Actions'); + + // make sure all rows have the download button + const rows = await findAllRows(); + for (const row of rows) { + const actionCell = await findCellInRow(row, { + columnIndex: actionsColumnIndex, + }); + expect( + await within(actionCell).findByRole('button', { + name: 'buttons.download', + }) + ).toBeInTheDocument(); + } }); }); diff --git a/packages/datagateway-dataview/src/views/table/isis/isisInvestigationsTable.component.tsx b/packages/datagateway-dataview/src/views/table/isis/isisInvestigationsTable.component.tsx index 5a73bf9fc..327f46472 100644 --- a/packages/datagateway-dataview/src/views/table/isis/isisInvestigationsTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/isis/isisInvestigationsTable.component.tsx @@ -1,50 +1,50 @@ import { - formatCountOrSize, + CalendarToday, + Fingerprint, + Person, + Public, + Save, + Subject, +} from '@mui/icons-material'; +import { + AdditionalFilters, + ColumnType, + DownloadButton, + externalSiteLink, + formatBytes, Investigation, + ISISInvestigationDetailsPanel, + parseSearchToQuery, Table, + TableActionProps, tableLink, - externalSiteLink, - useISISInvestigationsInfinite, - useISISInvestigationCount, - useISISInvestigationIds, - ColumnType, - parseSearchToQuery, useAddToCart, useCart, useDateFilter, - useInvestigationSizes, + useIds, + useInvestigationCount, + useInvestigationsInfinite, usePrincipalExperimenterFilter, - useSort, useRemoveFromCart, + useSort, useTextFilter, - TableActionProps, - DownloadButton, - ISISInvestigationDetailsPanel, } from 'datagateway-common'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import { useSelector } from 'react-redux'; +import { useHistory, useLocation } from 'react-router-dom'; import { IndexRange, TableCellProps } from 'react-virtualized'; import { StateType } from '../../../state/app.types'; -import SubjectIcon from '@material-ui/icons/Subject'; -import FingerprintIcon from '@material-ui/icons/Fingerprint'; -import PublicIcon from '@material-ui/icons/Public'; -import SaveIcon from '@material-ui/icons/Save'; -import PersonIcon from '@material-ui/icons/Person'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; -import { useSelector } from 'react-redux'; -import { useHistory, useLocation } from 'react-router'; - interface ISISInvestigationsTableProps { instrumentId: string; - instrumentChildId: string; - studyHierarchy: boolean; + facilityCycleId: string; } const ISISInvestigationsTable = ( props: ISISInvestigationsTableProps ): React.ReactElement => { - const { instrumentId, instrumentChildId, studyHierarchy } = props; + const { instrumentId, facilityCycleId } = props; const selectAllSetting = useSelector( (state: StateType) => state.dgdataview.selectAllSetting ); @@ -57,11 +57,24 @@ const ISISInvestigationsTable = ( [location.search] ); - const { data: totalDataCount } = useISISInvestigationCount( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy - ); + const investigationQueryFilters: AdditionalFilters = [ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'investigationInstruments.instrument.id': { + eq: parseInt(instrumentId), + }, + }), + }, + { + filterType: 'where', + filterValue: JSON.stringify({ + 'investigationFacilityCycles.facilityCycle.id': { + eq: parseInt(facilityCycleId), + }, + }), + }, + ]; // isMounted is used to disable queries when the component isn't fully mounted. // It prevents the request being sent twice if default sort is set. @@ -71,26 +84,42 @@ const ISISInvestigationsTable = ( setIsMounted(true); }, []); - const { fetchNextPage, data } = useISISInvestigationsInfinite( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy, + const { data: totalDataCount } = useInvestigationCount( + investigationQueryFilters + ); + const { fetchNextPage, data } = useInvestigationsInfinite( + [ + ...investigationQueryFilters, + { + filterType: 'include', + filterValue: JSON.stringify([ + { + investigationInstruments: 'instrument', + }, + { + dataCollectionInvestigations: { + dataCollection: { dataPublications: 'type' }, + }, + }, + { + investigationUsers: 'user', + }, + ]), + }, + ], + undefined, isMounted ); - const { data: allIds } = useISISInvestigationIds( - parseInt(instrumentId), - parseInt(instrumentChildId), - studyHierarchy, + const { data: allIds, isLoading: allIdsLoading } = useIds( + 'investigation', + investigationQueryFilters, selectAllSetting ); - const { data: cartItems } = useCart(); - const { mutate: addToCart, isLoading: addToCartLoading } = useAddToCart( - 'investigation' - ); - const { - mutate: removeFromCart, - isLoading: removeFromCartLoading, - } = useRemoveFromCart('investigation'); + const { data: cartItems, isLoading: cartLoading } = useCart(); + const { mutate: addToCart, isLoading: addToCartLoading } = + useAddToCart('investigation'); + const { mutate: removeFromCart, isLoading: removeFromCartLoading } = + useRemoveFromCart('investigation'); const selectedRows = React.useMemo( () => @@ -106,10 +135,18 @@ const ISISInvestigationsTable = ( [cartItems, selectAllSetting, allIds] ); - const aggregatedData: Investigation[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + /* istanbul ignore next */ + const aggregatedData: Investigation[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } + + return []; + }, [data]); const textFilter = useTextFilter(filters); const dateFilter = useDateFilter(filters); @@ -121,33 +158,29 @@ const ISISInvestigationsTable = ( [fetchNextPage] ); - const sizeQueries = useInvestigationSizes(data); - - const pathRoot = studyHierarchy ? 'browseStudyHierarchy' : 'browse'; - const instrumentChild = studyHierarchy ? 'study' : 'facilityCycle'; - const urlPrefix = `/${pathRoot}/instrument/${instrumentId}/${instrumentChild}/${instrumentChildId}/investigation`; - const detailsPanel = React.useCallback( ({ rowData, detailsPanelResize }) => ( push(`${urlPrefix}/${id}/dataset`)} + viewDatasets={(id: number) => + push(`${location.pathname}/${id}/dataset`) + } /> ), - [push, urlPrefix] + [push, location.pathname] ); const columns: ColumnType[] = React.useMemo( () => [ { - icon: SubjectIcon, + icon: Subject, label: t('investigations.title'), dataKey: 'title', cellContentRenderer: (cellProps: TableCellProps) => { const investigationData = cellProps.rowData as Investigation; return tableLink( - `${urlPrefix}/${investigationData.id}`, + `${location.pathname}/${investigationData.id}`, investigationData.title, view, 'isis-investigations-table-title' @@ -156,22 +189,29 @@ const ISISInvestigationsTable = ( filterComponent: textFilter, }, { - icon: FingerprintIcon, + icon: Fingerprint, label: t('investigations.name'), dataKey: 'name', filterComponent: textFilter, }, { - icon: PublicIcon, + icon: Public, label: t('investigations.doi'), - dataKey: 'studyInvestigations.study.pid', + dataKey: + 'dataCollectionInvestigations.dataCollection.dataPublications.pid', cellContentRenderer: (cellProps: TableCellProps) => { const investigationData = cellProps.rowData as Investigation; - if (investigationData?.studyInvestigations?.[0]?.study) { + const studyDataPublication = + investigationData.dataCollectionInvestigations?.filter( + (dci) => + dci.dataCollection?.dataPublications?.[0]?.type?.name === + 'study' + )?.[0]?.dataCollection?.dataPublications?.[0]; + if (studyDataPublication) { return externalSiteLink( - `https://doi.org/${investigationData.studyInvestigations[0].study.pid}`, - investigationData.studyInvestigations[0].study.pid, - 'isis-investigation-table-doi-link' + `https://doi.org/${studyDataPublication.pid}`, + studyDataPublication.pid, + 'isis-investigations-table-doi-link' ); } else { return ''; @@ -180,23 +220,24 @@ const ISISInvestigationsTable = ( filterComponent: textFilter, }, { - icon: SaveIcon, + icon: Save, label: t('investigations.size'), dataKey: 'size', cellContentRenderer: (cellProps: TableCellProps): number | string => - formatCountOrSize(sizeQueries[cellProps.rowIndex], true), + formatBytes(cellProps.rowData.fileSize), disableSort: true, }, { - icon: PersonIcon, + icon: Person, label: t('investigations.principal_investigators'), dataKey: 'investigationUsers.user.fullName', disableSort: true, cellContentRenderer: (cellProps: TableCellProps) => { const investigationData = cellProps.rowData as Investigation; - const principal_investigators = investigationData?.investigationUsers?.filter( - (iu) => iu.role === 'principal_experimenter' - ); + const principal_investigators = + investigationData?.investigationUsers?.filter( + (iu) => iu.role === 'principal_experimenter' + ); if (principal_investigators && principal_investigators.length !== 0) { return principal_investigators?.[0].user?.fullName; } else { @@ -206,14 +247,14 @@ const ISISInvestigationsTable = ( filterComponent: principalExperimenterFilter, }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('investigations.start_date'), dataKey: 'startDate', filterComponent: dateFilter, defaultSort: 'desc', }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('investigations.end_date'), dataKey: 'endDate', @@ -225,15 +266,19 @@ const ISISInvestigationsTable = ( textFilter, principalExperimenterFilter, dateFilter, - urlPrefix, + location.pathname, view, - sizeQueries, ] ); return (
), ]} diff --git a/packages/datagateway-dataview/src/views/table/isis/isisMyDataTable.component.test.tsx b/packages/datagateway-dataview/src/views/table/isis/isisMyDataTable.component.test.tsx index c64e819d9..96c18a7f4 100644 --- a/packages/datagateway-dataview/src/views/table/isis/isisMyDataTable.component.test.tsx +++ b/packages/datagateway-dataview/src/views/table/isis/isisMyDataTable.component.test.tsx @@ -1,10 +1,14 @@ -import { createMount } from '@material-ui/core/test-utils'; +import { + render, + type RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; import { dGCommonInitialState, - Investigation, - ISISInvestigationDetailsPanel, + type Investigation, readSciGatewayToken, - Table, useAddToCart, useAllFacilityCycles, useCart, @@ -12,21 +16,29 @@ import { useInvestigationCount, useInvestigationDetails, useInvestigationsInfinite, - useInvestigationSizes, useRemoveFromCart, } from 'datagateway-common'; -import { ReactWrapper } from 'enzyme'; -import { createMemoryHistory, History } from 'history'; -import React from 'react'; -import { QueryClientProvider, QueryClient } from 'react-query'; +import { createMemoryHistory, type History } from 'history'; +import * as React from 'react'; +import { QueryClient, QueryClientProvider } from 'react-query'; import { Provider } from 'react-redux'; -import { Router } from 'react-router'; -import { AnyAction } from 'redux'; +import { Router } from 'react-router-dom'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; -import { StateType } from '../../../state/app.types'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, + findAllRows, + findCellInRow, + findColumnHeaderByName, + findColumnIndexByName, + findRowAt, +} from '../../../setupTests'; +import type { StateType } from '../../../state/app.types'; import { initialState as dgDataViewInitialState } from '../../../state/reducers/dgdataview.reducer'; import ISISMyDataTable from './isisMyDataTable.component'; +import type { UserEvent } from '@testing-library/user-event/setup/setup'; +import userEvent from '@testing-library/user-event'; jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -48,18 +60,17 @@ jest.mock('datagateway-common', () => { }); describe('ISIS MyData table component', () => { - let mount; const mockStore = configureStore([thunk]); let state: StateType; let rowData: Investigation[]; let history: History; - let events: CustomEvent[] = []; + let user: UserEvent; - const createWrapper = ( + const renderComponent = ( element: React.ReactElement = - ): ReactWrapper => { + ): RenderResult => { const store = mockStore(state); - return mount( + return render( @@ -71,14 +82,8 @@ describe('ISIS MyData table component', () => { }; beforeEach(() => { - mount = createMount(); - events = []; history = createMemoryHistory(); - - document.dispatchEvent = (e: Event) => { - events.push(e as CustomEvent); - return true; - }; + user = userEvent.setup(); state = JSON.parse( JSON.stringify({ @@ -92,6 +97,8 @@ describe('ISIS MyData table component', () => { title: 'Test 1 title', name: 'Test 1 name', summary: 'foo bar', + fileSize: 1, + fileCount: 1, visitId: '1', doi: 'doi 1', investigationInstruments: [ @@ -100,25 +107,41 @@ describe('ISIS MyData table component', () => { instrument: { id: 3, name: 'LARMOR', + fullName: 'LARMORLARMOR', }, }, ], - studyInvestigations: [ + investigationFacilityCycles: [ { - id: 6, - study: { - id: 7, - pid: 'study pid', - name: 'study', - createTime: '2019-06-10', - modTime: '2019-06-10', + id: 192, + facilityCycle: { + id: 8, + name: 'Cycle name', + startDate: '2019-06-01', + endDate: '2019-07-01', }, + }, + ], + dataCollectionInvestigations: [ + { + id: 6, investigation: { id: 1, title: 'Test 1 title', name: 'Test 1 name', visitId: '1', }, + dataCollection: { + id: 11, + dataPublications: [ + { + id: 12, + pid: 'Data Publication Pid', + description: 'Data Publication description', + title: 'Data Publication', + }, + ], + }, }, ], startDate: '2019-06-10', @@ -128,6 +151,7 @@ describe('ISIS MyData table component', () => { (useCart as jest.Mock).mockReturnValue({ data: [], + isLoading: false, }); (useInvestigationCount as jest.Mock).mockReturnValue({ data: 0, @@ -136,13 +160,9 @@ describe('ISIS MyData table component', () => { data: { pages: [rowData] }, fetchNextPage: jest.fn(), }); - (useInvestigationSizes as jest.Mock).mockReturnValue([ - { - data: 1, - }, - ]); (useIds as jest.Mock).mockReturnValue({ data: [1], + isLoading: false, }); (useAddToCart as jest.Mock).mockReturnValue({ mutate: jest.fn(), @@ -152,16 +172,6 @@ describe('ISIS MyData table component', () => { mutate: jest.fn(), isLoading: false, }); - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 8, - name: 'Cycle name', - startDate: '2019-06-01', - endDate: '2019-07-01', - }, - ], - }); (readSciGatewayToken as jest.Mock).mockReturnValue({ username: 'testUser', }); @@ -171,124 +181,144 @@ describe('ISIS MyData table component', () => { }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); + it('renders correctly', async () => { + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - createWrapper(); - expect(useInvestigationCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigationUsers.user.name': { eq: 'testUser' }, - }), - }, - ]); - expect(useInvestigationsInfinite).toHaveBeenCalledWith( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigationUsers.user.name': { eq: 'testUser' }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify([ - { - investigationInstruments: 'instrument', - }, - { studyInvestigations: 'study' }, - ]), - }, - ], - undefined, - expect.any(Boolean) - ); - expect(useInvestigationSizes).toHaveBeenCalledWith({ - pages: [rowData], - }); - expect(useIds).toHaveBeenCalledWith( - 'investigation', - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigationUsers.user.name': { eq: 'testUser' }, - }), - }, - ], - true - ); - expect(useCart).toHaveBeenCalled(); - expect(useAddToCart).toHaveBeenCalledWith('investigation'); - expect(useRemoveFromCart).toHaveBeenCalledWith('investigation'); - expect(useAllFacilityCycles).toHaveBeenCalled(); + const rows = await findAllRows(); + expect(rows).toHaveLength(1); + + expect( + await findColumnHeaderByName('investigations.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.doi') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.visit_id') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.instrument') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.end_date') + ).toBeInTheDocument(); + + const row = rows[0]; + + // check that every cell contains the correct values + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.title'), + }) + ).getByText('Test 1 title') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.doi'), + }) + ).getByText('Data Publication Pid') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.visit_id'), + }) + ).getByText('1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.name'), + }) + ).getByText('Test 1 name') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.instrument'), + }) + ).getByText('LARMORLARMOR') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.size'), + }) + ).getByText('1 B') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.start_date'), + }) + ).getByText('2019-06-10') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.end_date'), + }) + ).getByText('2019-06-11') + ).toBeInTheDocument(); }); it('sorts by startDate desc on load', () => { - createWrapper(); - + renderComponent(); expect(history.location.search).toBe( `?sort=${encodeURIComponent(JSON.stringify({ startDate: 'desc' }))}` ); }); - it('calls useInvestigationsInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useInvestigationsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); - - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); + it('updates filter query params on text filter', async () => { + renderComponent(); - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, + const filterInput = await screen.findByRole('textbox', { + name: 'Filter by investigations.name', + hidden: true, }); - }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + await user.type(filterInput, 'test'); - const filterInput = wrapper - .find('[aria-label="Filter by investigations.name"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); - - expect(history.length).toBe(2); + // user.type inputs the given string character by character to simulate user typing + // each keystroke of user.type creates a new entry in the history stack + // so the initial entry + 4 characters in "test" = 5 entries + expect(history.length).toBe(5); expect(history.location.search).toBe( `?filters=${encodeURIComponent( '{"name":{"value":"test","type":"include"}}' )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + await user.clear(filterInput); - expect(history.length).toBe(3); + expect(history.length).toBe(6); expect(history.location.search).toBe('?'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('updates filter query params on date filter', async () => { + applyDatePickerWorkaround(); - const filterInput = wrapper.find( - 'input[id="investigations.start_date filter from"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + renderComponent(); + + const filterInput = await screen.findByRole('textbox', { + name: 'investigations.start_date filter from', + }); + + await user.type(filterInput, '2019-08-06'); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -297,17 +327,19 @@ describe('ISIS MyData table component', () => { )}` ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + // await user.clear(filterInput); + await user.click(filterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); expect(history.length).toBe(3); expect(history.location.search).toBe('?'); + + cleanupDatePickerWorkaround(); }); it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - + renderComponent(); expect(history.length).toBe(1); expect(history.location.search).toBe( `?sort=${encodeURIComponent('{"startDate":"desc"}')}` @@ -327,13 +359,12 @@ describe('ISIS MyData table component', () => { ); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('updates sort query params on sort', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'investigations.title' }) + ); expect(history.length).toBe(2); expect(history.location.search).toBe( @@ -341,20 +372,22 @@ describe('ISIS MyData table component', () => { ); }); - it('calls addToCart mutate function on unchecked checkbox click', () => { + it('calls addToCart mutate function on unchecked checkbox click', async () => { const addToCart = jest.fn(); (useAddToCart as jest.Mock).mockReturnValue({ mutate: addToCart, loading: false, }); - const wrapper = createWrapper(); + renderComponent(); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + await user.click( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ); expect(addToCart).toHaveBeenCalledWith([1]); }); - it('calls removeFromCart mutate function on checked checkbox click', () => { + it('calls removeFromCart mutate function on checked checkbox click', async () => { (useCart as jest.Mock).mockReturnValue({ data: [ { @@ -365,6 +398,7 @@ describe('ISIS MyData table component', () => { parentEntities: [], }, ], + isLoading: false, }); const removeFromCart = jest.fn(); @@ -373,14 +407,15 @@ describe('ISIS MyData table component', () => { loading: false, }); - const wrapper = createWrapper(); - - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + renderComponent(); + await user.click( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ); expect(removeFromCart).toHaveBeenCalledWith([1]); }); - it('selected rows only considers relevant cart items', () => { + it('selected rows only considers relevant cart items', async () => { (useCart as jest.Mock).mockReturnValue({ data: [ { @@ -398,113 +433,106 @@ describe('ISIS MyData table component', () => { parentEntities: [], }, ], + isLoading: false, }); - const wrapper = createWrapper(); + renderComponent(); - const selectAllCheckbox = wrapper - .find('[aria-label="select all rows"]') - .first(); + const selectAllCheckbox = await screen.findByRole('checkbox', { + name: 'select all rows', + }); - expect(selectAllCheckbox.prop('checked')).toEqual(false); - expect(selectAllCheckbox.prop('data-indeterminate')).toEqual(false); + expect(selectAllCheckbox).not.toBeChecked(); + expect(selectAllCheckbox).toHaveAttribute('data-indeterminate', 'false'); }); - it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', () => { + it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', async () => { state.dgdataview.selectAllSetting = false; - const wrapper = createWrapper(); + renderComponent(); - expect(useIds).toHaveBeenCalledWith( - 'investigation', - expect.anything(), - false - ); - expect(useIds).not.toHaveBeenCalledWith( - 'investigation', - expect.anything(), - true - ); - expect(wrapper.exists('[aria-label="select all rows"]')).toBe(false); + await waitFor(() => { + expect( + screen.queryByRole('checkbox', { name: 'select all rows' }) + ).toBeNull(); + }); }); - it('displays details panel when expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); + it('displays details panel when expanded', async () => { + renderComponent(); + + // find the first row + const row = await findRowAt(0); + + await user.click( + await within(row).findByRole('button', { name: 'Show details' }) + ); - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeTruthy(); + expect( + await screen.findByTestId('isis-investigation-details-panel') + ).toBeInTheDocument(); }); - it('displays details panel when more information is expanded and navigates to datasets view when tab clicked', () => { - const wrapper = createWrapper(); + it('displays details panel when more information is expanded and navigates to datasets view when tab clicked', async () => { + renderComponent(); + + // find the first row + const row = await findRowAt(0); + + await user.click( + await within(row).findByRole('button', { name: 'Show details' }) + ); - const detailsPanelWrapper = createWrapper( - wrapper.find(Table).prop('detailsPanel')({ - rowData: rowData[0], - detailsPanelResize: jest.fn(), + await user.click( + await screen.findByRole('tab', { + name: 'investigations.details.datasets', }) ); - detailsPanelWrapper - .find('#investigation-datasets-tab') - .first() - .simulate('click'); expect(history.location.pathname).toBe( '/browse/instrument/3/facilityCycle/8/investigation/1/dataset' ); }); - it('displays DOI and renders the expected Link ', () => { - const wrapper = createWrapper(); + it('displays DOI and renders the expected Link ', async () => { + renderComponent(); expect( - wrapper.find('[data-testid="isis-mydata-table-doi-link"]').first().text() - ).toEqual('study pid'); - - expect( - wrapper - .find('[data-testid="isis-mydata-table-doi-link"]') - .first() - .prop('href') - ).toEqual('https://doi.org/study pid'); + await screen.findByRole('link', { name: 'Data Publication Pid' }) + ).toHaveAttribute('href', 'https://doi.org/Data Publication Pid'); }); - it('renders details panel without datasets link if no facility cycles', () => { + it('renders details panel without datasets link if no facility cycles', async () => { (useAllFacilityCycles as jest.Mock).mockReturnValue({ data: undefined, }); - const wrapper = createWrapper(); + renderComponent(); - const detailsPanelWrapper = createWrapper( - wrapper.find(Table).prop('detailsPanel')({ - rowData: rowData[0], - }) - ); - - expect( - detailsPanelWrapper.find('#investigation-datasets-tab').length - ).toEqual(0); + await waitFor(() => { + expect( + screen.queryByRole('tab', { + name: 'investigations.details.datasets', + }) + ).toBeNull(); + }); }); - it('renders title and name as links', () => { - const wrapper = createWrapper(); - + it('renders title and name as links', async () => { + renderComponent(); expect( - wrapper.find('[aria-colindex=3]').find('p').children() - ).toMatchSnapshot(); - + await screen.findByRole('link', { name: 'Test 1 title' }) + ).toBeInTheDocument(); expect( - wrapper.find('[aria-colindex=6]').find('p').children() - ).toMatchSnapshot(); + await screen.findByRole('link', { name: 'Data Publication Pid' }) + ).toBeInTheDocument(); }); - it('gracefully handles empty arrays, missing Study from Study Investigation object and missing Instrument from InvestigationInstrument object and missing facility cycles', () => { + it('gracefully handles empty arrays', async () => { // check it doesn't error if arrays are empty rowData[0] = { ...rowData[0], investigationInstruments: [], - studyInvestigations: [], + dataCollectionInvestigations: [], }; (useInvestigationsInfinite as jest.Mock).mockReturnValue({ data: { pages: [rowData] }, @@ -513,31 +541,14 @@ describe('ISIS MyData table component', () => { (useAllFacilityCycles as jest.Mock).mockReturnValue({ data: [], }); - let wrapper = createWrapper(); - - expect(() => wrapper).not.toThrowError(); - - // check it renders plain text if valid facility cycle can't be found - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 9, - startDate: '2018-01-01', - endDate: '2019-01-01', - }, - ], - }); - wrapper = createWrapper(); - - expect(wrapper.find('[aria-colindex=3]').find('p').text()).toEqual( - 'Test 1 title' - ); + renderComponent(); - expect(wrapper.find('[aria-colindex=6]').find('p').text()).toEqual( - 'Test 1 name' - ); + const rows = await screen.findAllByRole('row'); + // 2 rows expected, 1 for the header row, and 1 for the items in rowData. + expect(rows).toHaveLength(2); + }); - // now check that blank is returned if objects are missing + it('gracefully handles missing Study from Study Investigation object and missing Instrument from InvestigationInstrument object', async () => { rowData[0] = { ...rowData[0], investigationInstruments: [ @@ -545,7 +556,7 @@ describe('ISIS MyData table component', () => { id: 1, }, ], - studyInvestigations: [ + dataCollectionInvestigations: [ { id: 6, }, @@ -555,10 +566,24 @@ describe('ISIS MyData table component', () => { data: { pages: [rowData] }, fetchNextPage: jest.fn(), }); - wrapper = createWrapper(); + renderComponent(); + + const doiColumnIndex = await findColumnIndexByName('investigations.doi'); + const instrumentColumnIndex = await findColumnIndexByName( + 'investigations.instrument' + ); - expect(wrapper.find('[aria-colindex=4]').find('p').text()).toEqual(''); + const rows = await screen.findAllByRole('row'); + // 2 rows expected, 1 for the header row, and 1 for the items in rowData. + expect(rows).toHaveLength(2); - expect(wrapper.find('[aria-colindex=7]').find('p').text()).toEqual(''); + const row = await findRowAt(0); + + expect( + findCellInRow(row, { columnIndex: doiColumnIndex }) + ).toHaveTextContent(''); + expect( + findCellInRow(row, { columnIndex: instrumentColumnIndex }) + ).toHaveTextContent(''); }); }); diff --git a/packages/datagateway-dataview/src/views/table/isis/isisMyDataTable.component.tsx b/packages/datagateway-dataview/src/views/table/isis/isisMyDataTable.component.tsx index 102d43799..938b2548a 100644 --- a/packages/datagateway-dataview/src/views/table/isis/isisMyDataTable.component.tsx +++ b/packages/datagateway-dataview/src/views/table/isis/isisMyDataTable.component.tsx @@ -1,39 +1,43 @@ +import { + Assessment, + CalendarToday, + Fingerprint, + Public, + Save, + Subject, +} from '@mui/icons-material'; import { ColumnType, - formatCountOrSize, + externalSiteLink, + FACILITY_NAME, + formatBytes, Investigation, + ISISInvestigationDetailsPanel, parseSearchToQuery, readSciGatewayToken, Table, tableLink, - externalSiteLink, useAddToCart, - useAllFacilityCycles, useCart, useDateFilter, useIds, useInvestigationCount, useInvestigationsInfinite, - useInvestigationSizes, - useSort, useRemoveFromCart, + useSort, useTextFilter, - ISISInvestigationDetailsPanel, +} from 'datagateway-common'; +import { + buildDatasetTableUrlForInvestigation, + buildInvestigationLandingUrl, } from 'datagateway-common'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import { useSelector } from 'react-redux'; +import { useHistory, useLocation } from 'react-router-dom'; import { IndexRange, TableCellProps } from 'react-virtualized'; import { StateType } from '../../../state/app.types'; -import SubjectIcon from '@material-ui/icons/Subject'; -import FingerprintIcon from '@material-ui/icons/Fingerprint'; -import PublicIcon from '@material-ui/icons/Public'; -import SaveIcon from '@material-ui/icons/Save'; -import AssessmentIcon from '@material-ui/icons/Assessment'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; -import { useSelector } from 'react-redux'; -import { useLocation, useHistory } from 'react-router'; - const ISISMyDataTable = (): React.ReactElement => { const selectAllSetting = useSelector( (state: StateType) => state.dgdataview.selectAllSetting @@ -48,15 +52,6 @@ const ISISMyDataTable = (): React.ReactElement => { [location.search] ); - const { data: totalDataCount } = useInvestigationCount([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'investigationUsers.user.name': { eq: username }, - }), - }, - ]); - // isMounted is used to disable queries when the component isn't fully mounted. // It prevents the request being sent twice if default sort is set. // It is not needed for cards/tables that don't have default sort. @@ -65,6 +60,14 @@ const ISISMyDataTable = (): React.ReactElement => { setIsMounted(true); }, []); + const { data: totalDataCount } = useInvestigationCount([ + { + filterType: 'where', + filterValue: JSON.stringify({ + 'investigationUsers.user.name': { eq: username }, + }), + }, + ]); const { fetchNextPage, data } = useInvestigationsInfinite( [ { @@ -79,14 +82,19 @@ const ISISMyDataTable = (): React.ReactElement => { { investigationInstruments: 'instrument', }, - { studyInvestigations: 'study' }, + { investigationFacilityCycles: 'facilityCycle' }, + { + dataCollectionInvestigations: { + dataCollection: 'dataPublications', + }, + }, ]), }, ], undefined, isMounted ); - const { data: allIds } = useIds( + const { data: allIds, isLoading: allIdsLoading } = useIds( 'investigation', [ { @@ -98,15 +106,11 @@ const ISISMyDataTable = (): React.ReactElement => { ], selectAllSetting ); - const { data: cartItems } = useCart(); - const { mutate: addToCart, isLoading: addToCartLoading } = useAddToCart( - 'investigation' - ); - const { - mutate: removeFromCart, - isLoading: removeFromCartLoading, - } = useRemoveFromCart('investigation'); - const { data: facilityCycles } = useAllFacilityCycles(); + const { data: cartItems, isLoading: cartLoading } = useCart(); + const { mutate: addToCart, isLoading: addToCartLoading } = + useAddToCart('investigation'); + const { mutate: removeFromCart, isLoading: removeFromCartLoading } = + useRemoveFromCart('investigation'); const selectedRows = React.useMemo( () => @@ -122,10 +126,18 @@ const ISISMyDataTable = (): React.ReactElement => { [cartItems, selectAllSetting, allIds] ); - const aggregatedData: Investigation[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + /* istanbul ignore next */ + const aggregatedData: Investigation[] = React.useMemo(() => { + if (data) { + if ('pages' in data) { + return data.pages.flat(); + } else if ((data as unknown) instanceof Array) { + return data; + } + } + + return []; + }, [data]); const textFilter = useTextFilter(filters); const dateFilter = useDateFilter(filters); @@ -136,79 +148,60 @@ const ISISMyDataTable = (): React.ReactElement => { [fetchNextPage] ); - const sizeQueries = useInvestigationSizes(data); - - const urlPrefix = React.useCallback( - (investigationData: Investigation): string => { - if ( - investigationData?.investigationInstruments?.[0]?.instrument && - facilityCycles - ) { - const facilityCycle = facilityCycles.find( - (facilitycycle) => - facilitycycle.startDate && - facilitycycle.endDate && - investigationData.startDate && - facilitycycle.startDate <= investigationData.startDate && - facilitycycle.endDate >= investigationData.startDate - ); - if (facilityCycle) { - return `/browse/instrument/${investigationData.investigationInstruments[0].instrument.id}/facilityCycle/${facilityCycle.id}/investigation`; - } - } - return ''; - }, - [facilityCycles] - ); - const detailsPanel = React.useCallback( - ({ rowData, detailsPanelResize }) => ( - - push(`${urlPrefix(rowData as Investigation)}/${id}/dataset`) - : undefined - } - /> - ), - [push, urlPrefix] + ({ rowData, detailsPanelResize }) => { + const datasetTableUrl = buildDatasetTableUrlForInvestigation({ + facilityName: FACILITY_NAME.isis, + investigation: rowData as Investigation, + }); + return ( + { + if (datasetTableUrl) push(datasetTableUrl); + }} + /> + ); + }, + [push] ); const columns: ColumnType[] = React.useMemo( () => [ { - icon: SubjectIcon, + icon: Subject, label: t('investigations.title'), dataKey: 'title', cellContentRenderer: (cellProps: TableCellProps) => { const investigationData = cellProps.rowData as Investigation; - const url = urlPrefix(investigationData); - if (url) { - return tableLink( - `${url}/${investigationData.id}`, - investigationData.title, - view, - 'isis-mydata-table-title' - ); - } else { - return investigationData.title; - } + const url = buildInvestigationLandingUrl(investigationData); + return url + ? tableLink( + url, + investigationData.title, + view, + 'isis-mydata-table-title' + ) + : investigationData.title; }, filterComponent: textFilter, }, { - icon: PublicIcon, + icon: Public, label: t('investigations.doi'), - dataKey: 'studyInvestigations.study.pid', + dataKey: + 'dataCollectionInvestigations.dataCollection.dataPublications.pid', cellContentRenderer: (cellProps: TableCellProps) => { const investigationData = cellProps.rowData as Investigation; - if (investigationData?.studyInvestigations?.[0]?.study) { + if ( + investigationData?.dataCollectionInvestigations?.[0]?.dataCollection + ?.dataPublications?.[0] + ) { return externalSiteLink( - `https://doi.org/${investigationData.studyInvestigations[0].study.pid}`, - investigationData.studyInvestigations[0].study.pid, + `https://doi.org/${investigationData.dataCollectionInvestigations?.[0]?.dataCollection?.dataPublications?.[0].pid}`, + investigationData.dataCollectionInvestigations?.[0] + ?.dataCollection?.dataPublications?.[0].pid, 'isis-mydata-table-doi-link' ); } else { @@ -218,32 +211,26 @@ const ISISMyDataTable = (): React.ReactElement => { filterComponent: textFilter, }, { - icon: FingerprintIcon, + icon: Fingerprint, label: t('investigations.visit_id'), dataKey: 'visitId', filterComponent: textFilter, }, { - icon: SubjectIcon, + icon: Subject, label: t('investigations.name'), dataKey: 'name', cellContentRenderer: (cellProps: TableCellProps) => { const investigationData = cellProps.rowData as Investigation; - const url = urlPrefix(investigationData); - if (url) { - return tableLink( - `${url}/${investigationData.id}`, - investigationData.name, - view - ); - } else { - return investigationData.name; - } + const url = buildInvestigationLandingUrl(investigationData); + return url + ? tableLink(url, investigationData.name, view) + : investigationData.name; }, filterComponent: textFilter, }, { - icon: AssessmentIcon, + icon: Assessment, label: t('investigations.instrument'), dataKey: 'investigationInstruments.instrument.fullName', cellContentRenderer: (cellProps: TableCellProps) => { @@ -251,40 +238,44 @@ const ISISMyDataTable = (): React.ReactElement => { if (investigationData?.investigationInstruments?.[0]?.instrument) { return investigationData.investigationInstruments[0].instrument .fullName; - } else { - return ''; } + return ''; }, filterComponent: textFilter, }, { - icon: SaveIcon, + icon: Save, label: t('investigations.size'), dataKey: 'size', cellContentRenderer: (cellProps: TableCellProps): number | string => - formatCountOrSize(sizeQueries[cellProps.rowIndex], true), + formatBytes(cellProps.rowData.fileSize), disableSort: true, }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('investigations.start_date'), dataKey: 'startDate', filterComponent: dateFilter, defaultSort: 'desc', }, { - icon: CalendarTodayIcon, + icon: CalendarToday, label: t('investigations.end_date'), dataKey: 'endDate', filterComponent: dateFilter, }, ], - [t, textFilter, dateFilter, urlPrefix, view, sizeQueries] + [t, textFilter, dateFilter, view] ); return (
{ - const originalModule = jest.requireActual('datagateway-common'); - - return { - __esModule: true, - ...originalModule, - useStudyCount: jest.fn(), - useStudiesInfinite: jest.fn(), - }; -}); - -describe('ISIS Studies table component', () => { - let mount; - let mockStore; - let state: StateType; - let rowData: Study[]; - let history: History; - - const createWrapper = (): ReactWrapper => { - const store = mockStore(state); - return mount( - - - - - - - - ); - }; - - beforeEach(() => { - mount = createMount(); - rowData = [ - { - id: 1, - pid: 'doi', - name: 'Test 1', - modTime: '2000-01-01', - createTime: '2000-01-01', - }, - ]; - history = createMemoryHistory(); - - mockStore = configureStore([thunk]); - state = JSON.parse( - JSON.stringify({ - dgdataview: dgDataViewInitialState, - dgcommon: dGCommonInitialState, - }) - ); - - (useStudyCount as jest.Mock).mockReturnValue({ - data: 1, - isLoading: false, - }); - - (useStudiesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - }); - - afterEach(() => { - mount.cleanUp(); - jest.clearAllMocks(); - }); - - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); - - it('calls the correct data fetching hooks on load', () => { - const instrumentId = '1'; - createWrapper(); - expect(useStudyCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'studyInvestigations.investigation.investigationInstruments.instrument.id': { - eq: instrumentId, - }, - }), - }, - { - filterType: 'where', - filterValue: JSON.stringify({ - 'studyInvestigations.investigation.releaseDate': { - lt: '2021-10-27 00:00:00', - }, - }), - }, - ]); - expect(useStudiesInfinite).toHaveBeenCalledWith( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'studyInvestigations.investigation.investigationInstruments.instrument.id': { - eq: instrumentId, - }, - }), - }, - { - filterType: 'where', - filterValue: JSON.stringify({ - 'studyInvestigations.investigation.releaseDate': { - lt: '2021-10-27 00:00:00', - }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - studyInvestigations: 'investigation', - }), - }, - ], - expect.any(Boolean) - ); - }); - - it('calls useStudiesInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useStudiesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); - - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); - - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, - }); - }); - - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); - - const filterInput = wrapper - .find('[aria-label="Filter by studies.name"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); - - expect(history.length).toBe(2); - expect(history.location.search).toBe( - `?filters=${encodeURIComponent( - '{"name":{"value":"test","type":"include"}}' - )}` - ); - filterInput.instance().value = ''; - filterInput.simulate('change'); - - expect(history.length).toBe(3); - expect(history.location.search).toBe('?'); - }); - - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); - - const filterInput = wrapper.find('input[id="studies.end_date filter to"]'); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); - - expect(history.length).toBe(2); - expect(history.location.search).toBe( - `?filters=${encodeURIComponent( - '{"studyInvestigations.investigation.endDate":{"endDate":"2019-08-06"}}' - )}` - ); - - filterInput.instance().value = ''; - filterInput.simulate('change'); - - expect(history.length).toBe(3); - expect(history.location.search).toBe('?'); - }); - - it('uses default sort', () => { - const wrapper = createWrapper(); - wrapper.update(); - - expect(history.length).toBe(1); - expect(history.location.search).toBe( - `?sort=${encodeURIComponent( - '{"studyInvestigations.investigation.startDate":"desc"}' - )}` - ); - - // check that the data request is sent only once after mounting - expect(useStudiesInfinite).toHaveBeenCalledTimes(2); - expect(useStudiesInfinite).toHaveBeenCalledWith(expect.anything(), false); - expect(useStudiesInfinite).toHaveBeenLastCalledWith( - expect.anything(), - true - ); - }); - - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); - - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); - - expect(history.length).toBe(2); - expect(history.location.search).toBe( - `?sort=${encodeURIComponent('{"name":"asc"}')}` - ); - }); - - it('renders studies name as a link', () => { - const wrapper = createWrapper(); - - expect( - wrapper.find('[aria-colindex=1]').find('p').children() - ).toMatchSnapshot(); - }); - - it('displays Experiment DOI (PID) and renders the expected Link ', () => { - rowData = [ - { - ...rowData[0], - studyInvestigations: [ - { - id: 2, - study: { - ...rowData[0], - }, - investigation: { - id: 3, - name: 'Test', - title: 'Test investigation', - visitId: '3', - startDate: '2021-08-19', - endDate: '2021-08-20', - }, - }, - ], - }, - ]; - (useStudiesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - - const wrapper = createWrapper(); - expect( - wrapper.find('[data-testid="isis-study-table-doi-link"]').first().text() - ).toEqual('doi'); - - expect( - wrapper - .find('[data-testid="isis-study-table-doi-link"]') - .first() - .prop('href') - ).toEqual('https://doi.org/doi'); - }); - - it('displays information from investigation when investigation present', () => { - rowData = [ - { - ...rowData[0], - studyInvestigations: [ - { - id: 2, - study: { - ...rowData[0], - }, - investigation: { - id: 3, - name: 'Test', - title: 'Test investigation', - visitId: '3', - startDate: '2021-08-19', - endDate: '2021-08-20', - }, - }, - ], - }, - ]; - (useStudiesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - - const wrapper = createWrapper(); - - expect(wrapper.find('[aria-colindex=2]').find('p').first().text()).toBe( - 'Test investigation' - ); - }); - - it('renders fine when investigation is undefined', () => { - rowData = [ - { - ...rowData[0], - studyInvestigations: [ - { - id: 2, - study: { - ...rowData[0], - }, - }, - ], - }, - ]; - (useStudiesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - - expect(() => createWrapper()).not.toThrowError(); - }); -}); diff --git a/packages/datagateway-dataview/src/views/table/isis/isisStudiesTable.component.tsx b/packages/datagateway-dataview/src/views/table/isis/isisStudiesTable.component.tsx deleted file mode 100644 index a25f701cd..000000000 --- a/packages/datagateway-dataview/src/views/table/isis/isisStudiesTable.component.tsx +++ /dev/null @@ -1,191 +0,0 @@ -import { - Table, - tableLink, - parseSearchToQuery, - useStudiesInfinite, - useStudyCount, - ColumnType, - getStudyInfoInvestigation, - Study, - useDateFilter, - useSort, - useTextFilter, - externalSiteLink, -} from 'datagateway-common'; -import React from 'react'; -import { useTranslation } from 'react-i18next'; -import { IndexRange, TableCellProps } from 'react-virtualized'; - -import PublicIcon from '@material-ui/icons/Public'; -import FingerprintIcon from '@material-ui/icons/Fingerprint'; -import SubjectIcon from '@material-ui/icons/Subject'; -import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; -import { useLocation } from 'react-router'; -import { format, set } from 'date-fns'; - -interface ISISStudiesTableProps { - instrumentId: string; -} - -const ISISStudiesTable = (props: ISISStudiesTableProps): React.ReactElement => { - const { instrumentId } = props; - - const location = useLocation(); - const [t] = useTranslation(); - - const { filters, view, sort } = React.useMemo( - () => parseSearchToQuery(location.search), - [location.search] - ); - - const unembargoDate = format( - // set s and ms to 0 to escape recursive loop of fetching data every time they change - set(new Date(), { seconds: 0, milliseconds: 0 }), - 'yyyy-MM-dd HH:mm:ss' - ); - - const { data: totalDataCount } = useStudyCount([ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'studyInvestigations.investigation.investigationInstruments.instrument.id': { - eq: instrumentId, - }, - }), - }, - { - filterType: 'where', - filterValue: JSON.stringify({ - // this matches the ISIS ICAT rule - 'studyInvestigations.investigation.releaseDate': { - lt: unembargoDate, - }, - }), - }, - ]); - - // isMounted is used to disable queries when the component isn't fully mounted. - // It prevents the request being sent twice if default sort is set. - // It is not needed for cards/tables that don't have default sort. - const [isMounted, setIsMounted] = React.useState(false); - React.useEffect(() => { - setIsMounted(true); - }, []); - - const { fetchNextPage, data } = useStudiesInfinite( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - 'studyInvestigations.investigation.investigationInstruments.instrument.id': { - eq: instrumentId, - }, - }), - }, - { - filterType: 'where', - filterValue: JSON.stringify({ - // this matches the ISIS ICAT rule - 'studyInvestigations.investigation.releaseDate': { - lt: unembargoDate, - }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - studyInvestigations: 'investigation', - }), - }, - ], - isMounted - ); - - const aggregatedData: Study[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); - - const textFilter = useTextFilter(filters); - const dateFilter = useDateFilter(filters); - const handleSort = useSort(); - - const loadMoreRows = React.useCallback( - (offsetParams: IndexRange) => fetchNextPage({ pageParam: offsetParams }), - [fetchNextPage] - ); - - const columns: ColumnType[] = React.useMemo(() => { - const pathRoot = 'browseStudyHierarchy'; - const instrumentChild = 'study'; - return [ - { - icon: FingerprintIcon, - label: t('studies.name'), - dataKey: 'name', - cellContentRenderer: (cellProps: TableCellProps) => - tableLink( - `/${pathRoot}/instrument/${instrumentId}/${instrumentChild}/${cellProps.rowData.id}`, - cellProps.rowData.name, - view - ), - filterComponent: textFilter, - }, - { - icon: SubjectIcon, - label: t('studies.title'), - dataKey: 'studyInvestigations.investigation.title', - cellContentRenderer: (cellProps: TableCellProps) => - getStudyInfoInvestigation(cellProps.rowData as Study)?.title ?? '', - filterComponent: textFilter, - }, - { - icon: PublicIcon, - label: t('studies.pid'), - dataKey: 'pid', - cellContentRenderer: (cellProps: TableCellProps) => { - const studyData = cellProps.rowData as Study; - if (studyData?.pid) { - return externalSiteLink( - `https://doi.org/${studyData.pid}`, - studyData.pid, - 'isis-study-table-doi-link' - ); - } - }, - filterComponent: textFilter, - }, - { - icon: CalendarTodayIcon, - label: t('studies.start_date'), - dataKey: 'studyInvestigations.investigation.startDate', - cellContentRenderer: (cellProps: TableCellProps) => - getStudyInfoInvestigation(cellProps.rowData as Study)?.startDate ?? - '', - filterComponent: dateFilter, - defaultSort: 'desc', - }, - { - icon: CalendarTodayIcon, - label: t('studies.end_date'), - dataKey: 'studyInvestigations.investigation.endDate', - cellContentRenderer: (cellProps: TableCellProps) => - getStudyInfoInvestigation(cellProps.rowData as Study)?.endDate ?? '', - filterComponent: dateFilter, - }, - ]; - }, [t, textFilter, dateFilter, instrumentId, view]); - - return ( -
- ); -}; - -export default ISISStudiesTable; diff --git a/packages/datagateway-dataview/tsconfig.json b/packages/datagateway-dataview/tsconfig.json index 4aea8e9b3..48b66a451 100644 --- a/packages/datagateway-dataview/tsconfig.json +++ b/packages/datagateway-dataview/tsconfig.json @@ -17,13 +17,10 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "react", + "jsx": "react-jsx", "noFallthroughCasesInSwitch": true }, "include": [ "src" ], - "exclude": [ - "**/?*test.*", - ] } diff --git a/packages/datagateway-download/cypress.config.ts b/packages/datagateway-download/cypress.config.ts new file mode 100644 index 000000000..1065a7aba --- /dev/null +++ b/packages/datagateway-download/cypress.config.ts @@ -0,0 +1,31 @@ +import { defineConfig } from 'cypress'; +export default defineConfig({ + chromeWebSecurity: false, + video: false, + retries: { + runMode: 3, + openMode: 1, + }, + e2e: { + setupNodeEvents(on, config) { + on('task', { + failed: require('cypress-failed-log/src/failed')(), + }); + on('before:browser:launch', (browser, launchOptions) => { + if (browser.family === 'chromium' && browser.name !== 'electron') { + // Set pointer type to fine so that date inputs work properly + launchOptions.args.push('--blink-settings=primaryPointerType=4'); + } + + if (browser.family === 'firefox') { + // Set pointer type to fine so that date inputs work properly + launchOptions.preferences['ui.primaryPointerCapabilities'] = 4; + } + + // whatever you return here becomes the launchOptions + return launchOptions; + }); + }, + baseUrl: 'http://127.0.0.1:3000', + }, +}); diff --git a/packages/datagateway-download/cypress.json b/packages/datagateway-download/cypress.json deleted file mode 100644 index a28eafb4e..000000000 --- a/packages/datagateway-download/cypress.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "baseUrl": "http://127.0.0.1:3000", - "chomeWebSecurity": false, - "video": false, - "retries": { - "runMode": 3, - "openMode": 1 - } -} diff --git a/packages/datagateway-download/cypress/e2e/DOIGenerationForm.cy.ts b/packages/datagateway-download/cypress/e2e/DOIGenerationForm.cy.ts new file mode 100644 index 000000000..94b3f544e --- /dev/null +++ b/packages/datagateway-download/cypress/e2e/DOIGenerationForm.cy.ts @@ -0,0 +1,222 @@ +describe('DOI Generation form', () => { + beforeEach(() => { + cy.intercept('GET', '**/topcat/user/cart/**').as('fetchCart'); + cy.intercept('GET', '**/topcat/user/downloads**').as('fetchDownloads'); + cy.login( + { username: 'Chris481', password: 'pw', mechanism: 'simple' }, + 'Chris481' + ); + cy.clearDownloadCart(); + + cy.seedMintCart().then(() => { + cy.visit('/download').wait('@fetchCart'); + }); + }); + + afterEach(() => { + cy.clearDownloadCart(); + }); + + // tidy up the data publications table + after(() => { + cy.clearDataPublications(); + }); + + it('should be able to mint a mintable cart', () => { + cy.get('[aria-label="Calculating"]', { timeout: 20000 }).should( + 'not.exist' + ); + + cy.contains('Generate DOI').click(); + cy.url().should('include', '/download/mint'); + + cy.contains('button', 'Accept').should('be.visible'); + }); + + it('should not be able to try and mint a cart directly', () => { + cy.visit('/download/mint'); + + cy.url().should('match', /\/download$/); + }); + + describe('Form tests', () => { + beforeEach(() => { + cy.get('[aria-label="Calculating"]', { timeout: 20000 }).should( + 'not.exist' + ); + + cy.contains('Generate DOI').click(); + cy.contains('button', 'Accept').click(); + }); + + it('should not let user generate DOI when fields are still unfilled', () => { + cy.contains('button', 'Generate DOI').should('be.disabled'); + }); + + it('should let user generate DOI when fields are filled', () => { + cy.contains('DOI Title').parent().find('input').type('Test title'); + cy.contains('DOI Description') + .parent() + .find('textarea') + .first() + .type('Test description'); + + cy.contains('button', 'Generate DOI').click(); + + cy.contains('Mint Confirmation').should('be.visible'); + cy.contains('Mint was successful', { timeout: 10000 }).should( + 'be.visible' + ); + cy.contains('View Data Publication').click(); + + cy.url().should('match', /\/browse\/dataPublication\/[0-9]+$/); + }); + + it('should let user add and remove creators', () => { + cy.contains('DOI Title').parent().find('input').type('Test title'); + cy.contains('DOI Description') + .parent() + .find('textarea') + .first() + .type('Test description'); + + // wait for users to load + cy.contains('button', 'Generate DOI').should('not.be.disabled'); + + cy.contains('Username').parent().find('input').type('Michael222'); + cy.contains('button', 'Add Creator').click(); + + // check we can't delete "ourselves" + cy.contains('Thomas') + .parent() + .contains('button', 'Delete') + .should('be.disabled'); + + cy.contains('Randy').should('be.visible'); + cy.contains('Randy').parent().contains('button', 'Delete').click(); + cy.contains('Randy').should('not.exist'); + + cy.contains('button', 'Generate DOI').should('not.be.disabled'); + }); + + it('should let user add contributors and select their contributor type', () => { + cy.contains('DOI Title').parent().find('input').type('Test title'); + cy.contains('DOI Description') + .parent() + .find('textarea') + .first() + .type('Test description'); + + // wait for users to load + cy.contains('button', 'Generate DOI').should('not.be.disabled'); + + cy.contains('Username').parent().find('input').type('Michael222'); + cy.contains('button', 'Add Contributor').click(); + + // shouldn't let users submit DOIs without selecting a contributor type + cy.contains('button', 'Generate DOI').should('be.disabled'); + + cy.contains('label', 'Contributor Type').parent().click(); + + cy.contains('DataCollector').click(); + + // check that contributor info doesn't break the API + cy.contains('button', 'Generate DOI').click(); + + cy.contains('Mint was successful', { timeout: 10000 }).should( + 'be.visible' + ); + }); + + it('should not let user add invalid/duplicate Data Publication users', () => { + cy.contains('DOI Title').parent().find('input').type('Test title'); + cy.contains('DOI Description') + .parent() + .find('textarea') + .first() + .type('Test description'); + + // wait for users to load + cy.contains('button', 'Generate DOI').should('not.be.disabled'); + + cy.get('table[aria-labelledby="creators-label"] tbody tr').should( + 'have.length', + 1 + ); + + cy.contains('Username').parent().find('input').type('Chris481'); + cy.contains('button', 'Add Creator').click(); + + cy.get('table[aria-labelledby="creators-label"] tbody tr').should( + 'have.length', + 1 + ); + cy.contains('Cannot add duplicate user').should('be.visible'); + + cy.contains('Username').parent().find('input').type('invalid'); + cy.contains('button', 'Add Creator').click(); + cy.get('table[aria-labelledby="creators-label"] tbody tr').should( + 'have.length', + 1 + ); + cy.contains("No record found: name='invalid' in User").should( + 'be.visible' + ); + + cy.contains('button', 'Generate DOI').should('not.be.disabled'); + }); + + it('should let user add related DOIs and select their relation & resource type', () => { + cy.contains('DOI Title').parent().find('input').type('Test title'); + cy.contains('DOI Description') + .parent() + .find('textarea') + .first() + .type('Test description'); + + // wait for users to load + cy.contains('button', 'Generate DOI').should('not.be.disabled'); + + // DOI from https://support.datacite.org/docs/testing-guide + cy.contains(/^DOI$/).parent().find('input').type('10.17596/w76y-4s92'); + cy.contains('button', 'Add DOI').click(); + + // shouldn't let users submit DOIs without selecting a relation or resource type + cy.contains('button', 'Generate DOI').should('be.disabled'); + + cy.contains('label', 'Resource Type').parent().click(); + + cy.contains('Journal').click(); + + // shouldn't let users submit DOIs without selecting a relation type + cy.contains('button', 'Generate DOI').should('be.disabled'); + + cy.contains('label', 'Relationship').parent().click(); + + cy.contains('IsCitedBy').click(); + + // check that related DOIs info doesn't break the API + cy.contains('button', 'Generate DOI').click(); + + cy.contains('Mint was successful', { timeout: 10000 }).should( + 'be.visible' + ); + }); + + it('should let user see their current cart items', () => { + cy.contains('DATASET 75').should('be.visible'); + cy.get('table[aria-label="cart dataset table"] tbody tr').should( + 'have.length', + 1 + ); + + cy.contains('button', 'Datafiles').click(); + + cy.contains('Datafile 14').should('be.visible'); + cy.get('table[aria-label="cart datafile table"] tbody tr').should( + 'have.length', + 4 + ); + }); + }); +}); diff --git a/packages/datagateway-download/cypress/e2e/adminDownloadStatus.cy.ts b/packages/datagateway-download/cypress/e2e/adminDownloadStatus.cy.ts new file mode 100644 index 000000000..49f573dad --- /dev/null +++ b/packages/datagateway-download/cypress/e2e/adminDownloadStatus.cy.ts @@ -0,0 +1,175 @@ +describe('Admin Download Status', () => { + beforeEach(() => { + // set the viewport larger so all columns display nicely + // and sort indicators aren't covered + cy.viewport(1920, 1080); + + cy.intercept('GET', '**/getPercentageComplete**', '100'); + cy.intercept('GET', '**/topcat/admin/downloads**').as( + 'fetchAdminDownloads' + ); + + cy.login({ username: 'root', password: 'pw', mechanism: 'simple' }); + + // Ensure the downloads are cleared before running tests. + cy.clearDownloads(); + + cy.seedDownloads().then(() => { + cy.visit('/admin/download'); + + cy.wait('@fetchAdminDownloads'); + }); + }); + + it('should refresh the table when clicking the refresh downloads button', () => { + cy.get('[aria-label="Refresh download status table"]').should('exist'); + + cy.get('[aria-label="Refresh Downloads"]') + .next() + .then(($refreshTimeElem) => { + cy.wrap($refreshTimeElem.text()).as('lastRefreshTime'); + }); + + // fake the clock to advance time forward by 5 mins + cy.clock(Date.now()); + cy.tick(5 * 60 * 1000); + + cy.get('[aria-label="Refresh download status table"]').click(); + + cy.get('[aria-label="Refresh Downloads"]') + .next() + .then(($refreshTimeElem) => { + cy.get('@lastRefreshTime').should('not.equal', $refreshTimeElem.text()); + }); + }); + + it('should be able to sort by all sort directions on single and multiple columns', () => { + // remove default sort + cy.contains('[role="button"]', 'Requested Date').click(); + + // ascending order + cy.contains('[role="button"]', 'Access Method') + .as('accessMethodSortButton') + .click(); + + cy.get('[aria-sort="ascending"]').should('exist'); + cy.get('.MuiTableSortLabel-iconDirectionAsc').should('be.visible'); + cy.get('[aria-rowindex="1"] [aria-colindex="5"]').should( + 'have.text', + 'globus' + ); + + // descending order + cy.get('@accessMethodSortButton').click(); + + cy.get('[aria-sort="descending"]').should('exist'); + cy.get('.MuiTableSortLabel-iconDirectionDesc').should( + 'not.have.css', + 'opacity', + '0' + ); + cy.get('[aria-rowindex="1"] [aria-colindex="5"]').should( + 'have.text', + 'https' + ); + + // no order + cy.get('@accessMethodSortButton').click(); + + cy.get('[aria-sort="ascending"]').should('not.exist'); + cy.get('[aria-sort="descending"]').should('not.exist'); + cy.get('.MuiTableSortLabel-iconDirectionAsc').should('not.exist'); + + cy.get('[data-testid="SortIcon"]').should('have.length', 8); + cy.get('[data-testid="ArrowUpwardIcon"]').should('not.exist'); + + cy.get('[aria-rowindex="1"] [aria-colindex="5"]').should( + 'have.text', + 'https' + ); + + // multiple columns (shift + click) + cy.contains('[role="button"]', 'Deleted').click(); + cy.contains('[role="button"]', 'Availability').click({ shiftKey: true }); + cy.get('[aria-sort="ascending"]').should('have.length', 2); + + cy.get('[aria-rowindex="2"] [aria-colindex="6"]').should( + 'have.text', + 'Available' + ); + cy.get('[aria-rowindex="3"] [aria-colindex="6"]').should( + 'have.text', + 'Expired' + ); + + // should replace previous sort when clicked without shift + cy.contains('[role="button"]', 'Prepared ID').click(); + cy.get('[aria-sort="ascending"]').should('have.length', 1); + }); + + it('should change icons when sorting on a column', () => { + // clear default sort + cy.contains('[role="button"]', 'Requested Date').click(); + + cy.get('[data-testid="SortIcon"]').should('have.length', 8); + + // check icon when clicking on a column + cy.contains('[role="button"]', 'ID').click(); + cy.get('[data-testid="ArrowDownwardIcon"]').should('have.length', 1); + cy.get('.MuiTableSortLabel-iconDirectionAsc').should('exist'); + + // check icon when clicking on a column again + cy.contains('[role="button"]', 'ID').click(); + cy.get('[data-testid="ArrowDownwardIcon"]').should('have.length', 1); + cy.get('.MuiTableSortLabel-iconDirectionAsc').should('not.exist'); + + // check icon when hovering over a column + cy.contains('[role="button"]', 'Full Name').trigger('mouseover'); + cy.get('[data-testid="ArrowUpwardIcon"]').should('have.length', 1); + cy.get('[data-testid="ArrowDownwardIcon"]').should('have.length', 1); + + // check icons when shift is held + cy.get('.App').trigger('keydown', { key: 'Shift' }); + cy.get('[data-testid="AddIcon"]').should('have.length', 6); + }); + + it('should be able to filter with both text & date filters on multiple columns', () => { + cy.get('[aria-rowcount]') + .invoke('attr', 'aria-rowcount') + .as('initialRowCount', { type: 'static' }); + const now = Date.now(); + // plus and minus 5 seconds from "now" + const fromDate = new Date(now - 5000); + const toDate = new Date(now + 5000); + + cy.get('input[id="Requested Date filter from"]').type( + fromDate.toLocaleString('sv').split(' ').join('') + ); + cy.get('input[id="Requested Date filter to"]').type( + toDate.toLocaleString('sv').split(' ').join('') + ); + + cy.get('@initialRowCount').then((initialRowCount) => { + cy.get(`[aria-rowcount="${initialRowCount}"]`).should('not.exist'); + }); + cy.get('[aria-rowcount="0"]').should('not.exist'); + + cy.get('[aria-rowcount]') + .invoke('attr', 'aria-rowcount') + .as('dateFilterRowCount', { type: 'static' }); + + cy.get('[aria-label="Filter by Availability"]') + .first() + .type('Available', { force: true }); + + cy.get('[aria-rowindex="1"] [aria-colindex="6"]').should( + 'have.text', + 'Available' + ); + + cy.get('@dateFilterRowCount').then((dateFilterRowCount) => { + cy.get(`[aria-rowcount="${dateFilterRowCount}"]`).should('not.exist'); + }); + cy.get('[aria-rowcount="0"]').should('not.exist'); + }); +}); diff --git a/packages/datagateway-download/cypress/integration/app.spec.ts b/packages/datagateway-download/cypress/e2e/app.cy.ts similarity index 100% rename from packages/datagateway-download/cypress/integration/app.spec.ts rename to packages/datagateway-download/cypress/e2e/app.cy.ts diff --git a/packages/datagateway-download/cypress/integration/downloadCart.spec.ts b/packages/datagateway-download/cypress/e2e/downloadCart.cy.ts similarity index 85% rename from packages/datagateway-download/cypress/integration/downloadCart.spec.ts rename to packages/datagateway-download/cypress/e2e/downloadCart.cy.ts index 6d9594417..3ff3de9c3 100644 --- a/packages/datagateway-download/cypress/integration/downloadCart.spec.ts +++ b/packages/datagateway-download/cypress/e2e/downloadCart.cy.ts @@ -21,13 +21,12 @@ describe('Download Cart', () => { // Ensure we can move away from the table and come back to it. cy.get('[aria-label="Download selection panel"]').should('exist'); // Wait for the downloads to be fetched before moving back to the cart. - cy.get('[aria-label="Downloads"]') - .should('exist') - .click() - .wait('@fetchDownloads'); + cy.get('[aria-label="Downloads"]').should('exist').click(); + cy.wait('@fetchDownloads'); cy.get('[aria-label="Download status panel"]').should('exist'); - cy.get('[aria-label="Selection').click().wait('@fetchCart'); + cy.get('[aria-label="Selection').click(); + cy.wait('@fetchCart'); cy.get('[aria-label="Download selection panel"]').should('exist'); cy.get('[aria-rowcount=59]', { timeout: 10000 }).should('exist'); @@ -69,11 +68,19 @@ describe('Download Cart', () => { 'investigation' ); - cy.contains('[role="button"]', 'Name').click(); + // multisort with shift key + cy.contains('[role="button"]', 'Name').click({ shiftKey: true }); cy.get('[aria-rowindex=1] [aria-colindex=1]').should( 'have.text', 'INVESTIGATION 10' ); + + // replace previous sory by clicking without shift key + cy.contains('[role="button"]', 'Name').click(); + cy.get('[aria-rowindex=1] [aria-colindex=1]').should( + 'have.text', + 'INVESTIGATION 8' + ); }); it('should be able to filter cart items by name and type', () => { @@ -138,4 +145,13 @@ describe('Download Cart', () => { .should('exist') .click(); }); + + it('should not be able to mint an unmintable cart', () => { + cy.get('[aria-label="Calculating"]', { timeout: 20000 }).should( + 'not.exist' + ); + + // this "button" is a link so can't actually be disabled, check pointer-events + cy.contains('Generate DOI').should('have.css', 'pointer-events', 'none'); + }); }); diff --git a/packages/datagateway-download/cypress/integration/downloadConfirmation.spec.ts b/packages/datagateway-download/cypress/e2e/downloadConfirmation.cy.ts similarity index 84% rename from packages/datagateway-download/cypress/integration/downloadConfirmation.spec.ts rename to packages/datagateway-download/cypress/e2e/downloadConfirmation.cy.ts index 91e0d8b6c..e04998fc0 100644 --- a/packages/datagateway-download/cypress/integration/downloadConfirmation.spec.ts +++ b/packages/datagateway-download/cypress/e2e/downloadConfirmation.cy.ts @@ -27,9 +27,9 @@ describe('Download Confirmation', () => { cy.get('[aria-label="Download confirmation dialog"]').should('exist'); }); - it('should load correctly and display the confirmation dialog for the cart items', () => { + it('should load correctly and display the confirmation dialog for the cart items & let the dialog be closed', () => { // Show the correct download size of the cart items. - cy.contains('Download Size: 11.01 GB').should('exist'); + cy.contains('Download Size: 3.12 GB').should('exist'); // Shows HTTPS as the default access method. cy.contains('#confirm-access-method', 'HTTPS').should('exist'); @@ -38,27 +38,20 @@ describe('Download Confirmation', () => { cy.get('#download-table').should('exist'); cy.contains( '#download-table-one', - '23 hours, 19 minutes, 46 seconds' + '6 hours, 36 minutes, 34 seconds' ).should('exist'); - cy.contains('#download-table-thirty', '46 minutes, 39 seconds').should( + cy.contains('#download-table-thirty', '13 minutes, 13 seconds').should( 'exist' ); - cy.contains('#download-table-hundred', '13 minutes, 59 seconds').should( + cy.contains('#download-table-hundred', '3 minutes, 57 seconds').should( 'exist' ); - }); - it('should prevent download requests with an invalid email address', () => { - // Enter in an invalid email address. - cy.get('#confirm-download-email').type('email.address'); + cy.get('[aria-label="Close download confirmation dialog"]').should('exist'); - // Ensure that the download button is disabled. - cy.get('#download-confirmation-download').should('be.disabled'); + cy.get('[aria-label="Close download confirmation dialog"]').click(); - // Complete the remainder of the email and ensure the email is not invalid anymore - // as the download button is enabled. - cy.get('#confirm-download-email').type('@test.com'); - cy.get('#download-confirmation-download').should('be.enabled'); + cy.get('[aria-label="Download confirmation dialog"]').should('not.exist'); }); it('should be able to submit a download request and start immediate download with default values (HTTPS)', () => { @@ -78,6 +71,13 @@ describe('Download Confirmation', () => { 'exist' ); cy.contains('#confirm-success-access-method', 'HTTPS').should('exist'); + + // Click on the download status link and expect the download + // status panel to have been displayed. + cy.contains('#download-confirmation-status-link', 'View My Downloads') + .should('exist') + .click(); + cy.get('[aria-label="Download status panel"]').should('exist'); }); it('should not be able to submit a download request with a disabled access method (Globus)', () => { @@ -114,7 +114,16 @@ describe('Download Confirmation', () => { cy.get('#confirm-download-name').type('test-file-name'); // Set email address. - cy.get('#confirm-download-email').type('test@email.com'); + // Enter in an invalid email address. + cy.get('#confirm-download-email').type('email.address'); + + // Ensure that the download button is disabled. + cy.get('#download-confirmation-download').should('be.disabled'); + + // Complete the remainder of the email and ensure the email is not invalid anymore + // as the download button is enabled. + cy.get('#confirm-download-email').type('@test.com'); + cy.get('#download-confirmation-download').should('be.enabled'); // Request download. cy.get('#download-confirmation-download').click(); @@ -129,30 +138,9 @@ describe('Download Confirmation', () => { 'exist' ); cy.contains('#confirm-success-access-method', 'HTTPS').should('exist'); - cy.contains('#confirm-success-email-address', 'test@email.com').should( - 'exist' - ); - }); - - // This needs to be implemented once the tab has been included into the code. - it('should be able to link to the downloads status tab upon successful download confirmation', () => { - cy.get('#download-confirmation-download').click(); - - cy.get('#download-confirmation-success').should('exist'); - - // Click on the download status link and expect the download - // status panel to have been displayed. - cy.contains('#download-confirmation-status-link', 'View My Downloads') - .should('exist') - .click(); - cy.get('[aria-label="Download status panel"]').should('exist'); - }); - - it('should be able to close the download confirmation dialog', () => { - cy.get('[aria-label="Close download confirmation dialog"]').should('exist'); - - cy.get('[aria-label="Close download confirmation dialog"]').click(); - - cy.get('[aria-label="Download confirmation dialog"]').should('not.exist'); + cy.contains( + '#confirm-success-email-address', + 'email.address@test.com' + ).should('exist'); }); }); diff --git a/packages/datagateway-download/cypress/e2e/downloadStatus.cy.ts b/packages/datagateway-download/cypress/e2e/downloadStatus.cy.ts new file mode 100644 index 000000000..606c9331f --- /dev/null +++ b/packages/datagateway-download/cypress/e2e/downloadStatus.cy.ts @@ -0,0 +1,236 @@ +import { format } from 'date-fns-tz'; + +describe('Download Status', () => { + before(() => { + // Ensure the downloads are cleared before running tests. + cy.login(); + + // Seed the initial downloads. + cy.clearDownloads(); + }); + + beforeEach(() => { + cy.intercept('GET', '**/getPercentageComplete**', '100'); + cy.intercept('GET', '**/topcat/user/downloads**').as('fetchDownloads'); + cy.login(); + + // Ensure the downloads are cleared before running tests. + cy.clearDownloads(); + + cy.seedDownloads().then(() => { + cy.visit('/download'); + + cy.get('[aria-label="Downloads"]').should('exist'); + cy.get('[aria-label="Downloads"]').click(); + cy.wait('@fetchDownloads'); + }); + }); + + it('should load correctly and display download status table & show correct info & links', () => { + cy.title().should('equal', 'DataGateway Download'); + cy.get('#datagateway-download').should('be.visible'); + + cy.get('[aria-label="Download status panel"]').should('exist'); + + cy.contains('[aria-colindex="1"]', 'test-file-1') + .should('be.visible') + .and('not.be.disabled'); + + // We are not clicking and proceeding to download the item in this test + // but instead checking that the link exists and it is possible to be clicked. + cy.get('a[aria-label="Download test-file-1"]').should('not.be.empty'); + cy.get('a[aria-label="Download test-file-1"]') + .should('have.prop', 'href') + .and('contain', 'getData'); + }); + + it('should refresh the table when clicking the refresh downloads button', () => { + cy.get('[aria-label="Refresh Downloads"]') + .next() + .children() + .first() + .then(($refreshTimeElem) => { + cy.wrap($refreshTimeElem.text()).as('lastRefreshTime'); + }); + + // fake the clock to advance time forward by 5 mins + cy.clock(Date.now()); + cy.tick(5 * 60 * 1000); + + cy.get('[aria-label="Refresh download status table"]').should('exist'); + cy.get('[aria-label="Refresh download status table"]').click(); + + cy.get('[aria-label="Refresh Downloads"]') + .next() + .children() + .first() + .then(($refreshTimeElem) => { + cy.get('@lastRefreshTime').should('not.equal', $refreshTimeElem.text()); + }); + }); + + it('should be able to sort by all sort directions on single and multiple columns', () => { + // remove default sort + cy.contains('[role="button"]', 'Requested Date').click(); + + // ascending + cy.contains('[role="button"]', 'Download Name') + .as('nameSortButton') + .click(); + + cy.get('[aria-sort="ascending"]').should('exist'); + cy.get('.MuiTableSortLabel-iconDirectionAsc').should('be.visible'); + + cy.get('[aria-rowindex="1"] [aria-colindex="1"]').should( + 'have.text', + 'test-file-1' + ); + + // descending + cy.get('@nameSortButton').click(); + + cy.get('[aria-sort="descending"]').should('exist'); + cy.get('.MuiTableSortLabel-iconDirectionDesc').should( + 'not.have.css', + 'opacity', + '0' + ); + cy.get('[aria-rowindex="1"] [aria-colindex="1"]').should( + 'have.text', + 'test-file-4' + ); + + cy.get('[aria-rowindex="1"] [aria-colindex="3"]').should( + 'have.text', + 'Expired' + ); + + // no order + cy.get('@nameSortButton').click(); + + cy.get('[aria-sort="ascending"]').should('not.exist'); + cy.get('[aria-sort="descending"]').should('not.exist'); + cy.get('.MuiTableSortLabel-iconDirectionAsc').should('not.exist'); + + cy.get('[data-testid="SortIcon"]').should('have.length', 4); + cy.get('[data-testid="ArrowUpwardIcon"]').should('not.exist'); + + cy.get('[aria-rowindex="1"] [aria-colindex="1"]').should( + 'have.text', + 'test-file-1' + ); + + cy.get('[aria-rowindex="1"] [aria-colindex="3"]').should( + 'have.text', + 'Available' + ); + + // multiple columns (shift + click) + cy.contains('[role="button"]', 'Download Name').click(); + cy.contains('[role="button"]', 'Availability').click({ shiftKey: true }); + cy.get('[aria-sort="ascending"]').should('have.length', 2); + + cy.get('[aria-rowindex="1"] [aria-colindex="3"]').contains('Available'); + + // should replace previous sort when clicked without shift + cy.contains('[role="button"]', 'Access Method').click(); + cy.get('[aria-sort="ascending"]').should('have.length', 1); + cy.get('[aria-rowindex="1"] [aria-colindex="1"]').contains('test-file-2'); + }); + + it('should change icons when sorting on a column', () => { + // clear default sort + cy.contains('[role="button"]', 'Requested Date').click(); + + cy.get('[data-testid="SortIcon"]').should('have.length', 4); + + // check icon when clicking on a column + cy.contains('[role="button"]', 'Download Name').click(); + cy.get('[data-testid="ArrowDownwardIcon"]').should('have.length', 1); + cy.get('.MuiTableSortLabel-iconDirectionAsc').should('exist'); + + // check icon when clicking on a column again + cy.contains('[role="button"]', 'Download Name').click(); + cy.get('[data-testid="ArrowDownwardIcon"]').should('have.length', 1); + cy.get('.MuiTableSortLabel-iconDirectionAsc').should('not.exist'); + + // check icon when hovering over a column + cy.contains('[role="button"]', 'Access Method').trigger('mouseover'); + cy.get('[data-testid="ArrowUpwardIcon"]').should('have.length', 1); + cy.get('[data-testid="ArrowDownwardIcon"]').should('have.length', 1); + + // check icons when shift is held + cy.get('.App').trigger('keydown', { key: 'Shift' }); + cy.get('[data-testid="AddIcon"]').should('have.length', 2); + }); + + it('should be able to filter with both text & date filters on multiple columns', () => { + cy.get('input[id="Requested Date filter from"]').type( + '2020-01-31 00:00:00' + ); + + const date = new Date(); + date.setDate(1); + date.setMonth(date.getMonth() - 1); + // MUIv5 datetime pickers don't allow for time to be graphically selected + // This is because the relevant elements are elements with pointer-events: none + // Therefore, we settle for typing the date and time instead + cy.get('input[id="Requested Date filter to"]').type( + format(date, 'yyyy-MM-dd HH:mm:ss') + ); + + // There should not be results for this time period. + cy.get('[aria-rowcount="0"]').should('exist'); + + const currDate = new Date(); + currDate.setHours(0, 0, 0, 0); + + cy.get('input[id="Requested Date filter from"]').clear(); + cy.get('input[id="Requested Date filter to"]').clear(); + cy.get('[aria-rowcount="4"]').should('exist'); + + cy.get('input[id="Requested Date filter from"]').type( + format(currDate, 'yyyy-MM-dd HH:mm:ss') + ); + + cy.get('[aria-rowcount="4"]').should('exist'); + + // account for whether the download progress feature is enabled or not + cy.get('[role="columnheader"]') + .eq(3) + .then(($fourthColHeader) => { + if ($fourthColHeader.text().includes('Progress')) { + cy.get('[aria-rowindex="1"] [aria-colindex="5"]').should( + 'contain', + format(currDate, 'yyyy-MM-dd') + ); + } else { + cy.get('[aria-rowindex="1"] [aria-colindex="4"]').should( + 'contain', + format(currDate, 'yyyy-MM-dd') + ); + } + }); + + cy.get('[aria-label="Filter by Access Method"]').first().type('globus'); + + cy.get('[aria-rowcount="2"]').should('exist'); + + cy.get('[aria-label="Filter by Availability"]').first().type('restoring'); + + cy.get('[aria-rowcount="1"]').should('exist'); + }); + + it('should be able to remove a download', () => { + cy.intercept('PUT', '**/topcat/user/download/*/isDeleted').as( + 'removeFromDownloads' + ); + + cy.contains('[aria-colindex="1"]', 'test-file-4').should('be.visible'); + cy.get('[aria-label="Remove test-file-4 from downloads"]').click({ + force: true, + }); + cy.wait('@removeFromDownloads'); + cy.contains('test-file-4').should('not.exist'); + }); +}); diff --git a/packages/datagateway-download/cypress/integration/downloadTab.spec.ts b/packages/datagateway-download/cypress/e2e/downloadTab.cy.ts similarity index 88% rename from packages/datagateway-download/cypress/integration/downloadTab.spec.ts rename to packages/datagateway-download/cypress/e2e/downloadTab.cy.ts index cc85bad38..bfe3b7ca0 100644 --- a/packages/datagateway-download/cypress/integration/downloadTab.spec.ts +++ b/packages/datagateway-download/cypress/e2e/downloadTab.cy.ts @@ -12,17 +12,15 @@ describe('Download Cart', () => { cy.clearDownloadCart(); }); - it('should load correctly and display selection panel', () => { + it('should display the selection tab on every page reload', () => { cy.title().should('equal', 'DataGateway Download'); cy.get('#datagateway-download').should('be.visible'); cy.get('[aria-label="Selection"]').should('exist'); cy.get('[aria-label="Downloads"]').should('exist'); cy.get('[aria-label="Download selection panel"]').should('be.visible'); cy.get('[aria-label="Download status panel"]').should('not.be.visible'); - }); - it('should display the selection tab on every page reload', () => { - cy.get('[aria-label="Downloads"]').should('exist').click(); + cy.get('[aria-label="Downloads"]').click(); cy.get('[aria-label="Download status panel"]').should('be.visible'); cy.get('[aria-label="Download selection panel"]').should('not.be.visible'); diff --git a/packages/datagateway-download/cypress/integration/adminDownloadStatus.spec.ts b/packages/datagateway-download/cypress/integration/adminDownloadStatus.spec.ts deleted file mode 100644 index e1cd31789..000000000 --- a/packages/datagateway-download/cypress/integration/adminDownloadStatus.spec.ts +++ /dev/null @@ -1,227 +0,0 @@ -describe('Admin Download Status', () => { - before(() => { - // Ensure the downloads are cleared before running tests. - cy.login({ username: 'root', password: 'pw', mechanism: 'simple' }); - - // Seed the initial downloads. - cy.clearDownloads(); - }); - - beforeEach(() => { - cy.intercept('GET', '**/topcat/admin/downloads**').as( - 'fetchAdminDownloads' - ); - - cy.login({ username: 'root', password: 'pw', mechanism: 'simple' }); - - // Ensure the downloads are cleared before running tests. - cy.clearDownloads(); - - cy.seedDownloads().then(() => { - cy.visit('/admin/download'); - }); - }); - - it('should load correctly and display admin download status table', () => { - cy.title().should('equal', 'DataGateway Download'); - cy.get('#datagateway-download').should('be.visible'); - }); - - it('should refresh the table when clicking the refresh downloads button', () => { - cy.get('[aria-label="Refresh download status table"]').should('exist'); - - // Typical `.should('match'...)` doesn't work for text, tries to match the element, - // hence a slightly different approach for doing regex on the actual text - cy.get('[aria-rowindex="1"] [aria-colindex="4"]') - .find('p') - .should(($preparedId) => { - expect($preparedId[0].textContent).match( - /[0-9a-zA-Z]{8}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{12}/ - ); - }); - - cy.get('[aria-label="Refresh download status table"]').click(); - - cy.get('[aria-rowindex="1"] [aria-colindex="4"]') - .find('p') - .should(($preparedId) => { - expect($preparedId[0].textContent).match( - /[0-9a-zA-Z]{8}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{12}/ - ); - }); - }); - - describe('should be able to sort download items by', () => { - it('ascending order', () => { - // Table is sorted by Requested Date by default. To keep working test, we will remove all sorts on the table beforehand - cy.get('.react-draggable') - .eq(7) - .trigger('mousedown') - .trigger('mousemove', { clientX: 800 }) - .trigger('mouseup'); - cy.contains('[role="button"]', 'Requested Date').click(); - - cy.get('.react-draggable') - .eq(4) - .trigger('mousedown') - .trigger('mousemove', { clientX: 600 }) - .trigger('mouseup'); - cy.contains('[role="button"]', 'Access Method').click(); - - cy.get('[aria-sort="ascending"]').should('exist'); - cy.get('.MuiTableSortLabel-iconDirectionAsc').should('be.visible'); - cy.get('[aria-rowindex="1"] [aria-colindex="5"]').should( - 'have.text', - 'globus' - ); - }); - - it('descending order', () => { - // Table is sorted by Requested Date by default. To keep working test, we will remove all sorts on the table beforehand - cy.get('.react-draggable') - .eq(7) - .trigger('mousedown') - .trigger('mousemove', { clientX: 800 }) - .trigger('mouseup'); - cy.contains('[role="button"]', 'Requested Date').click(); - - cy.get('.react-draggable') - .eq(4) - .trigger('mousedown') - .trigger('mousemove', { clientX: 600 }) - .trigger('mouseup'); - cy.contains('[role="button"]', 'Access Method').click(); - cy.contains('[role="button"]', 'Access Method').click(); - - cy.get('[aria-sort="descending"]').should('exist'); - cy.get('.MuiTableSortLabel-iconDirectionDesc').should( - 'not.have.css', - 'opacity', - '0' - ); - cy.get('[aria-rowindex="1"] [aria-colindex="5"]').should( - 'have.text', - 'https' - ); - }); - - it('no order', () => { - // Table is sorted by Requested Date by default. To keep working test, we will remove all sorts on the table beforehand - cy.get('.react-draggable') - .eq(7) - .trigger('mousedown') - .trigger('mousemove', { clientX: 800 }) - .trigger('mouseup'); - cy.contains('[role="button"]', 'Requested Date').click(); - - cy.get('.react-draggable') - .eq(3) - .trigger('mousedown') - .trigger('mousemove', { clientX: 500 }) - .trigger('mouseup'); - cy.contains('[role="button"]', 'Prepared ID').click(); - cy.contains('[role="button"]', 'Prepared ID').click(); - cy.contains('[role="button"]', 'Prepared ID').click(); - - cy.get('[aria-sort="ascending"]').should('not.exist'); - cy.get('.MuiTableSortLabel-iconDirectionDesc').should('not.exist'); - cy.get('.MuiTableSortLabel-iconDirectionAsc').should( - 'have.css', - 'opacity', - '0' - ); - cy.get('[aria-rowindex="1"] [aria-colindex="4"]') - .find('p') - .should(($preparedId) => { - expect($preparedId[0].textContent).match( - /[0-9a-zA-Z]{8}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{12}/ - ); - }); - }); - - it('multiple columns', () => { - // Table is sorted by Requested Date by default. To keep working test, we will remove all sorts on the table beforehand - cy.get('.react-draggable') - .eq(7) - .trigger('mousedown') - .trigger('mousemove', { clientX: 800 }) - .trigger('mouseup'); - cy.contains('[role="button"]', 'Requested Date').click(); - - cy.get('.react-draggable') - .eq(4) - .trigger('mousedown') - .trigger('mousemove', { clientX: 550 }) - .trigger('mouseup'); - cy.contains('[role="button"]', 'Access Method').click(); - - cy.get('.react-draggable') - .eq(2) - .trigger('mousedown') - .trigger('mousemove', { clientX: 400 }) - .trigger('mouseup'); - cy.contains('[role="button"]', 'Username').click(); - - cy.get('[aria-rowindex="1"] [aria-colindex="5"]').should( - 'have.text', - 'globus' - ); - }); - }); - - describe('should be able to filter download items by', () => { - it('text', () => { - cy.get('[aria-label="Filter by Availability"]') - .first() - .type('Available', { force: true }); - - cy.get('[aria-rowindex="1"] [aria-colindex="6"]').should( - 'have.text', - 'Available' - ); - }); - - it('date between', () => { - const currDate = new Date(); - - cy.get('input[id="Requested Date filter from"]').type( - currDate.toISOString().slice(0, 10) - ); - - cy.get('input[id="Requested Date filter to"]').type( - currDate.toISOString().slice(0, 10) - ); - - cy.get('[aria-rowcount="0"]').should('not.exist'); - }); - - it('multiple columns', () => { - cy.get('[role="columnheader"]').eq(4).as('accessColumn'); - cy.get('[role="columnheader"]').eq(5).as('availabilityColumn'); - - cy.get('.react-draggable') - .eq(4) - .trigger('mousedown') - .trigger('mousemove', { clientX: 500 }) - .trigger('mouseup'); - - cy.get('.react-draggable') - .eq(5) - .trigger('mousedown') - .trigger('mousemove', { clientX: 700 }) - .trigger('mouseup'); - - cy.get('[aria-label="Filter by Access Method') - .first() - .type('globus', { force: true }); - cy.get('[aria-label="Filter by Availability"]') - .first() - .type('restoring', { force: true }); - - cy.get('[aria-rowindex="1"] [aria-colindex="5"]').should( - 'have.text', - 'globus' - ); - }); - }); -}); diff --git a/packages/datagateway-download/cypress/integration/downloadStatus.spec.ts b/packages/datagateway-download/cypress/integration/downloadStatus.spec.ts deleted file mode 100644 index 5abe1f3e4..000000000 --- a/packages/datagateway-download/cypress/integration/downloadStatus.spec.ts +++ /dev/null @@ -1,230 +0,0 @@ -import { format } from 'date-fns-tz'; - -describe('Download Status', () => { - before(() => { - // Ensure the downloads are cleared before running tests. - cy.login(); - - // Seed the initial downloads. - cy.clearDownloads(); - }); - - beforeEach(() => { - cy.intercept('GET', '**/topcat/user/downloads**').as('fetchDownloads'); - cy.login(); - - // Ensure the downloads are cleared before running tests. - cy.clearDownloads(); - - cy.seedDownloads().then(() => { - cy.visit('/download'); - - cy.get('[aria-label="Downloads"]').should('exist'); - cy.get('[aria-label="Downloads"]') - .click() - .then(() => { - cy.wait('@fetchDownloads'); - }); - }); - }); - - it('should load correctly and display download status table', () => { - cy.title().should('equal', 'DataGateway Download'); - cy.get('#datagateway-download').should('be.visible'); - - cy.get('[aria-label="Download status panel"]').should('exist'); - }); - - it('should refresh the table when clicking the refresh downloads button', () => { - cy.get('[aria-label="Refresh download status table"]').should('exist'); - cy.get('[aria-rowindex="1"] [aria-colindex="1"]').should( - 'have.text', - 'test-file-4' - ); - cy.get('[aria-label="Refresh download status table"]').click(); - }); - - describe('should be able to sort download items by', () => { - it('ascending order', () => { - // Table is sorted by Requested Date by default. To keep working test, we will remove all sorts on the table beforehand - cy.contains('[role="button"]', 'Requested Date').click(); - - cy.contains('[role="button"]', 'Download Name').click(); - - cy.get('[aria-sort="ascending"]').should('exist'); - cy.get('.MuiTableSortLabel-iconDirectionAsc').should('be.visible'); - - cy.get('[aria-rowindex="1"] [aria-colindex="1"]').should( - 'have.text', - 'test-file-1' - ); - }); - - it('descending order', () => { - // Table is sorted by Requested Date by default. To keep working test, we will remove all sorts on the table beforehand - cy.contains('[role="button"]', 'Requested Date').click(); - - cy.contains('[role="button"]', 'Download Name').click(); - cy.contains('[role="button"]', 'Download Name').click(); - - cy.get('[aria-sort="descending"]').should('exist'); - cy.get('.MuiTableSortLabel-iconDirectionDesc').should( - 'not.have.css', - 'opacity', - '0' - ); - cy.get('[aria-rowindex="1"] [aria-colindex="1"]').should( - 'have.text', - 'test-file-4' - ); - - cy.get('[aria-rowindex="1"] [aria-colindex="3"]').should( - 'have.text', - 'Expired' - ); - }); - - it('no order', () => { - // Table is sorted by Requested Date by default. To keep working test, we will remove all sorts on the table beforehand - cy.contains('[role="button"]', 'Requested Date').click(); - - cy.contains('[role="button"]', 'Download Name').click(); - cy.contains('[role="button"]', 'Download Name').click(); - cy.contains('[role="button"]', 'Download Name').click(); - - cy.get('[aria-sort="ascending"]').should('not.exist'); - cy.get('.MuiTableSortLabel-iconDirectionDesc').should('not.exist'); - cy.get('.MuiTableSortLabel-iconDirectionAsc').should( - 'have.css', - 'opacity', - '0' - ); - cy.get('[aria-rowindex="1"] [aria-colindex="1"]').should( - 'have.text', - 'test-file-4' - ); - - cy.get('[aria-rowindex="1"] [aria-colindex="3"]').should( - 'have.text', - 'Expired' - ); - }); - - it('multiple columns', () => { - // Table is sorted by Requested Date by default. To keep working test, we will remove all sorts on the table beforehand - cy.contains('[role="button"]', 'Requested Date').click(); - - cy.contains('[role="button"]', 'Access Method').click(); - cy.contains('[role="button"]', 'Availability').click(); - - cy.get('[aria-rowindex="1"] [aria-colindex="1"]').should( - 'have.text', - 'test-file-4' - ); - }); - }); - - describe('should be able to filter download items by', () => { - it('text', () => { - cy.get('[aria-label="Filter by Download Name"]').first().type('file'); - - cy.get('[aria-rowcount="4"]').should('exist'); - - cy.get('[aria-rowindex="1"] [aria-colindex="3"]').should( - 'have.text', - 'Expired' - ); - }); - - it('date between', () => { - cy.get('input[id="Requested Date filter from"]').type('2020-01-31 00:00'); - - const date = new Date(); - const month = date.toLocaleString('default', { month: 'long' }); - const year = date.getFullYear(); - - cy.get('input[id="Requested Date filter to"]') - .parent() - .find('button') - .click(); - - cy.contains(`${month} ${year}`) - .parent() - .parent() - .find('button') - .first() - .click(); - - cy.get('.MuiPickersDay-day[tabindex="0"]').first().click(); - - cy.contains('OK').click(); - - date.setDate(1); - date.setMonth(date.getMonth() - 1); - - cy.get('input[id="Requested Date filter to"]').should( - 'have.value', - format(date, 'yyyy-MM-dd HH:mm') - ); - - // There should not be results for this time period. - cy.get('[aria-rowcount="0"]').should('exist'); - - const currDate = new Date(); - - cy.get('input[id="Requested Date filter from"]').clear(); - cy.get('input[id="Requested Date filter to"]').clear(); - cy.get('[aria-rowcount="4"]').should('exist'); - - cy.get('input[id="Requested Date filter from"]').type( - format(currDate, 'yyyy-MM-dd HH:mm') - ); - - cy.get('[aria-rowindex="1"] [aria-colindex="1"]').should( - 'have.text', - 'test-file-4' - ); - - cy.get('[aria-rowindex="1"] [aria-colindex="2"]').should( - 'have.text', - 'globus' - ); - - cy.get('[aria-rowcount="4"]').should('exist'); - }); - - it('multiple columns', () => { - cy.get('[aria-label="Filter by Access Method').first().type('globus'); - - cy.get('[aria-label="Filter by Availability"]').first().type('restoring'); - - cy.get('[aria-rowcount="2"]').should('exist'); - }); - }); - - it('should have a download link for an item', () => { - cy.contains('[aria-colindex="1"]', 'test-file-1') - .should('be.visible') - .and('not.be.disabled'); - - // We are not clicking and proceeding to download the item in this test - // but instead checking that the link exists and it is possible to be clicked. - cy.get('a[aria-label="Download test-file-1"]').should('not.be.empty'); - cy.get('a[aria-label="Download test-file-1"]') - .should('have.prop', 'href') - .and('contain', 'getData'); - }); - - it('should be able to remove a download', () => { - cy.intercept('PUT', '**/topcat/user/download/*/isDeleted').as( - 'removeFromDownloads' - ); - - cy.contains('[aria-colindex="1"]', 'test-file-4').should('be.visible'); - cy.get('[aria-label="Remove test-file-4 from downloads"]').click({ - force: true, - }); - cy.wait('@removeFromDownloads'); - cy.contains('test-file-4').should('not.exist'); - }); -}); diff --git a/packages/datagateway-download/cypress/plugins/index.js b/packages/datagateway-download/cypress/plugins/index.js deleted file mode 100644 index 0a062758f..000000000 --- a/packages/datagateway-download/cypress/plugins/index.js +++ /dev/null @@ -1,22 +0,0 @@ -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -module.exports = (on, config) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config - on('task', { - // eslint-disable-next-line @typescript-eslint/no-var-requires - failed: require('cypress-failed-log/src/failed')(), - }); -}; diff --git a/packages/datagateway-download/cypress/support/commands.js b/packages/datagateway-download/cypress/support/commands.js index 9bd8dc280..94092eae3 100644 --- a/packages/datagateway-download/cypress/support/commands.js +++ b/packages/datagateway-download/cypress/support/commands.js @@ -89,35 +89,45 @@ export const readSciGatewayToken = () => { }; }; -Cypress.Commands.add('login', (credentials) => { - return cy.readFile('server/e2e-settings.json').then((settings) => { - let body = { - username: '', - password: '', - mechanism: 'anon', - }; - if (credentials) { - body = credentials; - } - cy.request('POST', `${settings.apiUrl}/sessions`, body).then((response) => { - const jwtHeader = { alg: 'HS256', typ: 'JWT' }; - const payload = { - sessionId: response.body.sessionID, - username: 'test', +Cypress.Commands.add('login', (credentials, user) => { + cy.session([credentials, user], () => { + cy.request('datagateway-download-settings.json').then((response) => { + const settings = response.body; + let body = { + username: '', + password: '', + mechanism: 'anon', }; - const jwt = jsrsasign.KJUR.jws.JWS.sign( - 'HS256', - jwtHeader, - payload, - 'shh' + if (credentials) { + body = credentials; + } + cy.request('POST', `${settings.apiUrl}/sessions`, body).then( + (response) => { + const jwtHeader = { alg: 'HS256', typ: 'JWT' }; + const payload = { + sessionId: response.body.sessionID, + username: user + ? user + : body.mechanism === 'anon' + ? 'anon/anon' + : 'Michael222', + }; + const jwt = jsrsasign.KJUR.jws.JWS.sign( + 'HS256', + jwtHeader, + payload, + 'shh' + ); + window.localStorage.setItem('scigateway:token', jwt); + } ); - window.localStorage.setItem('scigateway:token', jwt); }); }); }); Cypress.Commands.add('clearDownloadCart', () => { - return cy.readFile('server/e2e-settings.json').then((settings) => { + return cy.request('datagateway-download-settings.json').then((response) => { + const settings = response.body; cy.request({ method: 'DELETE', url: `${settings.downloadApiUrl}/user/cart/${settings.facilityName}/cartItems`, @@ -136,7 +146,31 @@ Cypress.Commands.add('seedDownloadCart', () => { .map((value, index) => `${entities[index % 2]} ${index}`) .join(', '); - return cy.readFile('server/e2e-settings.json').then((settings) => { + return cy.request('datagateway-download-settings.json').then((response) => { + const settings = response.body; + cy.request({ + method: 'POST', + url: `${settings.downloadApiUrl}/user/cart/${settings.facilityName}/cartItems`, + body: { + sessionId: readSciGatewayToken().sessionId, + items, + }, + form: true, + }); + }); +}); + +Cypress.Commands.add('seedMintCart', () => { + const items = [ + 'dataset 75', + 'datafile 371', + 'datafile 14', + 'datafile 133', + 'datafile 252', + ].join(', '); + + return cy.request('datagateway-download-settings.json').then((response) => { + const settings = response.body; cy.request({ method: 'POST', url: `${settings.downloadApiUrl}/user/cart/${settings.facilityName}/cartItems`, @@ -149,8 +183,35 @@ Cypress.Commands.add('seedDownloadCart', () => { }); }); +Cypress.Commands.add('clearDataPublications', () => { + return cy.request('datagateway-download-settings.json').then((response) => { + const settings = response.body; + + cy.request({ + method: 'GET', + url: `${settings.apiUrl}/datapublications`, + headers: { Authorization: `Bearer ${readSciGatewayToken().sessionId}` }, + qs: { + where: JSON.stringify({ title: { eq: 'Test title' } }), + }, + }).then((response) => { + const datapublications = response.body; + datapublications.forEach((datapublication) => { + cy.request({ + method: 'DELETE', + url: `${settings.apiUrl}/datapublications/${datapublication.id}`, + headers: { + Authorization: `Bearer ${readSciGatewayToken().sessionId}`, + }, + }); + }); + }); + }); +}); + Cypress.Commands.add('addCartItem', (cartItem) => { - return cy.readFile('server/e2e-settings.json').then((settings) => { + return cy.request('datagateway-download-settings.json').then((response) => { + const settings = response.body; cy.request({ method: 'POST', url: `${settings.downloadApiUrl}/user/cart/${settings.facilityName}/cartItems`, @@ -164,7 +225,8 @@ Cypress.Commands.add('addCartItem', (cartItem) => { }); Cypress.Commands.add('seedDownloads', () => { - return cy.readFile('server/e2e-settings.json').then((settings) => { + return cy.request('datagateway-download-settings.json').then((response) => { + const settings = response.body; let i = 1; for (var info of downloadsInfo) { // Seed a single cart item as items are cleared after each download. @@ -220,7 +282,8 @@ Cypress.Commands.add('seedDownloads', () => { }); Cypress.Commands.add('clearDownloads', () => { - return cy.readFile('server/e2e-settings.json').then((settings) => { + return cy.request('datagateway-download-settings.json').then((response) => { + const settings = response.body; cy.request({ method: 'GET', url: `${settings.downloadApiUrl}/user/downloads`, diff --git a/packages/datagateway-download/cypress/support/index.js b/packages/datagateway-download/cypress/support/e2e.js similarity index 100% rename from packages/datagateway-download/cypress/support/index.js rename to packages/datagateway-download/cypress/support/e2e.js diff --git a/packages/datagateway-download/cypress/support/index.d.ts b/packages/datagateway-download/cypress/support/index.d.ts index 500a77baf..110365b48 100644 --- a/packages/datagateway-download/cypress/support/index.d.ts +++ b/packages/datagateway-download/cypress/support/index.d.ts @@ -1,14 +1,26 @@ declare namespace Cypress { interface Chainable { - login(credentials?: { - username: string; - password: string; - mechanism: string; - }): Cypress.Chainable; + login( + credentials?: { + username: string; + password: string; + mechanism: string; + }, + user?: string + ): Cypress.Chainable; + clearDownloadCart(): Cypress.Chainable; + seedDownloadCart(): Cypress.Chainable; + + seedMintCart(): Cypress.Chainable; + + clearDataPublications(): Cypress.Chainable; + addCartItem(cartItem: string): Cypress.Chainable; + seedDownloads(): Cypress.Chainable; + clearDownloads(): Cypress.Chainable; } } diff --git a/packages/datagateway-download/cypress/tsconfig.json b/packages/datagateway-download/cypress/tsconfig.json index d38e7a12f..bd61c5f93 100644 --- a/packages/datagateway-download/cypress/tsconfig.json +++ b/packages/datagateway-download/cypress/tsconfig.json @@ -3,7 +3,11 @@ "strict": true, "baseUrl": "../node_modules", "target": "es5", - "lib": ["es5", "dom"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "types": ["cypress"] }, "include": ["**/*"] diff --git a/packages/datagateway-download/package.json b/packages/datagateway-download/package.json index 41b265733..ae990531e 100644 --- a/packages/datagateway-download/package.json +++ b/packages/datagateway-download/package.json @@ -1,66 +1,72 @@ { "name": "datagateway-download", - "version": "1.1.3", + "version": "2.0.0", "private": true, "dependencies": { - "@material-ui/core": "^4.11.3", - "@material-ui/icons": "^4.11.2", - "@material-ui/lab": "^4.0.0-alpha.58", - "@types/jest": "^27.4.0", - "@types/node": "^17.0.17", - "@types/react": "^17.0.2", - "@types/react-dom": "^17.0.1", - "axios": "^0.26.0", - "datagateway-common": "^1.1.3", - "date-fns": "^2.28.0", - "date-fns-tz": "^1.1.6", - "history": "^4.10.1", - "i18next": "^21.6.13", - "i18next-browser-languagedetector": "^6.1.2", - "i18next-http-backend": "^1.3.2", - "lodash.chunk": "^4.2.0", - "loglevel": "^1.8.0", + "@craco/craco": "7.1.0", + "@emotion/react": "11.11.1", + "@emotion/styled": "11.11.0", + "@mui/icons-material": "5.11.0", + "@mui/material": "5.11.0", + "@types/jest": "29.5.2", + "@types/jsrsasign": "10.5.2", + "@types/lodash.chunk": "4.2.6", + "@types/node": "20.11.5", + "@types/react": "17.0.39", + "@types/react-dom": "17.0.11", + "@types/react-router-dom": "5.3.3", + "@types/react-virtualized": "9.21.10", + "axios": "1.6.1", + "datagateway-common": "^2.0.0", + "date-fns": "2.30.0", + "date-fns-tz": "2.0.0", + "eslint-config-prettier": "8.10.0", + "eslint-plugin-cypress": "2.15.1", + "eslint-plugin-prettier": "4.2.1", + "history": "4.10.1", + "i18next": "22.0.3", + "i18next-browser-languagedetector": "7.2.0", + "i18next-http-backend": "2.4.2", + "jsrsasign": "11.0.0", + "lodash.chunk": "4.2.0", + "loglevel": "1.9.1", "p-limit": "3.1.0", - "react": "^16.13.1", - "react-dom": "^16.11.0", - "react-i18next": "^11.15.4", - "react-query": "^3.18.1", - "react-router-dom": "^5.3.0", + "prettier": "2.8.0", + "react": "17.0.2", + "react-dom": "17.0.2", + "react-i18next": "12.3.1", + "react-query": "3.39.2", + "react-router-dom": "5.3.0", "react-scripts": "5.0.0", - "react-virtualized": "^9.22.3", - "single-spa-react": "^4.3.1", - "tslib": "^2.3.0", - "typescript": "4.5.3" + "react-virtualized": "9.22.3", + "single-spa-react": "4.6.1", + "tslib": "2.6.0", + "typescript": "5.3.3" }, "devDependencies": { - "@craco/craco": "^6.4.3", - "@testing-library/react-hooks": "^7.0.1", - "@types/jsrsasign": "^9.0.3", - "@types/lodash.chunk": "^4.2.6", - "@typescript-eslint/eslint-plugin": "^5.5.0", - "@typescript-eslint/parser": "^5.13.0", - "babel-eslint": "10.1.0", - "cross-env": "^7.0.3", - "cypress": "9.5.1", - "cypress-failed-log": "^2.9.1", - "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.15.6", - "enzyme-to-json": "^3.6.1", - "eslint": "^8.9.0", - "eslint-config-prettier": "^8.3.0", - "eslint-config-react-app": "^7.0.0", - "eslint-plugin-cypress": "^2.12.1", - "eslint-plugin-prettier": "^3.3.1", - "jsrsasign": "^10.5.8", - "lint-staged": "^10.5.4", - "prettier": "^2.2.1", - "serve": "^13.0.2", - "start-server-and-test": "^1.14.0" + "@babel/eslint-parser": "7.23.3", + "@testing-library/jest-dom": "6.4.1", + "@testing-library/react": "12.1.3", + "@testing-library/react-hooks": "8.0.1", + "@testing-library/user-event": "14.5.2", + "@types/jsrsasign": "10.5.2", + "@types/lodash.chunk": "4.2.6", + "@typescript-eslint/eslint-plugin": "5.62.0", + "@typescript-eslint/parser": "5.62.0", + "cross-env": "7.0.3", + "cypress": "13.6.4", + "cypress-failed-log": "2.10.0", + "eslint": "8.56.0", + "eslint-config-react-app": "7.0.0", + "jest-fail-on-console": "3.1.1", + "lint-staged": "13.3.0", + "serve": "14.2.0", + "start-server-and-test": "2.0.0" }, "scripts": { "start": "craco start", "build": "craco build", - "serve:build": "yarn build & serve -l 5001 build", + "serve:build": "yarn build && serve -l 5001 build", "test": "craco test --env=jsdom --coverage --watchAll=false", "test:watch": "craco test --env=jsdom --watch", "build:e2e": "cross-env REACT_APP_E2E_TESTING=true GENERATE_SOURCEMAP=false craco build", @@ -69,7 +75,7 @@ "e2e": "start-server-and-test e2e:serve http://localhost:3000 cy:run", "cy:open": "cypress open", "cy:run": "cypress run", - "lint:js": "eslint --ext=tsx --ext=ts --ext=js --ext=jsx --fix ./src && yarn build", + "lint:js": "eslint --max-warnings=0 --ext=tsx --ext=ts --ext=js --ext=jsx --fix ./src ./cypress && tsc --noEmit", "eject": "react-scripts eject", "pre-commit": "lint-staged" }, @@ -96,8 +102,8 @@ ] }, "jest": { - "snapshotSerializers": [ - "enzyme-to-json/serializer" + "transformIgnorePatterns": [ + "node_modules/(?!axios)" ], "collectCoverageFrom": [ "src/**/*.{tsx,ts,js,jsx}", diff --git a/packages/datagateway-download/public/datagateway-download-settings.example.json b/packages/datagateway-download/public/datagateway-download-settings.example.json index 52e863264..58b15575a 100644 --- a/packages/datagateway-download/public/datagateway-download-settings.example.json +++ b/packages/datagateway-download/public/datagateway-download-settings.example.json @@ -62,5 +62,8 @@ "order": 1 } ], - "pluginHost": "http://localhost:3000" + "pluginHost": "http://localhost:3000", + "uiFeatures": { + "downloadProgress": false + } } diff --git a/packages/datagateway-download/public/index.html b/packages/datagateway-download/public/index.html index 91d5eccc8..638640b82 100644 --- a/packages/datagateway-download/public/index.html +++ b/packages/datagateway-download/public/index.html @@ -25,12 +25,12 @@ Learn how to configure a non-root public URL by running `npm run build`. --> DataGateway Download diff --git a/packages/datagateway-download/public/res/default.json b/packages/datagateway-download/public/res/default.json index ba4da5171..415b80cfc 100644 --- a/packages/datagateway-download/public/res/default.json +++ b/packages/datagateway-download/public/res/default.json @@ -34,7 +34,11 @@ "expired": "Expired", "paused": "Paused", "preparing": "Preparing", - "restoring": "Restoring from tape" + "restoring": "Restoring from tape", + "progress": "Progress", + "calculating_progress": "Calculating...", + "progress_unavailable": "Unknown", + "progress_complete": "" }, "downloadConfirmDialog": { "close_arialabel": "Close download confirmation dialog", @@ -69,7 +73,8 @@ "confirmation_download_name": "Download Name", "confirmation_access_method": "Access Method", "confirmation_email": "Email Address", - "view_my_downloads": "View My Downloads" + "view_my_downloads": "View My Downloads", + "submitting_cart": "Preparing..." }, "downloadCart": { "name": "Name", @@ -80,6 +85,9 @@ "remove": "Remove {{name}} from selection", "remove_all": "Remove All", "download": "Download Selection", + "generate_DOI": "Generate DOI", + "mintability_loading": "Checking whether you have permission to mint these files...", + "not_mintable": "You do not have permission to mint these files", "number_of_files": "Number of files", "total_size": "Total size", "no_selections": "No data selected. <2>Browse or <6>search for data.", @@ -88,5 +96,50 @@ "empty_items_error": "You have selected some empty items - please remove them to proceed with downloading your selection", "file_limit_error": "Too many files - you have exceeded limit of {{fileCountMax}} files - please remove some files", "size_limit_error": "Too much data - you have exceeded limit of {{totalSizeMax}} - please remove some files" + }, + "acceptDataPolicy": { + "accept": "Accept", + "data_policy": "Accept data policy: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum lore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." + }, + "DOIGenerationForm": { + "page_header": "Generate DOI", + "data_header": "Data", + "form_header": "Details", + "title": "DOI Title", + "description": "DOI Description", + "creators": "Creators & Contributors", + "username": "Username", + "add_creator": "Add Creator", + "add_contributor": "Add Contributor", + "creator_name": "Name", + "creator_affiliation": "Affiliation", + "creator_email": "Email", + "creator_type": "Contributor Type", + "creator_action": "Action", + "delete_creator": "Delete", + "related_dois": "Related DOIs", + "related_doi": "DOI", + "add_related_doi": "Add DOI", + "related_doi_doi": "DOI", + "related_doi_relationship": "Relationship", + "related_doi_resource_type": "Resource Type", + "related_doi_action": "Action", + "delete_related_doi": "Delete", + "generate_DOI": "Generate DOI", + "cart_tabs_aria_label": "cart tabs", + "cart_tab_investigations": "Investigations", + "cart_tab_datasets": "Datasets", + "cart_tab_datafiles": "Datafiles", + "cart_table_name": "Name" + }, + "DOIConfirmDialog": { + "dialog_title": "Mint Confirmation", + "mint_success": "Mint was successful", + "mint_error": "Mint was unsuccessful", + "mint_loading": "Loading...", + "concept_doi_label": "Concept DOI", + "version_doi_label": "Version DOI", + "error_label": "Error", + "view_data_publication": "View Data Publication" } -} \ No newline at end of file +} diff --git a/packages/datagateway-download/server/e2e-settings.json b/packages/datagateway-download/server/e2e-settings.json index fa852da0a..676dd62aa 100644 --- a/packages/datagateway-download/server/e2e-settings.json +++ b/packages/datagateway-download/server/e2e-settings.json @@ -3,6 +3,8 @@ "apiUrl": "http://localhost:5000", "downloadApiUrl": "https://localhost:8181/topcat", "idsUrl": "https://localhost:8181/ids", + "doiMinterUrl": "http://localhost:8000", + "dataCiteUrl": "https://api.test.datacite.org", "fileCountMax": 5000, "totalSizeMax": 1000000000000, "accessMethods": { @@ -61,5 +63,6 @@ "admin": true, "order": 0 } - ] + ], + "uiFeatures": [] } diff --git a/packages/datagateway-download/server/e2e-test-server.js b/packages/datagateway-download/server/e2e-test-server.js index d8b59ed6b..57d55d6b3 100644 --- a/packages/datagateway-download/server/e2e-test-server.js +++ b/packages/datagateway-download/server/e2e-test-server.js @@ -1,11 +1,21 @@ -var express = require('express'); -var path = require('path'); -var serveStatic = require('serve-static'); +const express = require('express'); +const path = require('path'); +const serveStatic = require('serve-static'); -var app = express(); +const app = express(); app.get('/datagateway-download-settings.json', function (req, res) { - res.sendFile(path.resolve('./server/e2e-settings.json')); + // detect if the E2E test is running inside CI + // If so, use the settings file specific to E2E + // Otherwise, use the same settings file that is also for running the app normally (yarn start etc). + const isCiEnv = process.env.CI; + res.sendFile( + path.resolve( + isCiEnv + ? './server/e2e-settings.json' + : './public/datagateway-download-settings.json' + ) + ); }); app.use( diff --git a/packages/datagateway-download/src/App.test.tsx b/packages/datagateway-download/src/App.test.tsx index 13edb219e..b2256b55e 100644 --- a/packages/datagateway-download/src/App.test.tsx +++ b/packages/datagateway-download/src/App.test.tsx @@ -1,27 +1,14 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; -import { createMount } from '@material-ui/core/test-utils'; -import { mount as enzymeMount } from 'enzyme'; -import * as log from 'loglevel'; +import { render } from '@testing-library/react'; +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; import { act } from 'react-dom/test-utils'; -import { StylesProvider } from '@material-ui/core/styles'; +import App, { ErrorFallback } from './App'; import { flushPromises } from './setupTests'; jest.mock('loglevel'); jest.mock('./ConfigProvider'); describe('App', () => { - let mount: typeof enzymeMount; - - beforeAll(() => { - mount = createMount(); - }); - - afterAll(() => { - mount.cleanUp(); - }); - it('renders without crashing', async () => { const div = document.createElement('div'); @@ -33,24 +20,11 @@ describe('App', () => { ReactDOM.unmountComponentAtNode(div); }); +}); - it('catches errors using componentDidCatch and shows fallback UI', async () => { - const wrapper = mount(); - const error = new Error('test'); - - await act(async () => { - await flushPromises(); - }); - - wrapper.find(StylesProvider).simulateError(error); - - expect(wrapper.exists('.error')).toBe(true); - - expect(log.error).toHaveBeenCalled(); - const mockLog = (log.error as jest.Mock).mock; - - expect(mockLog.calls[0][0]).toEqual( - `datagateway-download failed with error: ${error}` - ); +describe('ErrorFallback', () => { + it('should should render an error message for when app fails catastrophically', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); }); }); diff --git a/packages/datagateway-download/src/App.tsx b/packages/datagateway-download/src/App.tsx index 1058ddbe3..949eb9d34 100644 --- a/packages/datagateway-download/src/App.tsx +++ b/packages/datagateway-download/src/App.tsx @@ -1,32 +1,19 @@ -import React, { Component } from 'react'; -import * as log from 'loglevel'; -import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; - -import DownloadTabs from './downloadTab/downloadTab.component'; - -import { - createGenerateClassName, - StylesProvider, -} from '@material-ui/core/styles'; -import ConfigProvider from './ConfigProvider'; import { + DGThemeProvider, MicroFrontendId, Preloader, RequestPluginRerenderType, } from 'datagateway-common'; -import { DGThemeProvider } from 'datagateway-common'; -import AdminDownloadStatusTable from './downloadStatus/adminDownloadStatusTable.component'; -import { QueryClientProvider, QueryClient } from 'react-query'; +import React, { Component } from 'react'; +import { QueryClient, QueryClientProvider } from 'react-query'; import { ReactQueryDevtools } from 'react-query/devtools'; +import { BrowserRouter as Router, Link, Route, Switch } from 'react-router-dom'; -const generateClassName = createGenerateClassName({ - productionPrefix: 'dgwd', +import ConfigProvider from './ConfigProvider'; +import DOIGenerationForm from './DOIGenerationForm/DOIGenerationForm.component'; +import AdminDownloadStatusTable from './downloadStatus/adminDownloadStatusTable.component'; - // Only set disable when we are in production and not running e2e tests; - // ensures class selectors are working on tests. - disableGlobal: - process.env.NODE_ENV === 'production' && !process.env.REACT_APP_E2E_TESTING, -}); +import DownloadTabs from './downloadTab/downloadTab.component'; const queryClient = new QueryClient({ defaultOptions: { @@ -37,6 +24,26 @@ const queryClient = new QueryClient({ }, }); +/** + * A fallback component when the app fails to render. + */ +function ErrorFallback(): JSX.Element { + return ( +
+
+ Something went wrong... +
+
+ ); +} + class App extends Component { public constructor(props: unknown) { super(props); @@ -67,59 +74,45 @@ class App extends Component { document.removeEventListener(MicroFrontendId, this.handler); } - public componentDidCatch(error: Error | null): void { - this.setState({ hasError: true }); - log.error(`datagateway-download failed with error: ${error}`); - } - public render(): React.ReactNode { - if (this.state.hasError) { - return ( -
-
- Something went wrong... -
-
- ); - } - return (
- - - - - Finished loading - } - > - - - - - - - - - - - - - - - - + + + + Finished loading + } + > + + + {/* development redirect route so people don't get confused by blank screen */} + Downloads} + /> + + + + + + + + + + + + + + + +
); } } export default App; +export { ErrorFallback }; diff --git a/packages/datagateway-download/src/ConfigProvider.test.tsx b/packages/datagateway-download/src/ConfigProvider.test.tsx index 0701e3f73..3a9dbc70e 100644 --- a/packages/datagateway-download/src/ConfigProvider.test.tsx +++ b/packages/datagateway-download/src/ConfigProvider.test.tsx @@ -1,8 +1,8 @@ -import { createMount } from '@material-ui/core/test-utils'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; import axios from 'axios'; -import { ReactWrapper } from 'enzyme'; -import * as log from 'loglevel'; -import React from 'react'; +import log from 'loglevel'; +import * as React from 'react'; import ConfigProvider, { DownloadSettingsContext } from './ConfigProvider'; import { flushPromises } from './setupTests'; @@ -12,7 +12,7 @@ const ConfigTest: React.FC = (): React.ReactElement => { const settings = React.useContext(DownloadSettingsContext); // Return the settings as a string to inspect later in tests. - return
{JSON.stringify(settings)}
; + return
{JSON.stringify(settings)}
; }; jest.mock('./settings', () => ({ @@ -42,68 +42,63 @@ jest.mock('./settings', () => ({ })); describe('ConfigProvider', () => { - let mount; - beforeEach(() => { - mount = createMount(); global.document.dispatchEvent = jest.fn(); global.CustomEvent = jest.fn(); }); afterEach(() => { - mount.cleanUp(); - (axios.get as jest.Mock).mockClear(); (log.error as jest.Mock).mockClear(); (CustomEvent as jest.Mock).mockClear(); }); // Create a wrapper for our settings tests. - const createWrapper = (): ReactWrapper => { - return mount( + const renderComponent = (): RenderResult => + render( ); - }; it('settings are loaded', async () => { - // Create the wrapper and wait for it to load. - const wrapper = createWrapper(); + renderComponent(); // Preloader is in a loading state when ConfigProvider is // loading the configuration. - expect(wrapper.find('Preloader').prop('loading')).toBe(true); + expect(await screen.findByRole('progressbar')).toBeInTheDocument(); + // pretend settings has finished loading. await flushPromises(); - wrapper.update(); - expect(wrapper.find('Preloader').prop('loading')).toBe(false); - expect(wrapper.exists('#settings')).toBe(true); - expect(wrapper.find('#settings').text()).toEqual( - JSON.stringify({ - facilityName: 'Generic', - idsUrl: 'ids', - apiUrl: 'api', - downloadApiUrl: 'download-api', - fileCountMax: 5000, - totalSizeMax: 1000000000000, - accessMethods: { - https: { - idsUrl: 'https-ids', - displayName: 'HTTPS', - description: 'HTTP description', + await waitFor(() => { + expect(screen.queryByRole('progressbar')).toBeNull(); + expect(screen.getByTestId('settings')).toBeInTheDocument(); + expect(screen.getByTestId('settings')).toHaveTextContent( + JSON.stringify({ + facilityName: 'Generic', + idsUrl: 'ids', + apiUrl: 'api', + downloadApiUrl: 'download-api', + fileCountMax: 5000, + totalSizeMax: 1000000000000, + accessMethods: { + https: { + idsUrl: 'https-ids', + displayName: 'HTTPS', + description: 'HTTP description', + }, }, - }, - routes: [ - { - section: 'section', - link: 'link', - displayName: 'displayName', - }, - ], - pluginHost: 'http://localhost:3000/', - }) - ); + routes: [ + { + section: 'section', + link: 'link', + displayName: 'displayName', + }, + ], + pluginHost: 'http://localhost:3000/', + }) + ); + }); }); }); diff --git a/packages/datagateway-download/src/ConfigProvider.tsx b/packages/datagateway-download/src/ConfigProvider.tsx index 9c756d707..f5c7ee468 100644 --- a/packages/datagateway-download/src/ConfigProvider.tsx +++ b/packages/datagateway-download/src/ConfigProvider.tsx @@ -15,6 +15,8 @@ export interface DownloadSettings { apiUrl: string; downloadApiUrl: string; idsUrl: string; + doiMinterUrl?: string; + dataCiteUrl?: string; fileCountMax?: number; totalSizeMax?: number; @@ -23,23 +25,36 @@ export interface DownloadSettings { routes: PluginRoute[]; helpSteps: { target: string; content: string }[]; pluginHost?: string; + + /** + * A map of UI flags that can toggle certain UI features.. + */ + uiFeatures: { + /** + * Enables download progress to be displayed in download status tables when set to true. + */ + downloadProgress: boolean; + }; } -const initialConfiguration = { +const initialConfiguration: DownloadSettings = { facilityName: '', apiUrl: '', downloadApiUrl: '', idsUrl: '', + doiMinterUrl: '', fileCountMax: undefined, totalSizeMax: undefined, accessMethods: {}, routes: [], helpSteps: [], + uiFeatures: { + downloadProgress: false, + }, }; -export const DownloadSettingsContext = React.createContext( - initialConfiguration -); +export const DownloadSettingsContext = + React.createContext(initialConfiguration); class ConfigProvider extends React.Component< { children: React.ReactNode }, diff --git a/packages/datagateway-download/src/DOIGenerationForm/DOIConfirmDialog.component.test.tsx b/packages/datagateway-download/src/DOIGenerationForm/DOIConfirmDialog.component.test.tsx new file mode 100644 index 000000000..6a37b6def --- /dev/null +++ b/packages/datagateway-download/src/DOIGenerationForm/DOIConfirmDialog.component.test.tsx @@ -0,0 +1,94 @@ +import { render, RenderResult, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { createMemoryHistory, MemoryHistory } from 'history'; +import * as React from 'react'; +import { Router } from 'react-router-dom'; +import DOIConfirmDialog from './DOIConfirmDialog.component'; + +describe('DOI Confirm Dialogue component', () => { + let user: ReturnType; + let props: React.ComponentProps; + + const renderComponent = (): RenderResult & { history: MemoryHistory } => { + const history = createMemoryHistory(); + return { + history, + ...render( + + + + ), + }; + }; + + beforeEach(() => { + user = userEvent.setup(); + props = { + open: true, + mintingStatus: 'loading', + data: undefined, + error: null, + setClose: jest.fn(), + }; + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should show loading indicator when mintingStatus is loading', async () => { + renderComponent(); + + expect(screen.getByRole('progressbar')).toBeInTheDocument(); + expect( + screen.getByText('DOIConfirmDialog.mint_loading') + ).toBeInTheDocument(); + + // expect user can't close the dialog + await user.type(screen.getByRole('dialog'), '{Esc}'); + expect( + screen.queryByRole('button', { + name: 'downloadConfirmDialog.close_arialabel', + }) + ).not.toBeInTheDocument(); + expect(props.setClose).not.toHaveBeenCalled(); + }); + + it('should show success indicators when mintingStatus is success and allow user to view their data publication', async () => { + props.mintingStatus = 'success'; + props.data = { + concept: { data_publication: '123456', doi: 'test_doi' }, + version: { data_publication: '1234561', doi: 'test_doiv1' }, + }; + const { history } = renderComponent(); + + expect( + screen.getByText('DOIConfirmDialog.mint_success') + ).toBeInTheDocument(); + expect(screen.getByText(/test_doi$/)).toBeInTheDocument(); + expect(screen.getByText(/test_doiv1$/)).toBeInTheDocument(); + + await user.click( + screen.getByRole('link', { + name: 'DOIConfirmDialog.view_data_publication', + }) + ); + expect(history.location).toMatchObject({ + pathname: `/browse/dataPublication/${props.data.version.data_publication}`, + }); + }); + + it('should show error indicators when mintingStatus is error and allow user to close the dialog', async () => { + props.mintingStatus = 'error'; + // @ts-expect-error fake minimal axios error + props.error = { response: { data: { detail: 'error msg' } } }; + renderComponent(); + + expect(screen.getByText('DOIConfirmDialog.mint_error')).toBeInTheDocument(); + expect(screen.getByText('error msg', { exact: false })).toBeInTheDocument(); + + // use Esc to close dialog + await user.type(screen.getByRole('dialog'), '{Esc}'); + expect(props.setClose).toHaveBeenCalled(); + }); +}); diff --git a/packages/datagateway-download/src/DOIGenerationForm/DOIConfirmDialog.component.tsx b/packages/datagateway-download/src/DOIGenerationForm/DOIConfirmDialog.component.tsx new file mode 100644 index 000000000..917726f1f --- /dev/null +++ b/packages/datagateway-download/src/DOIGenerationForm/DOIConfirmDialog.component.tsx @@ -0,0 +1,140 @@ +import { + Button, + CircularProgress, + Dialog, + Grid, + Typography, +} from '@mui/material'; +import { AxiosError } from 'axios'; +import { Mark } from 'datagateway-common'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { QueryStatus } from 'react-query'; +import { Link } from 'react-router-dom'; + +import type { DoiResponse } from '../downloadApi'; +import DialogContent from '../downloadConfirmation/dialogContent.component'; +import DialogTitle from '../downloadConfirmation/dialogTitle.component'; + +interface DOIConfirmDialogProps { + open: boolean; + mintingStatus: QueryStatus; + data: DoiResponse | undefined; + error: AxiosError<{ + detail: { msg: string }[] | string; + }> | null; + + setClose: () => void; +} + +const DOIConfirmDialog: React.FC = ( + props: DOIConfirmDialogProps +) => { + const { open, mintingStatus, data, error, setClose } = props; + + const isMintError = mintingStatus === 'error'; + + const isMintSuccess = mintingStatus === 'success'; + + const isMintLoading = mintingStatus === 'loading'; + + const [t] = useTranslation(); + + return ( + { + if (isMintError) { + setClose(); + } + }} + open={open} + fullWidth={true} + maxWidth={'sm'} + > +
+ setClose() : undefined}> + {t('DOIConfirmDialog.dialog_title')} + + + + + {isMintSuccess ? ( + + ) : isMintError ? ( + + ) : isMintLoading ? ( + + ) : null} + + + {isMintSuccess ? ( + + {t('DOIConfirmDialog.mint_success')} + + ) : isMintError ? ( + + {t('DOIConfirmDialog.mint_error')} + + ) : ( + + {t('DOIConfirmDialog.mint_loading')} + + )} + + {isMintSuccess && data && ( + + + {`${t('DOIConfirmDialog.concept_doi_label')}: ${ + data.concept.doi + }`} + + + {`${t('DOIConfirmDialog.version_doi_label')}: ${ + data.version.doi + }`} + + + )} + + {isMintError && error && ( + + + {`${t('DOIConfirmDialog.error_label')}: + ${ + error.response?.data?.detail + ? typeof error.response.data.detail === 'string' + ? error.response.data.detail + : error.response.data.detail[0].msg + : error.message + }`} + + + )} + + {isMintSuccess && data && ( + + + + )} + + +
+
+ ); +}; + +export default DOIConfirmDialog; diff --git a/packages/datagateway-download/src/DOIGenerationForm/DOIGenerationForm.component.test.tsx b/packages/datagateway-download/src/DOIGenerationForm/DOIGenerationForm.component.test.tsx new file mode 100644 index 000000000..0e19c66cb --- /dev/null +++ b/packages/datagateway-download/src/DOIGenerationForm/DOIGenerationForm.component.test.tsx @@ -0,0 +1,525 @@ +import { + render, + RenderResult, + screen, + waitForElementToBeRemoved, + within, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { fetchDownloadCart } from 'datagateway-common'; +import { createMemoryHistory, MemoryHistory } from 'history'; +import * as React from 'react'; +import { QueryClient, QueryClientProvider, setLogger } from 'react-query'; +import { Router } from 'react-router-dom'; +import { DownloadSettingsContext } from '../ConfigProvider'; +import { mockCartItems, mockedSettings } from '../testData'; +import { + checkUser, + DOIRelationType, + DOIResourceType, + fetchDOI, + getCartUsers, + isCartMintable, + mintCart, +} from '../downloadApi'; +import DOIGenerationForm from './DOIGenerationForm.component'; + +setLogger({ + log: console.log, + warn: console.warn, + error: jest.fn(), +}); + +jest.mock('datagateway-common', () => { + const originalModule = jest.requireActual('datagateway-common'); + + return { + __esModule: true, + ...originalModule, + fetchDownloadCart: jest.fn(), + }; +}); + +jest.mock('../downloadApi', () => { + const originalModule = jest.requireActual('../downloadApi'); + + return { + ...originalModule, + isCartMintable: jest.fn(), + getCartUsers: jest.fn(), + checkUser: jest.fn(), + mintCart: jest.fn(), + fetchDOI: jest.fn(), + }; +}); + +const createTestQueryClient = (): QueryClient => + new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }); + +const renderComponent = ( + history = createMemoryHistory({ + initialEntries: [{ pathname: '/download/mint', state: { fromCart: true } }], + }) +): RenderResult & { history: MemoryHistory } => ({ + history, + ...render( + + + + + + + + ), +}); + +describe('DOI generation form component', () => { + let user: ReturnType; + + beforeEach(() => { + user = userEvent.setup(); + + ( + fetchDownloadCart as jest.MockedFunction + ).mockResolvedValue(mockCartItems); + + ( + isCartMintable as jest.MockedFunction + ).mockResolvedValue(true); + + // mock mint cart error to test dialog can be closed after it errors + (mintCart as jest.MockedFunction).mockRejectedValue( + 'error' + ); + + ( + getCartUsers as jest.MockedFunction + ).mockResolvedValue([ + { + id: 1, + name: '1', + fullName: 'User 1', + email: 'user1@example.com', + affiliation: 'Example Uni', + }, + ]); + + (checkUser as jest.MockedFunction).mockResolvedValue({ + id: 2, + name: '2', + fullName: 'User 2', + email: 'user2@example.com', + affiliation: 'Example 2 Uni', + }); + + (fetchDOI as jest.MockedFunction).mockResolvedValue({ + id: '1', + type: 'DOI', + attributes: { + doi: 'related.doi.1', + titles: [{ title: 'Related DOI 1' }], + url: 'www.example.com', + }, + }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should redirect back to /download if user directly accesses the url', async () => { + const { history } = renderComponent(createMemoryHistory()); + + expect(history.location).toMatchObject({ pathname: '/download' }); + }); + + it('should render the data policy before loading the form', async () => { + renderComponent(); + + expect( + screen.getByRole('button', { name: 'acceptDataPolicy.accept' }) + ).toBeInTheDocument(); + expect( + screen.queryByText('DOIGenerationForm.page_header') + ).not.toBeInTheDocument(); + }); + + it('should let the user fill in the required fields and submit a mint request', async () => { + renderComponent(); + + // accept data policy + await user.click( + screen.getByRole('button', { name: 'acceptDataPolicy.accept' }) + ); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.title' }), + 't' + ); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.description' }), + 'd' + ); + + await user.click( + screen.getByRole('button', { name: 'DOIGenerationForm.generate_DOI' }) + ); + + expect( + await screen.findByRole('dialog', { + name: 'DOIConfirmDialog.dialog_title', + }) + ).toBeInTheDocument(); + + await user.click( + screen.getByRole('button', { + name: 'downloadConfirmDialog.close_arialabel', + }) + ); + + await waitForElementToBeRemoved(() => + screen.queryByRole('dialog', { + name: 'DOIConfirmDialog.dialog_title', + }) + ); + }); + + it('should not let the user submit a mint request if required fields are missing but can submit once all are filled in', async () => { + renderComponent(); + + // accept data policy + await user.click( + screen.getByRole('button', { name: 'acceptDataPolicy.accept' }) + ); + + // missing title + expect( + screen.getByRole('button', { name: 'DOIGenerationForm.generate_DOI' }) + ).toBeDisabled(); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.title' }), + 't' + ); + + // missing description + expect( + screen.getByRole('button', { name: 'DOIGenerationForm.generate_DOI' }) + ).toBeDisabled(); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.description' }), + 'd' + ); + + // missing cart users + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.username' }), + '2' + ); + + await user.click( + screen.getByRole('button', { name: 'DOIGenerationForm.add_contributor' }) + ); + + // missing contributor type + expect( + screen.getByRole('button', { name: 'DOIGenerationForm.generate_DOI' }) + ).toBeDisabled(); + + await user.click( + screen.getByRole('button', { + name: /DOIGenerationForm.creator_type/i, + }) + ); + await user.click( + await screen.findByRole('option', { name: 'DataCollector' }) + ); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.related_doi' }), + '1' + ); + + await user.click( + screen.getByRole('button', { name: 'DOIGenerationForm.add_related_doi' }) + ); + + // missing relationship type + expect( + screen.getByRole('button', { name: 'DOIGenerationForm.generate_DOI' }) + ).toBeDisabled(); + + await user.click( + screen.getByRole('button', { + name: /DOIGenerationForm.related_doi_relationship/i, + }) + ); + await user.click(await screen.findByRole('option', { name: 'IsCitedBy' })); + + // missing resource type + expect( + screen.getByRole('button', { name: 'DOIGenerationForm.generate_DOI' }) + ).toBeDisabled(); + + await user.click( + screen.getByRole('button', { + name: /DOIGenerationForm.related_doi_resource_type/i, + }) + ); + await user.click(await screen.findByRole('option', { name: 'Journal' })); + + await user.click( + screen.getByRole('button', { name: 'DOIGenerationForm.generate_DOI' }) + ); + + expect(mintCart).toHaveBeenCalledWith( + mockCartItems, + { + title: 't', + description: 'd', + creators: [ + { username: '1', contributor_type: 'Creator' }, + { username: '2', contributor_type: 'DataCollector' }, + ], + related_items: [ + { + title: 'Related DOI 1', + fullReference: '', + identifier: 'related.doi.1', + relationType: DOIRelationType.IsCitedBy, + relatedItemType: DOIResourceType.Journal, + }, + ], + }, + expect.any(Object) + ); + }); + + it('should not let the user submit a mint request if cart fails to load', async () => { + ( + fetchDownloadCart as jest.MockedFunction + ).mockRejectedValue({ message: 'error' }); + renderComponent(); + + // accept data policy + await user.click( + screen.getByRole('button', { name: 'acceptDataPolicy.accept' }) + ); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.title' }), + 't' + ); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.description' }), + 'd' + ); + + // missing cart + expect( + screen.getByRole('button', { name: 'DOIGenerationForm.generate_DOI' }) + ).toBeDisabled(); + }); + + it('should not let the user submit a mint request if cart is empty', async () => { + ( + fetchDownloadCart as jest.MockedFunction + ).mockResolvedValue([]); + renderComponent(); + + // accept data policy + await user.click( + screen.getByRole('button', { name: 'acceptDataPolicy.accept' }) + ); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.title' }), + 't' + ); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.description' }), + 'd' + ); + + // empty cart + expect( + screen.getByRole('button', { name: 'DOIGenerationForm.generate_DOI' }) + ).toBeDisabled(); + }); + + it('should not let the user submit a mint request if no users selected', async () => { + ( + getCartUsers as jest.MockedFunction + ).mockResolvedValue([]); + renderComponent(); + + // accept data policy + await user.click( + screen.getByRole('button', { name: 'acceptDataPolicy.accept' }) + ); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.title' }), + 't' + ); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.description' }), + 'd' + ); + + // no users + expect( + screen.getByRole('button', { name: 'DOIGenerationForm.generate_DOI' }) + ).toBeDisabled(); + + // expect add user + add contributor buttons to also be disabled + expect( + screen.getByRole('button', { name: 'DOIGenerationForm.add_creator' }) + ).toBeDisabled(); + expect( + screen.getByRole('button', { name: 'DOIGenerationForm.add_contributor' }) + ).toBeDisabled(); + }); + + it('should let the user change cart tabs', async () => { + renderComponent(); + + // accept data policy + await user.click( + screen.getByRole('button', { name: 'acceptDataPolicy.accept' }) + ); + + expect( + within( + screen.getByRole('table', { name: 'cart investigation table' }) + ).getByRole('cell', { name: 'INVESTIGATION 1' }) + ).toBeInTheDocument(); + + await user.click( + screen.getByRole('tab', { name: 'DOIGenerationForm.cart_tab_datasets' }) + ); + + expect( + within( + screen.getByRole('table', { name: 'cart dataset table' }) + ).getByRole('cell', { name: 'DATASET 1' }) + ).toBeInTheDocument(); + }); + + describe('only displays cart tabs if the corresponding entity type exists in the cart: ', () => { + it('investigations', async () => { + ( + fetchDownloadCart as jest.MockedFunction + ).mockResolvedValue([mockCartItems[0]]); + + renderComponent(); + + // accept data policy + await user.click( + screen.getByRole('button', { name: 'acceptDataPolicy.accept' }) + ); + + expect( + within( + screen.getByRole('table', { name: 'cart investigation table' }) + ).getByRole('cell', { name: 'INVESTIGATION 1' }) + ).toBeInTheDocument(); + + expect( + screen.getByRole('tab', { + name: 'DOIGenerationForm.cart_tab_investigations', + }) + ).toBeInTheDocument(); + expect( + screen.queryByRole('tab', { + name: 'DOIGenerationForm.cart_tab_datasets', + }) + ).not.toBeInTheDocument(); + expect( + screen.queryByRole('tab', { + name: 'DOIGenerationForm.cart_tab_datafiles', + }) + ).not.toBeInTheDocument(); + }); + + it('datasets', async () => { + ( + fetchDownloadCart as jest.MockedFunction + ).mockResolvedValue([mockCartItems[2]]); + + renderComponent(); + + // accept data policy + await user.click( + screen.getByRole('button', { name: 'acceptDataPolicy.accept' }) + ); + + expect( + within( + screen.getByRole('table', { name: 'cart dataset table' }) + ).getByRole('cell', { name: 'DATASET 1' }) + ).toBeInTheDocument(); + + expect( + screen.queryByRole('tab', { + name: 'DOIGenerationForm.cart_tab_investigations', + }) + ).not.toBeInTheDocument(); + expect( + screen.getByRole('tab', { name: 'DOIGenerationForm.cart_tab_datasets' }) + ).toBeInTheDocument(); + expect( + screen.queryByRole('tab', { + name: 'DOIGenerationForm.cart_tab_datafiles', + }) + ).not.toBeInTheDocument(); + }); + + it('datafiles', async () => { + ( + fetchDownloadCart as jest.MockedFunction + ).mockResolvedValue([mockCartItems[3]]); + + renderComponent(); + + // accept data policy + await user.click( + screen.getByRole('button', { name: 'acceptDataPolicy.accept' }) + ); + + expect( + within( + screen.getByRole('table', { name: 'cart datafile table' }) + ).getByRole('cell', { name: 'DATAFILE 1' }) + ).toBeInTheDocument(); + + expect( + screen.queryByRole('tab', { + name: 'DOIGenerationForm.cart_tab_investigations', + }) + ).not.toBeInTheDocument(); + expect( + screen.queryByRole('tab', { + name: 'DOIGenerationForm.cart_tab_datasets', + }) + ).not.toBeInTheDocument(); + expect( + screen.getByRole('tab', { + name: 'DOIGenerationForm.cart_tab_datafiles', + }) + ).toBeInTheDocument(); + }); + }); +}); diff --git a/packages/datagateway-download/src/DOIGenerationForm/DOIGenerationForm.component.tsx b/packages/datagateway-download/src/DOIGenerationForm/DOIGenerationForm.component.tsx new file mode 100644 index 000000000..543ef4b3d --- /dev/null +++ b/packages/datagateway-download/src/DOIGenerationForm/DOIGenerationForm.component.tsx @@ -0,0 +1,299 @@ +import { + Box, + Button, + Grid, + Paper, + Tab, + Table, + TableBody, + TableCell, + TableHead, + TableRow, + Tabs, + TextField, + Typography, +} from '@mui/material'; +import { readSciGatewayToken } from 'datagateway-common'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { Redirect, useLocation } from 'react-router-dom'; +import { ContributorType, type RelatedDOI } from '../downloadApi'; +import { useCart, useCartUsers, useMintCart } from '../downloadApiHooks'; +import AcceptDataPolicy from './acceptDataPolicy.component'; +import CreatorsAndContributors, { + ContributorUser, +} from './creatorsAndContributors.component'; +import DOIConfirmDialog from './DOIConfirmDialog.component'; +import RelatedDOIs from './relatedDOIs.component'; + +const DOIGenerationForm: React.FC = () => { + const [acceptedDataPolicy, setAcceptedDataPolicy] = React.useState(false); + const [selectedUsers, setSelectedUsers] = React.useState( + [] + ); + const [relatedDOIs, setRelatedDOIs] = React.useState([]); + const [title, setTitle] = React.useState(''); + const [description, setDescription] = React.useState(''); + const [currentTab, setCurrentTab] = React.useState< + 'investigation' | 'dataset' | 'datafile' + >('investigation'); + const [showMintConfirmation, setShowMintConfirmation] = React.useState(false); + + const handleTabChange = ( + event: React.SyntheticEvent, + newValue: 'investigation' | 'dataset' | 'datafile' + ): void => { + setCurrentTab(newValue); + }; + + const { data: cart } = useCart(); + const { data: users } = useCartUsers(cart); + const { + mutate: mintCart, + status: mintingStatus, + data: mintData, + error: mintError, + } = useMintCart(); + + React.useEffect(() => { + if (users) + setSelectedUsers( + users.map((user) => ({ + ...user, + contributor_type: ContributorType.Creator, + })) + ); + }, [users]); + + React.useEffect(() => { + if (cart) { + if (cart?.some((cartItem) => cartItem.entityType === 'investigation')) + setCurrentTab('investigation'); + else if (cart?.some((cartItem) => cartItem.entityType === 'dataset')) + setCurrentTab('dataset'); + else if (cart?.some((cartItem) => cartItem.entityType === 'datafile')) + setCurrentTab('datafile'); + } + }, [cart]); + + const location = useLocation<{ fromCart: boolean } | undefined>(); + + const [t] = useTranslation(); + + // redirect if the user tries to access the link directly instead of from the cart + if (!location.state?.fromCart) { + return ; + } + + return ( + + {acceptedDataPolicy ? ( + <> + + {/* need to specify colour is textPrimary since this Typography is not in a Paper */} + + {t('DOIGenerationForm.page_header')} + + + {/* use row-reverse, justifyContent start and the "wrong" order of components to make overflow layout nice + i.e. data summary presented at top before DOI form, but in non-overflow + mode it's DOI form on left and data summary on right */} + + + + + {t('DOIGenerationForm.data_header')} + + + + + + {cart?.some( + (cartItem) => cartItem.entityType === 'investigation' + ) && ( + + )} + {cart?.some( + (cartItem) => cartItem.entityType === 'dataset' + ) && ( + + )} + {cart?.some( + (cartItem) => cartItem.entityType === 'datafile' + ) && ( + + )} + + + {/* TODO: do we need to display more info in this table? + we could rejig the fetch for users to return more info we want + as we're already querying every item in the cart there */} +
+ + + + {t('DOIGenerationForm.cart_table_name')} + + + + + {cart + ?.filter( + (cartItem) => cartItem.entityType === currentTab + ) + .map((cartItem) => ( + + {cartItem.name} + + ))} + +
+ + + + + + {t('DOIGenerationForm.form_header')} + + + + setTitle(event.target.value)} + /> + + + setDescription(event.target.value)} + /> + + + + + + + + + + + + + + + {/* Show the download confirmation dialog. */} + setShowMintConfirmation(false)} + /> + + ) : ( + setAcceptedDataPolicy(true)} + /> + )} + + ); +}; + +export default DOIGenerationForm; diff --git a/packages/datagateway-download/src/DOIGenerationForm/acceptDataPolicy.component.tsx b/packages/datagateway-download/src/DOIGenerationForm/acceptDataPolicy.component.tsx new file mode 100644 index 000000000..57c17f91f --- /dev/null +++ b/packages/datagateway-download/src/DOIGenerationForm/acceptDataPolicy.component.tsx @@ -0,0 +1,45 @@ +import { Button, Grid, Paper, Typography } from '@mui/material'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +type AcceptDataPolicyProps = { + acceptDataPolicy: () => void; +}; + +const AcceptDataPolicy: React.FC = (props) => { + const [t] = useTranslation(); + return ( + + + + + {/* TODO: write data policy text */} + + {t('acceptDataPolicy.data_policy')} + + + + + + + + + ); +}; + +export default AcceptDataPolicy; diff --git a/packages/datagateway-download/src/DOIGenerationForm/creatorsAndContributors.component.test.tsx b/packages/datagateway-download/src/DOIGenerationForm/creatorsAndContributors.component.test.tsx new file mode 100644 index 000000000..f00d715a5 --- /dev/null +++ b/packages/datagateway-download/src/DOIGenerationForm/creatorsAndContributors.component.test.tsx @@ -0,0 +1,278 @@ +import { render, RenderResult, screen, within } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; +import { QueryClient, QueryClientProvider, setLogger } from 'react-query'; +import { DownloadSettingsContext } from '../ConfigProvider'; +import { mockedSettings } from '../testData'; +import { checkUser, ContributorType } from '../downloadApi'; +import CreatorsAndContributors from './creatorsAndContributors.component'; + +setLogger({ + log: console.log, + warn: console.warn, + error: jest.fn(), +}); + +jest.mock('datagateway-common', () => { + const originalModule = jest.requireActual('datagateway-common'); + + return { + __esModule: true, + ...originalModule, + readSciGatewayToken: jest.fn(() => ({ + username: '1', + })), + }; +}); + +jest.mock('../downloadApi', () => { + const originalModule = jest.requireActual('../downloadApi'); + + return { + ...originalModule, + + checkUser: jest.fn(), + }; +}); + +const createTestQueryClient = (): QueryClient => + new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }); + +describe('DOI generation form component', () => { + let user: ReturnType; + + let props: React.ComponentProps; + + const TestComponent: React.FC = () => { + const [selectedUsers, changeSelectedUsers] = React.useState( + // eslint-disable-next-line react/prop-types + props.selectedUsers + ); + + return ( + + + + + + ); + }; + + const renderComponent = (): RenderResult => render(); + + beforeEach(() => { + user = userEvent.setup(); + + props = { + selectedUsers: [ + { + id: 1, + name: '1', + fullName: 'User 1', + email: 'user1@example.com', + affiliation: 'Example Uni', + contributor_type: ContributorType.Creator, + }, + { + id: 2, + name: '2', + fullName: 'User 2', + email: 'user2@example.com', + affiliation: 'Example 2 Uni', + contributor_type: ContributorType.Creator, + }, + ], + changeSelectedUsers: jest.fn(), + }; + (checkUser as jest.MockedFunction).mockResolvedValue({ + id: 3, + name: '3', + fullName: 'User 3', + email: 'user3@example.com', + affiliation: 'Example 3 Uni', + }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should let the user delete users (but not delete the logged in user)', async () => { + renderComponent(); + + expect( + within(screen.getByRole('table', { name: 'DOIGenerationForm.creators' })) + .getAllByRole('row') + .slice(1) // ignores the header row + ).toHaveLength(2); + expect( + screen.getByRole('cell', { name: 'user2@example.com' }) + ).toBeInTheDocument(); + + const userDeleteButtons = screen.getAllByRole('button', { + name: 'DOIGenerationForm.delete_creator', + }); + expect(userDeleteButtons[0]).toBeDisabled(); + + await user.click(userDeleteButtons[1]); + + expect( + within(screen.getByRole('table', { name: 'DOIGenerationForm.creators' })) + .getAllByRole('row') + .slice(1) + ).toHaveLength(1); + expect( + screen.getByRole('cell', { name: 'Example Uni' }) + ).toBeInTheDocument(); + }); + + it('should let the user add creators (but not duplicate users or if checkUser fails)', async () => { + renderComponent(); + + expect( + within(screen.getByRole('table', { name: 'DOIGenerationForm.creators' })) + .getAllByRole('row') + .slice(1) // ignores the header row + ).toHaveLength(2); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.username' }), + '3' + ); + + await user.click( + screen.getByRole('button', { name: 'DOIGenerationForm.add_creator' }) + ); + + expect( + within(screen.getByRole('table', { name: 'DOIGenerationForm.creators' })) + .getAllByRole('row') + .slice(1) // ignores the header row + ).toHaveLength(3); + expect(screen.getByRole('cell', { name: 'User 3' })).toBeInTheDocument(); + expect(screen.getAllByRole('cell', { name: 'Creator' }).length).toBe(3); + + // test errors on duplicate user + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.username' }), + '3' + ); + + await user.click( + screen.getByRole('button', { name: 'DOIGenerationForm.add_creator' }) + ); + + expect( + within(screen.getByRole('table', { name: 'DOIGenerationForm.creators' })) + .getAllByRole('row') + .slice(1) // ignores the header row + ).toHaveLength(3); + expect(screen.getByText('Cannot add duplicate user')).toBeInTheDocument(); + expect( + screen.getByRole('textbox', { name: 'DOIGenerationForm.username' }) + ).toHaveValue(''); + + // test errors with various API error responses + (checkUser as jest.MockedFunction).mockRejectedValueOnce({ + response: { data: { detail: 'error msg' }, status: 404 }, + }); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.username' }), + '4' + ); + + await user.click( + screen.getByRole('button', { name: 'DOIGenerationForm.add_creator' }) + ); + + expect(await screen.findByText('error msg')).toBeInTheDocument(); + expect( + within(screen.getByRole('table', { name: 'DOIGenerationForm.creators' })) + .getAllByRole('row') + .slice(1) // ignores the header row + ).toHaveLength(3); + + (checkUser as jest.MockedFunction).mockRejectedValue({ + response: { data: { detail: [{ msg: 'error msg 2' }] }, status: 404 }, + }); + await user.click( + screen.getByRole('button', { name: 'DOIGenerationForm.add_creator' }) + ); + + expect(await screen.findByText('error msg 2')).toBeInTheDocument(); + expect( + within(screen.getByRole('table', { name: 'DOIGenerationForm.creators' })) + .getAllByRole('row') + .slice(1) // ignores the header row + ).toHaveLength(3); + + (checkUser as jest.MockedFunction).mockRejectedValueOnce({ + response: { status: 422 }, + }); + await user.click( + screen.getByRole('button', { name: 'DOIGenerationForm.add_creator' }) + ); + + expect(await screen.findByText('Error')).toBeInTheDocument(); + expect( + within(screen.getByRole('table', { name: 'DOIGenerationForm.creators' })) + .getAllByRole('row') + .slice(1) // ignores the header row + ).toHaveLength(3); + }); + + it('should let the user add contributors & select their contributor type', async () => { + renderComponent(); + + expect( + within(screen.getByRole('table', { name: 'DOIGenerationForm.creators' })) + .getAllByRole('row') + .slice(1) // ignores the header row + ).toHaveLength(2); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.username' }), + '3' + ); + + await user.click( + screen.getByRole('button', { name: 'DOIGenerationForm.add_contributor' }) + ); + + expect( + within(screen.getByRole('table', { name: 'DOIGenerationForm.creators' })) + .getAllByRole('row') + .slice(1) // ignores the header row + ).toHaveLength(3); + expect(screen.getByRole('cell', { name: 'User 3' })).toBeInTheDocument(); + + expect( + screen.getByRole('button', { + name: /DOIGenerationForm.creator_type/i, + }) + ).toBeInTheDocument(); + + await user.click( + screen.getByRole('button', { + name: /DOIGenerationForm.creator_type/i, + }) + ); + await user.click( + await screen.findByRole('option', { name: 'DataCollector' }) + ); + + expect(screen.queryByRole('option')).not.toBeInTheDocument(); + // check that the option is actually selected in the table even after the menu closes + expect(screen.getByText('DataCollector')).toBeInTheDocument(); + }); +}); diff --git a/packages/datagateway-download/src/DOIGenerationForm/creatorsAndContributors.component.tsx b/packages/datagateway-download/src/DOIGenerationForm/creatorsAndContributors.component.tsx new file mode 100644 index 000000000..5cca13279 --- /dev/null +++ b/packages/datagateway-download/src/DOIGenerationForm/creatorsAndContributors.component.tsx @@ -0,0 +1,289 @@ +import { + Button, + CircularProgress, + FormControl, + Grid, + InputLabel, + MenuItem, + Paper, + Select, + Table, + TableBody, + TableCell, + TableHead, + TableRow, + TextField, + Typography, +} from '@mui/material'; +import { AxiosError } from 'axios'; +import { readSciGatewayToken, User } from 'datagateway-common'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { ContributorType } from '../downloadApi'; +import { useCheckUser } from '../downloadApiHooks'; + +export type ContributorUser = User & { + contributor_type: ContributorType | ''; +}; + +const compareUsers = (a: ContributorUser, b: ContributorUser): number => { + if ( + a.contributor_type === ContributorType.Creator && + b.contributor_type !== ContributorType.Creator + ) { + return -1; + } else if ( + b.contributor_type === ContributorType.Creator && + a.contributor_type !== ContributorType.Creator + ) { + return 1; + } else return 0; +}; + +type CreatorsAndContributorsProps = { + selectedUsers: ContributorUser[]; + changeSelectedUsers: React.Dispatch>; +}; + +const CreatorsAndContributors: React.FC = ( + props +) => { + const { selectedUsers, changeSelectedUsers } = props; + const [t] = useTranslation(); + const [username, setUsername] = React.useState(''); + const [usernameError, setUsernameError] = React.useState(''); + const { refetch: checkUser } = useCheckUser(username); + + /** + * Returns a function, which you pass true or false to depending on whether + * it's the creator button or not, and returns the relevant click handler + */ + const handleAddCreatorOrContributorClick = React.useCallback( + (creator: boolean) => () => { + // don't let the user add duplicates + if ( + selectedUsers.every((selectedUser) => selectedUser.name !== username) + ) { + checkUser({ throwOnError: true }) + .then((response) => { + // add user + if (response.data) { + const user: ContributorUser = { + ...response.data, + contributor_type: creator ? ContributorType.Creator : '', + }; + changeSelectedUsers((selectedUsers) => [...selectedUsers, user]); + setUsername(''); + } + }) + .catch( + ( + error: AxiosError<{ + detail: { msg: string }[] | string; + }> + ) => { + // TODO: check this is the right message from the API + setUsernameError( + error.response?.data?.detail + ? typeof error.response.data.detail === 'string' + ? error.response.data.detail + : error.response.data.detail[0].msg + : 'Error' + ); + } + ); + } else { + setUsernameError('Cannot add duplicate user'); + setUsername(''); + } + }, + [changeSelectedUsers, checkUser, selectedUsers, username] + ); + + return ( + + theme.palette.mode === 'dark' + ? theme.palette.grey[800] + : theme.palette.grey[100], + padding: 1, + }} + elevation={0} + variant="outlined" + > + + + + {t('DOIGenerationForm.creators')} + + + 0 ? 2 : 0, + }} + > + + 0} + helperText={usernameError.length > 0 ? usernameError : ''} + color="secondary" + sx={{ + // this CSS makes it so that the helperText doesn't mess with the button alignment + '& .MuiFormHelperText-root': { + position: 'absolute', + bottom: '-1.5rem', + }, + }} + InputProps={{ + sx: { + backgroundColor: 'background.default', + }, + }} + value={username} + onChange={(event) => { + setUsername(event.target.value); + setUsernameError(''); + }} + /> + + + + + + + + + + + + + + + {t('DOIGenerationForm.creator_name')} + + {t('DOIGenerationForm.creator_affiliation')} + + {t('DOIGenerationForm.creator_email')} + {t('DOIGenerationForm.creator_type')} + {t('DOIGenerationForm.creator_action')} + + + + {selectedUsers.length === 0 && ( + + + + + + )} + {[...selectedUsers] // need to spread so we don't alter underlying array + .sort(compareUsers) + .map((user) => ( + + {user.fullName} + {user?.affiliation} + {user?.email} + + {user.contributor_type === ContributorType.Creator ? ( + ContributorType.Creator + ) : ( + + + {t('DOIGenerationForm.creator_type')} + + + + )} + + + + + + ))} + +
+
+
+
+ ); +}; + +export default CreatorsAndContributors; diff --git a/packages/datagateway-download/src/DOIGenerationForm/relatedDOIs.component.test.tsx b/packages/datagateway-download/src/DOIGenerationForm/relatedDOIs.component.test.tsx new file mode 100644 index 000000000..78c095b7c --- /dev/null +++ b/packages/datagateway-download/src/DOIGenerationForm/relatedDOIs.component.test.tsx @@ -0,0 +1,205 @@ +import { render, RenderResult, screen, within } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; +import { QueryClient, QueryClientProvider, setLogger } from 'react-query'; +import { DownloadSettingsContext } from '../ConfigProvider'; +import { mockedSettings } from '../testData'; +import { fetchDOI } from '../downloadApi'; +import RelatedDOIs from './relatedDOIs.component'; + +setLogger({ + log: console.log, + warn: console.warn, + error: jest.fn(), +}); + +jest.mock('../downloadApi', () => { + const originalModule = jest.requireActual('../downloadApi'); + + return { + ...originalModule, + + fetchDOI: jest.fn(), + }; +}); + +const createTestQueryClient = (): QueryClient => + new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }); + +describe('DOI generation form component', () => { + let user: ReturnType; + + let props: React.ComponentProps; + + const TestComponent: React.FC = () => { + const [relatedDOIs, changeRelatedDOIs] = React.useState( + // eslint-disable-next-line react/prop-types + props.relatedDOIs + ); + + return ( + + + + + + ); + }; + + const renderComponent = (): RenderResult => render(); + + beforeEach(() => { + user = userEvent.setup(); + + props = { + relatedDOIs: [ + { + title: 'Related DOI 1', + fullReference: '', + identifier: 'related.doi.1', + relationType: '', + relatedItemType: '', + }, + ], + changeRelatedDOIs: jest.fn(), + }; + (fetchDOI as jest.MockedFunction).mockResolvedValue({ + id: '2', + type: 'DOI', + attributes: { + doi: 'related.doi.2', + titles: [{ title: 'Related DOI 2' }], + url: 'www.example.com', + }, + }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should let the user add related dois (but not if fetchDOI fails) + lets you change the relation type + resource type', async () => { + renderComponent(); + + expect( + within( + screen.getByRole('table', { name: 'DOIGenerationForm.related_dois' }) + ) + .getAllByRole('row') + .slice(1) // ignores the header row + ).toHaveLength(1); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.related_doi' }), + '2' + ); + + await user.click( + screen.getByRole('button', { name: 'DOIGenerationForm.add_related_doi' }) + ); + + expect( + within( + screen.getByRole('table', { name: 'DOIGenerationForm.related_dois' }) + ) + .getAllByRole('row') + .slice(1) // ignores the header row + ).toHaveLength(2); + expect( + screen.getByRole('cell', { name: 'related.doi.2' }) + ).toBeInTheDocument(); + + await user.click( + screen.getAllByRole('button', { + name: /DOIGenerationForm.related_doi_relationship/i, + })[0] + ); + await user.click(await screen.findByRole('option', { name: 'IsCitedBy' })); + + expect(screen.queryByRole('option')).not.toBeInTheDocument(); + // check that the option is actually selected in the table even after the menu closes + expect(screen.getByText('IsCitedBy')).toBeInTheDocument(); + + await user.click( + screen.getAllByRole('button', { + name: /DOIGenerationForm.related_doi_resource_type/i, + })[0] + ); + await user.click(await screen.findByRole('option', { name: 'Journal' })); + + expect(screen.queryByRole('option')).not.toBeInTheDocument(); + // check that the option is actually selected in the table even after the menu closes + expect(screen.getByText('Journal')).toBeInTheDocument(); + + // test errors with various API error responses + (fetchDOI as jest.MockedFunction).mockRejectedValueOnce({ + response: { data: { errors: [{ title: 'error msg' }] }, status: 404 }, + }); + + await user.type( + screen.getByRole('textbox', { name: 'DOIGenerationForm.related_doi' }), + '3' + ); + + await user.click( + screen.getByRole('button', { name: 'DOIGenerationForm.add_related_doi' }) + ); + + expect(await screen.findByText('error msg')).toBeInTheDocument(); + expect( + within( + screen.getByRole('table', { name: 'DOIGenerationForm.related_dois' }) + ) + .getAllByRole('row') + .slice(1) // ignores the header row + ).toHaveLength(2); + }); + + it('should let the user delete related dois', async () => { + renderComponent(); + + expect( + within( + screen.getByRole('table', { name: 'DOIGenerationForm.related_dois' }) + ) + .getAllByRole('row') + .slice(1) // ignores the header row + ).toHaveLength(1); + expect( + screen.getByRole('cell', { name: 'related.doi.1' }) + ).toBeInTheDocument(); + + await user.click( + screen.getByRole('button', { + name: 'DOIGenerationForm.delete_related_doi', + }) + ); + + expect( + screen.queryByRole('table', { name: 'DOIGenerationForm.related_dois' }) + ).not.toBeInTheDocument(); + }); + + it('should render dois as links and show title on hover', async () => { + renderComponent(); + + const doiLink = screen.getByRole('link', { name: 'related.doi.1' }); + + expect(doiLink).toHaveAttribute('href', 'https://doi.org/related.doi.1'); + + await user.hover(doiLink); + + expect( + await screen.findByRole('tooltip', { name: 'Related DOI 1' }) + ).toBeInTheDocument(); + }); +}); diff --git a/packages/datagateway-download/src/DOIGenerationForm/relatedDOIs.component.tsx b/packages/datagateway-download/src/DOIGenerationForm/relatedDOIs.component.tsx new file mode 100644 index 000000000..d02e9da0f --- /dev/null +++ b/packages/datagateway-download/src/DOIGenerationForm/relatedDOIs.component.tsx @@ -0,0 +1,278 @@ +import { + Button, + FormControl, + Grid, + InputLabel, + Link, + MenuItem, + Paper, + Select, + Table, + TableBody, + TableCell, + TableHead, + TableRow, + TextField, + Typography, +} from '@mui/material'; +import { AxiosError } from 'axios'; +import { StyledTooltip } from 'datagateway-common/lib/arrowtooltip.component'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { DOIRelationType, DOIResourceType, RelatedDOI } from '../downloadApi'; +import { useCheckDOI } from '../downloadApiHooks'; + +type RelatedDOIsProps = { + relatedDOIs: RelatedDOI[]; + changeRelatedDOIs: React.Dispatch>; +}; + +const RelatedDOIs: React.FC = (props) => { + const { relatedDOIs, changeRelatedDOIs } = props; + const [t] = useTranslation(); + const [relatedDOI, setRelatedDOI] = React.useState(''); + const [relatedDOIError, setRelatedDOIError] = React.useState(''); + const { refetch: checkDOI } = useCheckDOI(relatedDOI); + + return ( + + theme.palette.mode === 'dark' + ? theme.palette.grey[800] + : theme.palette.grey[100], + padding: 1, + }} + elevation={0} + variant="outlined" + > + + + + {t('DOIGenerationForm.related_dois')} + + + 0 ? 2 : 0, + }} + > + + 0} + helperText={relatedDOIError.length > 0 ? relatedDOIError : ''} + color="secondary" + sx={{ + // this CSS makes it so that the helperText doesn't mess with the button alignment + '& .MuiFormHelperText-root': { + position: 'absolute', + bottom: '-1.5rem', + }, + }} + InputProps={{ + sx: { + backgroundColor: 'background.default', + }, + }} + value={relatedDOI} + onChange={(event) => { + setRelatedDOI(event.target.value); + setRelatedDOIError(''); + }} + /> + + + + + + {relatedDOIs.length > 0 && ( + + + + + + {t('DOIGenerationForm.related_doi_doi')} + + + {t('DOIGenerationForm.related_doi_relationship')} + + + {t('DOIGenerationForm.related_doi_resource_type')} + + + {t('DOIGenerationForm.related_doi_action')} + + + + + {relatedDOIs.map((relatedItem) => ( + + + + + {relatedItem.identifier} + + + + + + + {t('DOIGenerationForm.related_doi_relationship')} + + + + + + + + {t('DOIGenerationForm.related_doi_resource_type')} + + + + + + + + + ))} + +
+
+ )} +
+
+ ); +}; + +export default RelatedDOIs; diff --git a/packages/datagateway-download/src/__mocks__/lodash.debounce.ts b/packages/datagateway-download/src/__mocks__/lodash.debounce.ts index 59142c3e6..3c86a2a0c 100644 --- a/packages/datagateway-download/src/__mocks__/lodash.debounce.ts +++ b/packages/datagateway-download/src/__mocks__/lodash.debounce.ts @@ -1,5 +1,8 @@ // TODO: move __mocks__ folder back to package root once facebook/create-react-app#7539 is fixed -const func = () => (fn: (args: A) => T): ((args: A) => T) => fn; +const func = + () => + (fn: (args: A) => T): ((args: A) => T) => + fn; export default func; diff --git a/packages/datagateway-download/src/__mocks__/loglevel.ts b/packages/datagateway-download/src/__mocks__/loglevel.ts new file mode 100644 index 000000000..01d81f572 --- /dev/null +++ b/packages/datagateway-download/src/__mocks__/loglevel.ts @@ -0,0 +1,3 @@ +// TODO: move __mocks__ folder back to package root once facebook/create-react-app#7539 is fixed + +export default jest.createMockFromModule('loglevel'); diff --git a/packages/datagateway-download/src/__snapshots__/App.test.tsx.snap b/packages/datagateway-download/src/__snapshots__/App.test.tsx.snap new file mode 100644 index 000000000..982765460 --- /dev/null +++ b/packages/datagateway-download/src/__snapshots__/App.test.tsx.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ErrorFallback should should render an error message for when app fails catastrophically 1`] = ` + +
+
+ Something went wrong... +
+
+
+`; diff --git a/packages/datagateway-download/src/downloadApi.test.ts b/packages/datagateway-download/src/downloadApi.test.ts index c02aee810..26385f10b 100644 --- a/packages/datagateway-download/src/downloadApi.test.ts +++ b/packages/datagateway-download/src/downloadApi.test.ts @@ -1,16 +1,19 @@ import axios from 'axios'; import { handleICATError } from 'datagateway-common'; import { + adminDownloadDeleted, + adminDownloadStatus, downloadDeleted, downloadPreparedCart, + fetchAdminDownloads, fetchDownloads, + getDataUrl, getDownload, + getDownloadTypeStatus, + getPercentageComplete, submitCart, - getDataUrl, - fetchAdminDownloads, - adminDownloadDeleted, - adminDownloadStatus, } from './downloadApi'; +import { mockedSettings } from './testData'; jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -22,28 +25,6 @@ jest.mock('datagateway-common', () => { }; }); -// Create our mocked datagateway-download mockedSettings file. -const mockedSettings = { - facilityName: 'LILS', - apiUrl: 'https://example.com/api', - downloadApiUrl: 'https://example.com/downloadApi', - idsUrl: 'https://example.com/ids', - fileCountMax: 5000, - totalSizeMax: 1000000000000, - accessMethods: { - https: { - idsUrl: 'https://example.com/ids', - displayName: 'HTTPS', - description: 'Example description for HTTPS access method.', - }, - globus: { - idsUrl: 'https://example.com/ids', - displayName: 'Globus', - description: 'Example description for Globus access method.', - }, - }, -}; - describe('Download Cart API functions test', () => { afterEach(() => { (handleICATError as jest.Mock).mockClear(); @@ -55,7 +36,7 @@ describe('Download Cart API functions test', () => { return Promise.resolve({ data: { facilityName: mockedSettings.facilityName, - userName: 'test user', + userrName: 'test user', cartItems: [], downloadId: 1, }, @@ -86,42 +67,6 @@ describe('Download Cart API functions test', () => { params ); }); - - it('returns -1 if an errors occurs and logs the error upon unsuccessful response', async () => { - axios.post = jest.fn().mockImplementation(() => { - return Promise.reject({ - message: 'Test error message', - }); - }); - - // Wait for our mocked response with a download id. - const downloadId = await submitCart( - 'globus', - 'test@email.com', - 'test-file', - { - facilityName: mockedSettings.facilityName, - downloadApiUrl: mockedSettings.downloadApiUrl, - } - ); - const params = new URLSearchParams(); - params.append('sessionId', ''); - params.append('transport', 'globus'); - params.append('email', 'test@email.com'); - params.append('fileName', 'test-file'); - params.append('zipType', 'ZIP'); - - expect(downloadId).toBe(-1); - expect(axios.post).toHaveBeenCalled(); - expect(axios.post).toHaveBeenCalledWith( - `${mockedSettings.downloadApiUrl}/user/cart/${mockedSettings.facilityName}/submit`, - params - ); - expect(handleICATError).toHaveBeenCalled(); - expect(handleICATError).toHaveBeenCalledWith({ - message: 'Test error message', - }); - }); }); describe('getDownload', () => { @@ -174,36 +119,6 @@ describe('Download Cart API functions test', () => { } ); }); - - it('returns null if error occurs and logs the error message upon unsuccessful response', async () => { - axios.get = jest.fn().mockImplementation(() => - Promise.reject({ - message: 'Test error message', - }) - ); - - const download = await getDownload(1, { - facilityName: mockedSettings.facilityName, - downloadApiUrl: mockedSettings.downloadApiUrl, - }); - - expect(download).toBe(null); - expect(axios.get).toHaveBeenCalled(); - expect(axios.get).toHaveBeenCalledWith( - `${mockedSettings.downloadApiUrl}/user/downloads`, - { - params: { - sessionId: null, - facilityName: mockedSettings.facilityName, - queryOffset: `where download.id = 1`, - }, - } - ); - expect(handleICATError).toHaveBeenCalled(); - expect(handleICATError).toHaveBeenCalledWith({ - message: 'Test error message', - }); - }); }); describe('downloadPreparedCart', () => { @@ -312,36 +227,6 @@ describe('Download Status API functions test', () => { } ); }); - - it('returns empty array and logs error upon unsuccessful response', async () => { - axios.get = jest.fn().mockImplementation(() => - Promise.reject({ - message: 'Test error message', - }) - ); - - const returnData = await fetchDownloads({ - facilityName: mockedSettings.facilityName, - downloadApiUrl: mockedSettings.downloadApiUrl, - }); - - expect(returnData).toEqual([]); - expect(axios.get).toHaveBeenCalled(); - expect(axios.get).toHaveBeenCalledWith( - `${mockedSettings.downloadApiUrl}/user/downloads`, - { - params: { - sessionId: null, - facilityName: mockedSettings.facilityName, - queryOffset: 'where download.isDeleted = false', - }, - } - ); - expect(handleICATError).toHaveBeenCalled(); - expect(handleICATError).toHaveBeenCalledWith({ - message: 'Test error message', - }); - }); }); describe('downloadDeleted', () => { @@ -364,34 +249,6 @@ describe('Download Status API functions test', () => { params ); }); - - it('logs an error upon unsuccessful response', async () => { - axios.put = jest.fn().mockImplementation(() => - Promise.reject({ - message: 'Test error message', - }) - ); - - await downloadDeleted(1, true, { - facilityName: mockedSettings.facilityName, - downloadApiUrl: mockedSettings.downloadApiUrl, - }); - - const params = new URLSearchParams(); - params.append('facilityName', mockedSettings.facilityName); - params.append('sessionId', ''); - params.append('value', 'true'); - - expect(axios.put).toHaveBeenCalled(); - expect(axios.put).toHaveBeenCalledWith( - `${mockedSettings.downloadApiUrl}/user/download/1/isDeleted`, - params - ); - expect(handleICATError).toHaveBeenCalled(); - expect(handleICATError).toHaveBeenCalledWith({ - message: 'Test error message', - }); - }); }); describe('getDataUrl', () => { @@ -490,36 +347,6 @@ describe('Admin Download Status API functions test', () => { } ); }); - - it('returns empty array and logs error upon unsuccessful response', async () => { - axios.get = jest.fn().mockImplementation(() => - Promise.reject({ - message: 'Test error message', - }) - ); - - const returnData = await fetchAdminDownloads({ - facilityName: mockedSettings.facilityName, - downloadApiUrl: mockedSettings.downloadApiUrl, - }); - - expect(returnData).toEqual([]); - expect(axios.get).toHaveBeenCalled(); - expect(axios.get).toHaveBeenCalledWith( - `${mockedSettings.downloadApiUrl}/admin/downloads`, - { - params: { - sessionId: null, - facilityName: mockedSettings.facilityName, - queryOffset: 'where download.isDeleted = false', - }, - } - ); - expect(handleICATError).toHaveBeenCalled(); - expect(handleICATError).toHaveBeenCalledWith({ - message: 'Test error message', - }); - }); }); describe('adminDownloadDeleted', () => { @@ -542,34 +369,6 @@ describe('Admin Download Status API functions test', () => { params ); }); - - it('logs an error upon unsuccessful response', async () => { - axios.put = jest.fn().mockImplementation(() => - Promise.reject({ - message: 'Test error message', - }) - ); - - await adminDownloadDeleted(1, true, { - facilityName: mockedSettings.facilityName, - downloadApiUrl: mockedSettings.downloadApiUrl, - }); - - const params = new URLSearchParams(); - params.append('facilityName', mockedSettings.facilityName); - params.append('sessionId', ''); - params.append('value', 'true'); - - expect(axios.put).toHaveBeenCalled(); - expect(axios.put).toHaveBeenCalledWith( - `${mockedSettings.downloadApiUrl}/admin/download/1/isDeleted`, - params - ); - expect(handleICATError).toHaveBeenCalled(); - expect(handleICATError).toHaveBeenCalledWith({ - message: 'Test error message', - }); - }); }); describe('adminDownloadStatus', () => { @@ -592,33 +391,59 @@ describe('Admin Download Status API functions test', () => { params ); }); + }); - it('logs an error upon unsuccessful response', async () => { - axios.put = jest.fn().mockImplementation(() => - Promise.reject({ - message: 'Test error message', - }) - ); + describe('getDownloadTypeStatus', () => { + it('should retrieve the status of the given download type', async () => { + axios.get = jest.fn().mockResolvedValue({ + data: { + disabled: false, + message: '', + }, + }); - await adminDownloadStatus(1, 'RESTORING', { + const response = await getDownloadTypeStatus('https', { facilityName: mockedSettings.facilityName, downloadApiUrl: mockedSettings.downloadApiUrl, }); - const params = new URLSearchParams(); - params.append('facilityName', mockedSettings.facilityName); - params.append('sessionId', ''); - params.append('value', 'RESTORING'); + expect(response).toEqual({ + type: 'https', + disabled: false, + message: '', + }); + }); + }); - expect(axios.put).toHaveBeenCalled(); - expect(axios.put).toHaveBeenCalledWith( - `${mockedSettings.downloadApiUrl}/admin/download/1/status`, - params - ); - expect(handleICATError).toHaveBeenCalled(); - expect(handleICATError).toHaveBeenCalledWith({ - message: 'Test error message', + describe('getPercentageComplete', () => { + it('should return the percentage of a download restore from 0 to 100', async () => { + axios.get = jest.fn().mockResolvedValue({ + data: '2', }); + + const response = await getPercentageComplete({ + preparedId: '1', + settings: { + idsUrl: mockedSettings.idsUrl, + }, + }); + + expect(response).toEqual(2); + }); + + it('should return the status of a download restore', async () => { + axios.get = jest.fn().mockResolvedValue({ + data: 'INVALID', + }); + + const response = await getPercentageComplete({ + preparedId: '1', + settings: { + idsUrl: mockedSettings.idsUrl, + }, + }); + + expect(response).toEqual('INVALID'); }); }); }); diff --git a/packages/datagateway-download/src/downloadApi.ts b/packages/datagateway-download/src/downloadApi.ts index d089388aa..ed46ada72 100644 --- a/packages/datagateway-download/src/downloadApi.ts +++ b/packages/datagateway-download/src/downloadApi.ts @@ -1,14 +1,16 @@ -import axios, { AxiosResponse } from 'axios'; -import * as log from 'loglevel'; -import { - SubmitCart, +import axios, { AxiosError } from 'axios'; +import type { Datafile, + Dataset, Download, - readSciGatewayToken, - handleICATError, DownloadCart, DownloadCartItem, + Investigation, + SubmitCart, + User, } from 'datagateway-common'; +import { readSciGatewayToken } from 'datagateway-common'; +import type { DownloadSettings } from './ConfigProvider'; export const removeAllDownloadCartItems: (settings: { facilityName: string; @@ -35,7 +37,7 @@ export const removeAllDownloadCartItems: (settings: { export const removeFromCart = ( entityType: 'investigation' | 'dataset' | 'datafile', entityIds: number[], - config: { facilityName: string; downloadApiUrl: string } + config: Pick ): Promise => { const { facilityName, downloadApiUrl } = config; @@ -57,29 +59,23 @@ export const getIsTwoLevel: (settings: { }) => Promise = (settings: { idsUrl: string }) => { return axios .get(`${settings.idsUrl}/isTwoLevel`) - .then((response) => { - return response.data; - }); + .then((response) => response.data); }; +export type SubmitCartZipType = 'ZIP' | 'ZIP_AND_COMPRESS'; + export const submitCart: ( transport: string, emailAddress: string, fileName: string, - settings: { - facilityName: string; - downloadApiUrl: string; - }, - zipType?: 'ZIP' | 'ZIP_AND_COMPRESS' + settings: Pick, + zipType?: SubmitCartZipType ) => Promise = ( - transport: string, - emailAddress: string, - fileName: string, - settings: { - facilityName: string; - downloadApiUrl: string; - }, - zipType?: 'ZIP' | 'ZIP_AND_COMPRESS' + transport, + emailAddress, + fileName, + settings, + zipType ) => { const params = new URLSearchParams(); @@ -98,25 +94,15 @@ export const submitCart: ( params ) .then((response) => { - log.debug(response); - // Get the downloadId that was returned from the IDS server. - const downloadId = response.data['downloadId']; - return downloadId; - }) - .catch((error) => { - handleICATError(error); - return -1; + return response.data['downloadId']; }); }; export const fetchDownloads: ( - settings: { facilityName: string; downloadApiUrl: string }, - queryOffset?: string -) => Promise = ( - settings: { facilityName: string; downloadApiUrl: string }, + settings: Pick, queryOffset?: string -) => { +) => Promise = (settings, queryOffset) => { return axios .get(`${settings.downloadApiUrl}/user/downloads`, { params: { @@ -127,22 +113,13 @@ export const fetchDownloads: ( : queryOffset, }, }) - .then((response) => { - return response.data; - }) - .catch((error) => { - handleICATError(error); - return []; - }); + .then((response) => response.data); }; export const fetchAdminDownloads: ( - settings: { facilityName: string; downloadApiUrl: string }, + settings: Pick, queryOffset?: string -) => Promise = ( - settings: { facilityName: string; downloadApiUrl: string }, - queryOffset?: string -) => { +) => Promise = (settings, queryOffset) => { return axios .get(`${settings.downloadApiUrl}/admin/downloads`, { params: { @@ -153,22 +130,13 @@ export const fetchAdminDownloads: ( : queryOffset, }, }) - .then((response) => { - return response.data; - }) - .catch((error) => { - handleICATError(error); - return []; - }); + .then((response) => response.data); }; export const getDownload: ( downloadId: number, - settings: { facilityName: string; downloadApiUrl: string } -) => Promise = ( - downloadId: number, - settings: { facilityName: string; downloadApiUrl: string } -) => { + settings: Pick +) => Promise = (downloadId, settings) => { return axios .get(`${settings.downloadApiUrl}/user/downloads`, { params: { @@ -177,14 +145,7 @@ export const getDownload: ( queryOffset: `where download.id = ${downloadId}`, }, }) - .then((response) => { - const download = response.data[0]; - return download; - }) - .catch((error) => { - handleICATError(error); - return null; - }); + .then((response) => response.data[0]); }; export const downloadPreparedCart: ( @@ -212,15 +173,23 @@ export const downloadPreparedCart: ( } }; +/** + * Describes the status of a download type. + */ +export interface DownloadTypeStatus { + type: string; + disabled: boolean; + message: string; +} + export const getDownloadTypeStatus: ( transportType: string, - settings: { facilityName: string; downloadApiUrl: string } -) => Promise<{ disabled: boolean; message: string } | null> = ( - transportType: string, - settings: { facilityName: string; downloadApiUrl: string } -) => { - return axios - .get( + settings: Pick +) => Promise = (transportType, settings) => + axios + // the server doesn't put the transport type into the response object + // it will be put in after the fact so that it is easier to work with + .get>( `${settings.downloadApiUrl}/user/downloadType/${transportType}/status`, { params: { @@ -229,29 +198,15 @@ export const getDownloadTypeStatus: ( }, } ) - .then( - ( - response: AxiosResponse<{ - disabled: boolean; - message: string; - }> - ) => { - return response.data; - } - ) - .catch((error) => { - if (error) handleICATError(error); - return null; - }); -}; + .then((response) => ({ + type: transportType, + ...response.data, + })); export const downloadDeleted: ( downloadId: number, deleted: boolean, - settings: { - facilityName: string; - downloadApiUrl: string; - } + settings: Pick ) => Promise = ( downloadId: number, deleted: boolean, @@ -265,26 +220,16 @@ export const downloadDeleted: ( params.append('sessionId', readSciGatewayToken().sessionId || ''); params.append('value', JSON.stringify(deleted)); - return axios - .put( - `${settings.downloadApiUrl}/user/download/${downloadId}/isDeleted`, - params - ) - .then(() => { - // do nothing - }) - .catch((error) => { - handleICATError(error); - }); + return axios.put( + `${settings.downloadApiUrl}/user/download/${downloadId}/isDeleted`, + params + ); }; export const adminDownloadDeleted: ( downloadId: number, deleted: boolean, - settings: { - facilityName: string; - downloadApiUrl: string; - } + settings: Pick ) => Promise = ( downloadId: number, deleted: boolean, @@ -298,147 +243,60 @@ export const adminDownloadDeleted: ( params.append('sessionId', readSciGatewayToken().sessionId || ''); params.append('value', JSON.stringify(deleted)); - return axios - .put( - `${settings.downloadApiUrl}/admin/download/${downloadId}/isDeleted`, - params - ) - .then(() => { - // do nothing - }) - .catch((error) => { - handleICATError(error); - }); + return axios.put( + `${settings.downloadApiUrl}/admin/download/${downloadId}/isDeleted`, + params + ); }; export const adminDownloadStatus: ( downloadId: number, status: string, - settings: { - facilityName: string; - downloadApiUrl: string; - } + settings: Pick ) => Promise = ( downloadId: number, status: string, - settings: { - facilityName: string; - downloadApiUrl: string; - } + settings: Pick ) => { const params = new URLSearchParams(); params.append('facilityName', settings.facilityName); params.append('sessionId', readSciGatewayToken().sessionId || ''); params.append('value', status); - return axios - .put( - `${settings.downloadApiUrl}/admin/download/${downloadId}/status`, - params - ) - .then(() => { - // do nothing - }) - .catch((error) => { - handleICATError(error); - }); + return axios.put( + `${settings.downloadApiUrl}/admin/download/${downloadId}/status`, + params + ); }; -export const getSize: ( - entityId: number, - entityType: string, - settings: { - facilityName: string; - apiUrl: string; - downloadApiUrl: string; - } -) => Promise = ( - entityId: number, - entityType: string, - settings: { - facilityName: string; - apiUrl: string; - downloadApiUrl: string; - } -) => { - if (entityType === 'datafile') { - return axios - .get(`${settings.apiUrl}/datafiles/${entityId}`, { - headers: { - Authorization: `Bearer ${readSciGatewayToken().sessionId}`, - }, - }) - .then((response) => { - const size = response.data['fileSize'] as number; - return size; - }); - } else { - return axios - .get(`${settings.downloadApiUrl}/user/getSize`, { - params: { - sessionId: readSciGatewayToken().sessionId, - facilityName: settings.facilityName, - entityType: entityType, - entityId: entityId, - }, - }) - .then((response) => { - return response.data; - }); - } -}; +export interface FileSizeAndCount { + fileCount?: number; + fileSize?: number; +} -export const getDatafileCount: ( +export const getFileSizeAndCount: ( entityId: number, - entityType: string, - settings: { apiUrl: string } -) => Promise = ( - entityId: number, - entityType: string, - settings: { apiUrl: string } -) => { - if (entityType === 'datafile') { - // need to do this in a setTimeout to ensure it doesn't block the main thread - return new Promise((resolve) => - window.setTimeout(() => { - resolve(1); - }, 0) - ); - } else if (entityType === 'dataset') { - return axios - .get(`${settings.apiUrl}/datafiles/count`, { - params: { - where: { - 'dataset.id': { - eq: entityId, - }, - }, - }, - headers: { - Authorization: `Bearer ${readSciGatewayToken().sessionId}`, - }, - }) - .then((response) => { - return response.data; - }); - } else { - return axios - .get(`${settings.apiUrl}/datafiles/count`, { - params: { - where: { - 'dataset.investigation.id': { - eq: entityId, - }, - }, - }, + entityType: 'investigation' | 'dataset' | 'datafile', + settings: Pick +) => Promise = (entityId, entityType, settings) => { + return axios + .get( + `${settings.apiUrl}/${entityType}s/${entityId}`, + { headers: { Authorization: `Bearer ${readSciGatewayToken().sessionId}`, }, - }) - .then((response) => { - return response.data; - }); - } + } + ) + .then((response) => { + return { + fileCount: + entityType === 'datafile' + ? 1 + : (response.data as Dataset | Investigation).fileCount, + fileSize: response.data.fileSize, + }; + }); }; export const getDataUrl = ( @@ -451,3 +309,357 @@ export const getDataUrl = ( readSciGatewayToken().sessionId }&preparedId=${preparedId}&outname=${fileName}`; }; + +/** + * Describes the progress of a download. Can be a percentage between 0-100 + * or a string describing the status of the download. + */ +export type DownloadProgress = number | string; + +/** + * Return a percentage of files that have been restored for the given prepared ID. + * This will normally be an integer value between 0 and 100 but can also be a status value such as "UNKNOWN" + */ +export const getPercentageComplete = async ({ + preparedId, + settings: { idsUrl }, +}: { + preparedId: string; + settings: { idsUrl: string }; +}): Promise => { + const { data } = await axios.get(`${idsUrl}/getPercentageComplete`, { + params: { preparedId }, + }); + // try to parse the incoming data as a float + const maybeNumber = parseFloat(data); + // if data is not a number (NaN), it is a status value + const isStatus = Number.isNaN(maybeNumber); + return isStatus ? data : maybeNumber; +}; + +/** + * Returns true if a user is able to mint a DOI for their cart, otherwise false + */ +export const isCartMintable = async ( + cart: DownloadCartItem[], + doiMinterUrl: string +): Promise => { + const investigations: number[] = []; + const datasets: number[] = []; + const datafiles: number[] = []; + cart.forEach((cartItem) => { + if (cartItem.entityType === 'investigation') + investigations.push(cartItem.entityId); + if (cartItem.entityType === 'dataset') datasets.push(cartItem.entityId); + if (cartItem.entityType === 'datafile') datafiles.push(cartItem.entityId); + }); + const { status } = await axios.post( + `${doiMinterUrl}/ismintable`, + { + ...(investigations.length > 0 + ? { investigation_ids: investigations } + : {}), + ...(datasets.length > 0 ? { dataset_ids: datasets } : {}), + ...(datafiles.length > 0 ? { datafile_ids: datafiles } : {}), + }, + { + headers: { + Authorization: `Bearer ${readSciGatewayToken().sessionId}`, + }, + } + ); + + return status === 200; +}; + +export enum ContributorType { + Creator = 'Creator', + ContactPerson = 'ContactPerson', + DataCollector = 'DataCollector', + DataCurator = 'DataCurator', + DataManager = 'DataManager', + Distributor = 'Distributor', + Editor = 'Editor', + HostingInstitution = 'HostingInstitution', + Producer = 'Producer', + ProjectLeader = 'ProjectLeader', + ProjectManager = 'ProjectManager', + ProjectMember = 'ProjectMember', + RegistrationAgency = 'RegistrationAgency', + RelatedPerson = 'RelatedPerson', + Researcher = 'Researcher', + ResearchGroup = 'ResearchGroup', + RightsHolder = 'RightsHolder', + Sponsor = 'Sponsor', + Supervisor = 'Supervisor', + WorkPackageLeader = 'WorkPackageLeader', + Other = 'Other', +} + +export enum DOIRelationType { + IsCitedBy = 'IsCitedBy', + Cites = 'Cites', + IsSupplementTo = 'IsSupplementTo', + IsSupplementedBy = 'IsSupplementedBy', + IsContinuedBy = 'IsContinuedBy', + Continues = 'Continues', + IsDescribedBy = 'IsDescribedBy', + Describes = 'Describes', + HasMetadata = 'HasMetadata', + IsMetadataFor = 'IsMetadataFor', + HasVersion = 'HasVersion', + IsVersionOf = 'IsVersionOf', + IsNewVersionOf = 'IsNewVersionOf', + IsPreviousVersionOf = 'IsPreviousVersionOf', + IsPartOf = 'IsPartOf', + HasPart = 'HasPart', + IsPublishedIn = 'IsPublishedIn', + IsReferencedBy = 'IsReferencedBy', + References = 'References', + IsDocumentedBy = 'IsDocumentedBy', + Documents = 'Documents', + IsCompiledBy = 'IsCompiledBy', + Compiles = 'Compiles', + IsVariantFormOf = 'IsVariantFormOf', + IsOriginalFormOf = 'IsOriginalFormOf', + IsIdenticalTo = 'IsIdenticalTo', + IsReviewedBy = 'IsReviewedBy', + Reviews = 'Reviews', + IsDerivedFrom = 'IsDerivedFrom', + IsSourceOf = 'IsSourceOf', + IsRequiredBy = 'IsRequiredBy', + Requires = 'Requires', + Obsoletes = 'Obsoletes', + IsObsoletedBy = 'IsObsoletedBy', +} + +export enum DOIResourceType { + Audiovisual = 'Audiovisual', + Book = 'Book', + BookChapter = 'BookChapter', + Collection = 'Collection', + ComputationalNotebook = 'ComputationalNotebook', + ConferencePaper = 'ConferencePaper', + ConferenceProceeding = 'ConferenceProceeding', + DataPaper = 'DataPaper', + Dataset = 'Dataset', + Dissertation = 'Dissertation', + Event = 'Event', + Image = 'Image', + InteractiveResource = 'InteractiveResource', + Journal = 'Journal', + JournalArticle = 'JournalArticle', + Model = 'Model', + OutputManagementPlan = 'OutputManagementPlan', + PeerReview = 'PeerReview', + PhysicalObject = 'PhysicalObject', + Preprint = 'Preprint', + Report = 'Report', + Service = 'Service', + Software = 'Software', + Sound = 'Sound', + Standard = 'Standard', + Text = 'Text', + Workflow = 'Workflow', + Other = 'Other', +} + +export interface DoiMetadata { + title: string; + description: string; + creators?: { username: string; contributor_type: ContributorType }[]; + related_items: RelatedDOI[]; +} + +export type RelatedDOI = { + title: string; + fullReference: string; + identifier: string; + relationType: DOIRelationType | ''; + relatedItemType: DOIResourceType | ''; +}; + +export interface DoiResponse { + concept: DoiResult; + version: DoiResult; +} + +export interface DoiResult { + data_publication: string; + doi: string; +} + +/** + * Mint a DOI for a cart, returns a DataPublication ID & DOI + */ +export const mintCart = ( + cart: DownloadCartItem[], + doiMetadata: DoiMetadata, + settings: Pick +): Promise => { + const investigations: number[] = []; + const datasets: number[] = []; + const datafiles: number[] = []; + cart.forEach((cartItem) => { + if (cartItem.entityType === 'investigation') + investigations.push(cartItem.entityId); + if (cartItem.entityType === 'dataset') datasets.push(cartItem.entityId); + if (cartItem.entityType === 'datafile') datafiles.push(cartItem.entityId); + }); + return axios + .post( + `${settings.doiMinterUrl}/mint`, + { + metadata: { + ...doiMetadata, + resource_type: investigations.length === 0 ? 'Dataset' : 'Collection', + }, + ...(investigations.length > 0 + ? { investigation_ids: investigations } + : {}), + ...(datasets.length > 0 ? { dataset_ids: datasets } : {}), + ...(datafiles.length > 0 ? { datafile_ids: datafiles } : {}), + }, + { + headers: { + Authorization: `Bearer ${readSciGatewayToken().sessionId}`, + }, + } + ) + .then((response) => response.data); +}; + +const fetchEntityUsers = ( + apiUrl: string, + entityId: number, + entityType: 'investigation' | 'dataset' | 'datafile' +): Promise => { + const params = new URLSearchParams(); + params.append('where', JSON.stringify({ id: { eq: entityId } })); + + if (entityType === 'investigation') + params.append('include', JSON.stringify({ investigationUsers: 'user' })); + if (entityType === 'dataset') + params.append( + 'include', + JSON.stringify({ investigation: { investigationUsers: 'user' } }) + ); + if (entityType === 'datafile') + params.append( + 'include', + JSON.stringify({ + dataset: { investigation: { investigationUsers: 'user' } }, + }) + ); + + return axios + .get(`${apiUrl}/${entityType}s`, { + params, + headers: { + Authorization: `Bearer ${readSciGatewayToken().sessionId}`, + }, + }) + .then((response) => { + const entity = response.data[0]; + if (entityType === 'investigation') { + return (entity as Investigation).investigationUsers?.map( + (iUser) => iUser.user + ) as User[]; + } + if (entityType === 'dataset') { + return (entity as Dataset).investigation?.investigationUsers?.map( + (iUser) => iUser.user + ) as User[]; + } + if (entityType === 'datafile') + return ( + entity as Datafile + ).dataset?.investigation?.investigationUsers?.map( + (iUser) => iUser.user + ) as User[]; + return []; + }); +}; + +/** + * Deduplicates items in an array + * @param array Array to make unique + * @param key Function to apply to an array item that returns a primitive that keys that item + * @returns a deduplicated array + */ +function uniqBy(array: T[], key: (item: T) => number | string): T[] { + const seen: Record = {}; + return array.filter(function (item) { + const k = key(item); + return seen.hasOwnProperty(k) ? false : (seen[k] = true); + }); +} + +/** + * Returns a list of users from ICAT which are InvestigationUsers for each item in the cart + */ +export const getCartUsers = async ( + cart: DownloadCartItem[], + settings: Pick +): Promise => { + let users: User[] = []; + for (const cartItem of cart) { + const entityUsers = await fetchEntityUsers( + settings.apiUrl, + cartItem.entityId, + cartItem.entityType + ); + users = users.concat(entityUsers); + } + + users = uniqBy(users, (item) => item.id); + + return users; +}; + +/** + * Sends an username to the API and it checks if it's a valid ICAT User, on success + * it returns the User, on failure it returns 404 + */ +export const checkUser = ( + username: string, + settings: Pick +): Promise => { + return axios + .get(`${settings.doiMinterUrl}/user/${username}`, { + headers: { + Authorization: `Bearer ${readSciGatewayToken().sessionId}`, + }, + }) + .then((response) => { + return response.data; + }); +}; + +interface DataCiteResponse { + data: DataCiteDOI; +} + +export interface DataCiteDOI { + id: string; + type: string; + attributes: { + doi: string; + titles: { title: string }[]; + url: string; + }; +} +/** + * Retrieve metadata for a DOI + * @param doi The DOI to fetch metadata for + */ +export const fetchDOI = ( + doi: string, + settings: Pick +): Promise => { + return axios + .get(`${settings.dataCiteUrl}/dois/${doi}`) + .then((response) => { + return response.data.data; + }); +}; diff --git a/packages/datagateway-download/src/downloadApiHooks.test.tsx b/packages/datagateway-download/src/downloadApiHooks.test.tsx index 3a52cd0df..7d5423269 100644 --- a/packages/datagateway-download/src/downloadApiHooks.test.tsx +++ b/packages/datagateway-download/src/downloadApiHooks.test.tsx @@ -1,19 +1,38 @@ -import axios from 'axios'; -import { DownloadCartItem, handleICATError } from 'datagateway-common'; import { - useCart, - useRemoveAllFromCart, - useRemoveEntityFromCart, - useIsTwoLevel, - useSizes, - useDatafileCounts, -} from './downloadApiHooks'; -import { renderHook, WrapperComponent } from '@testing-library/react-hooks'; -import React from 'react'; + act, + renderHook, + WrapperComponent, +} from '@testing-library/react-hooks'; +import axios, { AxiosError } from 'axios'; +import { Download, InvalidateTokenType } from 'datagateway-common'; +import { handleICATError, NotificationType } from 'datagateway-common'; import { createMemoryHistory } from 'history'; +import * as React from 'react'; import { QueryClient, QueryClientProvider, setLogger } from 'react-query'; import { Router } from 'react-router-dom'; import { DownloadSettingsContext } from './ConfigProvider'; +import { + useAdminDownloadDeleted, + useAdminDownloads, + useAdminUpdateDownloadStatus, + useCart, + useCartUsers, + useCheckUser, + useDownloadOrRestoreDownload, + useDownloadPercentageComplete, + useDownloads, + useDownloadTypeStatuses, + useFileSizesAndCounts, + useIsCartMintable, + useIsTwoLevel, + useMintCart, + useRemoveAllFromCart, + useRemoveEntityFromCart, + useSubmitCart, +} from './downloadApiHooks'; +import { mockCartItems, mockDownloadItems, mockedSettings } from './testData'; +import log from 'loglevel'; +import { ContributorType } from './downloadApi'; jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -26,28 +45,6 @@ jest.mock('datagateway-common', () => { }; }); -// Create our mocked datagateway-download mockedSettings file. -const mockedSettings = { - facilityName: 'LILS', - apiUrl: 'https://example.com/api', - downloadApiUrl: 'https://example.com/downloadApi', - idsUrl: 'https://example.com/ids', - fileCountMax: 5000, - totalSizeMax: 1000000000000, - accessMethods: { - https: { - idsUrl: 'https://example.com/ids', - displayName: 'HTTPS', - description: 'Example description for HTTPS access method.', - }, - globus: { - idsUrl: 'https://example.com/ids', - displayName: 'Globus', - description: 'Example description for Globus access method.', - }, - }, -}; - // silence react-query errors setLogger({ log: console.log, @@ -60,16 +57,20 @@ const createTestQueryClient = (): QueryClient => defaultOptions: { queries: { retry: false, + // set retryDelay = 0 to make retries quick for custom retry functions + retryDelay: 0, }, }, }); -const createReactQueryWrapper = (): WrapperComponent => { +const createReactQueryWrapper = ( + settings = mockedSettings +): WrapperComponent => { const testQueryClient = createTestQueryClient(); const history = createMemoryHistory(); const wrapper: WrapperComponent = ({ children }) => ( - + {children} @@ -80,9 +81,29 @@ const createReactQueryWrapper = (): WrapperComponent => { return wrapper; }; -describe('Download Cart API react-query hooks test', () => { +describe('Download API react-query hooks test', () => { + const localStorageGetItemMock = jest.spyOn( + window.localStorage.__proto__, + 'getItem' + ); + let events: CustomEvent<{ + detail: { type: string; payload?: unknown }; + }>[] = []; + + beforeEach(() => { + events = []; + + document.dispatchEvent = (e: Event) => { + events.push( + e as CustomEvent<{ detail: { type: string; payload?: unknown } }> + ); + return true; + }; + }); + afterEach(() => { - (handleICATError as jest.Mock).mockClear(); + jest.clearAllMocks(); + localStorageGetItemMock.mockReset(); }); describe('useCart', () => { @@ -174,9 +195,7 @@ describe('Download Cart API react-query hooks test', () => { expect(result.current.data).toBeUndefined(); expect(axios.delete).toHaveBeenCalled(); - expect( - axios.delete - ).toHaveBeenCalledWith( + expect(axios.delete).toHaveBeenCalledWith( `${mockedSettings.downloadApiUrl}/user/cart/${mockedSettings.facilityName}/cartItems`, { params: { sessionId: null, items: '*' } } ); @@ -187,9 +206,11 @@ describe('Download Cart API react-query hooks test', () => { .fn() .mockImplementationOnce(() => Promise.reject({ - code: '431', + response: { + status: 431, + }, message: 'Test 431 error message', - }) + } as AxiosError) ) .mockImplementation(() => Promise.reject({ @@ -205,9 +226,7 @@ describe('Download Cart API react-query hooks test', () => { await waitFor(() => result.current.isError, { timeout: 2000 }); - expect( - axios.delete - ).toHaveBeenCalledWith( + expect(axios.delete).toHaveBeenCalledWith( `${mockedSettings.downloadApiUrl}/user/cart/${mockedSettings.facilityName}/cartItems`, { params: { sessionId: null, items: '*' } } ); @@ -244,9 +263,7 @@ describe('Download Cart API react-query hooks test', () => { expect(result.current.data).toEqual([]); expect(axios.delete).toHaveBeenCalled(); - expect( - axios.delete - ).toHaveBeenCalledWith( + expect(axios.delete).toHaveBeenCalledWith( `${mockedSettings.downloadApiUrl}/user/cart/${mockedSettings.facilityName}/cartItems`, { params: { sessionId: null, items: 'datafile 1' } } ); @@ -257,9 +274,11 @@ describe('Download Cart API react-query hooks test', () => { .fn() .mockImplementationOnce(() => Promise.reject({ - code: '431', + response: { + status: 431, + }, message: 'Test 431 error message', - }) + } as AxiosError) ) .mockImplementation(() => Promise.reject({ @@ -275,9 +294,7 @@ describe('Download Cart API react-query hooks test', () => { await waitFor(() => result.current.isError, { timeout: 2000 }); - expect( - axios.delete - ).toHaveBeenCalledWith( + expect(axios.delete).toHaveBeenCalledWith( `${mockedSettings.downloadApiUrl}/user/cart/${mockedSettings.facilityName}/cartItems`, { params: { sessionId: null, items: 'investigation 1' } } ); @@ -331,65 +348,27 @@ describe('Download Cart API react-query hooks test', () => { }); }); - describe('useSizes', () => { - it('returns the sizes of all the items in a cart', async () => { + describe('useFileCountsAndSizes', () => { + it('returns the sizes and counts of all the items in a cart', async () => { axios.get = jest .fn() - .mockImplementation((path) => { - if (path.includes('datafiles/')) { - return Promise.resolve({ - data: { - id: 1, - name: 'test datafile', - fileSize: 1, - }, - }); - } else { - return Promise.resolve({ - data: 1, - }); - } - }) + .mockImplementation(() => + Promise.resolve({ + data: { fileCount: 7, fileSize: 21 }, + }) + ) .mockImplementationOnce(() => Promise.reject({ message: 'simulating a failed response', }) ); - const cartItems: DownloadCartItem[] = [ - { - entityId: 1, - entityType: 'investigation', - id: 1, - name: 'INVESTIGATION 1', - parentEntities: [], - }, - { - entityId: 2, - entityType: 'dataset', - id: 2, - name: 'DATASET 2', - parentEntities: [], - }, - { - entityId: 3, - entityType: 'datafile', - id: 3, - name: 'DATAFILE 1', - parentEntities: [], - }, + const { result, waitFor } = renderHook( + () => useFileSizesAndCounts(mockCartItems), { - entityId: 4, - entityType: 'investigation', - id: 4, - name: 'INVESTIGATION 1', - parentEntities: [], - }, - ]; - - const { result, waitFor } = renderHook(() => useSizes(cartItems), { - wrapper: createReactQueryWrapper(), - }); + wrapper: createReactQueryWrapper(), + } + ); await waitFor(() => result.current.every((query) => query.isSuccess || query.isError) @@ -397,34 +376,37 @@ describe('Download Cart API react-query hooks test', () => { expect(result.current.map((query) => query.data)).toEqual([ undefined, - 1, - 1, - 1, + { fileSize: 21, fileCount: 7 }, + { fileSize: 21, fileCount: 7 }, + { fileSize: 21, fileCount: 1 }, ]); + expect(axios.get).toHaveBeenCalledTimes(4); expect(axios.get).toHaveBeenCalledWith( - `${mockedSettings.downloadApiUrl}/user/getSize`, + `${mockedSettings.apiUrl}/investigations/1`, { - params: { - sessionId: null, - facilityName: mockedSettings.facilityName, - entityType: 'investigation', - entityId: 1, + headers: { + Authorization: 'Bearer null', }, } ); expect(axios.get).toHaveBeenCalledWith( - `${mockedSettings.downloadApiUrl}/user/getSize`, + `${mockedSettings.apiUrl}/investigations/2`, { - params: { - sessionId: null, - facilityName: mockedSettings.facilityName, - entityType: 'dataset', - entityId: 2, + headers: { + Authorization: 'Bearer null', + }, + } + ); + expect(axios.get).toHaveBeenCalledWith( + `${mockedSettings.apiUrl}/datasets/3`, + { + headers: { + Authorization: 'Bearer null', }, } ); expect(axios.get).toHaveBeenCalledWith( - `${mockedSettings.apiUrl}/datafiles/${3}`, + `${mockedSettings.apiUrl}/datafiles/4`, { headers: { Authorization: 'Bearer null', @@ -440,106 +422,1430 @@ describe('Download Cart API react-query hooks test', () => { }); }); - describe('useDatafileCounts', () => { - it('returns the counts of all the items in a cart', async () => { - axios.get = jest - .fn() - .mockImplementation(() => - Promise.resolve({ - data: 1, - }) - ) - .mockImplementationOnce(() => - Promise.reject({ - message: 'simulating a failed response', - }) - ); + describe('useDownloads', () => { + it('should retrieve user downloads', async () => { + axios.get = jest.fn().mockResolvedValue({ data: mockDownloadItems }); - const cartItems: DownloadCartItem[] = [ - { - entityId: 1, - entityType: 'investigation', - id: 1, - name: 'INVESTIGATION 1', - parentEntities: [], - }, + const { result, waitFor } = renderHook(() => useDownloads(), { + wrapper: createReactQueryWrapper(), + }); + + await waitFor(() => result.current.isSuccess); + + expect(axios.get).toHaveBeenCalledWith( + `${mockedSettings.downloadApiUrl}/user/downloads`, { - entityId: 2, - entityType: 'investigation', - id: 2, - name: 'INVESTIGATION 2', - parentEntities: [], - }, + params: { + sessionId: null, + facilityName: mockedSettings.facilityName, + queryOffset: 'where download.isDeleted = false', + }, + } + ); + expect(result.current.data).toEqual(mockDownloadItems); + }); + + it('should call handleICATError on failure', async () => { + axios.get = jest.fn().mockRejectedValue({ + message: 'Test error message', + }); + + const { result, waitFor } = renderHook(() => useDownloads(), { + wrapper: createReactQueryWrapper(), + }); + + await waitFor(() => result.current.isError); + + expect(axios.get).toHaveBeenCalledWith( + `${mockedSettings.downloadApiUrl}/user/downloads`, { - entityId: 3, - entityType: 'dataset', - id: 3, - name: 'DATASET 1', - parentEntities: [], - }, + params: { + sessionId: null, + facilityName: mockedSettings.facilityName, + queryOffset: 'where download.isDeleted = false', + }, + } + ); + expect(handleICATError).toHaveBeenCalledWith({ + message: 'Test error message', + }); + }); + }); + + describe('useDownloadOrRestoreDownload', () => { + it('should delete download with given id and update the download list upon success', async () => { + axios.get = jest.fn().mockResolvedValue({ data: mockDownloadItems }); + axios.put = jest.fn().mockImplementation(() => Promise.resolve()); + + const { result, waitFor } = renderHook( + () => ({ + useDownloads: useDownloads(), + useDownloadOrRestoreDownload: useDownloadOrRestoreDownload(), + }), + { wrapper: createReactQueryWrapper() } + ); + + // wait for useDownloads to finish loading mock download items + await waitFor(() => result.current.useDownloads.isSuccess); + // delete the mock item + result.current.useDownloadOrRestoreDownload.mutate({ + downloadId: 1, + deleted: true, + }); + // wait for mutation to complete + await waitFor( + () => result.current.useDownloadOrRestoreDownload.isSuccess + ); + + expect(result.current.useDownloads.data).toHaveLength( + mockDownloadItems.length - 1 + ); + expect( + result.current.useDownloads.data?.find(({ id }) => id === 123) + ).toBeUndefined(); + }); + + it('should restore download with given id and update download list upon success', async () => { + const mockRestoredDownload: Download = { + createdAt: 'created-at', + downloadItems: [], + facilityName: mockedSettings.facilityName, + fileName: 'file-name', + fullName: 'fullName', + id: 124, + isDeleted: false, + isEmailSent: false, + isTwoLevel: false, + preparedId: 'prepare-id', + sessionId: 'session-id', + size: 21, + status: 'PREPARING', + transport: 'http', + userName: 'username', + email: 'a@b.c', + }; + + axios.get = jest.fn().mockImplementation((url, { params }) => { + // api call from fetchDownloads + if ( + url === `${mockedSettings.downloadApiUrl}/user/downloads` && + params.queryOffset === 'where download.isDeleted = false' + ) + return Promise.resolve({ data: mockDownloadItems }); + + // api call from getDownload + if ( + url === `${mockedSettings.downloadApiUrl}/user/downloads` && + params.queryOffset === 'where download.id = 124' + ) + return Promise.resolve({ data: [mockRestoredDownload] }); + + return Promise.reject(); + }); + + axios.put = jest.fn().mockImplementation(() => Promise.resolve()); + + const { result, waitFor } = renderHook( + () => ({ + useDownloads: useDownloads(), + useDownloadOrRestoreDownload: useDownloadOrRestoreDownload(), + }), { - entityId: 4, - entityType: 'datafile', - id: 4, - name: 'DATAFILE 1', - parentEntities: [], - }, - ]; + wrapper: createReactQueryWrapper(), + } + ); + + await waitFor(() => result.current.useDownloads.isSuccess); + result.current.useDownloadOrRestoreDownload.mutate({ + downloadId: 124, + deleted: false, + }); + await waitFor( + () => result.current.useDownloadOrRestoreDownload.isSuccess + ); + + const newList = result.current.useDownloads.data; + + expect(newList).toHaveLength(mockDownloadItems.length + 1); + expect(newList?.find(({ id }) => id === 124)).toEqual( + mockRestoredDownload + ); + }); + + it('should call handleICATError if an error is encountered', async () => { + axios.put = jest.fn().mockRejectedValue({ + message: 'Test error message', + }); const { result, waitFor } = renderHook( - () => useDatafileCounts(cartItems), + () => useDownloadOrRestoreDownload(), { wrapper: createReactQueryWrapper(), } ); - await waitFor(() => - result.current.every((query) => query.isSuccess || query.isError) + result.current.mutate({ + downloadId: 123, + deleted: true, + }); + await waitFor(() => result.current.isError); + + expect(handleICATError).toHaveBeenCalledWith({ + message: 'Test error message', + }); + }); + }); + + describe('useAdminDownloads', () => { + it('should fetch admin downloads with pagination', async () => { + axios.get = jest.fn().mockResolvedValue({ data: mockDownloadItems }); + + // first, test fetching initial data + + const { result, waitFor } = renderHook( + () => useAdminDownloads({ initialQueryOffset: 'LIMIT 0, 50' }), + { + wrapper: createReactQueryWrapper(), + } ); - expect(result.current.map((query) => query.data)).toEqual([ - undefined, - 1, - 1, + await waitFor(() => result.current.isSuccess); + + expect(axios.get).toHaveBeenNthCalledWith( 1, - ]); - expect(axios.get).toHaveBeenCalledTimes(3); - expect(axios.get).toHaveBeenCalledWith( - `${mockedSettings.apiUrl}/datafiles/count`, + `${mockedSettings.downloadApiUrl}/admin/downloads`, { params: { - where: { - 'dataset.investigation.id': { - eq: 2, - }, - }, + sessionId: null, + facilityName: mockedSettings.facilityName, + queryOffset: 'LIMIT 0, 50', }, - headers: { - Authorization: 'Bearer null', + } + ); + expect(result.current.data?.pages).toEqual([mockDownloadItems]); + + // then test fetching next page + + result.current.fetchNextPage({ + pageParam: 'LIMIT 50, 100', + }); + await waitFor(() => result.current.isFetchingNextPage); + await waitFor( + () => !result.current.isFetchingNextPage && result.current.isSuccess + ); + + expect(axios.get).toHaveBeenNthCalledWith( + 2, + `${mockedSettings.downloadApiUrl}/admin/downloads`, + { + params: { + sessionId: null, + facilityName: mockedSettings.facilityName, + queryOffset: 'LIMIT 50, 100', }, } ); + expect(result.current.data?.pages).toEqual([ + mockDownloadItems, + mockDownloadItems, + ]); + }); + + it('should call handleICATError when an error is encountered', async () => { + axios.get = jest.fn().mockRejectedValue({ + message: 'Test error message', + }); + + const { result, waitFor } = renderHook( + () => useAdminDownloads({ initialQueryOffset: 'LIMIT 0, 50' }), + { + wrapper: createReactQueryWrapper(), + } + ); + + await waitFor(() => result.current.isError); + expect(axios.get).toHaveBeenCalledWith( - `${mockedSettings.apiUrl}/datafiles/count`, + `${mockedSettings.downloadApiUrl}/admin/downloads`, { params: { - where: { - 'dataset.id': { - eq: 3, - }, - }, - }, - headers: { - Authorization: 'Bearer null', + sessionId: null, + facilityName: mockedSettings.facilityName, + queryOffset: 'LIMIT 0, 50', }, } ); - expect(handleICATError).toHaveBeenCalledWith( + expect(handleICATError).toHaveBeenCalledWith({ + message: 'Test error message', + }); + }); + }); + + describe('useAdminDownloadDeleted', () => { + it('should delete download with the given id', async () => { + // the way the mocked mutation is handled is through this isMutated flag. + // initially, isMutated is false, and the mocked implementation + // of axios.get will return the unmodified download item list. + // after isMutated is set to true + // (which is done when manually calling the mutation function) + // axios.get will return the updated download item list instead, + // to simulate server updating the list. + // + // this is needed because after mutation is successful, + // onSettled is called which will call invalidateQueries, causing + // axios.get to be called again. without the flag, + // it will just always return the old list. + + let isMutated = false; + const deletedDownload = { + ...mockDownloadItems.find(({ id }) => id === 1), + isDeleted: true, + }; + + axios.get = jest.fn().mockImplementation((url, { params }) => { + // fetchAdminDownloads from useAdminDownloads + if ( + url === `${mockedSettings.downloadApiUrl}/admin/downloads` && + params.queryOffset === 'LIMIT 0, 50' + ) + return Promise.resolve({ + data: isMutated + ? mockDownloadItems.map((download) => + download.id === deletedDownload.id + ? deletedDownload + : download + ) + : mockDownloadItems, + }); + + // fetchAdminDownloads from onSuccess of useAdminDownloadDeleted + if ( + url === `${mockedSettings.downloadApiUrl}/admin/downloads` && + params.queryOffset === 'WHERE download.id = 1' + ) + return Promise.resolve({ + data: [deletedDownload], + }); + + return Promise.reject(); + }); + + axios.put = jest.fn().mockImplementation(() => Promise.resolve()); + + const { result, waitFor } = renderHook( + () => ({ + useAdminDownloads: useAdminDownloads({ + initialQueryOffset: 'LIMIT 0, 50', + }), + useAdminDownloadDeleted: useAdminDownloadDeleted(), + }), { - message: 'simulating a failed response', - }, - false + wrapper: createReactQueryWrapper(), + } + ); + + // wait for admin downloads to finish loading + await waitFor(() => result.current.useAdminDownloads.isSuccess); + isMutated = true; + result.current.useAdminDownloadDeleted.mutate({ + downloadId: 1, + deleted: true, + }); + // wait for mutation to complete + await waitFor(() => result.current.useAdminDownloadDeleted.isSuccess); + + const updated = result.current.useAdminDownloads.data?.pages?.[0]?.find( + ({ id }) => id === 1 ); + + expect(updated?.isDeleted).toBe(true); + }); + + it('should restore download with the given id', async () => { + // the way the mocked mutation is handled is through this isMutated flag. + // initially, isMutated is false, and the mocked implementation + // of axios.get will return the unmodified download item list. + // after isMutated is set to true + // (which is done when manually calling the mutation function) + // axios.get will return the updated download item list instead, + // to simulate server updating the list. + // + // this is needed because after mutation is successful, + // onSettled is called which will call invalidateQueries, causing + // axios.get to be called again. without the flag, + // it will just always return the old list. + + let isMutated = false; + const restoredDownload: Download = { + createdAt: '2020-02-25T15:05:29Z', + downloadItems: [{ entityId: 1, entityType: 'investigation', id: 1 }], + email: 'test1@email.com', + facilityName: 'LILS', + fileName: 'test-file-1', + fullName: 'Person 1', + id: 6, + isDeleted: false, + isEmailSent: true, + isTwoLevel: false, + preparedId: 'test-prepared-id', + sessionId: 'test-session-id', + size: 1000, + status: 'COMPLETE', + transport: 'https', + userName: 'test user', + }; + // mockDownloadItems all have isDeleted set to false + // I made a new Download object with isDeleted set to true + // to simulate the action of restoring a download + // it will be appended to mockDownloadItems + const deletedDownload = { + ...restoredDownload, + isDeleted: true, + }; + + axios.get = jest.fn().mockImplementation((url, { params }) => { + // fetchAdminDownloads from useAdminDownloads + if ( + url === `${mockedSettings.downloadApiUrl}/admin/downloads` && + params.queryOffset === 'LIMIT 0, 50' + ) + return Promise.resolve({ + data: isMutated + ? [...mockDownloadItems, deletedDownload].map((download) => + download.id === restoredDownload.id + ? restoredDownload + : download + ) + : [...mockDownloadItems, deletedDownload], + }); + + // fetchAdminDownloads from onSuccess of useAdminDownloadDeleted + if ( + url === `${mockedSettings.downloadApiUrl}/admin/downloads` && + params.queryOffset === `WHERE download.id = ${restoredDownload.id}` + ) + return Promise.resolve({ + data: [restoredDownload], + }); + + return Promise.reject(); + }); + + axios.put = jest.fn().mockImplementation(() => Promise.resolve()); + + const { result, waitFor } = renderHook( + () => ({ + useAdminDownloads: useAdminDownloads({ + initialQueryOffset: 'LIMIT 0, 50', + }), + useAdminDownloadDeleted: useAdminDownloadDeleted(), + }), + { + wrapper: createReactQueryWrapper(), + } + ); + + // wait for admin downloads to finish loading + await waitFor(() => result.current.useAdminDownloads.isSuccess); + isMutated = true; + result.current.useAdminDownloadDeleted.mutate({ + downloadId: 6, + deleted: false, + }); + // wait for mutation to complete + await waitFor(() => result.current.useAdminDownloadDeleted.isSuccess); + + const updated = result.current.useAdminDownloads.data?.pages?.[0]?.find( + ({ id }) => id === restoredDownload.id + ); + + expect(updated?.isDeleted).toBe(false); + }); + + it('should call handleICATError when an error is encountered', async () => { + axios.put = jest.fn().mockRejectedValue({ + message: 'Test error message', + }); + + const { result, waitFor } = renderHook(() => useAdminDownloadDeleted(), { + wrapper: createReactQueryWrapper(), + }); + + result.current.mutate({ + downloadId: 1, + deleted: true, + }); + await waitFor(() => result.current.isError); + + expect(handleICATError).toHaveBeenCalledWith({ + message: 'Test error message', + }); + }); + }); + + describe('useAdminUpdateDownloadStatus', () => { + it('should update status of download with the given id', async () => { + // the way the mocked mutation is handled is through this isMutated flag. + // initially, isMutated is false, and the mocked implementation + // of axios.get will return the unmodified download item list. + // after isMutated is set to true + // (which is done when manually calling the mutation function) + // axios.get will return the updated download item list instead, + // to simulate server updating the list. + // + // this is needed because after mutation is successful, + // onSettled is called which will call invalidateQueries, causing + // axios.get to be called again. without the flag, + // it will just always return the old list. + + let isMutated = false; + + const updatedDownload: Download = { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + ...mockDownloadItems.find(({ id }) => id === 1)!, + status: 'PREPARING', + }; + + axios.get = jest.fn().mockImplementation(() => + Promise.resolve({ + data: isMutated + ? mockDownloadItems.map((download) => + download.id === updatedDownload.id ? updatedDownload : download + ) + : mockDownloadItems, + }) + ); + axios.put = jest.fn().mockImplementation(() => Promise.resolve()); + + const { result, waitFor } = renderHook( + () => ({ + useAdminDownloads: useAdminDownloads({ + initialQueryOffset: 'LIMIT 0, 50 ', + }), + useAdminUpdateDownloadStatus: useAdminUpdateDownloadStatus(), + }), + { + wrapper: createReactQueryWrapper(), + } + ); + + await waitFor(() => result.current.useAdminDownloads.isSuccess); + isMutated = true; + result.current.useAdminUpdateDownloadStatus.mutate({ + downloadId: 1, + status: 'PREPARING', + }); + await waitFor( + () => result.current.useAdminUpdateDownloadStatus.isSuccess + ); + + expect( + result.current.useAdminDownloads.data?.pages?.[0]?.find( + ({ id }) => id === 1 + ) + ).toEqual(updatedDownload); + }); + + it('should call handleICATError and rollback optimistic changes if an error is encountered', async () => { + axios.put = jest.fn().mockRejectedValue({ + message: 'Test error message', + }); + axios.get = jest.fn().mockResolvedValue({ data: mockDownloadItems }); + + const { result, waitFor } = renderHook( + () => ({ + useAdminDownloads: useAdminDownloads({ + initialQueryOffset: 'LIMIT 0, 50', + }), + useAdminUpdateDownloadStatus: useAdminUpdateDownloadStatus(), + }), + { wrapper: createReactQueryWrapper() } + ); + + await waitFor(() => result.current.useAdminDownloads.isSuccess); + result.current.useAdminUpdateDownloadStatus.mutate({ + downloadId: 1, + status: 'PREPARING', + }); + await waitFor(() => result.current.useAdminUpdateDownloadStatus.isError); + + expect(handleICATError).toHaveBeenCalledWith({ + message: 'Test error message', + }); + expect(result.current.useAdminDownloads.data?.pages).toEqual([ + mockDownloadItems, + ]); + }); + }); + + describe('useSubmitCart', () => { + it('should submit cart and clear cart on success', async () => { + axios.post = jest.fn().mockResolvedValue({ data: 123 }); + axios.get = jest + .fn() + .mockResolvedValueOnce({ + data: { + cartItems: mockCartItems, + }, + }) + .mockResolvedValueOnce({ data: { cartItems: [] } }); + + const { result, waitFor } = renderHook( + () => ({ + useSubmitCart: useSubmitCart(), + useCart: useCart(), + }), + { wrapper: createReactQueryWrapper() } + ); + + // wait for the cart to finish loading + await waitFor(() => result.current.useCart.isSuccess); + // submit the cart + result.current.useSubmitCart.mutate({ + emailAddress: 'cat@dog.com', + fileName: 'test-file', + transport: 'https', + }); + // wait for cart submission to finish + await waitFor(() => result.current.useSubmitCart.isSuccess); + + expect(result.current.useCart.data).toEqual([]); + }); + + it('should call handleICATError when an error is encountered', async () => { + axios.post = jest.fn().mockRejectedValue({ + message: 'test error message', + }); + axios.get = jest.fn().mockResolvedValueOnce({ + data: { + cartItems: mockCartItems, + }, + }); + + const { result, waitFor } = renderHook( + () => ({ + useSubmitCart: useSubmitCart(), + useCart: useCart(), + }), + { wrapper: createReactQueryWrapper() } + ); + + await waitFor(() => result.current.useCart.isSuccess); + result.current.useSubmitCart.mutate({ + emailAddress: 'a@b.c', + fileName: 'test-file', + transport: 'https', + }); + await waitFor(() => result.current.useSubmitCart.isError); + + expect(handleICATError).toHaveBeenCalledWith({ + message: 'test error message', + }); + }); + }); + + describe('useDownloadTypeStatuses', () => { + const downloadTypes = ['https', 'globus']; + + let queryClient: QueryClient; + + beforeAll(() => { + queryClient = new QueryClient(); + }); + + afterEach(() => { + queryClient.clear(); + }); + + it('should query statuses of download types', async () => { + axios.get = jest.fn().mockResolvedValue({ + data: { + disabled: false, + message: '', + }, + }); + + const { result, waitFor } = renderHook( + () => useDownloadTypeStatuses({ downloadTypes }), + { wrapper: createReactQueryWrapper() } + ); + + await waitFor(() => result.current.every((query) => query.isSuccess)); + + const data = result.current.map(({ data }) => data); + expect(data).toEqual([ + { + type: 'https', + disabled: false, + message: '', + }, + { + type: 'globus', + disabled: false, + message: '', + }, + ]); + }); + + it('should dispatch event with the error messages of download type queries with errors', async () => { + axios.get = jest + .fn() + .mockResolvedValueOnce({ + data: { + disabled: false, + message: '', + }, + }) + .mockImplementationOnce(() => + Promise.reject({ + message: 'Test error message', + }) + ); + + const dispatchEventSpy = jest.spyOn(document, 'dispatchEvent'); + + const { result, waitFor } = renderHook( + () => useDownloadTypeStatuses({ downloadTypes }), + { wrapper: createReactQueryWrapper() } + ); + + await waitFor(() => + result.current.every((query) => query.isSuccess || query.isError) + ); + + expect((dispatchEventSpy.mock.calls[0][0] as CustomEvent).detail).toEqual( + { + type: NotificationType, + payload: { + severity: 'error', + message: + 'downloadConfirmDialog.access_method_error {method:GLOBUS}', + }, + } + ); + }); + + it('should refetch data on every hook call', async () => { + axios.get = jest.fn().mockResolvedValue({ + data: { + disabled: false, + message: '', + }, + }); + + const wrapper = createReactQueryWrapper(); + + const { result, waitFor } = renderHook( + () => + useDownloadTypeStatuses({ + downloadTypes: ['https'], + }), + { wrapper } + ); + + await waitFor(() => result.current.every((query) => query.isSuccess)); + + expect(result.current[0].isStale).toBe(true); + expect(axios.get).toHaveBeenCalledTimes(1); + + await act(async () => { + const { result: newResult } = renderHook( + () => + useDownloadTypeStatuses({ + downloadTypes: ['https'], + }), + { wrapper } + ); + + await waitFor(() => + newResult.current.every((query) => query.isSuccess) + ); + + expect(newResult.current[0].isStale).toBe(true); + expect(axios.get).toHaveBeenCalledTimes(2); + }); + }); + }); + + describe('useDownloadPercentageComplete', () => { + it('should query progress of a download restore', async () => { + axios.get = jest.fn().mockResolvedValue({ + data: '30', + }); + + const { result, waitFor } = renderHook( + () => + useDownloadPercentageComplete({ + download: mockDownloadItems[0], + }), + { + wrapper: createReactQueryWrapper(), + } + ); + await waitFor(() => result.current.isSuccess); + + expect(result.current.data).toEqual(30); + }); + + it('should query status of a download restore', async () => { + axios.get = jest.fn().mockResolvedValue({ + data: 'UNKNOWN', + }); + + const { result, waitFor } = renderHook( + () => + useDownloadPercentageComplete({ + download: mockDownloadItems[0], + }), + { + wrapper: createReactQueryWrapper(), + } + ); + await waitFor(() => result.current.isSuccess); + + expect(result.current.data).toEqual('UNKNOWN'); + }); + + it('should call handleICATError when an error is encountered', async () => { + axios.get = jest.fn().mockRejectedValue({ + message: 'Test error message', + }); + + const { result, waitFor } = renderHook( + () => + useDownloadPercentageComplete({ + download: mockDownloadItems[0], + }), + { + wrapper: createReactQueryWrapper(), + } + ); + await waitFor(() => result.current.isError); + + expect(handleICATError).toHaveBeenCalledWith( + { + message: 'Test error message', + }, + false + ); + }); + }); + + describe('useIsCartMintable', () => { + it('should check whether a cart is mintable', async () => { + axios.post = jest + .fn() + .mockResolvedValue({ data: undefined, status: 200 }); + + const { result, waitFor } = renderHook( + () => useIsCartMintable(mockCartItems), + { + wrapper: createReactQueryWrapper(), + } + ); + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(result.current.data).toEqual(true); + expect(axios.post).toHaveBeenCalledWith( + `${mockedSettings.doiMinterUrl}/ismintable`, + { + investigation_ids: [1, 2], + dataset_ids: [3], + datafile_ids: [4], + }, + { headers: { Authorization: 'Bearer null' } } + ); + }); + + it('should be disabled if doiMinterUrl is not defined', async () => { + const { result } = renderHook(() => useIsCartMintable(mockCartItems), { + wrapper: createReactQueryWrapper({ + ...mockedSettings, + doiMinterUrl: undefined, + }), + }); + + expect(result.current.isIdle).toEqual(true); + expect(axios.post).not.toHaveBeenCalled(); + }); + + it('should return false if cart is undefined', async () => { + const { result, waitFor } = renderHook( + () => useIsCartMintable(undefined), + { + wrapper: createReactQueryWrapper(), + } + ); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(result.current.data).toEqual(false); + expect(axios.post).not.toHaveBeenCalled(); + }); + + it('should return false if cart is empty', async () => { + const { result, waitFor } = renderHook(() => useIsCartMintable([]), { + wrapper: createReactQueryWrapper(), + }); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(result.current.data).toEqual(false); + expect(axios.post).not.toHaveBeenCalled(); + }); + + it('should handle 401 by broadcasting an invalidate token message with autologin being true', async () => { + localStorageGetItemMock.mockImplementation((name) => { + return name === 'autoLogin' ? 'true' : null; + }); + + const error = { + message: 'Test error message', + response: { + status: 401, + }, + }; + axios.post = jest.fn().mockRejectedValue(error); + + const { result, waitFor } = renderHook( + () => useIsCartMintable([mockCartItems[0]]), + { + wrapper: createReactQueryWrapper(), + } + ); + await waitFor(() => expect(result.current.isError).toBe(true)); + + expect(log.error).toHaveBeenCalledWith(error); + expect(axios.post).toHaveBeenCalledTimes(4); + expect(axios.post).toHaveBeenCalledWith( + `${mockedSettings.doiMinterUrl}/ismintable`, + { + investigation_ids: [1], + }, + { headers: { Authorization: 'Bearer null' } } + ); + expect(events.length).toBe(1); + expect(events[0].detail).toEqual({ + type: InvalidateTokenType, + payload: { + severity: 'error', + message: 'Your session has expired, please reload the page', + }, + }); + }); + + it('should handle 401 by broadcasting an invalidate token message with autologin being false', async () => { + localStorageGetItemMock.mockImplementation((name) => { + return name === 'autoLogin' ? 'false' : null; + }); + + const error = { + message: 'Test error message', + response: { + status: 401, + }, + }; + axios.post = jest.fn().mockRejectedValue(error); + + const { result, waitFor } = renderHook( + () => useIsCartMintable([mockCartItems[3]]), + { + wrapper: createReactQueryWrapper(), + } + ); + await waitFor(() => expect(result.current.isError).toBe(true)); + + expect(log.error).toHaveBeenCalledWith(error); + expect(axios.post).toHaveBeenCalledTimes(4); + expect(axios.post).toHaveBeenCalledWith( + `${mockedSettings.doiMinterUrl}/ismintable`, + { + datafile_ids: [4], + }, + { headers: { Authorization: 'Bearer null' } } + ); + expect(events.length).toBe(1); + expect(events[0].detail).toEqual({ + type: InvalidateTokenType, + payload: { + severity: 'error', + message: 'Your session has expired, please login again', + }, + }); + }); + + it('should not log 403 errors or retry them', async () => { + const error = { + message: 'Test error message', + response: { + status: 403, + }, + }; + axios.post = jest.fn().mockRejectedValue(error); + + const { result, waitFor } = renderHook( + () => useIsCartMintable(mockCartItems), + { + wrapper: createReactQueryWrapper(), + } + ); + await waitFor(() => expect(result.current.isError).toBe(true)); + + expect(log.error).not.toHaveBeenCalled(); + expect(axios.post).toHaveBeenCalledTimes(1); + }); + }); + + describe('useMintCart', () => { + const doiMetadata = { + title: 'Test title', + description: 'Test description', + creators: [{ username: '1', contributor_type: ContributorType.Creator }], + related_items: [], + }; + it('should send a request to mint a cart', async () => { + axios.post = jest.fn().mockResolvedValue({ + data: { + concept: { doi: 'test doi', data_publication: '1' }, + version: { doi: 'test doi v1', data_publication: '11' }, + }, + status: 200, + }); + + const { result } = renderHook(() => useMintCart(), { + wrapper: createReactQueryWrapper(), + }); + + await act(async () => { + await result.current.mutateAsync({ cart: mockCartItems, doiMetadata }); + }); + + expect(result.current.data).toEqual({ + concept: { doi: 'test doi', data_publication: '1' }, + version: { doi: 'test doi v1', data_publication: '11' }, + }); + expect(axios.post).toHaveBeenCalledWith( + `${mockedSettings.doiMinterUrl}/mint`, + { + metadata: { + ...doiMetadata, + resource_type: 'Collection', + }, + investigation_ids: [1, 2], + dataset_ids: [3], + datafile_ids: [4], + }, + { headers: { Authorization: 'Bearer null' } } + ); + }); + + it('should handle 401 by broadcasting an invalidate token message with autologin being true', async () => { + localStorageGetItemMock.mockImplementation((name) => { + return name === 'autoLogin' ? 'true' : null; + }); + + const error = { + message: 'Test error message', + response: { + status: 401, + }, + }; + axios.post = jest.fn().mockRejectedValue(error); + + const { result, waitFor } = renderHook(() => useMintCart(), { + wrapper: createReactQueryWrapper(), + }); + + act(() => { + result.current.mutate({ cart: [mockCartItems[0]], doiMetadata }); + }); + await waitFor(() => expect(result.current.isError).toBe(true)); + + expect(log.error).toHaveBeenCalledWith(error); + expect(axios.post).toHaveBeenCalledWith( + `${mockedSettings.doiMinterUrl}/mint`, + { + metadata: { + ...doiMetadata, + resource_type: 'Collection', + }, + investigation_ids: [1], + }, + { headers: { Authorization: 'Bearer null' } } + ); + expect(events.length).toBe(1); + expect(events[0].detail).toEqual({ + type: InvalidateTokenType, + payload: { + severity: 'error', + message: 'Your session has expired, please reload the page', + }, + }); + }); + + it('should handle 401 by broadcasting an invalidate token message with autologin being false', async () => { + localStorageGetItemMock.mockImplementation((name) => { + return name === 'autoLogin' ? 'false' : null; + }); + + const error = { + message: 'Test error message', + response: { + status: 401, + }, + }; + axios.post = jest.fn().mockRejectedValue(error); + + const { result, waitFor } = renderHook(() => useMintCart(), { + wrapper: createReactQueryWrapper(), + }); + + act(() => { + result.current.mutate({ cart: [mockCartItems[3]], doiMetadata }); + }); + await waitFor(() => expect(result.current.isError).toBe(true)); + + expect(log.error).toHaveBeenCalledWith(error); + expect(axios.post).toHaveBeenCalledWith( + `${mockedSettings.doiMinterUrl}/mint`, + { + metadata: { + ...doiMetadata, + resource_type: 'Dataset', + }, + datafile_ids: [4], + }, + { headers: { Authorization: 'Bearer null' } } + ); + expect(events.length).toBe(1); + expect(events[0].detail).toEqual({ + type: InvalidateTokenType, + payload: { + severity: 'error', + message: 'Your session has expired, please login again', + }, + }); + }); + }); + + describe('useCartUsers', () => { + it('should get a list of users associated with each cart item', async () => { + axios.get = jest.fn().mockImplementation((url) => { + if (url.includes('investigations')) { + return Promise.resolve({ + data: [ + { + investigationUsers: [ + { user: { id: 1, name: 'user 1' } }, + { user: { id: 2, name: 'user 2' } }, + ], + }, + ], + }); + } + if (url.includes('datasets')) { + return Promise.resolve({ + data: [ + { + investigation: { + investigationUsers: [ + { user: { id: 2, name: 'user 2' } }, + { user: { id: 3, name: 'user 3' } }, + ], + }, + }, + ], + }); + } + if (url.includes('datafiles')) { + return Promise.resolve({ + data: [ + { + dataset: { + investigation: { + investigationUsers: [ + { user: { id: 3, name: 'user 3' } }, + { user: { id: 4, name: 'user 4' } }, + ], + }, + }, + }, + ], + }); + } else { + return Promise.resolve({ data: [] }); + } + }); + + const { result, waitFor } = renderHook( + () => useCartUsers(mockCartItems), + { + wrapper: createReactQueryWrapper(), + } + ); + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + // data should be deduped + expect(result.current.data).toEqual([ + { id: 1, name: 'user 1' }, + { id: 2, name: 'user 2' }, + { id: 3, name: 'user 3' }, + { id: 4, name: 'user 4' }, + ]); + // needs to get called once for each item in the cart + expect(axios.get).toHaveBeenCalledTimes(mockCartItems.length); + + const inv1Params = new URLSearchParams(); + inv1Params.append( + 'where', + JSON.stringify({ + id: { eq: 1 }, + }) + ); + inv1Params.append( + 'include', + JSON.stringify({ + investigationUsers: 'user', + }) + ); + + expect(axios.get).toHaveBeenCalledWith( + `${mockedSettings.apiUrl}/investigations`, + expect.objectContaining({ + params: inv1Params, + }) + ); + + const inv2Params = new URLSearchParams(); + inv2Params.append( + 'where', + JSON.stringify({ + id: { eq: 2 }, + }) + ); + inv2Params.append( + 'include', + JSON.stringify({ + investigationUsers: 'user', + }) + ); + + expect(axios.get).toHaveBeenCalledWith( + `${mockedSettings.apiUrl}/investigations`, + expect.objectContaining({ + params: inv2Params, + }) + ); + + const dsParams = new URLSearchParams(); + dsParams.append( + 'where', + JSON.stringify({ + id: { eq: 3 }, + }) + ); + dsParams.append( + 'include', + JSON.stringify({ + investigation: { investigationUsers: 'user' }, + }) + ); + + expect(axios.get).toHaveBeenCalledWith( + `${mockedSettings.apiUrl}/datasets`, + expect.objectContaining({ + params: dsParams, + }) + ); + + const dfParams = new URLSearchParams(); + dfParams.append( + 'where', + JSON.stringify({ + id: { eq: 4 }, + }) + ); + dfParams.append( + 'include', + JSON.stringify({ + datasets: { investigation: { investigationUsers: 'user' } }, + }) + ); + + expect(axios.get).toHaveBeenCalledWith( + `${mockedSettings.apiUrl}/datafiles`, + expect.objectContaining({ + params: dfParams, + }) + ); + }); + + it('should not query for users if cart is undefined', async () => { + const { result, waitFor } = renderHook(() => useCartUsers(undefined), { + wrapper: createReactQueryWrapper(), + }); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(result.current.data).toEqual([]); + expect(axios.get).not.toHaveBeenCalled(); + }); + }); + + describe('useCheckUser', () => { + it('should check whether a user exists in ICAT', async () => { + axios.get = jest + .fn() + .mockResolvedValue({ data: { id: 1, name: 'user 1' } }); + + const { result, waitFor } = renderHook(() => useCheckUser('user 1'), { + wrapper: createReactQueryWrapper(), + }); + expect(result.current.isIdle).toBe(true); + act(() => { + result.current.refetch(); + }); + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(result.current.data).toEqual({ id: 1, name: 'user 1' }); + expect(axios.get).toHaveBeenCalledWith( + `${mockedSettings.doiMinterUrl}/user/${'user 1'}`, + { headers: { Authorization: 'Bearer null' } } + ); + }); + + it('should handle 401 by broadcasting an invalidate token message with autologin being true', async () => { + localStorageGetItemMock.mockImplementation((name) => { + return name === 'autoLogin' ? 'true' : null; + }); + + const error = { + message: 'Test error message', + response: { + status: 401, + }, + }; + axios.get = jest.fn().mockRejectedValue(error); + + const { result, waitFor } = renderHook(() => useCheckUser('user 1'), { + wrapper: createReactQueryWrapper(), + }); + expect(result.current.isIdle).toBe(true); + act(() => { + result.current.refetch(); + }); + await waitFor(() => expect(result.current.isError).toBe(true)); + + expect(log.error).toHaveBeenCalledWith(error); + expect(axios.get).toHaveBeenCalledTimes(1); + expect(events.length).toBe(1); + expect(events[0].detail).toEqual({ + type: InvalidateTokenType, + payload: { + severity: 'error', + message: 'Your session has expired, please reload the page', + }, + }); + }); + + it('should handle 401 by broadcasting an invalidate token message with autologin being false', async () => { + localStorageGetItemMock.mockImplementation((name) => { + return name === 'autoLogin' ? 'false' : null; + }); + + const error = { + message: 'Test error message', + response: { + status: 401, + }, + }; + axios.get = jest.fn().mockRejectedValue(error); + + const { result, waitFor } = renderHook(() => useCheckUser('user 1'), { + wrapper: createReactQueryWrapper(), + }); + expect(result.current.isIdle).toBe(true); + act(() => { + result.current.refetch(); + }); + await waitFor(() => expect(result.current.isError).toBe(true)); + + expect(log.error).toHaveBeenCalledWith(error); + expect(axios.get).toHaveBeenCalledTimes(1); + expect(events.length).toBe(1); + expect(events[0].detail).toEqual({ + type: InvalidateTokenType, + payload: { + severity: 'error', + message: 'Your session has expired, please login again', + }, + }); + }); + + it('should not retry 404 errors', async () => { + const error = { + message: 'Test error message', + response: { + status: 404, + }, + }; + axios.get = jest.fn().mockRejectedValue(error); + + const { result, waitFor } = renderHook(() => useCheckUser('user 1'), { + wrapper: createReactQueryWrapper(), + }); + expect(result.current.isIdle).toBe(true); + act(() => { + result.current.refetch(); + }); + await waitFor(() => expect(result.current.isError).toBe(true)); + + expect(log.error).toHaveBeenCalledWith(error); + expect(axios.get).toHaveBeenCalledTimes(1); + }); + + it('should not retry 422 errors', async () => { + const error = { + message: 'Test error message', + response: { + status: 422, + }, + }; + axios.get = jest.fn().mockRejectedValue(error); + + const { result, waitFor } = renderHook(() => useCheckUser('user 1'), { + wrapper: createReactQueryWrapper(), + }); + expect(result.current.isIdle).toBe(true); + act(() => { + result.current.refetch(); + }); + await waitFor(() => expect(result.current.isError).toBe(true)); + + expect(log.error).toHaveBeenCalledWith(error); + expect(axios.get).toHaveBeenCalledTimes(1); + }); + + it('should retry other errors', async () => { + const error = { + message: 'Test error message', + response: { + status: 400, + }, + }; + axios.get = jest.fn().mockRejectedValue(error); + + const { result, waitFor } = renderHook(() => useCheckUser('user 1'), { + wrapper: createReactQueryWrapper(), + }); + expect(result.current.isIdle).toBe(true); + act(() => { + result.current.refetch(); + }); + await waitFor(() => expect(result.current.isError).toBe(true)); + + expect(log.error).toHaveBeenCalledWith(error); + expect(axios.get).toHaveBeenCalledTimes(4); }); }); }); diff --git a/packages/datagateway-download/src/downloadApiHooks.ts b/packages/datagateway-download/src/downloadApiHooks.ts index a25f68e84..16087535c 100644 --- a/packages/datagateway-download/src/downloadApiHooks.ts +++ b/packages/datagateway-download/src/downloadApiHooks.ts @@ -1,35 +1,112 @@ -import React from 'react'; import { AxiosError } from 'axios'; +import { + Download, + DownloadStatus, + InvalidateTokenType, + User, +} from 'datagateway-common'; import { DownloadCartItem, - handleICATError, fetchDownloadCart, + handleICATError, + MicroFrontendId, + NotificationType, retryICATErrors, } from 'datagateway-common'; -import { DownloadSettingsContext } from './ConfigProvider'; +import log from 'loglevel'; +import pLimit from 'p-limit'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; import { - UseQueryResult, - useQuery, + InfiniteData, + useInfiniteQuery, + UseInfiniteQueryResult, useMutation, + UseMutationOptions, UseMutationResult, + useQueries, + useQuery, useQueryClient, UseQueryOptions, - useQueries, + UseQueryResult, } from 'react-query'; -import pLimit from 'p-limit'; +import { DownloadSettingsContext } from './ConfigProvider'; import { + checkUser, + DoiMetadata, + DoiResponse, + DownloadProgress, + DownloadTypeStatus, + fetchDOI, + FileSizeAndCount, + getCartUsers, + getFileSizeAndCount, + isCartMintable, + mintCart, + RelatedDOI, + SubmitCartZipType, +} from './downloadApi'; +import { + adminDownloadDeleted, + adminDownloadStatus, + downloadDeleted, + fetchAdminDownloads, + fetchDownloads, + getDownload, + getDownloadTypeStatus, + getIsTwoLevel, + getPercentageComplete, removeAllDownloadCartItems, removeFromCart, - getSize, - getDatafileCount, - getIsTwoLevel, + submitCart, } from './downloadApi'; +/** + * An enumeration of react query keys. + */ +export enum QueryKey { + /** + * Key for querying a particular download. + */ + DOWNLOAD = 'download', + + /** + * Key for querying list of downloads. + */ + DOWNLOADS = 'downloads', + + /** + * Key for querying the status of a particular download type + */ + DOWNLOAD_TYPE_STATUS = 'download-type-status', + + /** + * Key for querying the progress of a download. + */ + DOWNLOAD_PROGRESS = 'download-progress', + + /** + * Key for querying list of admin downloads + */ + ADMIN_DOWNLOADS = 'admin-downloads', + + /** + * Key for querying the download cart. + */ + CART = 'cart', +} + +/** + * Defines the function that when called will roll back any optimistic changes + * performed during a mutation. + */ +type RollbackFunction = () => void; + export const useCart = (): UseQueryResult => { const settings = React.useContext(DownloadSettingsContext); const { facilityName, downloadApiUrl } = settings; return useQuery( - 'cart', + QueryKey.CART, () => fetchDownloadCart({ facilityName, @@ -57,12 +134,12 @@ export const useRemoveAllFromCart = (): UseMutationResult< return useMutation( () => removeAllDownloadCartItems({ facilityName, downloadApiUrl }), { - onSuccess: (data) => { - queryClient.setQueryData('cart', []); + onSuccess: () => { + queryClient.setQueryData(QueryKey.CART, []); }, retry: (failureCount, error) => { // if we get 431 we know this is an intermittent error so retry - if (error.code === '431' && failureCount < 3) { + if (error.response?.status === 431 && failureCount < 3) { return true; } else { return false; @@ -92,11 +169,11 @@ export const useRemoveEntityFromCart = (): UseMutationResult< }), { onSuccess: (data) => { - queryClient.setQueryData('cart', data); + queryClient.setQueryData(QueryKey.CART, data); }, retry: (failureCount, error) => { // if we get 431 we know this is an intermittent error so retry - if (error.code === '431' && failureCount < 3) { + if (error.response?.status === 431 && failureCount < 3) { return true; } else { return false; @@ -121,70 +198,88 @@ export const useIsTwoLevel = (): UseQueryResult => { }); }; -// TODO: refactor rest of dg-download to use react-query -// export const useSubmitCart = (): UseMutationResult< -// number, -// AxiosError, -// { -// transport: string; -// emailAddress: string; -// fileName: string; -// zipType?: 'ZIP' | 'ZIP_AND_COMPRESS'; -// } -// > => { -// const queryClient = useQueryClient(); -// const settings = React.useContext(DownloadSettingsContext); -// const { facilityName, downloadApiUrl } = settings; - -// return useMutation( -// ({ transport, emailAddress, fileName, zipType }) => -// submitCart( -// transport, -// emailAddress, -// fileName, -// { -// facilityName, -// downloadApiUrl, -// }, -// zipType -// ), -// { -// onSuccess: (data) => { -// queryClient.setQueryData('cart', data); -// }, -// onError: (error) => { -// handleICATError(error); -// }, -// } -// ); -// }; - -const sizesLimit = pLimit(20); - -export const useSizes = ( +export interface SubmitCartParams { + transport: string; + emailAddress: string; + fileName: string; + zipType?: SubmitCartZipType; +} + +/** + * A React hook for submitting a download cart. + * Returns the download id for the submitted cart, which can then be used + * to query more info. + */ +export const useSubmitCart = ( + options?: UseMutationOptions< + number, + AxiosError, + SubmitCartParams, + RollbackFunction + > +): UseMutationResult< + number, + AxiosError, + SubmitCartParams, + RollbackFunction +> => { + const queryClient = useQueryClient(); + const settings = React.useContext(DownloadSettingsContext); + const { facilityName, downloadApiUrl } = settings; + + return useMutation( + ({ transport, emailAddress, fileName, zipType }) => + submitCart( + transport, + emailAddress, + fileName, + { + facilityName, + downloadApiUrl, + }, + zipType + ), + { + onError: (error, _, rollback) => { + handleICATError(error); + if (rollback) rollback(); + }, + + onSettled: () => { + queryClient.invalidateQueries(QueryKey.CART); + }, + + ...(options ?? {}), + } + ); +}; + +const fileSizeAndCountLimit = pLimit(20); + +export const useFileSizesAndCounts = ( data: DownloadCartItem[] | undefined -): UseQueryResult[] => { +): UseQueryResult[] => { const settings = React.useContext(DownloadSettingsContext); const { facilityName, apiUrl, downloadApiUrl } = settings; - const queryConfigs: UseQueryOptions< - number, - AxiosError, - number, - ['size', number] - >[] = React.useMemo(() => { + const queryConfigs: { + queryKey: [string, number]; + staleTime: number; + queryFn: () => Promise; + retry: (failureCount: number, error: AxiosError) => boolean; + }[] = React.useMemo(() => { return data ? data.map((cartItem) => { const { entityId, entityType } = cartItem; return { - queryKey: ['size', entityId], + queryKey: ['fileSizeAndCount', entityId], queryFn: () => - sizesLimit(getSize, entityId, entityType, { + fileSizeAndCountLimit(getFileSizeAndCount, entityId, entityType, { facilityName, apiUrl, downloadApiUrl, }), - onError: (error) => { + onError: (error: AxiosError) => { handleICATError(error, false); }, retry: retryICATErrors, @@ -194,59 +289,666 @@ export const useSizes = ( : []; }, [data, facilityName, apiUrl, downloadApiUrl]); - // useQueries doesn't allow us to specify type info, so ignore this line - // since we strongly type the queries object anyway - // we also need to prettier-ignore to make sure we don't wrap onto next line + return useQueries(queryConfigs); +}; + +export interface UseDownloadParams { + id: number; +} + +/** + * A React hook that fetches a single download with the given id. + * useQuery options can be passed in, which will override the default used. + * + * Example: + * ``` + * useDownload({ + * id: 123, + * select: (download) => format(download) + * }) + * ``` + */ +export const useDownload = ({ + id, + ...queryOptions +}: UseDownloadParams & + UseQueryOptions< + Download, + AxiosError, + T, + [QueryKey.DOWNLOAD, number] + >): UseQueryResult => { + // Load the download settings for use. + const downloadSettings = React.useContext(DownloadSettingsContext); + + return useQuery( + [QueryKey.DOWNLOAD, id], + () => + getDownload(id, { + facilityName: downloadSettings.facilityName, + downloadApiUrl: downloadSettings.downloadApiUrl, + }), + { + onError: (error) => { + handleICATError(error); + }, + retry: retryICATErrors, + ...queryOptions, + } + ); +}; + +/** + * A React hook that fetches all downloads created by the user. + */ +export const useDownloads = ( + queryOptions?: UseQueryOptions< + Download[], + AxiosError, + TData, + QueryKey.DOWNLOADS + > +): UseQueryResult => { + // Load the download settings for use. + const downloadSettings = React.useContext(DownloadSettingsContext); + + return useQuery( + QueryKey.DOWNLOADS, + () => + fetchDownloads({ + facilityName: downloadSettings.facilityName, + downloadApiUrl: downloadSettings.downloadApiUrl, + }), + { + onError: (error) => { + handleICATError(error); + }, + retry: retryICATErrors, + ...queryOptions, + } + ); +}; + +export interface UseDownloadDeletedParams { + downloadId: number; + deleted: boolean; +} + +/** + * A React query that provides a mutation for deleting a download item. + */ +export const useDownloadOrRestoreDownload = (): UseMutationResult< + void, + AxiosError, + UseDownloadDeletedParams, + RollbackFunction +> => { + const queryClient = useQueryClient(); + // Load the download settings for use. + const downloadSettings = React.useContext(DownloadSettingsContext); + + return useMutation( + ({ downloadId, deleted }) => + downloadDeleted(downloadId, deleted, { + facilityName: downloadSettings.facilityName, + downloadApiUrl: downloadSettings.downloadApiUrl, + }), + { + onMutate: ({ downloadId, deleted }) => { + const prevDownloads = queryClient.getQueryData(QueryKey.DOWNLOADS); + + if (deleted) { + queryClient.setQueryData( + QueryKey.DOWNLOADS, + // updater fn returns undefined if prev data is also undefined + // note that it is not until v4 can the updater return undefined + // in v4, when the updater returns undefined, react-query will bail out + // and do nothing + // + // not sure how it works in v3, but returning an empty array feels wrong + // here because of semantics - + // undefined means the query is unavailable, but an empty array + // indicates there's no download item. + // hence FormattedDownload[] | undefined is passed to setQueryData + // to allow undefined to be returned + // + // TODO: when migrating to react-query v4, the "| undefined" part is no longer needed and can be removed. + // + // related issue: https://github.com/TanStack/query/issues/506 + (oldDownloads) => + oldDownloads && + oldDownloads.filter((download) => download.id !== downloadId) + ); + } + + return () => + queryClient.setQueryData(QueryKey.DOWNLOADS, prevDownloads); + }, + + onSuccess: async (_, { downloadId, deleted }) => { + if (!deleted) { + // download is restored (un-deleted), fetch the download info + const restoredDownload = await getDownload(downloadId, { + facilityName: downloadSettings.facilityName, + downloadApiUrl: downloadSettings.downloadApiUrl, + }); + + if (restoredDownload) { + queryClient.setQueryData( + QueryKey.DOWNLOADS, + (downloads) => downloads && [...downloads, restoredDownload] + ); + } + } + }, + + onError: (error, _, rollback) => { + handleICATError(error); + if (rollback) rollback(); + }, + + retry: (failureCount, error) => { + // if we get 431 we know this is an intermittent error so retry + return error.response?.status === 431 && failureCount < 3; + }, + } + ); +}; + +export const useDownloadTypeStatuses = ({ + downloadTypes, + ...queryOptions +}: { + downloadTypes: string[]; +} & UseQueryOptions): UseQueryResult< + TData, + AxiosError +>[] => { + // Load the download settings for use + const downloadSettings = React.useContext(DownloadSettingsContext); + const [t] = useTranslation(); + + const queryCount = downloadTypes.length; + const loadedQueriesCount = React.useRef(0); + const downloadTypesWithError = React.useRef([]); + + function broadcastError(message: string): void { + document.dispatchEvent( + new CustomEvent(MicroFrontendId, { + detail: { + type: NotificationType, + payload: { + severity: 'error', + message, + }, + }, + }) + ); + } + + function handleQueryError(downloadType: string): void { + downloadTypesWithError.current.push(downloadType); + + if (loadedQueriesCount.current === queryCount) { + if (downloadTypesWithError.current.length === queryCount) { + broadcastError(t('downloadConfirmDialog.access_methods_error')); + } else { + downloadTypesWithError.current.forEach((type) => { + broadcastError( + t('downloadConfirmDialog.access_method_error', { + method: type.toUpperCase(), + }) + ); + }); + } + } + } + + const queries = downloadTypes.map< + UseQueryOptions + >((type) => ({ + queryKey: [QueryKey.DOWNLOAD_TYPE_STATUS, type], + queryFn: () => + getDownloadTypeStatus(type, { + facilityName: downloadSettings.facilityName, + downloadApiUrl: downloadSettings.downloadApiUrl, + }), + onSettled: (_, error) => { + loadedQueriesCount.current += 1; + if (error) handleQueryError(type); + }, + ...queryOptions, + cacheTime: 0, + staleTime: 0, + })); + + // I have spent hours on this trying to make the type work, + // but due to the limitation of TypeScript, it is basically impossible + // for the type system to infer the return type of select properly. + // https://github.com/TanStack/query/pull/2634#issuecomment-939537730 + // // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - // prettier-ignore - const queries: UseQueryResult[] = useQueries(queryConfigs); + return useQueries(queries); +}; + +/** + * A React hook for querying admin downloads. Supports infinite scrolling. + * + * @param initialQueryOffset The initial query offset for the list of downloads. + */ +export const useAdminDownloads = ({ + initialQueryOffset, +}: { + initialQueryOffset: string; +}): UseInfiniteQueryResult => { + // Load the download settings for use + const downloadSettings = React.useContext(DownloadSettingsContext); + + return useInfiniteQuery( + [QueryKey.ADMIN_DOWNLOADS, initialQueryOffset], + ({ pageParam = initialQueryOffset }) => + fetchAdminDownloads( + { + facilityName: downloadSettings.facilityName, + downloadApiUrl: downloadSettings.downloadApiUrl, + }, + pageParam + ), + { + onError: (error) => { + handleICATError(error); + }, + } + ); +}; + +export interface AdminDownloadDeletedParams { + downloadId: number; + deleted: boolean; +} + +/** + * A React hook that provides a mutation function for deleting/restoring admin downloads. + */ +export const useAdminDownloadDeleted = (): UseMutationResult< + void, + AxiosError, + AdminDownloadDeletedParams, + RollbackFunction +> => { + const queryClient = useQueryClient(); + // Load the download settings for use. + const downloadSettings = React.useContext(DownloadSettingsContext); + + return useMutation( + ({ downloadId, deleted }) => + adminDownloadDeleted(downloadId, deleted, { + facilityName: downloadSettings.facilityName, + downloadApiUrl: downloadSettings.downloadApiUrl, + }), + { + onSuccess: async (_, { downloadId }) => { + const downloads = await fetchAdminDownloads( + { + facilityName: downloadSettings.facilityName, + downloadApiUrl: downloadSettings.downloadApiUrl, + }, + `WHERE download.id = ${downloadId}` + ); + if (downloads.length > 0) { + const updatedDownload = downloads[0]; + // updater fn returns undefined if prev data is also undefined + // note that it is not until v4 can the updater return undefined + // in v4, when the updater returns undefined, react-query will bail out + // and do nothing + // + // not sure how it works in v3, but returning an empty array feels wrong + // here because of semantics - + // undefined means the query is unavailable, but an empty array + // indicates there's no download item. + // hence FormattedDownload[] | undefined is passed to setQueryData + // to allow undefined to be returned + // + // TODO: when migrating to react-query v4, the "| undefined" part is no longer needed and can be removed. + // + // related issue: https://github.com/TanStack/query/issues/506 + queryClient.setQueryData | undefined>( + QueryKey.ADMIN_DOWNLOADS, + (oldData) => + oldData && { + ...oldData, + pages: oldData.pages.map((page) => + page.map((download) => + download.id === updatedDownload.id + ? updatedDownload + : download + ) + ), + } + ); + } + }, + + onError: (error) => { + handleICATError(error); + }, - return queries; + onSettled: () => { + queryClient.invalidateQueries(QueryKey.ADMIN_DOWNLOADS); + }, + } + ); }; -const datafileCountslimit = pLimit(20); +/** + * Parameters for {@link useAdminUpdateDownloadStatus} mutation. + */ +export interface AdminUpdateDownloadStatusParams { + downloadId: number; + status: DownloadStatus; +} -export const useDatafileCounts = ( - data: DownloadCartItem[] | undefined -): UseQueryResult[] => { +export const useAdminUpdateDownloadStatus = (): UseMutationResult< + void, + AxiosError, + AdminUpdateDownloadStatusParams, + RollbackFunction +> => { + const queryClient = useQueryClient(); + // Load the download settings for use. + const downloadSettings = React.useContext(DownloadSettingsContext); + + return useMutation( + ({ downloadId, status }) => + adminDownloadStatus(downloadId, status, { + facilityName: downloadSettings.facilityName, + downloadApiUrl: downloadSettings.downloadApiUrl, + }), + { + onMutate: ({ downloadId, status }) => { + const prevDownloads = queryClient.getQueryData( + QueryKey.ADMIN_DOWNLOADS + ); + + // updater fn returns undefined if prev data is also undefined + // note that it is not until v4 can the updater return undefined + // in v4, when the updater returns undefined, react-query will bail out + // and do nothing + // + // not sure how it works in v3, but returning an empty array feels wrong + // here because of semantics - + // undefined means the query is unavailable, but an empty array + // indicates there's no download item. + // hence FormattedDownload[] | undefined is passed to setQueryData + // to allow undefined to be returned + // + // TODO: when migrating to react-query v4, the "| undefined" part is no longer needed and can be removed. + // + // related issue: https://github.com/TanStack/query/issues/506 + queryClient.setQueryData | undefined>( + QueryKey.ADMIN_DOWNLOADS, + (oldData) => + oldData && { + ...oldData, + pages: oldData.pages.map((page) => + page.map((download) => + download.id === downloadId + ? { ...download, status } + : download + ) + ), + } + ); + + return () => + queryClient.setQueryData(QueryKey.ADMIN_DOWNLOADS, prevDownloads); + }, + + onError: (error, _, rollback) => { + handleICATError(error); + if (rollback) rollback(); + }, + + onSettled: () => { + queryClient.invalidateQueries(QueryKey.ADMIN_DOWNLOADS); + }, + } + ); +}; + +/** + * Queries the progress of a {@link Download}. + * @param download The {@link Download} that this query should query the restore progress of. + * @param queryOptions Optional `useQuery` option override. + */ +export const useDownloadPercentageComplete = ({ + download, + ...queryOptions +}: { download: Download } & UseQueryOptions< + DownloadProgress, + AxiosError, + T, + string[] +>): UseQueryResult => { + const { accessMethods } = React.useContext(DownloadSettingsContext); + const preparedId = download.preparedId; + const idsUrl = accessMethods[download.transport]?.idsUrl; + + return useQuery( + [QueryKey.DOWNLOAD_PROGRESS, preparedId], + () => + getPercentageComplete({ + preparedId: preparedId, + settings: { idsUrl: idsUrl ?? '' }, + }), + { + onError: (error) => { + handleICATError(error, false); + }, + ...queryOptions, + } + ); +}; + +/** + * Queries whether a cart is mintable. + * @param cart The {@link Cart} that is checked + */ +export const useIsCartMintable = ( + cart: DownloadCartItem[] | undefined +): UseQueryResult< + boolean, + AxiosError<{ detail: { msg: string }[] } | { detail: string }> +> => { const settings = React.useContext(DownloadSettingsContext); - const { apiUrl } = settings; + const { doiMinterUrl } = settings; - const queryConfigs: UseQueryOptions< - number, - AxiosError, - number, - ['datafileCount', number] - >[] = React.useMemo(() => { - return data - ? data.map((cartItem) => { - const { entityId, entityType } = cartItem; - return { - queryKey: ['datafileCount', entityId], - queryFn: () => - datafileCountslimit(getDatafileCount, entityId, entityType, { - apiUrl, - }), - onError: (error) => { - handleICATError(error, false); - }, - retry: retryICATErrors, - staleTime: Infinity, - enabled: entityType !== 'datafile', - initialData: entityType === 'datafile' ? 1 : undefined, - }; - }) - : []; - }, [data, apiUrl]); + return useQuery( + ['ismintable', cart], + () => { + if (doiMinterUrl && cart && cart.length > 0) + return isCartMintable(cart, doiMinterUrl); + else return Promise.resolve(false); + }, + { + onError: (error) => { + if (error.response?.status !== 403) log.error(error); + if (error.response?.status === 401) { + document.dispatchEvent( + new CustomEvent(MicroFrontendId, { + detail: { + type: InvalidateTokenType, + payload: { + severity: 'error', + message: + localStorage.getItem('autoLogin') === 'true' + ? 'Your session has expired, please reload the page' + : 'Your session has expired, please login again', + }, + }, + }) + ); + } + }, + retry: (failureCount, error) => { + // if we get 403 we know this is an legit response from the backend so don't bother retrying + // all other errors use default retry behaviour + if (error.response?.status === 403 || failureCount >= 3) { + return false; + } else { + return true; + } + }, + refetchOnWindowFocus: false, + enabled: typeof doiMinterUrl !== 'undefined', + } + ); +}; - // useQueries doesn't allow us to specify type info, so ignore this line - // since we strongly type the queries object anyway - // we also need to prettier-ignore to make sure we don't wrap onto next line - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - // prettier-ignore - const queries: UseQueryResult[] = useQueries(queryConfigs); +/** + * Mints a cart + * @param cart The {@link Cart} to mint + * @param doiMetadata The required metadata for the DOI + */ +export const useMintCart = (): UseMutationResult< + DoiResponse, + AxiosError<{ + detail: { msg: string }[] | string; + }>, + { cart: DownloadCartItem[]; doiMetadata: DoiMetadata } +> => { + const settings = React.useContext(DownloadSettingsContext); - return queries; + return useMutation( + ({ cart, doiMetadata }) => { + return mintCart(cart, doiMetadata, settings); + }, + { + onError: (error) => { + log.error(error); + if (error.response?.status === 401) { + document.dispatchEvent( + new CustomEvent(MicroFrontendId, { + detail: { + type: InvalidateTokenType, + payload: { + severity: 'error', + message: + localStorage.getItem('autoLogin') === 'true' + ? 'Your session has expired, please reload the page' + : 'Your session has expired, please login again', + }, + }, + }) + ); + } + }, + } + ); +}; + +/** + * Gets the total list of users associated with each item in the cart + * @param cart The {@link Cart} that we're getting the users for + */ +export const useCartUsers = ( + cart?: DownloadCartItem[] +): UseQueryResult => { + const settings = React.useContext(DownloadSettingsContext); + + return useQuery( + ['cartUsers', cart], + () => getCartUsers(cart ?? [], settings), + { + onError: handleICATError, + staleTime: Infinity, + } + ); +}; + +/** + * Checks whether a username belongs to an ICAT User + * @param username The username that we're checking + * @returns the {@link User} that matches the username, or 404 + */ +export const useCheckUser = ( + username: string +): UseQueryResult => { + const settings = React.useContext(DownloadSettingsContext); + + return useQuery( + ['checkUser', username], + () => checkUser(username, settings), + { + onError: (error) => { + log.error(error); + if (error.response?.status === 401) { + document.dispatchEvent( + new CustomEvent(MicroFrontendId, { + detail: { + type: InvalidateTokenType, + payload: { + severity: 'error', + message: + localStorage.getItem('autoLogin') === 'true' + ? 'Your session has expired, please reload the page' + : 'Your session has expired, please login again', + }, + }, + }) + ); + } + }, + retry: (failureCount: number, error: AxiosError) => { + if ( + // user not logged in, error code will log them out + error.response?.status === 401 || + // email doesn't match user - don't retry as this is a correct response from the server + error.response?.status === 404 || + // email is invalid - don't retry as this is correct response from the server + error.response?.status === 422 || + failureCount >= 3 + ) + return false; + return true; + }, + // set enabled false to only fetch on demand when the add creator button is pressed + enabled: false, + cacheTime: 0, + } + ); +}; + +/** + * Checks whether a DOI is valid and returns the DOI metadata + * @param doi The DOI that we're checking + * @returns the {@link RelatedDOI} that matches the username, or 404 + */ +export const useCheckDOI = ( + doi: string +): UseQueryResult => { + const settings = React.useContext(DownloadSettingsContext); + + return useQuery(['checkDOI', doi], () => fetchDOI(doi, settings), { + retry: (failureCount: number, error: AxiosError) => { + if ( + // DOI is invalid - don't retry as this is a correct response from the server + error.response?.status === 404 || + failureCount >= 3 + ) + return false; + return true; + }, + select: (doi) => ({ + title: doi.attributes.titles[0].title, + identifier: doi.attributes.doi, + fullReference: '', // TODO: what should we put here? + relationType: '', + relatedItemType: '', + }), + // set enabled false to only fetch on demand when the add creator button is pressed + enabled: false, + cacheTime: 0, + }); }; diff --git a/packages/datagateway-download/src/downloadCart/downloadCartItemLink.component.tsx b/packages/datagateway-download/src/downloadCart/downloadCartItemLink.component.tsx new file mode 100644 index 000000000..31a1cbbd2 --- /dev/null +++ b/packages/datagateway-download/src/downloadCart/downloadCartItemLink.component.tsx @@ -0,0 +1,32 @@ +import { Link as MuiLink } from '@mui/material'; +import React from 'react'; +import type { DownloadCartItem } from 'datagateway-common'; +import { useQuery } from 'react-query'; +import { Link } from 'react-router-dom'; + +type LinkBuilder = () => Promise; + +interface DownloadCartItemLinkProps { + cartItem: DownloadCartItem; + linkBuilder: LinkBuilder; +} + +function DownloadCartItemLink({ + cartItem, + linkBuilder, +}: DownloadCartItemLinkProps): JSX.Element { + const { data: link } = useQuery(['cartItemLink', cartItem.id], () => + linkBuilder() + ); + + return link ? ( + + {cartItem.name} + + ) : ( + <>{cartItem.name} + ); +} + +export default DownloadCartItemLink; +export type { LinkBuilder }; diff --git a/packages/datagateway-download/src/downloadCart/downloadCartTable.component.test.tsx b/packages/datagateway-download/src/downloadCart/downloadCartTable.component.test.tsx index 0f27808e3..43c9d43d8 100644 --- a/packages/datagateway-download/src/downloadCart/downloadCartTable.component.test.tsx +++ b/packages/datagateway-download/src/downloadCart/downloadCartTable.component.test.tsx @@ -1,20 +1,33 @@ -import React from 'react'; -import { createMount } from '@material-ui/core/test-utils'; -import DownloadCartTable from './downloadCartTable.component'; -import { DownloadCartItem, fetchDownloadCart } from 'datagateway-common'; -import { flushPromises } from '../setupTests'; -import { act } from 'react-dom/test-utils'; -import { DownloadSettings, DownloadSettingsContext } from '../ConfigProvider'; +import { + fireEvent, + render, + RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { fetchDownloadCart } from 'datagateway-common'; +import { createMemoryHistory, MemoryHistory } from 'history'; +import * as React from 'react'; +import { QueryClient, QueryClientProvider, setLogger } from 'react-query'; import { Router } from 'react-router-dom'; -import { ReactWrapper } from 'enzyme'; -import { createMemoryHistory } from 'history'; -import { QueryClientProvider, QueryClient } from 'react-query'; +import { DownloadSettingsContext } from '../ConfigProvider'; +import { mockCartItems, mockedSettings } from '../testData'; import { - getDatafileCount, - getSize, + getFileSizeAndCount, + isCartMintable, removeAllDownloadCartItems, removeFromCart, } from '../downloadApi'; +import DownloadCartTable from './downloadCartTable.component'; +import { createTheme } from '@mui/material'; + +setLogger({ + log: console.log, + warn: console.warn, + error: jest.fn(), +}); jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -32,558 +45,507 @@ jest.mock('../downloadApi', () => { return { ...originalModule, removeAllDownloadCartItems: jest.fn(), - getSize: jest.fn(), - getDatafileCount: jest.fn(), + getFileSizeAndCount: jest.fn(), getIsTwoLevel: jest.fn().mockResolvedValue(true), removeFromCart: jest.fn(), + isCartMintable: jest.fn(), }; }); -describe('Download cart table component', () => { - let mount; - let history; - let queryClient; - - let cartItems: DownloadCartItem[] = []; - - // Create our mocked datagateway-download settings file. - let mockedSettings: DownloadSettings = { - facilityName: 'LILS', - apiUrl: 'https://example.com/api', - downloadApiUrl: 'https://example.com/downloadApi', - idsUrl: 'https://example.com/ids', - fileCountMax: 5000, - totalSizeMax: 1000000000000, - accessMethods: { - https: { - idsUrl: 'https://example.com/ids', - displayName: 'HTTPS', - description: 'Example description for HTTPS access method.', - }, - globus: { - idsUrl: 'https://example.com/ids', - displayName: 'Globus', - description: 'Example description for Globus access method.', +const createTestQueryClient = (): QueryClient => + new QueryClient({ + defaultOptions: { + queries: { + retry: false, }, }, - routes: [], - helpSteps: [], + }); + +const renderComponent = (): RenderResult & { history: MemoryHistory } => { + const history = createMemoryHistory(); + return { + history: history, + ...render( + + + + + + + + ), }; +}; - const createWrapper = (): ReactWrapper => { - queryClient = new QueryClient(); - return mount( -
- - - - - - - -
- ); +describe('Download cart table component', () => { + let holder: HTMLElement | null; + let queryClient: QueryClient; + let user: ReturnType; + + const resetDOM = (): void => { + if (holder) document.body.removeChild(holder); + holder = document.getElementById('datagateway-download'); + if (holder) document.body.removeChild(holder); }; beforeEach(() => { - mount = createMount(); - history = createMemoryHistory(); - cartItems = [ - { - entityId: 1, - entityType: 'investigation', - id: 1, - name: 'INVESTIGATION 1', - parentEntities: [], - }, - { - entityId: 2, - entityType: 'investigation', - id: 2, - name: 'INVESTIGATION 2', - parentEntities: [], - }, - { - entityId: 3, - entityType: 'dataset', - id: 3, - name: 'DATASET 1', - parentEntities: [], - }, - { - entityId: 4, - entityType: 'datafile', - id: 4, - name: 'DATAFILE 1', - parentEntities: [], - }, - ]; - - (fetchDownloadCart as jest.MockedFunction< - typeof fetchDownloadCart - >).mockResolvedValue(cartItems); - (removeAllDownloadCartItems as jest.MockedFunction< - typeof removeAllDownloadCartItems - >).mockResolvedValue(undefined); - (removeFromCart as jest.MockedFunction< - typeof removeFromCart - >).mockImplementation((entityType, entityIds) => { - cartItems = cartItems.filter( - (item) => !entityIds.includes(item.entityId) + user = userEvent.setup(); + queryClient = new QueryClient(); + + //https://stackoverflow.com/questions/43694975/jest-enzyme-using-mount-document-getelementbyid-returns-null-on-componen + holder = document.createElement('div'); + holder.setAttribute('id', 'datagateway-download'); + document.body.appendChild(holder); + + ( + fetchDownloadCart as jest.MockedFunction + ).mockResolvedValue(mockCartItems); + ( + removeAllDownloadCartItems as jest.MockedFunction< + typeof removeAllDownloadCartItems + > + ).mockResolvedValue(undefined); + ( + removeFromCart as jest.MockedFunction + ).mockImplementation((entityType, entityIds) => { + return Promise.resolve( + mockCartItems.filter((item) => !entityIds.includes(item.entityId)) ); - return Promise.resolve(cartItems); }); - (getSize as jest.MockedFunction).mockResolvedValue(1); - (getDatafileCount as jest.MockedFunction< - typeof getDatafileCount - >).mockResolvedValue(7); + ( + getFileSizeAndCount as jest.MockedFunction + ).mockResolvedValue({ fileSize: 1, fileCount: 7 }); + ( + isCartMintable as jest.MockedFunction + ).mockResolvedValue(true); }); afterEach(() => { - mount.cleanUp(); + resetDOM(); jest.clearAllMocks(); jest.clearAllTimers(); jest.useRealTimers(); }); - it('renders no cart message correctly', async () => { - (fetchDownloadCart as jest.MockedFunction< - typeof fetchDownloadCart - >).mockResolvedValue([]); - - const wrapper = createWrapper(); + it('should render no cart message correctly', async () => { + (fetchDownloadCart as jest.Mock).mockResolvedValue([]); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + renderComponent(); - expect(wrapper.exists('[data-testid="no-selections-message"]')).toBe(true); + expect( + await screen.findByText('No data selected', { exact: false }) + ).toBeTruthy(); }); - it('fetches the download cart on load', async () => { - const wrapper = createWrapper(); + it('should show download sizes for cart items', async () => { + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - - expect(fetchDownloadCart).toHaveBeenCalled(); - expect(wrapper.find('[aria-colindex=1]').find('p').first().text()).toEqual( - 'INVESTIGATION 1' - ); + expect( + await screen.findByText('downloadCart.total_size: 4 B / 1 TB') + ).toBeTruthy(); }); - it('calculates sizes once cart items have been fetched', async () => { - const wrapper = createWrapper(); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - - expect(getSize).toHaveBeenCalledTimes(4); - expect(wrapper.find('[aria-colindex=3]').find('p').first().text()).toEqual( - '1 B' - ); - expect(wrapper.find('p#totalSizeDisplay').text()).toEqual( - 'downloadCart.total_size: 4 B / 1 TB' + it('should show progress indicator when calculating file count & size of cart', async () => { + (getFileSizeAndCount as jest.Mock).mockImplementation( + () => + new Promise((_) => { + // never resolve promise so that progress indicator stays visible. + }) ); - }); - it('calculates total file count once cart items have been fetched', async () => { - const wrapper = createWrapper(); + jest.useFakeTimers(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + renderComponent(); - expect(getDatafileCount).toHaveBeenCalledTimes(3); - expect(wrapper.find('[aria-colindex=4]').find('p').first().text()).toEqual( - '7' - ); - // datafiles should always be 1 and shouldn't call getDatafileCount - expect(wrapper.find('[aria-colindex=4]').find('p').last().text()).toEqual( - '1' - ); - - expect(wrapper.find('p#fileCountDisplay').text()).toEqual( - 'downloadCart.number_of_files: 22 / 5000' - ); + expect( + await screen.findAllByLabelText('downloadCart.calculating') + ).toHaveLength(2); }); - it('loads cart confirmation dialog when Download Cart button is clicked', async () => { - const wrapper = createWrapper(); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + it('should show total file count of the cart', async () => { + renderComponent(); - expect(wrapper.find('button#downloadCartButton').prop('disabled')).toBe( - false - ); - - wrapper.find('button#downloadCartButton').simulate('click'); - - // Update the wrapper with the loading dialog. - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - - // Update the wrapper with the download confirmation dialog. - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + expect( + await screen.findByText('downloadCart.number_of_files: 28 / 5000') + ).toBeTruthy(); + }); - expect(wrapper.exists('[aria-labelledby="downloadCartConfirmation"]')).toBe( - true - ); + it('should load cart confirmation dialog when Download Cart button is clicked', async () => { + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.click(await screen.findByText('downloadCart.download')); - // Close the confirmation dialog. - wrapper - .find('button[aria-label="downloadConfirmDialog.close_arialabel"]') - .simulate('click'); + expect( + await screen.findByLabelText('downloadConfirmDialog.dialog_arialabel') + ).toBeTruthy(); }); - it('removes all items from cart when Remove All button is clicked', async () => { - const wrapper = createWrapper(); + it('should remove all items from cart when Remove All button is clicked', async () => { + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - await flushPromises(); - wrapper.update(); - }); + await user.click(await screen.findByText('downloadCart.remove_all')); - await act(async () => { - wrapper.find('button#removeAllButton').simulate('click'); - await flushPromises(); - wrapper.update(); - }); - - expect(wrapper.exists('[data-testid="no-selections-message"]')).toBe(true); + expect( + await screen.findByText('No data selected', { exact: false }) + ).toBeTruthy(); }); it('disables remove all button while request is processing', async () => { // use this to manually resolve promise - let promiseResolve; + let promiseResolve = (): void => { + // no-op + }; - (removeAllDownloadCartItems as jest.MockedFunction< - typeof removeAllDownloadCartItems - >).mockImplementation( + ( + removeAllDownloadCartItems as jest.MockedFunction< + typeof removeAllDownloadCartItems + > + ).mockImplementation( () => new Promise((resolve) => { promiseResolve = resolve; }) ); - const wrapper = createWrapper(); + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - await flushPromises(); - wrapper.update(); - }); + await user.click( + await screen.findByRole('button', { name: 'downloadCart.remove_all' }) + ); - await act(async () => { - wrapper.find('button#removeAllButton').simulate('click'); - await flushPromises(); - wrapper.update(); - }); expect( - wrapper.find('button#removeAllButton').prop('disabled') - ).toBeTruthy(); - - await act(async () => { - promiseResolve(); - await flushPromises(); - wrapper.update(); - }); - - expect(wrapper.exists('[data-testid="no-selections-message"]')).toBe(true); - }); - - it('disables download button when there are empty items in the cart ', async () => { - (getSize as jest.MockedFunction) - .mockResolvedValueOnce(1) - .mockResolvedValueOnce(0); - (getDatafileCount as jest.MockedFunction< - typeof getDatafileCount - >).mockResolvedValueOnce(0); + await screen.findByRole('button', { name: 'downloadCart.remove_all' }) + ).toBeDisabled(); - const wrapper = createWrapper(); + promiseResolve(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - - expect(wrapper.exists('div#emptyFilesAlert')).toBeTruthy(); expect( - wrapper.find('button#downloadCartButton').prop('disabled') - ).toBeTruthy(); + await screen.findByTestId('no-selections-message') + ).toBeInTheDocument(); + }); - wrapper - .find(`button[aria-label="downloadCart.remove {name:INVESTIGATION 2}"]`) - .simulate('click'); + it('should disable download button when there are empty items in the cart ', async () => { + ( + getFileSizeAndCount as jest.MockedFunction + ).mockResolvedValue({ fileSize: 0, fileCount: 0 }); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + renderComponent(); - expect(wrapper.exists('div#emptyFilesAlert')).toBeTruthy(); expect( - wrapper.find('button#downloadCartButton').prop('disabled') + await screen.findByText('downloadCart.empty_items_error') ).toBeTruthy(); - wrapper - .find(`button[aria-label="downloadCart.remove {name:INVESTIGATION 1}"]`) - .simulate('click'); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - - expect(wrapper.exists('div#emptyFilesAlert')).toBeFalsy(); + const downloadButton = await screen.findByText('downloadCart.download'); + // cannot use user.click here because clicking disabled button will throw + fireEvent.click(downloadButton); + // should not show confirm dialog expect( - wrapper.find('button#downloadCartButton').prop('disabled') - ).toBeFalsy(); + screen.queryByText('downloadConfirmDialog.dialog_arialabel') + ).toBeNull(); }); - it("removes an item when said item's remove button is clicked", async () => { - const wrapper = createWrapper(); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - - await act(async () => { - wrapper.update(); - await flushPromises(); - }); + it("should remove an item when said item's remove button is clicked", async () => { + renderComponent(); - wrapper - .find(`button[aria-label="downloadCart.remove {name:INVESTIGATION 2}"]`) - .simulate('click'); - - expect( - wrapper - .find( - `button[aria-label="downloadCart.remove {name:INVESTIGATION 2}"] svg` - ) - .parent() - .prop('color') - ).toEqual('error'); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.click( + await screen.findByLabelText('downloadCart.remove {name:INVESTIGATION 2}') + ); - expect(removeFromCart).toHaveBeenCalled(); - expect(removeFromCart).toHaveBeenCalledWith('investigation', [2], { - facilityName: mockedSettings.facilityName, - downloadApiUrl: mockedSettings.downloadApiUrl, + await waitFor(async () => { + expect(screen.queryByText('INVESTIGATION 2')).toBeNull(); }); - expect( - wrapper.exists( - `[aria-label="downloadCart.remove {name:INVESTIGATION 2}"]` - ) - ).toBe(false); - expect(wrapper.exists('[aria-rowcount=3]')).toBe(true); }); - it('sorts data when headers are clicked', async () => { - const wrapper = createWrapper(); + it('should sort data when headers are clicked', async () => { + // use skipHover to avoid triggering sort tooltips which slow the test down + user = userEvent.setup({ skipHover: true }); + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); + const typeSortLabel = await screen.findByRole('button', { + name: 'downloadCart.type', }); - await act(async () => { - wrapper.update(); - await flushPromises(); - }); + await user.click(typeSortLabel); - const firstNameCell = wrapper.find('[aria-colindex=1]').find('p').first(); + let rows = await screen.findAllByText( + /(DATAFILE|DATASET|INVESTIGATION) \d/ + ); + // row should be sorted by type asc. + expect(rows[0]).toHaveTextContent('DATAFILE 1'); + expect(rows[1]).toHaveTextContent('DATASET 1'); + expect(rows[2]).toHaveTextContent('INVESTIGATION 1'); + expect(rows[3]).toHaveTextContent('INVESTIGATION 2'); + + await user.click(typeSortLabel); + + rows = await screen.findAllByText(/(DATAFILE|DATASET|INVESTIGATION) \d/); + // row should be sorted by type desc. + expect(rows[0]).toHaveTextContent('INVESTIGATION 1'); + expect(rows[1]).toHaveTextContent('INVESTIGATION 2'); + expect(rows[2]).toHaveTextContent('DATASET 1'); + expect(rows[3]).toHaveTextContent('DATAFILE 1'); + + const nameSortLabel = await screen.findByRole('button', { + name: 'downloadCart.name', + }); - const typeSortLabel = wrapper - .find('[role="columnheader"] span[role="button"]') - .at(1); + await user.keyboard('{Shift>}'); + await user.click(nameSortLabel); + await user.keyboard('{/Shift}'); + + rows = await screen.findAllByText(/(DATAFILE|DATASET|INVESTIGATION) \d/); + // row should be sorted by type desc & name asc. + expect(rows[0]).toHaveTextContent('INVESTIGATION 1'); + expect(rows[1]).toHaveTextContent('INVESTIGATION 2'); + expect(rows[2]).toHaveTextContent('DATASET 1'); + expect(rows[3]).toHaveTextContent('DATAFILE 1'); + + await user.keyboard('{Shift>}'); + await user.click(nameSortLabel); + await user.keyboard('{/Shift}'); + + rows = await screen.findAllByText(/(DATAFILE|DATASET|INVESTIGATION) \d/); + // row should be sorted by type desc & name desc. + expect(rows[0]).toHaveTextContent('INVESTIGATION 2'); + expect(rows[1]).toHaveTextContent('INVESTIGATION 1'); + expect(rows[2]).toHaveTextContent('DATASET 1'); + expect(rows[3]).toHaveTextContent('DATAFILE 1'); + + await user.click(nameSortLabel); + + rows = await screen.findAllByText(/(DATAFILE|DATASET|INVESTIGATION) \d/); + // row should be sorted by type desc. + expect(rows[0]).toHaveTextContent('INVESTIGATION 1'); + expect(rows[1]).toHaveTextContent('INVESTIGATION 2'); + expect(rows[2]).toHaveTextContent('DATASET 1'); + expect(rows[3]).toHaveTextContent('DATAFILE 1'); + + await user.click(nameSortLabel); + + rows = await screen.findAllByText(/(DATAFILE|DATASET|INVESTIGATION) \d/); + // row should be sorted by name asc. + expect(rows[0]).toHaveTextContent('DATAFILE 1'); + expect(rows[1]).toHaveTextContent('DATASET 1'); + expect(rows[2]).toHaveTextContent('INVESTIGATION 1'); + expect(rows[3]).toHaveTextContent('INVESTIGATION 2'); + }); - typeSortLabel.simulate('click'); + it('should filter data when text fields are typed into', async () => { + renderComponent(); - expect(firstNameCell.text()).toEqual('DATAFILE 1'); + // TEST NAME FILTER INPUT - typeSortLabel.simulate('click'); + expect(await screen.findByText('INVESTIGATION 2')).toBeTruthy(); - expect(firstNameCell.text()).toEqual('INVESTIGATION 1'); + const nameFilterInput = await screen.findByLabelText( + 'Filter by downloadCart.name' + ); + await user.type(nameFilterInput, '1'); - const nameSortLabel = wrapper - .find('[role="columnheader"] span[role="button"]') - .at(0); + await waitFor(async () => { + expect(screen.queryByText('INVESTIGATION 2')).toBeNull(); + }); - nameSortLabel.simulate('click'); + await user.clear(nameFilterInput); - expect(firstNameCell.text()).toEqual('INVESTIGATION 1'); + expect(await screen.findByText('INVESTIGATION 2')).toBeInTheDocument(); - nameSortLabel.simulate('click'); + // TEST TYPE FILTER INPUT - expect(firstNameCell.text()).toEqual('INVESTIGATION 2'); + expect(await screen.findByText('dataset')).toBeTruthy(); + expect(await screen.findByText('datafile')).toBeTruthy(); - nameSortLabel.simulate('click'); + const typeFilterInput = await screen.findByLabelText( + 'Filter by downloadCart.type' + ); + await user.type(typeFilterInput, 'investigation'); - expect(firstNameCell.text()).toEqual('INVESTIGATION 1'); + await waitFor(async () => { + expect(screen.queryByText('dataset')).toBeNull(); + expect(screen.queryByText('datafile')).toBeNull(); + }); }); - it('filters data when text fields are typed into', async () => { - const wrapper = createWrapper(); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + it('should display error alert if file/size limit exceeded', async () => { + renderComponent(); - await act(async () => { - wrapper.update(); - await flushPromises(); + await waitFor(() => { + expect( + screen.queryByText('downloadCart.file_limit_error', { exact: false }) + ).toBeNull(); + expect( + screen.queryByText('downloadCart.size_limit_error', { exact: false }) + ).toBeNull(); }); - const nameFilterInput = wrapper - .find('[aria-label="Filter by downloadCart.name"]') - .first(); - nameFilterInput.instance().value = '1'; - nameFilterInput.simulate('change'); - - expect(wrapper.exists('[aria-rowcount=3]')).toBe(true); - expect( - wrapper.exists( - '[aria-label="downloadCart.remove {name:INVESTIGATION 2}"]' - ) - ).toBe(false); - - const typeFilterInput = wrapper - .find('[aria-label="Filter by downloadCart.type"]') - .first(); - typeFilterInput.instance().value = 'data'; - typeFilterInput.simulate('change'); - - expect(wrapper.exists('[aria-rowcount=2]')).toBe(true); - expect( - wrapper.exists( - '[aria-label="downloadCart.remove {name:INVESTIGATION 1}"]' - ) - ).toBe(false); - - typeFilterInput.instance().value = ''; - typeFilterInput.simulate('change'); + resetDOM(); + render( + + + + + + + + ); - expect(wrapper.exists('[aria-rowcount=3]')).toBe(true); expect( - wrapper.exists( - '[aria-label="downloadCart.remove {name:INVESTIGATION 1}"]' + await screen.findByText( + 'downloadCart.size_limit_error {totalSizeMax:1 B}', + { exact: false } ) - ).toBe(true); + ).toBeTruthy(); - nameFilterInput.instance().value = ''; - nameFilterInput.simulate('change'); + resetDOM(); + render( + + + + + + + + ); - expect(wrapper.exists('[aria-rowcount=4]')).toBe(true); expect( - wrapper.exists( - '[aria-label="downloadCart.remove {name:INVESTIGATION 2}"]' + await screen.findByText( + 'downloadCart.file_limit_error {fileCountMax:1}', + { exact: false } ) - ).toBe(true); + ).toBeTruthy(); }); - it('displays error alert if file/size limit exceeded', async () => { - let wrapper = createWrapper(); + it('does not display error alerts if file/size limits are not set', async () => { + render( + + + + + + + + ); - await act(async () => { - await flushPromises(); - wrapper.update(); + await waitFor(() => { + expect( + screen.queryByText('downloadCart.file_limit_error', { exact: false }) + ).toBeNull(); + expect( + screen.queryByText('downloadCart.size_limit_error', { exact: false }) + ).toBeNull(); }); - // Make sure alerts are not displayed if under the limits - expect(wrapper.exists('div#fileLimitAlert')).toBeFalsy(); - expect(wrapper.exists('div#sizeLimitAlert')).toBeFalsy(); + expect( + await screen.findByText('downloadCart.total_size: 4 B', { exact: true }) + ).toBeTruthy(); + expect( + await screen.findByText('downloadCart.number_of_files: 28', { + exact: true, + }) + ).toBeTruthy(); + }); - const oldSettings = mockedSettings; - mockedSettings = { - ...oldSettings, - totalSizeMax: 1, - }; + it('should go to DOI generation form when Generate DOI button is clicked', async () => { + const { history } = renderComponent(); - wrapper = createWrapper(); + await user.click( + screen.getByRole('link', { name: 'downloadCart.generate_DOI' }) + ); - await act(async () => { - await flushPromises(); - wrapper.update(); + expect(history.location).toMatchObject({ + pathname: '/download/mint', + state: { fromCart: true }, }); + }); - // Make sure size limit alert is displayed if over the limit - expect(wrapper.exists('div#sizeLimitAlert')).toBeTruthy(); + it('should disable Generate DOI button when mintability is loading', async () => { + ( + isCartMintable as jest.MockedFunction + ).mockImplementation( + () => + new Promise((_) => { + // do nothing, simulating pending promise to test loading state + }) + ); + const { history } = renderComponent(); - mockedSettings = { - ...oldSettings, - fileCountMax: 1, - }; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const generateDOIButton = screen + .getByRole('link', { name: 'downloadCart.generate_DOI' }) + .closest('span')!; - wrapper = createWrapper(); + await user.hover(generateDOIButton); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + expect( + await screen.findByText('downloadCart.mintability_loading') + ).toBeInTheDocument(); - // Make sure file limit alert is displayed if over the limit - expect(wrapper.exists('div#fileLimitAlert')).toBeTruthy(); + await user.click(generateDOIButton); - mockedSettings = oldSettings; + expect(history.location).not.toMatchObject({ + pathname: '/download/mint', + state: { fromCart: true }, + }); }); - it('does not display error alerts if file/size limits are not set', async () => { - const oldSettings = mockedSettings; - mockedSettings = { - ...oldSettings, - totalSizeMax: undefined, - fileCountMax: undefined, - }; - - const wrapper = createWrapper(); - - await act(async () => { - await flushPromises(); - wrapper.update(); + it('should disable Generate DOI button when cart is not mintable', async () => { + ( + isCartMintable as jest.MockedFunction + ).mockRejectedValue({ + response: { + data: { detail: 'Not allowed to mint the following items: [2,4]' }, + status: 403, + }, }); + const { history } = renderComponent(); - // Make sure alerts are not displayed if limits are undefined - expect(wrapper.exists('div#fileLimitAlert')).toBeFalsy(); - expect(wrapper.exists('div#sizeLimitAlert')).toBeFalsy(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const generateDOIButton = screen + .getByRole('link', { name: 'downloadCart.generate_DOI' }) + .closest('span')!; - expect(wrapper.find('p#fileCountDisplay').text()).toEqual( - 'downloadCart.number_of_files: 22' - ); - expect(wrapper.find('p#totalSizeDisplay').text()).toEqual( - 'downloadCart.total_size: 4 B' - ); + await user.hover(generateDOIButton); + + expect( + await screen.findByText('downloadCart.not_mintable') + ).toBeInTheDocument(); + + const tableRows = within( + screen.getByRole('rowgroup', { name: 'grid' }) + ).getAllByRole('row'); + const muiErrorColor = createTheme().palette.error.main; + expect(tableRows[1]).toHaveStyle(`background-color: ${muiErrorColor}`); + expect(tableRows[1]).toHaveStyle(`background-color: ${muiErrorColor}`); + expect(tableRows[0]).not.toHaveStyle(`background-color: ${muiErrorColor}`); + expect(tableRows[2]).not.toHaveStyle(`background-color: ${muiErrorColor}`); + + await user.click(generateDOIButton); + + expect(history.location).not.toMatchObject({ + pathname: '/download/mint', + state: { fromCart: true }, + }); - mockedSettings = oldSettings; + await user.unhover(generateDOIButton); + for (const row of tableRows) { + expect(row).not.toHaveStyle(`background-color: ${muiErrorColor}`); + } }); }); diff --git a/packages/datagateway-download/src/downloadCart/downloadCartTable.component.tsx b/packages/datagateway-download/src/downloadCart/downloadCartTable.component.tsx index f818600a0..21245858c 100644 --- a/packages/datagateway-download/src/downloadCart/downloadCartTable.component.tsx +++ b/packages/datagateway-download/src/downloadCart/downloadCartTable.component.tsx @@ -1,55 +1,48 @@ -import React from 'react'; +import { RemoveCircle } from '@mui/icons-material'; import { - Table, - formatBytes, - TextColumnFilter, - Order, - TableActionProps, - DownloadCartItem, - DownloadCartTableItem, - TextFilter, - ColumnType, -} from 'datagateway-common'; -import { - IconButton, - Grid, - Paper, - Typography, + Alert, Button, + CircularProgress, + Grid, + IconButton, LinearProgress, - createStyles, - makeStyles, - Theme, Link, - CircularProgress, -} from '@material-ui/core'; -import { RemoveCircle } from '@material-ui/icons'; -import { Alert } from '@material-ui/lab'; + Paper, + Theme, + Tooltip, + Typography, +} from '@mui/material'; +import { + type ColumnType, + type DownloadCartItem, + type DownloadCartTableItem, + formatBytes, + type Order, + Table, + type TableActionProps, + TextColumnFilter, + type TextFilter, +} from 'datagateway-common'; +import React from 'react'; +import { Trans, useTranslation } from 'react-i18next'; +import { Link as RouterLink } from 'react-router-dom'; +import { DownloadSettingsContext } from '../ConfigProvider'; import { useCart, - useRemoveEntityFromCart, + useIsCartMintable, useIsTwoLevel, useRemoveAllFromCart, - useSizes, - useDatafileCounts, + useRemoveEntityFromCart, + useFileSizesAndCounts, } from '../downloadApiHooks'; import DownloadConfirmDialog from '../downloadConfirmation/downloadConfirmDialog.component'; -import { DownloadSettingsContext } from '../ConfigProvider'; -import { Trans, useTranslation } from 'react-i18next'; -import { Link as RouterLink } from 'react-router-dom'; -import { useQueryClient } from 'react-query'; - -const useStyles = makeStyles((theme: Theme) => - createStyles({ - noSelectionsMessage: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - color: (theme as any).colours?.contrastGrey, - paddingTop: theme.spacing(2), - paddingBottom: theme.spacing(2), - }, - }) -); +import DownloadCartItemLink from './downloadCartItemLink.component'; +import { + buildDatafileUrl, + buildDatasetUrl, + buildInvestigationUrl, +} from './urlBuilders'; interface DownloadCartTableProps { statusTabRedirect: () => void; @@ -58,64 +51,56 @@ interface DownloadCartTableProps { const DownloadCartTable: React.FC = ( props: DownloadCartTableProps ) => { - const classes = useStyles(); - const settings = React.useContext(DownloadSettingsContext); + const { + fileCountMax, + totalSizeMax, + apiUrl, + facilityName, + doiMinterUrl, + dataCiteUrl, + } = React.useContext(DownloadSettingsContext); const [sort, setSort] = React.useState<{ [column: string]: Order }>({}); const [filters, setFilters] = React.useState<{ [column: string]: { value?: string | number; type: string }; }>({}); - const fileCountMax = settings.fileCountMax; - const totalSizeMax = settings.totalSizeMax; - const [showConfirmation, setShowConfirmation] = React.useState(false); const { data: isTwoLevel } = useIsTwoLevel(); const { mutate: removeDownloadCartItem } = useRemoveEntityFromCart(); + const { mutate: removeAllDownloadCartItems, isLoading: removingAll } = + useRemoveAllFromCart(); + const { data: cartItems, isFetching: isFetchingCart } = useCart(); const { - mutate: removeAllDownloadCartItems, - isLoading: removingAll, - } = useRemoveAllFromCart(); - const { data, isFetching: dataLoading } = useCart(); + data: mintable, + isLoading: cartMintabilityLoading, + error: mintableError, + } = useIsCartMintable(cartItems); - const queryClient = useQueryClient(); - const setData = React.useCallback( - (newData: DownloadCartTableItem[]) => { - queryClient.setQueryData('cart', newData); - }, - [queryClient] - ); - - const fileCountQueries = useDatafileCounts(data); - const sizeQueries = useSizes(data); + const fileSizesAndCounts = useFileSizesAndCounts(cartItems); - const fileCount = React.useMemo(() => { + const { fileCount, totalSize } = React.useMemo(() => { return ( - fileCountQueries?.reduce((accumulator, nextItem) => { - if (nextItem.data && nextItem.data > -1) { - return accumulator + nextItem.data; - } else { - return accumulator; - } - }, 0) ?? -1 - ); - }, [fileCountQueries]); - - const totalSize = React.useMemo(() => { - return ( - sizeQueries?.reduce((accumulator, nextItem) => { - if (nextItem.data && nextItem.data > -1) { - return accumulator + nextItem.data; - } else { - return accumulator; - } - }, 0) ?? -1 + fileSizesAndCounts?.reduce( + (accumulator, nextItem) => { + return { + fileCount: nextItem.data?.fileCount + ? accumulator.fileCount + nextItem.data.fileCount + : accumulator.fileCount, + totalSize: nextItem.data?.fileSize + ? accumulator.totalSize + nextItem.data.fileSize + : accumulator.totalSize, + }; + }, + { fileCount: 0, totalSize: 0 } + ) ?? { fileCount: -1, totalSize: -1 } ); - }, [sizeQueries]); + }, [fileSizesAndCounts]); - const sizesLoading = sizeQueries.some((query) => query.isLoading); - const fileCountsLoading = fileCountQueries.some((query) => query.isLoading); + const fileSizesAndCountsLoading = fileSizesAndCounts.some( + (query) => query?.isLoading + ); const [t] = useTranslation(); @@ -138,12 +123,12 @@ const DownloadCartTable: React.FC = ( ); const sortedAndFilteredData = React.useMemo(() => { - const sizeAndCountAddedData = data?.map( + const sizeAndCountAddedData = cartItems?.map( (item, index) => ({ ...item, - size: sizeQueries?.[index]?.data ?? -1, - fileCount: fileCountQueries?.[index]?.data ?? -1, + size: fileSizesAndCounts?.[index]?.data?.fileSize ?? -1, + fileCount: fileSizesAndCounts?.[index]?.data?.fileCount ?? -1, } as DownloadCartTableItem) ); const filteredData = sizeAndCountAddedData?.filter((item) => { @@ -186,7 +171,33 @@ const DownloadCartTable: React.FC = ( } return filteredData?.sort(sortCartItems); - }, [data, sort, filters, sizeQueries, fileCountQueries]); + }, [cartItems, fileSizesAndCounts, filters, sort]); + + const unmintableEntityIDs: number[] | null | undefined = React.useMemo( + () => + mintableError?.response?.status === 403 && + typeof mintableError?.response?.data?.detail === 'string' && + JSON.parse( + mintableError.response.data.detail.substring( + mintableError.response.data.detail.indexOf('['), + mintableError.response.data.detail.lastIndexOf(']') + 1 + ) + ), + [mintableError] + ); + + const unmintableRowIDs = React.useMemo(() => { + if (unmintableEntityIDs && sortedAndFilteredData) { + return unmintableEntityIDs.map((id) => + sortedAndFilteredData.findIndex((entity) => entity.entityId === id) + ); + } else { + return []; + } + }, [unmintableEntityIDs, sortedAndFilteredData]); + + const [generateDOIButtonHover, setGenerateDOIButtonHover] = + React.useState(false); const columns: ColumnType[] = React.useMemo( () => [ @@ -194,6 +205,56 @@ const DownloadCartTable: React.FC = ( label: t('downloadCart.name'), dataKey: 'name', filterComponent: textFilter, + cellContentRenderer: (props) => { + const item: DownloadCartItem = props.rowData; + + switch (item.entityType) { + case 'investigation': + return ( + + buildInvestigationUrl({ + apiUrl, + facilityName, + investigationId: item.entityId, + }) + } + /> + ); + + case 'dataset': + return ( + + buildDatasetUrl({ + apiUrl, + facilityName, + datasetId: item.entityId, + }) + } + /> + ); + + case 'datafile': + return ( + + buildDatafileUrl({ + apiUrl, + facilityName, + datafileId: item.entityId, + }) + } + /> + ); + + default: + return item.name; + } + }, }, { label: t('downloadCart.type'), @@ -216,12 +277,14 @@ const DownloadCartTable: React.FC = ( }, }, ], - [t, textFilter] + [apiUrl, facilityName, t, textFilter] ); const onSort = React.useCallback( - (column: string, order: 'desc' | 'asc' | null) => { + (column: string, order: 'desc' | 'asc' | null, _, shiftDown?: boolean) => { if (order) { - setSort({ ...sort, [column]: order }); + shiftDown + ? setSort({ ...sort, [column]: order }) + : setSort({ [column]: order }); } else { const { [column]: order, ...restOfSort } = sort; setSort(restOfSort); @@ -263,256 +326,324 @@ const DownloadCartTable: React.FC = ( [removeDownloadCartItem, t] ); - const emptyItems = React.useMemo( - () => - sizeQueries.some((query) => query.data === 0) || - fileCountQueries.some((query) => query.data === 0), - [sizeQueries, fileCountQueries] + const emptyItems = fileSizesAndCounts.some( + (query) => query.data?.fileSize === 0 || query.data?.fileCount === 0 ); - return !dataLoading && data?.length === 0 ? ( -
- - - - - - No data selected.{' '} - - Browse - {' '} - or{' '} - - search - {' '} - for data?. - - - - - -
- ) : ( -
- - {/* Show loading progress if data is still being loaded */} - {dataLoading && ( - - - - )} - - {/* Table should take up page but leave room for: SG appbar, - SG footer, tabs, table padding, text below table, and buttons - (respectively). */} - fileCountMax) || - (totalSizeMax && totalSize > totalSizeMax) - ? ' - 2rem' - : '' - } - (1.75 * 0.875rem + 12px)`, - minHeight: 230, - overflowX: 'auto', - }} - > - - - - + {!isFetchingCart && cartItems?.length === 0 ? ( +
- - - {fileCountsLoading && ( - - )} - - {t('downloadCart.number_of_files')}:{' '} - {fileCount !== -1 - ? fileCount - : `${t('downloadCart.calculating')}...`} - {fileCountMax && ` / ${fileCountMax}`} - - - - {fileCountMax && fileCount > fileCountMax && ( - + + + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (theme as any).colours?.contrastGrey, + paddingTop: 2, + paddingBottom: 2, }} > - {t('downloadCart.file_limit_error', { - fileCountMax: fileCountMax, - })} - - )} - - - - - {sizesLoading && ( - - )} - - {t('downloadCart.total_size')}:{' '} - {totalSize !== -1 - ? formatBytes(totalSize) - : `${t('downloadCart.calculating')}...`} - {totalSizeMax && ` / ${formatBytes(totalSizeMax)}`} - + + No data selected.{' '} + + Browse + {' '} + or{' '} + + search + {' '} + for data?. + + + - - {totalSizeMax && totalSize > totalSizeMax && ( - - {t('downloadCart.size_limit_error', { - totalSizeMax: formatBytes(totalSizeMax), - })} - - )} - - - - {emptyItems && ( - - {t('downloadCart.empty_items_error')} - + +
+ ) : ( +
+ + {/* Show loading progress if data is still being loaded */} + {isLoading && ( + + + )} - - - {/* Request to remove all selections is in progress. To prevent excessive requests, disable button during request */} - +
+ - - + + {fileSizesAndCountsLoading && ( + + )} + + {t('downloadCart.total_size')}:{' '} + {totalSize !== -1 + ? formatBytes(totalSize) + : `${t('downloadCart.calculating')}...`} + {totalSizeMax && ` / ${formatBytes(totalSizeMax)}`} + + + + {totalSizeMax && totalSize > totalSizeMax && ( + + {t('downloadCart.size_limit_error', { + totalSizeMax: formatBytes(totalSizeMax), + })} + + )} + + + {emptyItems && ( + + + {t('downloadCart.empty_items_error')} + + + )} + + + {/* Request to remove all selections is in progress. To prevent excessive requests, disable button during request */} + + + {doiMinterUrl && dataCiteUrl && ( + + setGenerateDOIButtonHover(true)} + onMouseLeave={() => setGenerateDOIButtonHover(false)} + > + {/* need this span so the tooltip works when the button is disabled */} + + + + + + )} + + + + - - - + + )} {/* Show the download confirmation dialog. */} = ( open={showConfirmation} redirectToStatusTab={props.statusTabRedirect} setClose={() => setShowConfirmation(false)} - clearCart={() => setData([])} /> - + ); }; diff --git a/packages/datagateway-download/src/downloadCart/urlBuilders/buildDatafileUrl.test.ts b/packages/datagateway-download/src/downloadCart/urlBuilders/buildDatafileUrl.test.ts new file mode 100644 index 000000000..bc833a98b --- /dev/null +++ b/packages/datagateway-download/src/downloadCart/urlBuilders/buildDatafileUrl.test.ts @@ -0,0 +1,59 @@ +import axios from 'axios'; +import { mockDatafiles, mockedSettings } from '../../testData'; +import buildDatafileUrl from './buildDatafileUrl'; + +describe('buildDatafileUrl', () => { + beforeEach(() => { + axios.get = jest.fn().mockResolvedValue({ + data: [mockDatafiles[0]], + }); + }); + + it('should return a generic URL to the parent dataset of the datafile', async () => { + const url = await buildDatafileUrl({ + apiUrl: mockedSettings.apiUrl, + facilityName: mockedSettings.facilityName, + datafileId: 70, + }); + + expect(url).toBe('/browse/investigation/58/dataset/856/datafile'); + }); + + it('should return an ISIS URL to the parent dataset of the datafile', async () => { + const url = await buildDatafileUrl({ + apiUrl: mockedSettings.apiUrl, + facilityName: 'ISIS', + datafileId: 70, + }); + + expect(url).toBe( + '/browse/instrument/937/facilityCycle/402/investigation/58/dataset/856/datafile' + ); + }); + + it('should return a DLS URL to the parent dataset of the datafile', async () => { + const url = await buildDatafileUrl({ + apiUrl: mockedSettings.apiUrl, + facilityName: 'DLS', + datafileId: 70, + }); + + expect(url).toBe( + '/browse/proposal/investigation news/investigation/58/dataset/856/datafile' + ); + }); + + it('should return null if the parent dataset of the datafile cannot be fetched', async () => { + axios.get = jest.fn().mockResolvedValue({ + data: [], + }); + + const url = await buildDatafileUrl({ + apiUrl: mockedSettings.apiUrl, + facilityName: 'DLS', + datafileId: 70, + }); + + expect(url).toBeNull(); + }); +}); diff --git a/packages/datagateway-download/src/downloadCart/urlBuilders/buildDatafileUrl.ts b/packages/datagateway-download/src/downloadCart/urlBuilders/buildDatafileUrl.ts new file mode 100644 index 000000000..f9bdab949 --- /dev/null +++ b/packages/datagateway-download/src/downloadCart/urlBuilders/buildDatafileUrl.ts @@ -0,0 +1,67 @@ +import { type Datafile, fetchDatafiles } from 'datagateway-common'; +import { buildDatasetUrl } from '../urlBuilders'; + +async function fetchDatafile({ + apiUrl, + facilityName, + datafileId, +}: { + apiUrl: string; + facilityName: string; + datafileId: Datafile['id']; +}): Promise { + let includeField: string[]; + switch (facilityName) { + case 'ISIS': + includeField = [ + 'dataset.investigation.investigationInstruments.instrument', + 'dataset.investigation.investigationFacilityCycles.facilityCycle', + ]; + break; + default: + includeField = ['dataset.investigation']; + break; + } + + const datafiles = await fetchDatafiles(apiUrl, { sort: {}, filters: {} }, [ + { + filterType: 'where', + filterValue: JSON.stringify({ id: { eq: datafileId } }), + }, + { + filterType: 'include', + filterValue: JSON.stringify(includeField), + }, + ]); + + return datafiles[0] ?? null; +} + +/** + * Given either a dataset ID or a {@link Datafile} object, constructs a URL to the {@link Datafile}. + * The URL points to the dataset table the {@link Datafile} belongs to. + * + * @returns The URL to the dataset table that the datafile belongs to, + * or `null` if the URL cannot be constructed due to missing info. + */ +async function buildDatafileUrl({ + apiUrl, + facilityName, + datafileId, +}: { + datafileId: Datafile['id']; + apiUrl: string; + facilityName: string; +}): Promise { + const datafile = await fetchDatafile({ apiUrl, facilityName, datafileId }); + const dataset = datafile?.dataset; + if (!dataset) return null; + + return buildDatasetUrl({ + apiUrl, + facilityName, + dataset, + }); +} + +export default buildDatafileUrl; diff --git a/packages/datagateway-download/src/downloadCart/urlBuilders/buildDatasetUrl.test.ts b/packages/datagateway-download/src/downloadCart/urlBuilders/buildDatasetUrl.test.ts new file mode 100644 index 000000000..cede9295e --- /dev/null +++ b/packages/datagateway-download/src/downloadCart/urlBuilders/buildDatasetUrl.test.ts @@ -0,0 +1,141 @@ +import { mockDatasets, mockedSettings } from '../../testData'; +import axios from 'axios'; +import type { Dataset } from 'datagateway-common'; +import buildDatasetUrl from './buildDatasetUrl'; + +describe('buildDatasetUrl', () => { + describe('given a dataset ID', () => { + let dataset: Dataset; + + beforeEach(() => { + dataset = mockDatasets[0]; + axios.get = jest.fn().mockResolvedValue({ + data: [dataset], + }); + }); + + it('should return the generic URL to it', async () => { + const url = await buildDatasetUrl({ + apiUrl: mockedSettings.apiUrl, + facilityName: mockedSettings.facilityName, + datasetId: 856, + }); + + expect(url).toBe('/browse/investigation/58/dataset/856/datafile'); + }); + + it('should return the ISIS URL to it', async () => { + const url = await buildDatasetUrl({ + apiUrl: mockedSettings.apiUrl, + facilityName: 'ISIS', + datasetId: 856, + }); + + expect(url).toBe( + '/browse/instrument/937/facilityCycle/402/investigation/58/dataset/856/datafile' + ); + }); + + it('should return the DLS URL to it', async () => { + const url = await buildDatasetUrl({ + apiUrl: mockedSettings.apiUrl, + facilityName: 'DLS', + datasetId: 856, + }); + + expect(url).toBe( + '/browse/proposal/investigation news/investigation/58/dataset/856/datafile' + ); + }); + }); + + describe('given a dataset object', () => { + const dataset = mockDatasets[1]; + + it('should return the generic URL to it', async () => { + const url = await buildDatasetUrl({ + dataset, + apiUrl: mockedSettings.apiUrl, + facilityName: mockedSettings.facilityName, + }); + + expect(url).toBe('/browse/investigation/993/dataset/535/datafile'); + }); + + it('should return the ISIS URL to it', async () => { + const url = await buildDatasetUrl({ + dataset, + apiUrl: mockedSettings.apiUrl, + facilityName: 'ISIS', + }); + + expect(url).toBe( + '/browse/instrument/927/facilityCycle/402/investigation/993/dataset/535/datafile' + ); + }); + + it('should return the DLS URL to it', async () => { + const url = await buildDatasetUrl({ + dataset, + apiUrl: mockedSettings.apiUrl, + facilityName: 'DLS', + }); + + expect(url).toBe( + '/browse/proposal/investigation inn/investigation/993/dataset/535/datafile' + ); + }); + }); + + it('should return null if neither a dataset object nor a dataset id is provided', async () => { + const url = await buildDatasetUrl({ + apiUrl: mockedSettings.apiUrl, + facilityName: mockedSettings.facilityName, + }); + + expect(url).toBeNull(); + }); + + it('should return null if the dataset object cannot be fetched', async () => { + axios.get = jest.fn().mockResolvedValue({ + data: [], + }); + + const url = await buildDatasetUrl({ + apiUrl: mockedSettings.apiUrl, + facilityName: mockedSettings.facilityName, + datasetId: 856, + }); + + expect(url).toBeNull(); + }); + + it('should return null if the parent investigation of the dataset is not fetched', async () => { + const { investigation, ...dataset } = mockDatasets[0]; + + axios.get = jest.fn().mockResolvedValue({ + data: [dataset], + }); + + const url = await buildDatasetUrl({ + apiUrl: mockedSettings.apiUrl, + facilityName: mockedSettings.facilityName, + datasetId: 856, + }); + + expect(url).toBeNull(); + }); + + it('should return null if the parent investigation URL cannot be constructed', async () => { + const dataset = { ...mockDatasets[0] }; + delete dataset.investigation?.investigationInstruments; + + const url = await buildDatasetUrl({ + dataset, + apiUrl: mockedSettings.apiUrl, + facilityName: 'ISIS', + }); + + expect(url).toBeNull(); + }); +}); diff --git a/packages/datagateway-download/src/downloadCart/urlBuilders/buildDatasetUrl.ts b/packages/datagateway-download/src/downloadCart/urlBuilders/buildDatasetUrl.ts new file mode 100644 index 000000000..16a82ed56 --- /dev/null +++ b/packages/datagateway-download/src/downloadCart/urlBuilders/buildDatasetUrl.ts @@ -0,0 +1,87 @@ +import { type Dataset, fetchDatasets } from 'datagateway-common'; +import { buildInvestigationUrl } from '../urlBuilders'; + +async function fetchDataset({ + apiUrl, + facilityName, + datasetId, +}: { + apiUrl: string; + facilityName: string; + datasetId: Dataset['id']; +}): Promise { + let includeField: string[]; + switch (facilityName) { + case 'ISIS': + includeField = [ + 'investigation.investigationInstruments.instrument', + 'investigation.investigationFacilityCycles.facilityCycle', + ]; + break; + default: + includeField = ['investigation']; + break; + } + + const datasets = await fetchDatasets(apiUrl, { sort: {}, filters: {} }, [ + { + filterType: 'where', + filterValue: JSON.stringify({ id: { eq: datasetId } }), + }, + { + filterType: 'include', + filterValue: JSON.stringify(includeField), + }, + ]); + + return datasets[0] ?? null; +} + +/** + * Given either a dataset ID or a {@link Dataset} object, constructs a URL to the {@link Dataset}. + * + * If providing a {@link Dataset} object, the {@link Dataset.investigation} has to be present, + * and the {@link Investigation} object has to have the {@link Investigation.investigationInstruments} field. + * + * @returns The URL to the dataset table, or `null` if the URL cannot be constructed due to missing info. + */ +async function buildDatasetUrl({ + apiUrl, + facilityName, + datasetId, + dataset: providedDataset, +}: { + datasetId?: Dataset['id']; + dataset?: Dataset; + apiUrl: string; + facilityName: string; +}): Promise { + if (!datasetId && !providedDataset) { + // if neither a dataset object nor a dataset ID is provided, nothing can be built + // return nothing. + return null; + } + + let dataset: Dataset | null; + if (providedDataset) { + dataset = providedDataset; + } else if (datasetId) { + dataset = await fetchDataset({ apiUrl, facilityName, datasetId }); + } else { + return null; + } + + const investigation = dataset?.investigation; + if (!dataset || !investigation) return null; + + const prefixUrl = await buildInvestigationUrl({ + apiUrl, + facilityName, + investigation, + }); + if (!prefixUrl) return null; + + return `${prefixUrl}/${dataset.id}/datafile`; +} + +export default buildDatasetUrl; diff --git a/packages/datagateway-download/src/downloadCart/urlBuilders/buildInvestigationUrl.test.ts b/packages/datagateway-download/src/downloadCart/urlBuilders/buildInvestigationUrl.test.ts new file mode 100644 index 000000000..2a9d4ce54 --- /dev/null +++ b/packages/datagateway-download/src/downloadCart/urlBuilders/buildInvestigationUrl.test.ts @@ -0,0 +1,157 @@ +import buildInvestigationUrl from './buildInvestigationUrl'; +import { mockedSettings, mockInvestigations } from '../../testData'; +import axios from 'axios'; +import type { Investigation } from 'datagateway-common'; + +describe('buildInvestigationUrl', () => { + describe('given an investigation object', () => { + let investigation: Investigation; + + beforeEach(() => { + investigation = mockInvestigations[0]; + axios.get = jest.fn().mockResolvedValue({ + data: [investigation], + }); + }); + + it('should return a generic URL to it', async () => { + const url = await buildInvestigationUrl({ + investigation, + apiUrl: mockedSettings.apiUrl, + facilityName: 'SVELTE', + }); + + expect(url).toBe('/browse/investigation/58/dataset'); + }); + + it('should return an ISIS URL to it', async () => { + const url = await buildInvestigationUrl({ + investigation, + apiUrl: mockedSettings.apiUrl, + facilityName: 'ISIS', + }); + + expect(url).toBe( + '/browse/instrument/937/facilityCycle/402/investigation/58/dataset' + ); + }); + + it('should return a DLS URL to it', async () => { + const url = await buildInvestigationUrl({ + investigation, + apiUrl: mockedSettings.apiUrl, + facilityName: 'DLS', + }); + + expect(url).toBe( + '/browse/proposal/investigation news/investigation/58/dataset' + ); + }); + }); + + describe('given an investigation id', () => { + let investigation: Investigation; + + beforeEach(() => { + investigation = mockInvestigations[1]; + axios.get = jest.fn().mockResolvedValue({ + data: [investigation], + }); + }); + + it('should return a generic URL to it', async () => { + const url = await buildInvestigationUrl({ + investigationId: 993, + apiUrl: mockedSettings.apiUrl, + facilityName: 'SVELTE', + }); + + expect(url).toBe('/browse/investigation/993/dataset'); + }); + + it('should return an ISIS URL to it', async () => { + const url = await buildInvestigationUrl({ + investigationId: 993, + apiUrl: mockedSettings.apiUrl, + facilityName: 'ISIS', + }); + + expect(url).toBe( + '/browse/instrument/927/facilityCycle/402/investigation/993/dataset' + ); + }); + + it('should return a DLS URL to it', async () => { + const url = await buildInvestigationUrl({ + investigationId: 993, + apiUrl: mockedSettings.apiUrl, + facilityName: 'DLS', + }); + + expect(url).toBe( + '/browse/proposal/investigation inn/investigation/993/dataset' + ); + }); + }); + + it('should return null if neither an investigation object or an investigation id is provided', async () => { + const url = await buildInvestigationUrl({ + apiUrl: mockedSettings.apiUrl, + facilityName: mockedSettings.facilityName, + }); + + expect(url).toBeNull(); + }); + + it('should return null if the associated instruments for the investigation cannot be fetched', async () => { + const { investigationInstruments, ...investigation } = + mockInvestigations[0]; + + axios.get = jest.fn().mockResolvedValue({ + data: [investigation], + }); + + const url = await buildInvestigationUrl({ + investigationId: 993, + apiUrl: mockedSettings.apiUrl, + facilityName: 'ISIS', + }); + + expect(url).toBeNull(); + }); + + it('should return null if the investigation object does not belong to any facility cycle', async () => { + axios.get = jest.fn().mockResolvedValue({ + data: [ + { + ...mockInvestigations[0], + startDate: '1999-03-09T08:19:55Z', + endDate: '1999-03-19T08:19:55Z', + investigationFacilityCycles: null, + }, + ], + }); + + const url = await buildInvestigationUrl({ + investigationId: 993, + apiUrl: mockedSettings.apiUrl, + facilityName: 'ISIS', + }); + + expect(url).toBeNull(); + }); + + it('should return null if the investigation object cannot be fetched', async () => { + axios.get = jest.fn().mockResolvedValue({ + data: [], + }); + + const url = await buildInvestigationUrl({ + investigationId: 993, + apiUrl: mockedSettings.apiUrl, + facilityName: 'DLS', + }); + + expect(url).toBeNull(); + }); +}); diff --git a/packages/datagateway-download/src/downloadCart/urlBuilders/buildInvestigationUrl.ts b/packages/datagateway-download/src/downloadCart/urlBuilders/buildInvestigationUrl.ts new file mode 100644 index 000000000..985d8d434 --- /dev/null +++ b/packages/datagateway-download/src/downloadCart/urlBuilders/buildInvestigationUrl.ts @@ -0,0 +1,107 @@ +import { + type AdditionalFilters, + fetchInvestigations, + type Investigation, +} from 'datagateway-common'; + +async function fetchInvestigation({ + apiUrl, + facilityName, + investigationId, +}: { + apiUrl: string; + facilityName: string; + investigationId: number; +}): Promise { + const filters: AdditionalFilters = [ + { + filterType: 'where', + filterValue: JSON.stringify({ id: { eq: investigationId } }), + }, + ]; + + if (facilityName === 'ISIS') { + filters.push({ + filterType: 'include', + filterValue: JSON.stringify([ + 'investigationInstruments.instrument', + 'investigationFacilityCycles.facilityCycle', + ]), + }); + } + + const investigations = await fetchInvestigations( + apiUrl, + { sort: {}, filters: {} }, + filters + ); + return investigations[0] ?? null; +} + +/** + * Given either an investigation ID or an {@link Investigation} object, constructs a link to the {@link Investigation}. + * + * If providing an {@link Investigation} object, the {@link Investigation.investigationInstruments} field has to be present. + * + * @returns A URL to the investigation table, or `null` if the URL cannot be constructed due to missing info. + */ +async function buildInvestigationUrl({ + apiUrl, + facilityName, + investigation: providedInvestigation, + investigationId, +}: { + investigation?: Investigation; + investigationId?: Investigation['id']; + apiUrl: string; + facilityName: string; +}): Promise { + if (!investigationId && !providedInvestigation) { + // if neither an investigation object nor an investigation ID is provided, nothing can be built + // return nothing. + return null; + } + + if (facilityName !== 'ISIS' && facilityName !== 'DLS') { + if (investigationId) { + return `/browse/investigation/${investigationId}/dataset`; + } + if (providedInvestigation) { + return `/browse/investigation/${providedInvestigation.id}/dataset`; + } + return null; + } + + let investigation: Investigation | null; + if (providedInvestigation) { + investigation = providedInvestigation; + } else if (investigationId) { + investigation = await fetchInvestigation({ + apiUrl, + facilityName, + investigationId, + }); + } else { + return null; + } + + if (!investigation) return null; + + switch (facilityName) { + case 'ISIS': + const instrument = + investigation?.investigationInstruments?.[0]?.instrument; + if (!instrument) return null; + + const facilityCycle = + investigation?.investigationFacilityCycles?.[0]?.facilityCycle; + if (!facilityCycle) return null; + + return `/browse/instrument/${instrument.id}/facilityCycle/${facilityCycle.id}/investigation/${investigation.id}/dataset`; + + case 'DLS': + return `/browse/proposal/${investigation.name}/investigation/${investigation.id}/dataset`; + } +} + +export default buildInvestigationUrl; diff --git a/packages/datagateway-download/src/downloadCart/urlBuilders/index.ts b/packages/datagateway-download/src/downloadCart/urlBuilders/index.ts new file mode 100644 index 000000000..5e21bda0a --- /dev/null +++ b/packages/datagateway-download/src/downloadCart/urlBuilders/index.ts @@ -0,0 +1,3 @@ +export { default as buildInvestigationUrl } from './buildInvestigationUrl'; +export { default as buildDatasetUrl } from './buildDatasetUrl'; +export { default as buildDatafileUrl } from './buildDatafileUrl'; diff --git a/packages/datagateway-download/src/downloadConfirmation/DownloadRequestInfo.ts b/packages/datagateway-download/src/downloadConfirmation/DownloadRequestInfo.ts new file mode 100644 index 000000000..9ea265c36 --- /dev/null +++ b/packages/datagateway-download/src/downloadConfirmation/DownloadRequestInfo.ts @@ -0,0 +1,21 @@ +/** + * Metadata of a download request, e.g. transport method, download name, etc. + */ +interface DownloadRequestInfo { + /** + * Email address to send confirmation to. + * An empty string means the user did not provide one. + */ + emailAddress?: string; + /** + * A user-provided name for the download. + * An empty string means the user did not provide one. + */ + downloadName?: string; + /** + * The transport method that should be used for the download. + */ + transport: string; +} + +export default DownloadRequestInfo; diff --git a/packages/datagateway-download/src/downloadConfirmation/__snapshots__/dialogTitle.component.test.tsx.snap b/packages/datagateway-download/src/downloadConfirmation/__snapshots__/dialogTitle.component.test.tsx.snap new file mode 100644 index 000000000..5b0736b2f --- /dev/null +++ b/packages/datagateway-download/src/downloadConfirmation/__snapshots__/dialogTitle.component.test.tsx.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`DialogTitle should render correctly 1`] = ` + +

+

+ Title +

+ +

+
+`; diff --git a/packages/datagateway-download/src/downloadConfirmation/__snapshots__/downloadConfirmDialog.component.test.tsx.snap b/packages/datagateway-download/src/downloadConfirmation/__snapshots__/downloadConfirmDialog.component.test.tsx.snap index ce5bea10f..580ea2e36 100644 --- a/packages/datagateway-download/src/downloadConfirmation/__snapshots__/downloadConfirmDialog.component.test.tsx.snap +++ b/packages/datagateway-download/src/downloadConfirmation/__snapshots__/downloadConfirmDialog.component.test.tsx.snap @@ -1,7070 +1,569 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`DownloadConfirmDialog does not load the download speed/time table when isTwoLevel is true 1`] = ` - -
+ + + + + + + + +
+ 1 Mbps + + 30 Mbps + + 100 Mbps +
-
- - - - - -
- - -
+
+ < 1 downloadConfirmDialog.second {count:1} + - - -
-
- - - - -
- - -
- downloadConfirmDialog.dialog_title -
-
-
- - - - - - - - - -
-
-
-
-
- - - -
- - -
- - -
- - - - -
- - - - - - - - - - - - - -
- -
-
-
-
-
- - -

- downloadConfirmDialog.download_name_helpertext -

-
-
-
-
-
-
-
-
-
-
- - -
- - -
- - - - - - - - - - - - - HTTPS - , - , - ], - "classes": Object { - "disabled": "Mui-disabled", - "filled": "MuiSelect-filled", - "icon": "MuiSelect-icon", - "iconFilled": "MuiSelect-iconFilled", - "iconOpen": "MuiSelect-iconOpen", - "iconOutlined": "MuiSelect-iconOutlined", - "nativeInput": "MuiSelect-nativeInput", - "outlined": "MuiSelect-outlined", - "root": "MuiSelect-root", - "select": "MuiSelect-select", - "selectMenu": "MuiSelect-selectMenu", - }, - "id": "confirm-access-method", - "multiple": false, - "name": "Access Method", - "type": undefined, - "variant": "standard", - } - } - onChange={[Function]} - value="https" - > - - HTTPS - , - , - ], - "classes": Object { - "disabled": "Mui-disabled", - "filled": "MuiSelect-filled", - "icon": "MuiSelect-icon", - "iconFilled": "MuiSelect-iconFilled", - "iconOpen": "MuiSelect-iconOpen", - "iconOutlined": "MuiSelect-iconOutlined", - "nativeInput": "MuiSelect-nativeInput", - "outlined": "MuiSelect-outlined", - "root": "MuiSelect-root", - "select": "MuiSelect-select", - "selectMenu": "MuiSelect-selectMenu", - }, - "id": "confirm-access-method", - "multiple": false, - "name": "Access Method", - "type": undefined, - "variant": "standard", - } - } - onChange={[Function]} - value="https" - > - - HTTPS - , - , - ], - "classes": Object { - "disabled": "Mui-disabled", - "filled": "MuiSelect-filled", - "icon": "MuiSelect-icon", - "iconFilled": "MuiSelect-iconFilled", - "iconOpen": "MuiSelect-iconOpen", - "iconOutlined": "MuiSelect-iconOutlined", - "nativeInput": "MuiSelect-nativeInput", - "outlined": "MuiSelect-outlined", - "root": "MuiSelect-root", - "select": "MuiSelect-select", - "selectMenu": "MuiSelect-selectMenu", - }, - "id": "confirm-access-method", - "multiple": false, - "name": "Access Method", - "type": undefined, - "variant": "standard", - } - } - multiline={false} - onChange={[Function]} - type="text" - value="https" - > - - HTTPS - , - , - ], - "classes": Object { - "disabled": "Mui-disabled", - "filled": "MuiSelect-filled", - "icon": "MuiSelect-icon", - "iconFilled": "MuiSelect-iconFilled", - "iconOpen": "MuiSelect-iconOpen", - "iconOutlined": "MuiSelect-iconOutlined", - "nativeInput": "MuiSelect-nativeInput", - "outlined": "MuiSelect-outlined", - "root": "MuiSelect-root", - "select": "MuiSelect-select", - "selectMenu": "MuiSelect-selectMenu", - }, - "id": "confirm-access-method", - "multiple": false, - "name": "Access Method", - "type": undefined, - "variant": "standard", - } - } - multiline={false} - onChange={[Function]} - type="text" - value="https" - > -
- - - - - - - - - - - - -
-
-
-
-
-
-
- - -

- downloadConfirmDialog.access_method_helpertext -

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

- - downloadConfirmDialog.access_method_info - : - -

-
-
- HTTPS access method.", - } - } - id="confirm-access-method-https-description" - > - HTTPS access method.", - } - } - id="confirm-access-method-https-description" - > -

HTTPS access method.", - } - } - id="confirm-access-method-https-description" - /> - - - -

-
-
- - -
- - -

- - downloadConfirmDialog.download_size - : - - - 100 B -

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

- downloadConfirmDialog.email_help -

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - - -
- - - - - - - - - -
-
-
-
-
-
-
-
- - - -
+
+
+
+
+
+ +
+ - +
+

+ downloadConfirmDialog.email_help +

- - - - - - - +
+
+
+
+ +
+
+ + +
+
`; -exports[`DownloadConfirmDialog renders correctly 1`] = ` - -
- +
- - - - - - - -

- - downloadTab.last_checked - : - - - Sat, 01 Feb 2020 00:00:00 GMT -

-
-
- - + + + + +

+ + downloadTab.last_checked: + + Sat, 01 Feb 2020 00:00:00 GMT +

+ +
+
- - - - - - - - - - - -
+
+
+
+
+
+
+
+
+
+
+ +

+ downloadStatus.id +

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

+ downloadStatus.fullname +

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

+ downloadStatus.username +

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

+ downloadStatus.preparedId +

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

+ downloadStatus.transport +

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

+ downloadStatus.status +

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

+ downloadStatus.size +

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

+ downloadStatus.createdAt +

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

+ downloadStatus.deleted +

+ +
+
+
+
+
+
+
+
+
+
+
+ Actions +
+
+
+
+
+
+
+
+ + 1 + +
+
+
+
+
+
+
+ + Person 1 + +
+
+
+
+
+
+
+ + test user + +
+
+
+
+
+
+
+ + test-prepared-id + +
+
+
+
+
+
+
+ + https + +
+
+
+
+
+
+
+ + downloadStatus.complete + +
+
+
+
+
+
+
+ + 1 KB + +
+
+
+
+
+
+
+ + 2020-02-25 15:05:29 + +
+
+
+
+
+
+
+ + No + +
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + 2 + +
+
+
+
+
+
+
+ + Person 2 + +
+
+
+
+
+
+
+ + test user + +
+
+
+
+
+
+
+ + test-prepared-id + +
+
+
+
+
+
+
+ + globus + +
+
+
+
+
+
+
+ + downloadStatus.preparing + +
+
+
+
+
+
+
+ + 2 KB + +
+
+
+
+
+
+
+ + 2020-02-26 15:05:35 + +
+
+
+
+
+
+
+ + No + +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+ + 3 + +
+
+
+
+
+
+
+ + Person 3 + +
+
+
+
+
+
+
+ + test user + +
+
+
+
+
+
+
+ + test-prepared-id + +
+
+
+
+
+
+
+ + https + +
+
+
+
+
+
+
+ + downloadStatus.restoring + +
+
+
+
+
+
+
+ + 3 KB + +
+
+
+
+
+
+
+ + 2020-02-27 15:57:20 + +
+
+
+
+
+
+
+ + No + +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+ + 4 + +
+
+
+
+
+
+
+ + Person 4 + +
+
+
+
+
+
+
+ + test user + +
+
+
+
+
+
+
+ + test-prepared-id + +
+
+
+
+
+
+
+ + globus + +
+
+
+
+
+
+
+ + downloadStatus.expired + +
+
+
+
+
+
+
+ + 4 KB + +
+
+
+
+
+
+
+ + 2020-02-28 15:57:28 + +
+
+
+
+
+
+
+ + Yes + +
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + 5 + +
+
+
+
+
+
+
+ + Person 5 + +
+
+
+
+
+
+
+ + test user + +
+
+
+
+
+
+
+ + test-prepared-id + +
+
+
+
+
+
+
+ + globus + +
+
+
+
+
+
+
+ + downloadStatus.paused + +
+
+
+
+
+
+
+ + 5 KB + +
+
+
+
+
+
+
+ + 2020-03-01 15:57:28 + +
+
+
+
+
+
+
+ + No + +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `; diff --git a/packages/datagateway-download/src/downloadStatus/__snapshots__/downloadStatusTable.component.test.tsx.snap b/packages/datagateway-download/src/downloadStatus/__snapshots__/downloadStatusTable.component.test.tsx.snap index bb2d5ba8d..63b9a771b 100644 --- a/packages/datagateway-download/src/downloadStatus/__snapshots__/downloadStatusTable.component.test.tsx.snap +++ b/packages/datagateway-download/src/downloadStatus/__snapshots__/downloadStatusTable.component.test.tsx.snap @@ -1,72 +1,605 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Download Status Table renders correctly 1`] = ` -
- +
- - - - + + + + +
+
- - - -
+
+
+
+
+
+
+
+
+
+
+ +

+ downloadStatus.filename +

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

+ downloadStatus.transport +

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

+ downloadStatus.status +

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

+ downloadStatus.createdAt +

+ +
+
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+
+
+
+
+ Actions +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `; diff --git a/packages/datagateway-download/src/downloadStatus/adminDownloadStatusTable.component.test.tsx b/packages/datagateway-download/src/downloadStatus/adminDownloadStatusTable.component.test.tsx index 544a5c26b..f1f0f1e99 100644 --- a/packages/datagateway-download/src/downloadStatus/adminDownloadStatusTable.component.test.tsx +++ b/packages/datagateway-download/src/downloadStatus/adminDownloadStatusTable.component.test.tsx @@ -1,118 +1,62 @@ -import React from 'react'; -import { createMount, createShallow } from '@material-ui/core/test-utils'; -import { Download } from 'datagateway-common'; +import * as React from 'react'; import { adminDownloadDeleted, adminDownloadStatus, fetchAdminDownloads, + getDownload, + getPercentageComplete, } from '../downloadApi'; import AdminDownloadStatusTable from './adminDownloadStatusTable.component'; -import { act } from 'react-dom/test-utils'; -import { flushPromises } from '../setupTests'; -import { Select } from '@material-ui/core'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, + flushPromises, +} from '../setupTests'; +import userEvent from '@testing-library/user-event'; +import { + render, + RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; +import { QueryClient, QueryClientProvider } from 'react-query'; +import { mockDownloadItems, mockedSettings } from '../testData'; +import { DownloadSettingsContext } from '../ConfigProvider'; jest.mock('../downloadApi'); -describe('Admin Download Status Table', () => { - let shallow; - let mount; - - const downloadItems: Download[] = [ - { - createdAt: '2020-02-25T15:05:29Z', - downloadItems: [{ entityId: 1, entityType: 'investigation', id: 1 }], - email: 'test1@email.com', - facilityName: 'LILS', - fileName: 'test-file-1', - fullName: 'Person 1', - id: 1, - isDeleted: false, - isEmailSent: true, - isTwoLevel: false, - preparedId: 'test-prepared-id', - sessionId: 'test-session-id', - size: 1000, - status: 'COMPLETE', - transport: 'https', - userName: 'test user', - }, - { - createdAt: '2020-02-26T15:05:35Z', - downloadItems: [{ entityId: 2, entityType: 'investigation', id: 2 }], - email: 'test2@email.com', - facilityName: 'LILS', - fileName: 'test-file-2', - fullName: 'Person 2', - id: 2, - isDeleted: false, - isEmailSent: true, - isTwoLevel: false, - preparedId: 'test-prepared-id', - sessionId: 'test-session-id', - size: 2000, - status: 'PREPARING', - transport: 'globus', - userName: 'test user', - }, - { - createdAt: '2020-02-27T15:57:20Z', - downloadItems: [{ entityId: 3, entityType: 'investigation', id: 3 }], - email: 'test3@email.com', - facilityName: 'LILS', - fileName: 'test-file-3', - fullName: 'Person 3', - id: 3, - isDeleted: false, - isEmailSent: true, - isTwoLevel: false, - preparedId: 'test-prepared-id', - sessionId: 'test-session-id', - size: 3000, - status: 'RESTORING', - transport: 'https', - userName: 'test user', - }, - { - createdAt: '2020-02-28T15:57:28Z', - downloadItems: [{ entityId: 4, entityType: 'investigation', id: 4 }], - email: 'test4@email.com', - facilityName: 'LILS', - fileName: 'test-file-4', - fullName: 'Person 4', - id: 4, - isDeleted: true, - isEmailSent: true, - isTwoLevel: false, - preparedId: 'test-prepared-id', - sessionId: 'test-session-id', - size: 4000, - status: 'EXPIRED', - transport: 'globus', - userName: 'test user', - }, - { - createdAt: '2020-03-01T15:57:28Z[UTC]', - downloadItems: [{ entityId: 5, entityType: 'investigation', id: 5 }], - email: 'test5@email.com', - facilityName: 'LILS', - fileName: 'test-file-5', - fullName: 'Person 5', - id: 5, - isDeleted: false, - isEmailSent: true, - isTwoLevel: false, - preparedId: 'test-prepared-id', - sessionId: 'test-session-id', - size: 5000, - status: 'PAUSED', - transport: 'globus', - userName: 'test user', +const createTestQueryClient = (): QueryClient => + new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, }, - ]; + }); + +const renderComponent = ({ settings = mockedSettings } = {}): RenderResult => + render( + + + + + + ); + +describe('Admin Download Status Table', () => { + let user: ReturnType; beforeEach(() => { - shallow = createShallow({ untilSelector: 'div' }); - mount = createMount(); + user = userEvent.setup({ delay: null }); + + (getDownload as jest.MockedFunction).mockImplementation( + (id, _) => + Promise.resolve( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + mockDownloadItems.find((download) => download.id === id)! + ) + ); (fetchAdminDownloads as jest.Mock).mockImplementation( ( settings: { facilityName: string; downloadApiUrl: string }, @@ -121,7 +65,7 @@ describe('Admin Download Status Table', () => { //Only return the 5 results when initialy requesting so that only a total //of 5 results will be loaded if (queryOffset?.endsWith('LIMIT 0, 50')) - return Promise.resolve(downloadItems); + return Promise.resolve(mockDownloadItems); else return Promise.resolve([]); } ); @@ -134,500 +78,585 @@ describe('Admin Download Status Table', () => { }); afterEach(() => { - mount.cleanUp(); - (fetchAdminDownloads as jest.Mock).mockClear(); - (adminDownloadDeleted as jest.Mock).mockClear(); - (adminDownloadStatus as jest.Mock).mockClear(); + jest.clearAllMocks(); }); - it('renders correctly', () => { + it('should render correctly', async () => { const mockedDate = new Date(Date.UTC(2020, 1, 1, 0, 0, 0)).toUTCString(); global.Date.prototype.toLocaleString = jest.fn(() => mockedDate); - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); + const { asFragment } = renderComponent(); - it('fetches the download items and sorts by download requested time desc on load ', async () => { - const wrapper = mount( -
- -
- ); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + // wait for data to finish loading + expect( + await screen.findByText(mockedDate.toLocaleString()) + ).toBeInTheDocument(); - expect(fetchAdminDownloads).toHaveBeenCalledTimes(2); - expect(fetchAdminDownloads).toHaveBeenNthCalledWith( - 1, - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' ORDER BY download.createdAt desc, download.id ASC LIMIT 0, 50" - ); - expect(wrapper.exists('[aria-rowcount=5]')).toBe(true); + expect(asFragment()).toMatchSnapshot(); }); - it('fetches more download items when loadMoreRows is called', async () => { - const wrapper = mount( -
- -
- ); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + it('should fetch the download items and sorts by download requested time desc on load', async () => { + renderComponent(); - await act(async () => { - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 5, - stopIndex: 9, - }); - - await flushPromises(); - wrapper.update(); - }); - - expect(fetchAdminDownloads).toHaveBeenCalledTimes(3); - expect(fetchAdminDownloads).toHaveBeenLastCalledWith( - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' ORDER BY download.createdAt desc, download.id ASC LIMIT 5, 5" - ); - expect(wrapper.exists('[aria-rowcount=5]')).toBe(true); + const rows = await screen.findAllByText(/^\d$/); + expect(rows).toHaveLength(5); }); - it('translates the status strings correctly', async () => { - const wrapper = mount( -
- -
- ); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + it('should translate the status strings correctly', async () => { + renderComponent(); expect( - wrapper.find('[aria-rowindex=1]').find('[aria-colindex=6]').text() - ).toEqual('downloadStatus.complete'); + await screen.findByText('downloadStatus.paused') + ).toBeInTheDocument(); expect( - wrapper.find('[aria-rowindex=2]').find('[aria-colindex=6]').text() - ).toEqual('downloadStatus.preparing'); + await screen.findByText('downloadStatus.expired') + ).toBeInTheDocument(); expect( - wrapper.find('[aria-rowindex=3]').find('[aria-colindex=6]').text() - ).toEqual('downloadStatus.restoring'); + await screen.findByText('downloadStatus.restoring') + ).toBeInTheDocument(); expect( - wrapper.find('[aria-rowindex=4]').find('[aria-colindex=6]').text() - ).toEqual('downloadStatus.expired'); + await screen.findByText('downloadStatus.preparing') + ).toBeInTheDocument(); expect( - wrapper.find('[aria-rowindex=5]').find('[aria-colindex=6]').text() - ).toEqual('downloadStatus.paused'); + await screen.findByText('downloadStatus.complete') + ).toBeInTheDocument(); }); - it('re-fetches the download items when the refresh button is clicked', async () => { - const wrapper = mount( -
- -
- ); + it('should re-fetch the download items when the refresh button is clicked', async () => { + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - - await act(async () => { - wrapper - .find( - 'button[aria-label="downloadTab.refresh_download_status_arialabel"]' - ) - .simulate('click'); - await flushPromises(); - wrapper.update(); - }); + expect(await screen.findAllByText(/^\d$/)).toHaveLength( + mockDownloadItems.length + ); - expect(fetchAdminDownloads).toHaveBeenCalledTimes(3); - expect(fetchAdminDownloads).toHaveBeenNthCalledWith( - 3, - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' ORDER BY download.createdAt desc, download.id ASC LIMIT 0, 50" + (fetchAdminDownloads as jest.Mock).mockImplementation( + ( + settings: { facilityName: string; downloadApiUrl: string }, + queryOffset?: string + ) => { + //Only return the 5 results when initialy requesting so that only a total + //of 5 results will be loaded + if (queryOffset?.endsWith('LIMIT 0, 50')) + return mockDownloadItems.slice(0, mockDownloadItems.length - 1); + return Promise.resolve([]); + } ); - expect(wrapper.exists('[aria-rowcount=5]')).toBe(true); - }); - it('sends sort request on sort', async () => { - const wrapper = mount( -
- -
+ await user.click( + screen.getByRole('button', { + name: 'downloadTab.refresh_download_status_arialabel', + }) ); - await act(async () => { - await flushPromises(); - wrapper.update(); + await waitFor(() => { + expect(screen.queryAllByText(/^\d$/)).toHaveLength( + mockDownloadItems.length - 1 + ); }); + }); + + it('should send sort request on sort', async () => { + // use skipHover to avoid triggering sort tooltips which slow the test down + user = userEvent.setup({ delay: null, skipHover: true }); + renderComponent(); // Table is sorted by createdAt desc by default // To keep working test, we will remove all sorts on the table beforehand - const createdAtSortLabel = wrapper - .find('[role="columnheader"] span[role="button"]') - .at(6); - await act(async () => { - createdAtSortLabel.simulate('click'); - await flushPromises(); - wrapper.update(); - }); + await user.click(await screen.findByText('downloadStatus.createdAt')); // Get the Username sort header - const usernameSortLabel = wrapper - .find('[role="columnheader"] span[role="button"]') - .at(2); - await act(async () => { - usernameSortLabel.simulate('click'); - await flushPromises(); - wrapper.update(); - }); + const usernameSortLabel = await screen.findByText( + 'downloadStatus.username' + ); + + await user.click(usernameSortLabel); - expect(fetchAdminDownloads).toHaveBeenLastCalledWith( - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' ORDER BY download.userName asc, download.id ASC LIMIT 0, 50" + expect(fetchAdminDownloads).toHaveBeenCalledWith( + { + downloadApiUrl: mockedSettings.downloadApiUrl, + facilityName: mockedSettings.facilityName, + }, + `WHERE download.facilityName = '${mockedSettings.facilityName}' ORDER BY download.userName asc, download.id ASC LIMIT 0, 50` ); // Get the Access Method sort header. - const accessMethodSortLabel = wrapper - .find('[role="columnheader"] span[role="button"]') - .at(4); - await act(async () => { - accessMethodSortLabel.simulate('click'); - await flushPromises(); - wrapper.update(); - }); + const accessMethodSortLabel = await screen.findByText( + 'downloadStatus.transport' + ); - expect(fetchAdminDownloads).toHaveBeenLastCalledWith( - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' ORDER BY download.userName asc, download.transport asc, download.id ASC LIMIT 0, 50" + // should replace the sort by username with sort by access method + await user.click(accessMethodSortLabel); + expect(fetchAdminDownloads).toHaveBeenCalledWith( + { + downloadApiUrl: mockedSettings.downloadApiUrl, + facilityName: mockedSettings.facilityName, + }, + `WHERE download.facilityName = '${mockedSettings.facilityName}' ORDER BY download.transport asc, download.id ASC LIMIT 0, 50` ); - await act(async () => { - accessMethodSortLabel.simulate('click'); - await flushPromises(); - wrapper.update(); - }); + // should append sort if shift key is pressed + await user.keyboard('{Shift>}'); + await user.click(usernameSortLabel); + await user.keyboard('{/Shift}'); - expect(fetchAdminDownloads).toHaveBeenLastCalledWith( - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' ORDER BY download.userName asc, download.transport desc, download.id ASC LIMIT 0, 50" + expect(fetchAdminDownloads).toHaveBeenCalledWith( + { + downloadApiUrl: mockedSettings.downloadApiUrl, + facilityName: mockedSettings.facilityName, + }, + `WHERE download.facilityName = '${mockedSettings.facilityName}' ORDER BY download.transport asc, download.userName asc, download.id ASC LIMIT 0, 50` ); - await act(async () => { - accessMethodSortLabel.simulate('click'); - await flushPromises(); - wrapper.update(); - }); + await user.keyboard('{Shift>}'); + await user.click(accessMethodSortLabel); + await user.keyboard('{/Shift}'); - expect(fetchAdminDownloads).toHaveBeenLastCalledWith( - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' ORDER BY download.userName asc, download.id ASC LIMIT 0, 50" + expect(fetchAdminDownloads).toHaveBeenCalledWith( + { + downloadApiUrl: mockedSettings.downloadApiUrl, + facilityName: mockedSettings.facilityName, + }, + `WHERE download.facilityName = '${mockedSettings.facilityName}' ORDER BY download.transport desc, download.userName asc, download.id ASC LIMIT 0, 50` ); - }, 10000); - it('sends filter request on text filter', async () => { - const wrapper = mount( -
- -
+ await user.click(accessMethodSortLabel); + expect(fetchAdminDownloads).toHaveBeenCalledWith( + { + downloadApiUrl: mockedSettings.downloadApiUrl, + facilityName: mockedSettings.facilityName, + }, + `WHERE download.facilityName = '${mockedSettings.facilityName}' ORDER BY download.userName asc, download.id ASC LIMIT 0, 50` ); + }); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + describe('text filters', () => { + it('should filter username properly', async () => { + // use skipHover to avoid triggering sort tooltips which slow the test down + user = userEvent.setup({ delay: null, skipHover: true }); - // Table is sorted by createdAt desc by default - // To keep working test, we will remove all sorts on the table beforehand - const createdAtSortLabel = wrapper - .find('[role="columnheader"] span[role="button"]') - .at(6); - await act(async () => { - createdAtSortLabel.simulate('click'); + renderComponent(); await flushPromises(); - wrapper.update(); - }); - // Get the Username filter input - const usernameFilterInput = wrapper - .find('[aria-label="Filter by downloadStatus.username"]') - .first(); - await act(async () => { - usernameFilterInput.instance().value = 'test user'; - usernameFilterInput.simulate('change'); + // Table is sorted by createdAt desc by default + // To keep working test, we will remove all sorts on the table beforehand + await user.click(await screen.findByText('downloadStatus.createdAt')); + + // Get the Username filter input + const usernameFilterInput = await screen.findByLabelText( + 'Filter by downloadStatus.username' + ); + + await user.type(usernameFilterInput, 'test user'); await flushPromises(); - wrapper.update(); - }); - expect(fetchAdminDownloads).toHaveBeenLastCalledWith( - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' AND UPPER(download.userName) LIKE CONCAT('%', 'TEST USER', '%') ORDER BY download.id ASC LIMIT 0, 50" - ); - usernameFilterInput.instance().value = ''; - usernameFilterInput.simulate('change'); - - // Get the Availability filter input - const availabilityFilterInput = wrapper - .find('[aria-label="Filter by downloadStatus.status"]') - .first(); - await act(async () => { - availabilityFilterInput.instance().value = 'downloadStatus.complete'; - availabilityFilterInput.simulate('change'); + expect(fetchAdminDownloads).toHaveBeenCalledWith( + { + downloadApiUrl: mockedSettings.downloadApiUrl, + facilityName: mockedSettings.facilityName, + }, + `WHERE download.facilityName = '${mockedSettings.facilityName}' AND UPPER(download.userName) LIKE CONCAT('%', 'TEST USER', '%') ORDER BY download.id ASC LIMIT 0, 50` + ); + + await user.clear(usernameFilterInput); await flushPromises(); - wrapper.update(); + + expect(fetchAdminDownloads).toHaveBeenCalledWith( + { + downloadApiUrl: mockedSettings.downloadApiUrl, + facilityName: mockedSettings.facilityName, + }, + `WHERE download.facilityName = '${mockedSettings.facilityName}' ORDER BY download.id ASC LIMIT 0, 50` + ); }); - expect(fetchAdminDownloads).toHaveBeenLastCalledWith( - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' AND UPPER(download.status) LIKE CONCAT('%', 'COMPLETE', '%') ORDER BY download.id ASC LIMIT 0, 50" - ); + it('should filter download availability properly', async () => { + // use skipHover to avoid triggering sort tooltips which slow the test down + user = userEvent.setup({ delay: null, skipHover: true }); - // We simulate a change in the select from 'include' to 'exclude'. - const availabilityFilterSelect = wrapper.find(Select).at(5); - await act(async () => { - availabilityFilterSelect - .props() - .onChange({ target: { value: 'exclude' } }); + renderComponent(); await flushPromises(); - wrapper.update(); - }); - expect(fetchAdminDownloads).toHaveBeenLastCalledWith( - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' AND UPPER(download.status) NOT LIKE CONCAT('%', 'COMPLETE', '%') ORDER BY download.id ASC LIMIT 0, 50" - ); + // Table is sorted by createdAt desc by default + // To keep working test, we will remove all sorts on the table beforehand + await user.click(await screen.findByText('downloadStatus.createdAt')); + + // Get the Availability filter input + const availabilityFilterInput = screen.getByLabelText( + 'Filter by downloadStatus.status' + ); - await act(async () => { - availabilityFilterInput.instance().value = ''; - availabilityFilterInput.simulate('change'); + await user.type(availabilityFilterInput, 'downloadStatus.complete'); await flushPromises(); - wrapper.update(); - }); - expect(fetchAdminDownloads).toHaveBeenLastCalledWith( - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' ORDER BY download.id ASC LIMIT 0, 50" - ); - }, 10000); + expect(fetchAdminDownloads).toHaveBeenCalledWith( + { + downloadApiUrl: mockedSettings.downloadApiUrl, + facilityName: mockedSettings.facilityName, + }, + `WHERE download.facilityName = '${mockedSettings.facilityName}' AND UPPER(download.status) LIKE CONCAT('%', 'COMPLETE', '%') ORDER BY download.id ASC LIMIT 0, 50` + ); + + // We simulate a change in the select from 'include' to 'exclude'. + // click on the select box + await user.click( + screen.getAllByLabelText('include, exclude or exact')[5] + ); + // click on exclude option + await user.click( + within(await screen.findByRole('listbox')).getByText('Exclude') + ); + await flushPromises(); - it('sends filter request on date filter', async () => { - const wrapper = mount( -
- -
- ); + expect(fetchAdminDownloads).toHaveBeenCalledWith( + { + downloadApiUrl: mockedSettings.downloadApiUrl, + facilityName: mockedSettings.facilityName, + }, + `WHERE download.facilityName = '${mockedSettings.facilityName}' AND UPPER(download.status) NOT LIKE CONCAT('%', 'COMPLETE', '%') ORDER BY download.id ASC LIMIT 0, 50` + ); - await act(async () => { + await user.clear(availabilityFilterInput); await flushPromises(); - wrapper.update(); + + expect(fetchAdminDownloads).toHaveBeenCalledWith( + { + downloadApiUrl: mockedSettings.downloadApiUrl, + facilityName: mockedSettings.facilityName, + }, + `WHERE download.facilityName = '${mockedSettings.facilityName}' ORDER BY download.id ASC LIMIT 0, 50` + ); }); + }); + + it('sends filter request on date filter', async () => { + applyDatePickerWorkaround(); + // use skipHover to avoid triggering sort tooltips which slow the test down + user = userEvent.setup({ delay: null, skipHover: true }); + + renderComponent(); + await flushPromises(); // Table is sorted by createdAt desc by default // To keep working test, we will remove all sorts on the table beforehand - const createdAtSortLabel = wrapper - .find('[role="columnheader"] span[role="button"]') - .at(6); - await act(async () => { - createdAtSortLabel.simulate('click'); - await flushPromises(); - wrapper.update(); - }); + await user.click(await screen.findByText('downloadStatus.createdAt')); + await flushPromises(); // Get the Requested Data From filter input - const dateFromFilterInput = wrapper.find( - 'input[id="downloadStatus.createdAt filter from"]' - ); - await act(async () => { - dateFromFilterInput.instance().value = '2020-01-01 00:00'; - dateFromFilterInput.simulate('change'); - await flushPromises(); - wrapper.update(); + const dateFromFilterInput = screen.getByRole('textbox', { + name: 'downloadStatus.createdAt filter from', }); + await user.type(dateFromFilterInput, '2020-01-01_00:00:00'); + await flushPromises(); - expect(fetchAdminDownloads).toHaveBeenLastCalledWith( - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' AND download.createdAt BETWEEN {ts '2020-01-01 00:00'} AND {ts '9999-12-31 23:59'} ORDER BY download.id ASC LIMIT 0, 50" + expect(fetchAdminDownloads).toHaveBeenCalledWith( + { + downloadApiUrl: mockedSettings.downloadApiUrl, + facilityName: mockedSettings.facilityName, + }, + `WHERE download.facilityName = '${mockedSettings.facilityName}' AND download.createdAt BETWEEN {ts '2020-01-01 00:00:00'} AND {ts '9999-12-31 23:59:00'} ORDER BY download.id ASC LIMIT 0, 50` ); // Get the Requested Data To filter input - const dateToFilterInput = wrapper.find( - 'input[id="downloadStatus.createdAt filter to"]' - ); - await act(async () => { - dateToFilterInput.instance().value = '2020-01-02 23:59'; - dateToFilterInput.simulate('change'); - await flushPromises(); - wrapper.update(); + const dateToFilterInput = screen.getByRole('textbox', { + name: 'downloadStatus.createdAt filter to', }); - expect(fetchAdminDownloads).toHaveBeenLastCalledWith( - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' AND download.createdAt BETWEEN {ts '2020-01-01 00:00'} AND {ts '2020-01-02 23:59'} ORDER BY download.id ASC LIMIT 0, 50" + // in v6 of date-picker spaces are considered to be a '0' + // 20200102235900 is equivalent to 2020-01-02 03:59:00 + await user.type(dateToFilterInput, '2020-01-02_23:59:00'); + await flushPromises(); + + expect(fetchAdminDownloads).toHaveBeenCalledWith( + { + downloadApiUrl: mockedSettings.downloadApiUrl, + facilityName: mockedSettings.facilityName, + }, + `WHERE download.facilityName = '${mockedSettings.facilityName}' AND download.createdAt BETWEEN {ts '2020-01-01 00:00:00'} AND {ts '2020-01-02 23:59:00'} ORDER BY download.id ASC LIMIT 0, 50` ); - dateFromFilterInput.instance().value = ''; - dateFromFilterInput.simulate('change'); - dateToFilterInput.instance().value = ''; - dateToFilterInput.simulate('change'); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + (fetchAdminDownloads as jest.Mock).mockClear(); - expect(fetchAdminDownloads).toHaveBeenLastCalledWith( - { downloadApiUrl: '', facilityName: '' }, - "WHERE download.facilityName = '' ORDER BY download.id ASC LIMIT 0, 50" - ); - }, 10000); + await user.clear(dateFromFilterInput); + await user.clear(dateToFilterInput); + await flushPromises(); - it('sends restore item and item status requests when restore button is clicked', async () => { - const wrapper = mount( -
- -
+ expect(fetchAdminDownloads).toHaveBeenCalledWith( + { + downloadApiUrl: mockedSettings.downloadApiUrl, + facilityName: mockedSettings.facilityName, + }, + `WHERE download.facilityName = '${mockedSettings.facilityName}' ORDER BY download.id ASC LIMIT 0, 50` ); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + cleanupDatePickerWorkaround(); + }); - (fetchAdminDownloads as jest.Mock).mockImplementation(() => - Promise.resolve([ - { ...downloadItems[0], isDeleted: false, status: 'RESTORING' }, - ]) - ); + it('should send restore item and item status requests when restore button is clicked', async () => { + renderComponent(); - await act(async () => { - wrapper - .find( - 'button[aria-label="downloadStatus.restore {filename:test-file-4}"]' - ) - .simulate('click'); - await flushPromises(); - wrapper.update(); - }); + await flushPromises(); - expect(adminDownloadDeleted).toHaveBeenCalledWith(4, false, { - downloadApiUrl: '', - facilityName: '', + // without waitFor, + // toBeInTheDocument will complain it can't find the element + // even though findBy didn't throw... + // (it throws when the elemenet actually doesn't exist) + await waitFor(async () => { + expect( + await screen.findByRole('button', { + name: 'downloadStatus.restore {filename:test-file-4}', + }) + ).toBeInTheDocument(); }); - expect(fetchAdminDownloads).toHaveBeenLastCalledWith( - { downloadApiUrl: '', facilityName: '' }, - 'WHERE download.id = 4' + + (fetchAdminDownloads as jest.Mock).mockImplementation( + ( + settings: { facilityName: string; downloadApiUrl: string }, + queryOffset?: string + ) => { + //Only return the 5 results when initialy requesting so that only a total + //of 5 results will be loaded + if (queryOffset?.endsWith('LIMIT 0, 50')) + return Promise.resolve( + mockDownloadItems.map((d) => + d.id === 4 + ? { + ...d, + isDeleted: false, + status: 'RESTORING', + } + : d + ) + ); + return Promise.resolve([]); + } ); + + await user.click( + screen.getByRole('button', { + name: 'downloadStatus.restore {filename:test-file-4}', + }) + ); + + await flushPromises(); + expect( - wrapper.exists( - '[aria-label="downloadStatus.pause {filename:test-file-4}"]' - ) - ).toBeTruthy(); + await screen.findByRole('button', { + name: 'downloadStatus.pause {filename:test-file-4}', + }) + ).toBeInTheDocument(); }); - it('sends pause restore request when pause button is clicked', async () => { - const wrapper = mount( -
- -
+ it('should send pause restore request when pause button is clicked', async () => { + renderComponent(); + + await flushPromises(); + + expect( + await screen.findByRole('button', { + name: 'downloadStatus.pause {filename:test-file-3}', + }) + ).toBeInTheDocument(); + + (fetchAdminDownloads as jest.Mock).mockImplementation( + ( + settings: { facilityName: string; downloadApiUrl: string }, + queryOffset?: string + ) => { + //Only return the 5 results when initialy requesting so that only a total + //of 5 results will be loaded + if (queryOffset?.endsWith('LIMIT 0, 50')) + return Promise.resolve( + mockDownloadItems.map((d) => + d.id === 3 + ? { + ...d, + isDeleted: false, + status: 'PAUSED', + } + : d + ) + ); + return Promise.resolve([]); + } ); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.click( + screen.getByRole('button', { + name: 'downloadStatus.pause {filename:test-file-3}', + }) + ); - await act(async () => { - wrapper - .find( - 'button[aria-label="downloadStatus.pause {filename:test-file-3}"]' - ) - .simulate('click'); - await flushPromises(); - wrapper.update(); - }); + await flushPromises(); - expect(adminDownloadStatus).toHaveBeenCalledWith(3, 'PAUSED', { - downloadApiUrl: '', - facilityName: '', - }); expect( - wrapper.exists( - '[aria-label="downloadStatus.resume {filename:test-file-3}"]' - ) - ).toBeTruthy(); + await screen.findByRole('button', { + name: 'downloadStatus.resume {filename:test-file-3}', + }) + ).toBeInTheDocument(); }); - it('sends resume restore request when resume button is clicked', async () => { - const wrapper = mount( -
- -
+ it('should send resume restore request when resume button is clicked', async () => { + renderComponent(); + + await flushPromises(); + + expect( + screen.getByRole('button', { + name: 'downloadStatus.resume {filename:test-file-5}', + }) + ).toBeInTheDocument(); + + (fetchAdminDownloads as jest.Mock).mockImplementation( + ( + settings: { facilityName: string; downloadApiUrl: string }, + queryOffset?: string + ) => { + //Only return the 5 results when initialy requesting so that only a total + //of 5 results will be loaded + if (queryOffset?.endsWith('LIMIT 0, 50')) + return Promise.resolve( + mockDownloadItems.map((d) => + d.id === 5 + ? { + ...d, + isDeleted: false, + status: 'RESTORING', + } + : d + ) + ); + return Promise.resolve([]); + } ); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.click( + screen.getByRole('button', { + name: 'downloadStatus.resume {filename:test-file-5}', + }) + ); - await act(async () => { - wrapper - .find( - 'button[aria-label="downloadStatus.resume {filename:test-file-5}"]' - ) - .simulate('click'); - await flushPromises(); - wrapper.update(); - }); + await flushPromises(); - expect(adminDownloadStatus).toHaveBeenCalledWith(5, 'RESTORING', { - downloadApiUrl: '', - facilityName: '', - }); expect( - wrapper.exists( - '[aria-label="downloadStatus.pause {filename:test-file-5}"]' - ) - ).toBeTruthy(); + await screen.findByRole('button', { + name: 'downloadStatus.pause {filename:test-file-5}', + }) + ).toBeInTheDocument(); }); - it('sends delete item request when delete button is clicked', async () => { - const wrapper = mount( -
- -
+ it('should send delete item request when delete button is clicked', async () => { + renderComponent(); + + await flushPromises(); + + await waitFor(async () => { + expect( + await screen.findByRole('button', { + name: 'downloadStatus.delete {filename:test-file-1}', + }) + ).toBeInTheDocument(); + }); + + (fetchAdminDownloads as jest.Mock).mockImplementation( + ( + settings: { facilityName: string; downloadApiUrl: string }, + queryOffset?: string + ) => { + //Only return the 5 results when initialy requesting so that only a total + //of 5 results will be loaded + if (queryOffset?.endsWith('LIMIT 0, 50')) + return Promise.resolve( + mockDownloadItems.map((d) => + d.id === 1 + ? { + ...d, + isDeleted: true, + } + : d + ) + ); + return Promise.resolve([]); + } ); - await act(async () => { - await flushPromises(); - wrapper.update(); + await user.click( + await screen.findByRole('button', { + name: 'downloadStatus.delete {filename:test-file-1}', + }) + ); + + expect( + await screen.findByRole('button', { + name: 'downloadStatus.restore {filename:test-file-1}', + }) + ).toBeInTheDocument(); + }); + + it('should display progress ui if enabled', async () => { + ( + getPercentageComplete as jest.MockedFunction + ).mockResolvedValue(30); + + renderComponent({ + settings: { + ...mockedSettings, + uiFeatures: { + downloadProgress: true, + }, + }, + }); + + await waitFor(() => { + for (const progressBar of screen.getAllByRole('progressbar')) { + expect(progressBar).toBeInTheDocument(); + } + for (const progressText of screen.getAllByText('30%')) { + expect(progressText).toBeInTheDocument(); + } }); + }); - wrapper - .find('button[aria-label="downloadStatus.delete {filename:test-file-1}"]') - .simulate('click'); + it('should refresh download progress when refresh button is clicked', async () => { + ( + getPercentageComplete as jest.MockedFunction + ).mockResolvedValue(30); - await act(async () => { - await flushPromises(); - wrapper.update(); + renderComponent({ + settings: { + ...mockedSettings, + uiFeatures: { + downloadProgress: true, + }, + }, }); - expect(adminDownloadDeleted).toHaveBeenCalledWith(1, true, { - downloadApiUrl: '', - facilityName: '', + await waitFor(() => { + for (const progressBar of screen.getAllByRole('progressbar')) { + expect(progressBar).toBeInTheDocument(); + } + for (const progressText of screen.getAllByText('30%')) { + expect(progressText).toBeInTheDocument(); + } + }); + + // pretend the server returns an updated value + ( + getPercentageComplete as jest.MockedFunction + ).mockResolvedValue(50); + + await user.click( + screen.getByRole('button', { + name: 'downloadTab.refresh_download_status_arialabel', + }) + ); + + await waitFor(() => { + for (const progressBar of screen.getAllByRole('progressbar')) { + expect(progressBar).toBeInTheDocument(); + } + for (const progressText of screen.getAllByText('50%')) { + expect(progressText).toBeInTheDocument(); + } }); - expect( - wrapper.exists( - '[aria-label="downloadStatus.restore {filename:test-file-1}"]' - ) - ).toBeTruthy(); }); }); diff --git a/packages/datagateway-download/src/downloadStatus/adminDownloadStatusTable.component.tsx b/packages/datagateway-download/src/downloadStatus/adminDownloadStatusTable.component.tsx index 031e9aab0..6752b35b6 100644 --- a/packages/datagateway-download/src/downloadStatus/adminDownloadStatusTable.component.tsx +++ b/packages/datagateway-download/src/downloadStatus/adminDownloadStatusTable.component.tsx @@ -1,21 +1,18 @@ -import React, { useCallback, useMemo } from 'react'; +import React, { useCallback, useRef } from 'react'; import { CircularProgress, - createStyles, Grid, IconButton, LinearProgress, Paper, + styled, Typography, - Theme, - StyleRules, - withStyles, -} from '@material-ui/core'; +} from '@mui/material'; import { DateColumnFilter, DateFilter, - Download, + DownloadStatus, formatBytes, FormattedDownload, Order, @@ -27,33 +24,32 @@ import { import { useTranslation } from 'react-i18next'; import { IndexRange, TableCellProps } from 'react-virtualized'; -import { DownloadSettingsContext } from '../ConfigProvider'; -import { - adminDownloadDeleted, - adminDownloadStatus, - fetchAdminDownloads, -} from '../downloadApi'; import { PauseCircleFilled, PlayCircleFilled, + Refresh, RemoveCircle, Restore, -} from '@material-ui/icons'; -import RefreshIcon from '@material-ui/icons/Refresh'; +} from '@mui/icons-material'; import BlackTooltip from '../tooltip.component'; import { toDate } from 'date-fns-tz'; import { format } from 'date-fns'; +import { + QueryKey, + useAdminDownloadDeleted, + useAdminDownloads, + useAdminUpdateDownloadStatus, +} from '../downloadApiHooks'; +import { DownloadSettingsContext } from '../ConfigProvider'; +import useDownloadFormatter from './hooks/useDownloadFormatter'; +import DownloadProgressIndicator from './downloadProgressIndicator.component'; +import { useQueryClient } from 'react-query'; -const paperStyles = (theme: Theme): StyleRules => - createStyles({ - root: { - flexGrow: 1, - backgroundColor: theme.palette.background.default, - overflow: 'hidden', - }, - }); - -const StyledPaper = withStyles(paperStyles)(Paper); +const StyledPaper = styled(Paper)(({ theme }) => ({ + flexGrow: 1, + backgroundColor: theme.palette.background.default, + overflow: 'hidden', +})); const AdminDownloadStatusTable: React.FC = () => { // Load the settings for use @@ -67,23 +63,15 @@ const AdminDownloadStatusTable: React.FC = () => { | { value?: string | number; type: string } | { startDate?: string; endDate?: string }; }>({}); - const [data, setData] = React.useState([]); - const [dataLoaded, setDataLoaded] = React.useState(false); const [refreshDownloads, setRefreshDownloads] = React.useState(false); - const [lastChecked, setLastChecked] = React.useState( - new Date().toLocaleString() - ); const [t] = useTranslation(); - const dgDownloadElement = document.getElementById('datagateway-download'); - const downloadStatuses: { [key: string]: string } = useMemo(() => { - return { - COMPLETE: t('downloadStatus.complete'), - EXPIRED: t('downloadStatus.expired'), - PAUSED: t('downloadStatus.paused'), - PREPARING: t('downloadStatus.preparing'), - RESTORING: t('downloadStatus.restoring'), - }; - }, [t]); + const { formatDownload } = useDownloadFormatter(); + const { downloadStatusLabels: downloadStatuses } = useDownloadFormatter(); + const { mutate: adminDownloadDeleted } = useAdminDownloadDeleted(); + const { mutate: adminUpdateDownloadStatus } = useAdminUpdateDownloadStatus(); + const queryClient = useQueryClient(); + // whether this is component's first render. + const isFirstRender = useRef(true); const buildQueryOffset = useCallback(() => { let queryOffset = `WHERE download.facilityName = '${settings.facilityName}'`; @@ -91,8 +79,12 @@ const AdminDownloadStatusTable: React.FC = () => { if (typeof filter === 'object') { if (!Array.isArray(filter)) { if ('startDate' in filter || 'endDate' in filter) { - const startDate = filter.startDate ?? '0001-01-01 00:00'; - const endDate = filter.endDate ?? '9999-12-31 23:59'; + const startDate = filter.startDate + ? `${filter.startDate}` + : '0001-01-01 00:00:00'; + const endDate = filter.endDate + ? `${filter.endDate}` + : '9999-12-31 23:59:00'; queryOffset += ` AND download.${column} BETWEEN {ts '${startDate}'} AND {ts '${endDate}'}`; } @@ -123,102 +115,60 @@ const AdminDownloadStatusTable: React.FC = () => { return queryOffset; }, [filters, settings.facilityName, sort]); - const formatDownloads = useCallback( - (downloads: Download[]) => { - return downloads.map((download) => { - const formattedIsDeleted = download.isDeleted ? 'Yes' : 'No'; - const formattedStatus = - download.status in downloadStatuses - ? downloadStatuses[download.status] - : ''; - - return { - ...download, - isDeleted: formattedIsDeleted, - status: formattedStatus, - }; - }); - }, - [downloadStatuses] - ); - - const fetchInitialData = useCallback(() => { - const queryOffset = buildQueryOffset() + ' LIMIT 0, 50'; - return fetchAdminDownloads( - { - facilityName: settings.facilityName, - downloadApiUrl: settings.downloadApiUrl, - }, - queryOffset - ).then((downloads) => { - const formattedDownloads = formatDownloads(downloads); - setData([...formattedDownloads]); - }); - }, [ - buildQueryOffset, - formatDownloads, - settings.downloadApiUrl, - settings.facilityName, - ]); + const { + data, + isLoading, + isFetched, + isRefetching, + fetchNextPage, + refetch: refetchDownloads, + dataUpdatedAt, + } = useAdminDownloads({ + initialQueryOffset: `${buildQueryOffset()} LIMIT 0, 50`, + }); const fetchMoreData = useCallback( - (offsetParams: IndexRange) => { - let queryOffset = buildQueryOffset(); - queryOffset += ` LIMIT ${offsetParams.startIndex}, ${ - offsetParams.stopIndex - offsetParams.startIndex + 1 - }`; - - setDataLoaded(false); - return fetchAdminDownloads( - { - facilityName: settings.facilityName, - downloadApiUrl: settings.downloadApiUrl, - }, - queryOffset - ).then((downloads) => { - const formattedDownloads = formatDownloads(downloads); - setData([...data, ...formattedDownloads]); - setDataLoaded(true); - }); - }, - [ - buildQueryOffset, - data, - formatDownloads, - settings.downloadApiUrl, - settings.facilityName, - ] + (offsetParams: IndexRange) => + fetchNextPage({ + pageParam: `${buildQueryOffset()} LIMIT ${offsetParams.startIndex}, ${ + offsetParams.stopIndex - offsetParams.startIndex + 1 + }`, + }), + [buildQueryOffset, fetchNextPage] ); + const refreshTable = useCallback(async () => { + await Promise.all([ + // mark download progress queries as invalid so that react-query will refetch them as well. + queryClient.invalidateQueries(QueryKey.DOWNLOAD_PROGRESS), + refetchDownloads(), + ]); + setRefreshDownloads(false); + }, [queryClient, refetchDownloads]); + React.useEffect(() => { - // Clear the current contents, this will make sure - // there is visually a refresh of the table - setData([]); - - if (dgDownloadElement) { - setDataLoaded(false); - fetchInitialData(); - setDataLoaded(true); + if (refreshDownloads && isFetched) { + // user requested to refresh table + refreshTable(); } - }, [ - settings.facilityName, - settings.downloadApiUrl, - dgDownloadElement, - filters, - sort, - fetchInitialData, - ]); + }, [isFetched, refreshDownloads, refreshTable]); React.useEffect(() => { - if (refreshDownloads) { - setData([]); - setDataLoaded(false); - setRefreshDownloads(false); - fetchInitialData(); - setLastChecked(new Date().toLocaleString()); - setDataLoaded(true); + // useEffect is always called on first render + // we don't want to refetch when the initial fetch is already going + // we only want to refetch when sort and filters changes + // + // here we use a ref that is true on first render + // and we use that to check if this effect is run on first render + // if it is true, set it to false, + // so that subsequent calls of this effect due to sort and filters changes + // will allow refetch. + if (!isFirstRender.current) { + refetchDownloads({ cancelRefetch: true }); + } else { + isFirstRender.current = false; } - }, [fetchInitialData, refreshDownloads]); + }, [refetchDownloads, sort, filters]); const textFilter = (label: string, dataKey: string): React.ReactElement => ( { onChange={(value: { value?: string | number; type: string } | null) => { if (value) { if (dataKey === 'status') { - const downloadStatus = Object.keys(downloadStatuses).find( + const downloadStatus = ( + Object.keys(downloadStatuses) as DownloadStatus[] + ).find( (key) => downloadStatuses[key].toLowerCase() === (value.value as string).toLowerCase() @@ -234,8 +186,11 @@ const AdminDownloadStatusTable: React.FC = () => { if (typeof downloadStatus !== 'undefined') { value.value = downloadStatus; } + + setFilters({ ...filters, status: value }); + } else { + setFilters({ ...filters, [dataKey]: value }); } - setFilters({ ...filters, [dataKey]: value }); } else { const { [dataKey]: value, ...restOfFilters } = filters; setFilters(restOfFilters); @@ -261,6 +216,11 @@ const AdminDownloadStatusTable: React.FC = () => { /> ); + const tableItems = React.useMemo( + () => data?.pages.flatMap((page) => page.map(formatDownload)) ?? [], + [data?.pages, formatDownload] + ); + return ( @@ -288,8 +248,9 @@ const AdminDownloadStatusTable: React.FC = () => { 'downloadTab.refresh_download_status_arialabel' )} onClick={() => setRefreshDownloads(true)} + size="large" > - + ) : ( @@ -298,7 +259,10 @@ const AdminDownloadStatusTable: React.FC = () => { {!refreshDownloads ? (

- {t('downloadTab.last_checked')}: {lastChecked} + {t('downloadTab.last_checked')}: {' '} + {dataUpdatedAt > 0 + ? new Date(dataUpdatedAt).toLocaleString() + : ''}

) : (

@@ -310,16 +274,19 @@ const AdminDownloadStatusTable: React.FC = () => { {/* Show loading progress if data is still being loaded */} - {!dataLoaded && ( + {(isLoading || isRefetching) && ( )} + {/* Table should take up page but leave room for: SG appbar, SG footer, + tabs, admin header, table padding, text above table, and the LinearProgress above (respectively). */} { label: t('downloadStatus.status'), dataKey: 'status', filterComponent: textFilter, + cellContentRenderer: ({ rowData }) => + (rowData as FormattedDownload).formattedStatus, }, + ...(settings.uiFeatures.downloadProgress + ? [ + { + label: t('downloadStatus.progress'), + dataKey: 'progress', + disableSort: true, + cellContentRenderer: ({ + rowData, + }: TableCellProps) => ( + + ), + }, + ] + : []), { label: t('downloadStatus.size'), dataKey: 'size', @@ -369,7 +354,9 @@ const AdminDownloadStatusTable: React.FC = () => { dataKey: 'createdAt', cellContentRenderer: (props: TableCellProps) => { if (props.cellData) { - const date = toDate(props.cellData); + const date = toDate( + props.cellData.replace(/\[.*]/, '') + ); return format(date, 'yyyy-MM-dd HH:mm:ss'); } }, @@ -378,19 +365,28 @@ const AdminDownloadStatusTable: React.FC = () => { { label: t('downloadStatus.deleted'), dataKey: 'isDeleted', + cellContentRenderer: ({ rowData }) => + (rowData as FormattedDownload).formattedIsDeleted, }, ]} sort={sort} - onSort={(column: string, order: 'desc' | 'asc' | null) => { + onSort={( + column: string, + order: 'desc' | 'asc' | null, + _, + shiftDown?: boolean + ) => { if (order) { - setSort({ ...sort, [column]: order }); + shiftDown + ? setSort({ ...sort, [column]: order }) + : setSort({ [column]: order }); } else { const { [column]: order, ...restOfSort } = sort; setSort(restOfSort); } }} - data={data} - loading={!dataLoaded} + data={tableItems} + loading={isLoading} loadMoreRows={fetchMoreData} totalRowCount={Number.MAX_SAFE_INTEGER} actionsWidth={100} @@ -401,7 +397,7 @@ const AdminDownloadStatusTable: React.FC = () => { downloadItem.isDeleted ); - if (isDeleted === 'No') { + if (!isDeleted) { return null; } @@ -412,39 +408,12 @@ const AdminDownloadStatusTable: React.FC = () => { })} key="restore" size="small" - onClick={() => { - adminDownloadDeleted( - downloadItem.id as number, - false, - { - facilityName: settings.facilityName, - downloadApiUrl: settings.downloadApiUrl, - } - ).then(() => { - // Get the new status and isDeleted state of the download item - fetchAdminDownloads( - { - facilityName: settings.facilityName, - downloadApiUrl: settings.downloadApiUrl, - }, - `WHERE download.id = ${downloadItem.id}` - ).then((downloads) => { - const formattedDownload = formatDownloads( - downloads - )[0]; - downloadItem.status = formattedDownload.status; - downloadItem.isDeleted = - formattedDownload.isDeleted; - setData( - data.map((download) => - download.id === downloadItem.id - ? { ...download, ...downloadItem } - : download - ) - ); - }); - }); - }} + onClick={() => + adminDownloadDeleted({ + downloadId: downloadItem.id, + deleted: false, + }) + } > @@ -457,7 +426,7 @@ const AdminDownloadStatusTable: React.FC = () => { downloadItem.isDeleted ); - if (isDeleted === 'Yes') { + if (isDeleted) { return null; } @@ -468,25 +437,12 @@ const AdminDownloadStatusTable: React.FC = () => { })} key="delete" size="small" - onClick={() => { - adminDownloadDeleted( - downloadItem.id as number, - true, - { - facilityName: settings.facilityName, - downloadApiUrl: settings.downloadApiUrl, - } - ).then(() => { - downloadItem.isDeleted = 'Yes'; - setData( - data.map((download) => - download.id === downloadItem.id - ? { ...download, ...downloadItem } - : download - ) - ); - }); - }} + onClick={() => + adminDownloadDeleted({ + downloadId: downloadItem.id, + deleted: true, + }) + } > @@ -500,10 +456,10 @@ const AdminDownloadStatusTable: React.FC = () => { ); if ( - isDeleted === 'Yes' || - downloadItem.status === t('downloadStatus.complete') || - downloadItem.status === t('downloadStatus.expired') || - downloadItem.status !== t('downloadStatus.paused') + isDeleted || + downloadItem.status === 'COMPLETE' || + downloadItem.status === 'EXPIRED' || + downloadItem.status !== 'PAUSED' ) { return null; } @@ -515,27 +471,12 @@ const AdminDownloadStatusTable: React.FC = () => { })} key="resume" size="small" - onClick={() => { - adminDownloadStatus( - downloadItem.id as number, - 'RESTORING', - { - facilityName: settings.facilityName, - downloadApiUrl: settings.downloadApiUrl, - } - ).then(() => { - downloadItem.status = t( - 'downloadStatus.restoring' - ); - setData( - data.map((download) => - download.id === downloadItem.id - ? { ...download, ...downloadItem } - : download - ) - ); - }); - }} + onClick={() => + adminUpdateDownloadStatus({ + downloadId: downloadItem.id, + status: 'RESTORING', + }) + } > @@ -549,10 +490,10 @@ const AdminDownloadStatusTable: React.FC = () => { ); if ( - isDeleted === 'Yes' || - downloadItem.status === t('downloadStatus.complete') || - downloadItem.status === t('downloadStatus.expired') || - downloadItem.status === t('downloadStatus.paused') + isDeleted || + downloadItem.status === 'COMPLETE' || + downloadItem.status === 'EXPIRED' || + downloadItem.status === 'PAUSED' ) { return null; } @@ -564,25 +505,12 @@ const AdminDownloadStatusTable: React.FC = () => { })} key="pause" size="small" - onClick={() => { - adminDownloadStatus( - downloadItem.id as number, - 'PAUSED', - { - facilityName: settings.facilityName, - downloadApiUrl: settings.downloadApiUrl, - } - ).then(() => { - downloadItem.status = t('downloadStatus.paused'); - setData( - data.map((download) => - download.id === downloadItem.id - ? { ...download, ...downloadItem } - : download - ) - ); - }); - }} + onClick={() => + adminUpdateDownloadStatus({ + downloadId: downloadItem.id, + status: 'PAUSED', + }) + } > diff --git a/packages/datagateway-download/src/downloadStatus/downloadProgressIndicator.component.test.tsx b/packages/datagateway-download/src/downloadStatus/downloadProgressIndicator.component.test.tsx new file mode 100644 index 000000000..3d0ef687b --- /dev/null +++ b/packages/datagateway-download/src/downloadStatus/downloadProgressIndicator.component.test.tsx @@ -0,0 +1,183 @@ +import * as React from 'react'; +import { render, screen, RenderResult, waitFor } from '@testing-library/react'; +import type { Download } from 'datagateway-common'; +import { DownloadSettingsContext } from '../ConfigProvider'; +import { getDownload, getPercentageComplete } from '../downloadApi'; +import DownloadProgressIndicator from './downloadProgressIndicator.component'; +import { QueryClient, QueryClientProvider, setLogger } from 'react-query'; +import { mockedSettings, mockDownloadItems } from '../testData'; + +jest.mock('../downloadApi'); + +// silence react-query errors +setLogger({ + log: console.log, + warn: console.warn, + error: jest.fn(), +}); + +const createTestQueryClient = (): QueryClient => + new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }); + +const mockDownload: Download = { + ...mockDownloadItems[0], + status: 'RESTORING', +}; + +function renderComponent({ download = mockDownload } = {}): RenderResult { + return render( + + + + + + ); +} + +describe('DownloadProgressIndicator', () => { + describe('should show calculating text', () => { + it('when querying the download progress', async () => { + ( + getPercentageComplete as jest.MockedFunction< + typeof getPercentageComplete + > + ).mockReturnValue( + new Promise(() => { + // do nothing, pretend this is loading + }) + ); + + renderComponent(); + + expect( + await screen.findByText('downloadStatus.calculating_progress') + ).toBeInTheDocument(); + expect(screen.queryByText('20%')).toBeNull(); + }); + }); + + describe('should show the progress as complete', () => { + it('when download is completed', async () => { + ( + getDownload as jest.MockedFunction + ).mockResolvedValue({ + ...mockDownloadItems[0], + status: 'COMPLETE', + }); + + renderComponent({ + download: { + ...mockDownload, + status: 'COMPLETE', + }, + }); + + expect( + await screen.findByText('downloadStatus.progress_complete') + ).toBeInTheDocument(); + // should not show progress bar + expect(screen.queryByRole('progressbar')).toBeNull(); + }); + + it('when download is expired', async () => { + ( + getDownload as jest.MockedFunction + ).mockResolvedValue({ + ...mockDownloadItems[0], + status: 'EXPIRED', + }); + + renderComponent({ + download: { + ...mockDownload, + status: 'EXPIRED', + }, + }); + + expect( + await screen.findByText('downloadStatus.progress_complete') + ).toBeInTheDocument(); + // should not show progress bar + expect(screen.queryByRole('progressbar')).toBeNull(); + }); + }); + + describe('should show unavailable', () => { + it('when progress is unavailable', async () => { + ( + getPercentageComplete as jest.MockedFunction< + typeof getPercentageComplete + > + ).mockRejectedValue({ + message: 'test error', + }); + + renderComponent(); + + expect( + await screen.findByText('downloadStatus.progress_unavailable') + ).toBeInTheDocument(); + }); + }); + + it('should show progress at 0% when the download is being prepared', async () => { + renderComponent({ + download: { + ...mockDownload, + status: 'PREPARING', + }, + }); + + const progressBar = await screen.findByRole('progressbar'); + expect(progressBar).toBeInTheDocument(); + expect(progressBar).toHaveAttribute('aria-valuenow', '0'); + expect(screen.getByText('0%')).toBeInTheDocument(); + }); + + it('should show progress of the given download item', async () => { + ( + getPercentageComplete as jest.MockedFunction + ).mockResolvedValue(20); + + renderComponent(); + + await waitFor(async () => { + const progressBar = await screen.findByRole('progressbar'); + expect(progressBar).toBeInTheDocument(); + expect(progressBar).toHaveAttribute('aria-valuenow', '20'); + }); + expect(screen.getByText('20%')).toBeInTheDocument(); + }); + + it('should show progress at 99% if the download is being restored but server returns 100% progress', async () => { + ( + getPercentageComplete as jest.MockedFunction + ).mockResolvedValue(100); + + renderComponent(); + + const progressBar = await screen.findByRole('progressbar'); + expect(progressBar).toBeInTheDocument(); + expect(progressBar).toHaveAttribute('aria-valuenow', '99'); + expect(screen.getByText('99%')).toBeInTheDocument(); + }); + + it('should show progress status if the server does not return a number', async () => { + ( + getPercentageComplete as jest.MockedFunction + ).mockResolvedValue('INVALID'); + + renderComponent(); + + await waitFor(() => { + expect(screen.queryByRole('progressbar')).toBeNull(); + }); + expect(await screen.findByText('INVALID')).toBeInTheDocument(); + }); +}); diff --git a/packages/datagateway-download/src/downloadStatus/downloadProgressIndicator.component.tsx b/packages/datagateway-download/src/downloadStatus/downloadProgressIndicator.component.tsx new file mode 100644 index 000000000..69649dcad --- /dev/null +++ b/packages/datagateway-download/src/downloadStatus/downloadProgressIndicator.component.tsx @@ -0,0 +1,75 @@ +import { Box, LinearProgress, Typography } from '@mui/material'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import type { Download } from 'datagateway-common'; +import { useDownloadPercentageComplete } from '../downloadApiHooks'; + +interface DownloadProgressIndicatorProps { + download: Download; +} + +/** + * A component for showing the download progress of the given download item. + * + * @param download The download item that this component should show the progress of. + * @constructor + */ +function DownloadProgressIndicator({ + download, +}: DownloadProgressIndicatorProps): JSX.Element { + const [t] = useTranslation(); + const { data: progress, isLoading: isLoadingProgress } = + useDownloadPercentageComplete({ + download, + enabled: download.status === 'RESTORING' || download.status === 'PAUSED', + }); + + if (isLoadingProgress) { + return <>{t('downloadStatus.calculating_progress')}; + } + + // if the download is already completed/restored + // should show text such as N/A, completed, or empty string. + // depending on the translation configuration. + if (download.status === 'COMPLETE' || download.status === 'EXPIRED') + return <>{t('downloadStatus.progress_complete')}; + + // if the download is being prepared, show 0% + if (download.status === 'PREPARING') return ; + + // display a label indicating progress unavailable when + // progress is not returned or the download status doesn't match. + if (typeof progress === 'undefined') + return <>{t('downloadStatus.progress_unavailable')}; + + if (typeof progress === 'number') { + if (progress === 100) { + // confusing to show the user 100% when the status doesn't show complete + // progress is shown at 99% to indicate there is work still being done + // to avoid confusion + return ; + } + + return ; + } + + // server returned a status string, show it to the user. + return <>{progress}; +} + +function ProgressBar({ progress }: { progress: number }): JSX.Element { + return ( + + + + + + + {progress}% + + + + ); +} + +export default DownloadProgressIndicator; diff --git a/packages/datagateway-download/src/downloadStatus/downloadStatusTable.component.test.tsx b/packages/datagateway-download/src/downloadStatus/downloadStatusTable.component.test.tsx index 59c76b4be..775a4af2c 100644 --- a/packages/datagateway-download/src/downloadStatus/downloadStatusTable.component.test.tsx +++ b/packages/datagateway-download/src/downloadStatus/downloadStatusTable.component.test.tsx @@ -1,516 +1,436 @@ -import React from 'react'; +import { render, RenderResult, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; +import { QueryClient, QueryClientProvider } from 'react-query'; +import { + downloadDeleted, + fetchDownloads, + getDataUrl, + getPercentageComplete, +} from '../downloadApi'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, +} from '../setupTests'; import DownloadStatusTable from './downloadStatusTable.component'; -import { createShallow, createMount } from '@material-ui/core/test-utils'; -import { flushPromises } from '../setupTests'; -import { act } from 'react-dom/test-utils'; -import { fetchDownloads, downloadDeleted, getDataUrl } from '../downloadApi'; -import { Download } from 'datagateway-common'; +import { mockDownloadItems, mockedSettings } from '../testData'; +import { DownloadSettingsContext } from '../ConfigProvider'; jest.mock('../downloadApi'); -const RefreshHOC: React.FC<{ refresh: boolean }> = (props: { - refresh: boolean; -}): React.ReactElement => { - const [refreshTable, setRefreshTable] = React.useState(false); - - React.useEffect(() => { - setRefreshTable(props.refresh); - }, [props.refresh]); - - return ( -

- -
+const createTestQueryClient = (): QueryClient => + new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }); + +const renderComponent = ({ + settings = mockedSettings, + queryClient = createTestQueryClient(), +} = {}): RenderResult => + render( + + + + + ); -}; describe('Download Status Table', () => { - let shallow; - let mount; - - const downloadItems: Download[] = [ - { - createdAt: '2020-02-25T15:05:29Z', - downloadItems: [{ entityId: 1, entityType: 'investigation', id: 1 }], - email: 'test1@email.com', - facilityName: 'LILS', - fileName: 'test-file-1', - fullName: 'Person 1', - id: 1, - isDeleted: false, - isEmailSent: true, - isTwoLevel: false, - preparedId: 'test-prepared-id', - sessionId: 'test-session-id', - size: 1000, - status: 'COMPLETE', - transport: 'https', - userName: 'test user', - }, - { - createdAt: '2020-02-26T15:05:35Z', - downloadItems: [{ entityId: 2, entityType: 'investigation', id: 2 }], - email: 'test2@email.com', - facilityName: 'LILS', - fileName: 'test-file-2', - fullName: 'Person 2', - id: 2, - isDeleted: false, - isEmailSent: true, - isTwoLevel: false, - preparedId: 'test-prepared-id', - sessionId: 'test-session-id', - size: 2000, - status: 'PREPARING', - transport: 'globus', - userName: 'test user', - }, - { - createdAt: '2020-02-27T15:57:20Z', - downloadItems: [{ entityId: 3, entityType: 'investigation', id: 3 }], - email: 'test3@email.com', - facilityName: 'LILS', - fileName: 'test-file-3', - fullName: 'Person 3', - id: 3, - isDeleted: false, - isEmailSent: true, - isTwoLevel: false, - preparedId: 'test-prepared-id', - sessionId: 'test-session-id', - size: 3000, - status: 'RESTORING', - transport: 'https', - userName: 'test user', - }, - { - createdAt: '2020-02-28T15:57:28Z', - downloadItems: [{ entityId: 4, entityType: 'investigation', id: 4 }], - email: 'test4@email.com', - facilityName: 'LILS', - fileName: 'test-file-4', - fullName: 'Person 4', - id: 4, - isDeleted: false, - isEmailSent: true, - isTwoLevel: false, - preparedId: 'test-prepared-id', - sessionId: 'test-session-id', - size: 4000, - status: 'EXPIRED', - transport: 'globus', - userName: 'test user', - }, - { - createdAt: '2020-03-01T15:57:28Z[UTC]', - downloadItems: [{ entityId: 5, entityType: 'investigation', id: 5 }], - email: 'test5@email.com', - facilityName: 'LILS', - fileName: 'test-file-5', - fullName: 'Person 5', - id: 5, - isDeleted: false, - isEmailSent: true, - isTwoLevel: false, - preparedId: 'test-prepared-id', - sessionId: 'test-session-id', - size: 5000, - status: 'PAUSED', - transport: 'globus', - userName: 'test user', - }, - ]; + let user: ReturnType; beforeEach(() => { - shallow = createShallow({ untilSelector: 'div' }); - mount = createMount(); + user = userEvent.setup({ delay: null }); + (downloadDeleted as jest.Mock).mockImplementation(() => Promise.resolve()); (fetchDownloads as jest.Mock).mockImplementation(() => - Promise.resolve(downloadItems) + Promise.resolve(mockDownloadItems) ); (getDataUrl as jest.Mock).mockImplementation(() => '/getData'); }); afterEach(() => { - mount.cleanUp(); - (fetchDownloads as jest.Mock).mockClear(); - (downloadDeleted as jest.Mock).mockClear(); - (getDataUrl as jest.Mock).mockClear(); + jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = shallow( - - ); - expect(wrapper).toMatchSnapshot(); + it('should render correctly', () => { + const { asFragment } = renderComponent(); + expect(asFragment()).toMatchSnapshot(); }); - it('translates the status strings correctly', async () => { - const wrapper = mount( -
- -
- ); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + it('should translate the status strings correctly', async () => { + renderComponent(); expect( - wrapper.find('[aria-rowindex=1]').find('[aria-colindex=3]').text() - ).toEqual('downloadStatus.paused'); + await screen.findByText('downloadStatus.paused') + ).toBeInTheDocument(); expect( - wrapper.find('[aria-rowindex=2]').find('[aria-colindex=3]').text() - ).toEqual('downloadStatus.expired'); + await screen.findByText('downloadStatus.expired') + ).toBeInTheDocument(); expect( - wrapper.find('[aria-rowindex=3]').find('[aria-colindex=3]').text() - ).toEqual('downloadStatus.restoring'); + await screen.findByText('downloadStatus.restoring') + ).toBeInTheDocument(); expect( - wrapper.find('[aria-rowindex=4]').find('[aria-colindex=3]').text() - ).toEqual('downloadStatus.preparing'); + await screen.findByText('downloadStatus.preparing') + ).toBeInTheDocument(); expect( - wrapper.find('[aria-rowindex=5]').find('[aria-colindex=3]').text() - ).toEqual('downloadStatus.complete'); - }); - - it('fetches the download items on load', async () => { - const wrapper = mount( -
- -
- ); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - - expect(fetchDownloads).toHaveBeenCalled(); + await screen.findByText('downloadStatus.complete') + ).toBeInTheDocument(); }); - it('refreshes the tables when the refresh button has been clicked', async () => { - // Use our RefreshHOC and only modify the refresh prop - // we pass on to the DownloadStatusTable. - const wrapper = mount(); - - await act(async () => { - await flushPromises(); - wrapper.update(); + it('should refresh data & download progress when required', async () => { + ( + getPercentageComplete as jest.MockedFunction + ).mockResolvedValue(30); + const settings = { + ...mockedSettings, + uiFeatures: { + downloadProgress: true, + }, + }; + + const queryClient = createTestQueryClient(); + const { rerender } = renderComponent({ settings, queryClient }); + + expect(await screen.findByText('test-file-1')).toBeInTheDocument(); + expect(await screen.findByText('test-file-2')).toBeInTheDocument(); + expect(await screen.findByText('test-file-3')).toBeInTheDocument(); + expect(await screen.findByText('test-file-4')).toBeInTheDocument(); + expect(await screen.findByText('test-file-5')).toBeInTheDocument(); + + await waitFor(() => { + for (const progressBar of screen.getAllByRole('progressbar')) { + expect(progressBar).toBeInTheDocument(); + } + for (const progressText of screen.getAllByText('30%')) { + expect(progressText).toBeInTheDocument(); + } }); - // Set the refresh prop to false. - expect(wrapper.prop('refresh')).toBe(false); + // pretend server returned a different list (with only the restoring download) + (fetchDownloads as jest.Mock).mockReturnValueOnce([mockDownloadItems[2]]); + // pretend the server returns an updated value + ( + getPercentageComplete as jest.MockedFunction + ).mockResolvedValue(50); + rerender( + + + + + + ); - await act(async () => { - // Set the refresh prop to true. - wrapper.setProps({ refresh: true }); + await waitFor(() => { + expect(screen.getByText('test-file-3')).toBeInTheDocument(); + expect(screen.queryByText('test-file-1')).toBeNull(); + expect(screen.queryByText('test-file-2')).toBeNull(); + expect(screen.queryByText('test-file-4')).toBeNull(); + expect(screen.queryByText('test-file-5')).toBeNull(); - await flushPromises(); - wrapper.update(); + expect(screen.getByRole('progressbar')).toBeInTheDocument(); + expect(screen.getByText('50%')).toBeInTheDocument(); }); - - expect(wrapper.prop('refresh')).toBe(true); - - // Expect the downloads to have been fetched twice (on load and on refresh). - expect(fetchDownloads).toHaveBeenCalledTimes(2); }); it('should have a link for a download item', async () => { - const wrapper = mount( -
- -
- ); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + renderComponent(); // Expect globus download items to have been disabled. expect( - wrapper - .find( - 'button[aria-label="downloadStatus.download {filename:test-file-2}"]' - ) - .prop('disabled') - ).toBe(true); + await screen.findByRole('button', { + name: 'downloadStatus.download {filename:test-file-2}', + }) + ).toBeDisabled(); // Expect HTTPS download items with non-COMPLETE status to have been disabled. expect( - wrapper - .find( - 'button[aria-label="downloadStatus.download {filename:test-file-3}"]' - ) - .prop('disabled') - ).toBe(true); + await screen.findByRole('button', { + name: 'downloadStatus.download {filename:test-file-3}', + }) + ).toBeDisabled(); // Expect complete HTTPS download items to be downloadable // Check to see if the href contains the correct call. expect( - wrapper - .find('a[aria-label="downloadStatus.download {filename:test-file-1}"]') - .at(0) - .props().href - ).toContain('/getData'); + await screen.findByRole('link', { + name: 'downloadStatus.download {filename:test-file-1}', + }) + ).toHaveAttribute('href', '/getData'); }); - it("removes an item when said item's remove button is clicked", async () => { - const wrapper = mount( -
- -
- ); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + it("should remove an item when said item's remove button is clicked", async () => { + // downloadStatus.remove {filename:test-file-1} + renderComponent(); - wrapper - .find('button[aria-label="downloadStatus.remove {filename:test-file-1}"]') - .simulate('click'); + expect(await screen.findByText('test-file-1')).toBeInTheDocument(); - expect( - wrapper - .find( - 'button[aria-label="downloadStatus.remove {filename:test-file-1}"] svg' - ) - .parent() - .prop('color') - ).toEqual('error'); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.click( + await screen.findByRole('button', { + name: 'downloadStatus.remove {filename:test-file-1}', + }) + ); - expect(downloadDeleted).toHaveBeenCalled(); - expect(downloadDeleted).toHaveBeenCalledWith(1, true, { - downloadApiUrl: '', - facilityName: '', + await waitFor(() => { + expect(screen.queryByText('test-file-1')).toBeNull(); }); - expect( - wrapper.exists( - '[aria-label="downloadStatus.remove {filename:test-file-1}"]' - ) - ).toBe(false); - expect(wrapper.exists('[aria-rowcount=4]')).toBe(true); }); - it('sorts data when headers are clicked', async () => { - const wrapper = mount( -
- -
- ); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + it('should sort data when headers are clicked', async () => { + // use skipHover to avoid triggering sort tooltips which slow the test down + user = userEvent.setup({ delay: null, skipHover: true }); + renderComponent(); // Table is sorted by createdAt desc by default // To keep working test, we will remove all sorts on the table beforehand - const createdAtSortLabel = wrapper - .find('[role="columnheader"] span[role="button"]') - .at(3); - createdAtSortLabel.simulate('click'); - - const firstNameCell = wrapper.find('[aria-colindex=1]').find('p').first(); + await user.click(await screen.findByText('downloadStatus.createdAt')); // Get the access method sort header. - const accessMethodSortLabel = wrapper - .find('[role="columnheader"] span[role="button"]') - .at(1); + const accessMethodSortLabel = screen.getByText('downloadStatus.transport'); - accessMethodSortLabel.simulate('click'); + await user.click(accessMethodSortLabel); - expect(firstNameCell.text()).toEqual('test-file-5'); + // access methods should be in asc order, globus < https + let rows = await screen.findAllByText(/^test-file-\d$/); + expect(rows[0]).toHaveTextContent('test-file-2'); + expect(rows[1]).toHaveTextContent('test-file-4'); + expect(rows[2]).toHaveTextContent('test-file-5'); + expect(rows[3]).toHaveTextContent('test-file-1'); + expect(rows[4]).toHaveTextContent('test-file-3'); - accessMethodSortLabel.simulate('click'); + await user.click(accessMethodSortLabel); - expect(firstNameCell.text()).toEqual('test-file-3'); + // access methods should be in desc order, globus < https + rows = await screen.findAllByText(/^test-file-\d$/); + expect(rows[0]).toHaveTextContent('test-file-1'); + expect(rows[1]).toHaveTextContent('test-file-3'); + expect(rows[2]).toHaveTextContent('test-file-2'); + expect(rows[3]).toHaveTextContent('test-file-4'); + expect(rows[4]).toHaveTextContent('test-file-5'); // Get the download name sort header. - const nameSortLabel = wrapper - .find('[role="columnheader"] span[role="button"]') - .at(0); - - nameSortLabel.simulate('click'); - - expect(firstNameCell.text()).toEqual('test-file-1'); - - nameSortLabel.simulate('click'); - - expect(firstNameCell.text()).toEqual('test-file-3'); - - nameSortLabel.simulate('click'); - - expect(firstNameCell.text()).toEqual('test-file-3'); + const nameSortLabel = screen.getByText('downloadStatus.filename'); + + await user.keyboard('{Shift>}'); + await user.click(nameSortLabel); + await user.keyboard('{/Shift}'); + + // name should be in asc order + rows = await screen.findAllByText(/^test-file-\d$/); + expect(rows[0]).toHaveTextContent('test-file-1'); + expect(rows[1]).toHaveTextContent('test-file-3'); + expect(rows[2]).toHaveTextContent('test-file-2'); + expect(rows[3]).toHaveTextContent('test-file-4'); + expect(rows[4]).toHaveTextContent('test-file-5'); + + await user.keyboard('{Shift>}'); + await user.click(nameSortLabel); + await user.keyboard('{/Shift}'); + + // name should be in desc order + rows = await screen.findAllByText(/^test-file-\d$/); + expect(rows[0]).toHaveTextContent('test-file-3'); + expect(rows[1]).toHaveTextContent('test-file-1'); + expect(rows[2]).toHaveTextContent('test-file-5'); + expect(rows[3]).toHaveTextContent('test-file-4'); + expect(rows[4]).toHaveTextContent('test-file-2'); + + await user.click(accessMethodSortLabel); + + // name should be in desc order + rows = await screen.findAllByText(/^test-file-\d$/); + expect(rows[0]).toHaveTextContent('test-file-5'); + expect(rows[1]).toHaveTextContent('test-file-4'); + expect(rows[2]).toHaveTextContent('test-file-3'); + expect(rows[3]).toHaveTextContent('test-file-2'); + expect(rows[4]).toHaveTextContent('test-file-1'); + + await user.click(accessMethodSortLabel); + + // access methods should be in asc order, globus < https + rows = await screen.findAllByText(/^test-file-\d$/); + expect(rows[0]).toHaveTextContent('test-file-2'); + expect(rows[1]).toHaveTextContent('test-file-4'); + expect(rows[2]).toHaveTextContent('test-file-5'); + expect(rows[3]).toHaveTextContent('test-file-1'); + expect(rows[4]).toHaveTextContent('test-file-3'); }); - it('filters data when text fields are typed into', async () => { - const wrapper = mount( -
- -
- ); + it('should filter data when text fields are typed into', async () => { + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - - const downloadNameFilterInput = wrapper - .find('[aria-label="Filter by downloadStatus.filename"]') - .first(); - downloadNameFilterInput.instance().value = '1'; - downloadNameFilterInput.simulate('change'); - - expect(wrapper.exists('[aria-rowcount=1]')).toBe(true); - expect( - wrapper.exists( - '[aria-label="downloadStatus.remove {filename:test-file-1}"]' - ) - ).toBe(true); + const fileNameFilterBox = await screen.findByLabelText( + 'Filter by downloadStatus.filename' + ); + const downloadMethodFilterBox = await screen.findByLabelText( + 'Filter by downloadStatus.transport' + ); + const downloadStatusFilterBox = await screen.findByLabelText( + 'Filter by downloadStatus.status' + ); - const accessMethodFilterInput = wrapper - .find('[aria-label="Filter by downloadStatus.transport"]') - .first(); + // type into file name filter textbox + await user.type(fileNameFilterBox, '1'); - downloadNameFilterInput.instance().value = ''; - downloadNameFilterInput.simulate('change'); - accessMethodFilterInput.instance().value = 'https'; - accessMethodFilterInput.simulate('change'); + // should only show file-name-1 + expect(await screen.findByText('test-file-1')).toBeInTheDocument(); + expect(screen.queryByText('test-file-2')).toBeNull(); + expect(screen.queryByText('test-file-2')).toBeNull(); + expect(screen.queryByText('test-file-2')).toBeNull(); - expect(wrapper.exists('[aria-rowcount=2]')).toBe(true); - expect( - wrapper.exists( - '[aria-label="downloadStatus.remove {filename:test-file-2}"]' - ) - ).toBe(false); - expect( - wrapper.exists( - '[aria-label="downloadStatus.remove {filename:test-file-4}"]' - ) - ).toBe(false); + // clear file name filter textbox + await user.clear(fileNameFilterBox); + // type into download method filter textbox + await user.type(downloadMethodFilterBox, 'https'); - accessMethodFilterInput.instance().value = ''; - accessMethodFilterInput.simulate('change'); + expect(await screen.findByText('test-file-1')).toBeInTheDocument(); + expect(screen.getByText('test-file-3')).toBeInTheDocument(); + expect(screen.queryByText('test-file-2')).toBeNull(); + expect(screen.queryByText('test-file-4')).toBeNull(); // Test varying download availabilities. - const availabilityFilterInput = wrapper - .find('[aria-label="Filter by downloadStatus.status"]') - .first(); + await user.type(downloadStatusFilterBox, 'downloadStatus.complete'); - availabilityFilterInput.instance().value = 'downloadStatus.complete'; - availabilityFilterInput.simulate('change'); + expect(await screen.findByText('test-file-1')).toBeInTheDocument(); + expect(screen.queryByText('test-file-3')).toBeNull(); - expect(wrapper.exists('[aria-rowcount=1]')).toBe(true); - expect( - wrapper.exists( - '[aria-label="downloadStatus.remove {filename:test-file-1}"]' - ) - ).toBe(true); + await user.clear(downloadMethodFilterBox); + await user.clear(downloadStatusFilterBox); - availabilityFilterInput.instance().value = ''; - availabilityFilterInput.simulate('change'); - - expect(wrapper.exists('[aria-rowcount=5]')).toBe(true); + expect(await screen.findByText('test-file-1')).toBeInTheDocument(); + expect(screen.getByText('test-file-2')).toBeInTheDocument(); + expect(screen.getByText('test-file-3')).toBeInTheDocument(); + expect(screen.getByText('test-file-4')).toBeInTheDocument(); + expect(screen.getByText('test-file-5')).toBeInTheDocument(); }); - it('filters data when date filter is altered', async () => { - const wrapper = mount( -
- -
- ); + it('should filter data when date filter is altered', async () => { + applyDatePickerWorkaround(); + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); + const dateFromFilterInput = await screen.findByRole('textbox', { + name: 'downloadStatus.createdAt filter from', + }); + const dateToFilterInput = await screen.findByRole('textbox', { + name: 'downloadStatus.createdAt filter to', }); - const dateFromFilterInput = wrapper.find( - 'input[id="downloadStatus.createdAt filter from"]' - ); - - dateFromFilterInput.instance().value = '2020-01-01 00:00'; - dateFromFilterInput.simulate('change'); - - expect(wrapper.exists('[aria-rowcount=5]')).toBe(true); - - const dateToFilterInput = wrapper.find( - 'input[id="downloadStatus.createdAt filter to"]' - ); - - dateToFilterInput.instance().value = '2020-01-02 23:59'; - dateToFilterInput.simulate('change'); + // Type into date from filter textbox + await user.type(dateFromFilterInput, '2020-01-01 00:00:00'); + + // Should show all files + expect(await screen.findByText('test-file-1')).toBeInTheDocument(); + expect(await screen.findByText('test-file-2')).toBeInTheDocument(); + expect(await screen.findByText('test-file-3')).toBeInTheDocument(); + expect(await screen.findByText('test-file-4')).toBeInTheDocument(); + expect(await screen.findByText('test-file-5')).toBeInTheDocument(); + + // Type into date to filter textbox + await user.type(dateToFilterInput, '2020-01-02 23:59:00'); + + // Should show no files + await waitFor(() => { + expect(screen.queryByText('test-file-1')).toBeNull(); + expect(screen.queryByText('test-file-2')).toBeNull(); + expect(screen.queryByText('test-file-3')).toBeNull(); + expect(screen.queryByText('test-file-4')).toBeNull(); + expect(screen.queryByText('test-file-5')).toBeNull(); + }); - expect(wrapper.exists('[aria-rowcount=0]')).toBe(true); + // Clear both date filter textboxes + await user.clear(dateFromFilterInput); + await user.clear(dateToFilterInput); + // Type into both date filters + await user.type(dateFromFilterInput, '2020-02-26 00:00:00'); + await user.type(dateToFilterInput, '20200227235900'); + + // Should show only test-file-2 and test-file-3 + expect(await screen.findByText('test-file-2')).toBeInTheDocument(); + expect(await screen.findByText('test-file-3')).toBeInTheDocument(); + expect(screen.queryByText('test-file-1')).toBeNull(); + expect(screen.queryByText('test-file-4')).toBeNull(); + expect(screen.queryByText('test-file-5')).toBeNull(); + + // Clear both date filter textboxes + await user.clear(dateFromFilterInput); + await user.clear(dateToFilterInput); + // Type into only date from filter + await user.type(dateFromFilterInput, '2020-02-27 00:00:00'); + + // Should show test-file-3, test-file-4 and test-file-5 + expect(await screen.findByText('test-file-3')).toBeInTheDocument(); + expect(await screen.findByText('test-file-4')).toBeInTheDocument(); + expect(await screen.findByText('test-file-5')).toBeInTheDocument(); + expect(screen.queryByText('test-file-1')).toBeNull(); + expect(screen.queryByText('test-file-2')).toBeNull(); + + // Clear date from filter textbox + await user.click(dateFromFilterInput); + await user.keyboard('{Control}a{/Control}'); + await user.keyboard('{Delete}'); + // await user.clear(dateFromFilterInput); + // Type into only date to filter + await user.type(dateToFilterInput, '2020-02-27 00:00:00'); + + // Should show only test-file-1 and test-file-2 + expect(await screen.findByText('test-file-1')).toBeInTheDocument(); + expect(await screen.findByText('test-file-2')).toBeInTheDocument(); + expect(screen.queryByText('test-file-3')).toBeNull(); + expect(screen.queryByText('test-file-4')).toBeNull(); + expect(screen.queryByText('test-file-5')).toBeNull(); + + // create an invalid range + await user.type(dateFromFilterInput, '2020-02-28 00:00:00'); + + // should display error + expect(await screen.findAllByText('Invalid date-time range')); + + // Should show all files + expect(await screen.findByText('test-file-1')).toBeInTheDocument(); + expect(await screen.findByText('test-file-2')).toBeInTheDocument(); + expect(await screen.findByText('test-file-3')).toBeInTheDocument(); + expect(await screen.findByText('test-file-4')).toBeInTheDocument(); + expect(await screen.findByText('test-file-5')).toBeInTheDocument(); + + cleanupDatePickerWorkaround(); + }); - dateFromFilterInput.instance().value = '2020-02-26 00:00'; - dateFromFilterInput.simulate('change'); - dateToFilterInput.instance().value = '2020-02-27 23:59'; - dateToFilterInput.simulate('change'); + it('should display download progress ui if enabled', async () => { + ( + getPercentageComplete as jest.MockedFunction + ).mockResolvedValue(20); + + renderComponent({ + settings: { + ...mockedSettings, + uiFeatures: { + downloadProgress: true, + }, + }, + }); - expect(wrapper.exists('[aria-rowcount=2]')).toBe(true); - expect( - wrapper.exists( - '[aria-label="downloadStatus.remove {filename:test-file-1}"]' - ) - ).toBe(false); expect( - wrapper.exists( - '[aria-label="downloadStatus.remove {filename:test-file-4}"]' - ) - ).toBe(false); - - // Test when both date inputs are empty. - dateFromFilterInput.instance().value = ''; - dateFromFilterInput.simulate('change'); - - dateToFilterInput.instance().value = ''; - dateToFilterInput.simulate('change'); - - expect(wrapper.exists('[aria-rowcount=5]')).toBe(true); + await screen.findByText('downloadStatus.progress') + ).toBeInTheDocument(); + + await waitFor(() => { + for (const progressBar of screen.getAllByRole('progressbar')) { + expect(progressBar).toBeInTheDocument(); + } + for (const progressText of screen.getAllByText('20%')) { + expect(progressText).toBeInTheDocument(); + } + }); }); }); diff --git a/packages/datagateway-download/src/downloadStatus/downloadStatusTable.component.tsx b/packages/datagateway-download/src/downloadStatus/downloadStatusTable.component.tsx index 2358809ee..0c8f3c082 100644 --- a/packages/datagateway-download/src/downloadStatus/downloadStatusTable.component.tsx +++ b/packages/datagateway-download/src/downloadStatus/downloadStatusTable.component.tsx @@ -1,29 +1,37 @@ -import React from 'react'; -import { Grid, Paper, IconButton, LinearProgress } from '@material-ui/core'; +import React, { useCallback } from 'react'; +import { Grid, IconButton, LinearProgress, Paper } from '@mui/material'; import { - Table, - Order, - FormattedDownload, - TextColumnFilter, - TableActionProps, DateColumnFilter, DateFilter, + FormattedDownload, + Order, + Table, + TableActionProps, + TextColumnFilter, TextFilter, } from 'datagateway-common'; -import { fetchDownloads, downloadDeleted, getDataUrl } from '../downloadApi'; +import { getDataUrl } from '../downloadApi'; import { TableCellProps } from 'react-virtualized'; -import { RemoveCircle, GetApp } from '@material-ui/icons'; +import { GetApp, RemoveCircle } from '@mui/icons-material'; import BlackTooltip from '../tooltip.component'; import { DownloadSettingsContext } from '../ConfigProvider'; import { useTranslation } from 'react-i18next'; import { toDate } from 'date-fns-tz'; -import { format } from 'date-fns'; +import { format, isAfter, isBefore, isEqual, isWithinInterval } from 'date-fns'; +import DownloadProgressIndicator from './downloadProgressIndicator.component'; +import { useQueryClient } from 'react-query'; +import { + QueryKey, + useDownloadOrRestoreDownload, + useDownloads, +} from '../downloadApiHooks'; +import useDownloadFormatter from './hooks/useDownloadFormatter'; interface DownloadStatusTableProps { refreshTable: boolean; setRefreshTable: (refresh: boolean) => void; - setLastChecked: () => void; + setLastCheckedTimestamp: (timestamp: number) => void; } const DownloadStatusTable: React.FC = ( @@ -31,6 +39,9 @@ const DownloadStatusTable: React.FC = ( ) => { // Load the settings for use. const settings = React.useContext(DownloadSettingsContext); + const [t] = useTranslation(); + const { formatDownload } = useDownloadFormatter(); + const queryClient = useQueryClient(); // Sorting columns const [sort, setSort] = React.useState<{ [column: string]: Order }>({ @@ -41,76 +52,44 @@ const DownloadStatusTable: React.FC = ( | { value?: string | number; type: string } | { startDate?: string; endDate?: string }; }>({}); - const [data, setData] = React.useState([]); - const [dataLoaded, setDataLoaded] = React.useState(false); + const { + data: downloads, + isLoading, + isFetched, + refetch: refetchDownloads, + dataUpdatedAt, + } = useDownloads({ + select: (data) => data.map(formatDownload), + }); - const { refreshTable, setRefreshTable, setLastChecked } = props; - const [t] = useTranslation(); + const { + refreshTable: shouldRefreshTable, + setRefreshTable, + setLastCheckedTimestamp, + } = props; - const dgDownloadElement = document.getElementById('datagateway-download'); + const refreshTable = useCallback(async () => { + await Promise.all([ + // mark download progress queries as invalid so that react-query will refetch them as well. + queryClient.invalidateQueries(QueryKey.DOWNLOAD_PROGRESS), + refetchDownloads(), + ]); + setRefreshTable(false); + }, [queryClient, refetchDownloads, setRefreshTable]); + // detect table refresh and refetch data if needed React.useEffect(() => { - if (!dataLoaded || refreshTable) { - // Clear the current contents, this will make sure - // there is visually a refresh of the table. - setData([]); - - // Handle a refresh of the table. - if (refreshTable && dataLoaded) { - setDataLoaded(false); - setRefreshTable(false); - } - - if (!dataLoaded && dgDownloadElement) { - fetchDownloads({ - facilityName: settings.facilityName, - downloadApiUrl: settings.downloadApiUrl, - }).then((downloads) => { - // Replace the status field here - const formattedDownloads = downloads.map((download) => { - const formattedIsDeleted = download.isDeleted ? 'Yes' : 'No'; - let formattedStatus = ''; - switch (download.status) { - case 'COMPLETE': - formattedStatus = t('downloadStatus.complete'); - break; - case 'EXPIRED': - formattedStatus = t('downloadStatus.expired'); - break; - case 'PAUSED': - formattedStatus = t('downloadStatus.paused'); - break; - case 'PREPARING': - formattedStatus = t('downloadStatus.preparing'); - break; - case 'RESTORING': - formattedStatus = t('downloadStatus.restoring'); - break; - } - return { - ...download, - status: formattedStatus, - isDeleted: formattedIsDeleted, - }; - }); - setData([...formattedDownloads].reverse()); - setDataLoaded(true); + if (shouldRefreshTable && isFetched) { + refreshTable(); + } + }, [shouldRefreshTable, refreshTable, isFetched]); - // Set the time at which we set the download data. - setLastChecked(); - }); - } + // set table last checked time after fetching downloads + React.useEffect(() => { + if (dataUpdatedAt > 0) { + setLastCheckedTimestamp(dataUpdatedAt); } - }, [ - dataLoaded, - refreshTable, - setRefreshTable, - setLastChecked, - settings.facilityName, - settings.downloadApiUrl, - dgDownloadElement, - t, - ]); + }, [dataUpdatedAt, setLastCheckedTimestamp]); const textFilter = (label: string, dataKey: string): React.ReactElement => ( = ( // Handle filtering for both text and date filters. const sortedAndFilteredData = React.useMemo(() => { - const filteredData = data.filter((item) => { - for (const [key, value] of Object.entries(filters)) { + // if the list of downloads is unavailable, return an empty array + if (!downloads) return []; + + const filteredData = downloads.filter((item) => { + const filterEntries = Object.entries(filters); + const satisfiedFilters: boolean[] = []; + for (const [key, filter] of filterEntries) { const tableValue = item[key]; - if (tableValue !== undefined && typeof tableValue === 'string') { - if ( - typeof value === 'object' && - 'value' in value && - typeof value.value === 'string' && - (value.type === 'include' - ? !tableValue.toLowerCase().includes(value.value.toLowerCase()) - : tableValue.toLowerCase().includes(value.value.toLowerCase())) - ) { - return false; - } else if ( - typeof value === 'object' && - 'startDate' in value && - 'endDate' in value && - value.startDate - ) { - // Check that the given date is in the range specified by the filter. - const tableTimestamp = toDate(tableValue).getTime(); - const startTimestamp = toDate(value.startDate).getTime(); - const endTimestamp = value.endDate - ? new Date(value.endDate).getTime() - : Date.now(); - - if ( - !( - startTimestamp <= tableTimestamp && - tableTimestamp <= endTimestamp - ) - ) - return false; + + const isTableValueAString = + tableValue !== undefined && typeof tableValue === 'string'; + if (!isTableValueAString) { + satisfiedFilters.push(false); + continue; + } + + const isTextFilter = + typeof filter === 'object' && + 'value' in filter && + typeof filter.value === 'string'; + if (isTextFilter) { + const filterKeyword = (filter.value as string).toLowerCase(); + + satisfiedFilters.push( + filter.type === 'exact' + ? tableValue.toLowerCase() === filterKeyword + : filter.type === 'exclude' + ? !tableValue.toLowerCase().includes(filterKeyword) + : tableValue.toLowerCase().includes(filterKeyword) + ); + + continue; + } + + const isDateFilter = + typeof filter === 'object' && + 'startDate' in filter && + 'endDate' in filter; + if (isDateFilter) { + const tableDate = toDate(tableValue.replace(/\[.*]/, '')); + const startDateFilter = filter.startDate + ? toDate(filter.startDate) + : null; + const endDateFilter = filter.endDate ? toDate(filter.endDate) : null; + + if (startDateFilter && endDateFilter) { + try { + satisfiedFilters.push( + isWithinInterval(tableDate, { + start: startDateFilter, + end: endDateFilter, + }) + ); + } catch (e) { + if (e instanceof RangeError) { + // isWithinInterval throws with RangeError if startDate > endDate + // in the date filter we tell the user this is invalid, + // so handle it there and do nothing here + } else { + throw e; + } + } + + continue; + } + if (startDateFilter) { + satisfiedFilters.push( + isEqual(tableDate, startDateFilter) || + isAfter(tableDate, startDateFilter) + ); + + continue; + } + if (endDateFilter) { + satisfiedFilters.push( + isEqual(tableDate, endDateFilter) || + isBefore(tableDate, endDateFilter) + ); + + continue; } - } else { - return false; } + satisfiedFilters.push(false); } - return true; + + return satisfiedFilters.every((value) => value); }); function sortDownloadItems( @@ -234,23 +260,24 @@ const DownloadStatusTable: React.FC = ( } return filteredData.sort(sortDownloadItems); - }, [data, sort, filters]); + }, [downloads, sort, filters]); return ( {/* Show loading progress if data is still being loaded */} - {!dataLoaded && ( + {isLoading && ( )} {/* Table should take up page but leave room for: SG appbar, SG footer, - tabs,table padding, and text above table (respectively). */} + tabs,table padding, loading bar and text above table (respectively). */} = ( }, { label: t('downloadStatus.status'), - dataKey: 'status', + dataKey: 'formattedStatus', filterComponent: availabilityFilter, }, + ...(settings.uiFeatures.downloadProgress + ? [ + { + label: t('downloadStatus.progress'), + dataKey: 'progress', + disableSort: true, + cellContentRenderer: ({ rowData }: TableCellProps) => ( + + ), + }, + ] + : []), { label: t('downloadStatus.createdAt'), dataKey: 'createdAt', cellContentRenderer: (props: TableCellProps) => { if (props.cellData) { - const date = toDate(props.cellData); + const date = toDate(props.cellData.replace(/\[.*]/, '')); return format(date, 'yyyy-MM-dd HH:mm:ss'); } }, @@ -285,29 +326,31 @@ const DownloadStatusTable: React.FC = ( }, ]} sort={sort} - onSort={(column: string, order: 'desc' | 'asc' | null) => { + onSort={( + column: string, + order: 'desc' | 'asc' | null, + _, + shiftDown?: boolean + ) => { if (order) { - setSort({ ...sort, [column]: order }); + shiftDown + ? setSort({ ...sort, [column]: order }) + : setSort({ [column]: order }); } else { const { [column]: order, ...restOfSort } = sort; setSort(restOfSort); } }} data={sortedAndFilteredData} - loading={!dataLoaded} + loading={isLoading} // Pass in a custom actions column width to fit both buttons. actionsWidth={100} actions={[ function DownloadButton({ rowData }: TableActionProps) { const downloadItem = rowData as FormattedDownload; - const isHTTP = downloadItem.transport.match(/https|http/) - ? true - : false; + const isHTTP = !!downloadItem.transport.match(/https|http/); - const isComplete = - downloadItem.status === t('downloadStatus.complete') - ? true - : false; + const isComplete = downloadItem.status === 'COMPLETE'; const isDownloadable = isHTTP && isComplete; @@ -315,14 +358,13 @@ const DownloadStatusTable: React.FC = ( ( 'downloadStatus.non_https_download_disabled_tooltip', { transport: downloadItem.transport } - // for some reason it can't infer these types on its own - ) as string) - : (t( + ) + : t( 'downloadStatus.https_download_disabled_tooltip' - ) as string) + ) } enterDelay={500} // Disable error tooltip for downloadable HTTP(S) downloads. @@ -357,8 +399,10 @@ const DownloadStatusTable: React.FC = ( function RemoveButton({ rowData, }: TableActionProps): JSX.Element { + const { isLoading: isDeleting, mutate: downloadDeleted } = + useDownloadOrRestoreDownload(); const downloadItem = rowData as FormattedDownload; - const [isDeleting, setIsDeleting] = React.useState(false); + // const [isDeleting, setIsDeleting] = React.useState(false); return ( = ( key="remove" size="small" onClick={() => { - setIsDeleting(true); - downloadDeleted(downloadItem.id as number, true, { - facilityName: settings.facilityName, - downloadApiUrl: settings.downloadApiUrl, - }).then(() => - setData( - data.filter((item) => item.id !== downloadItem.id) - ) - ); + downloadDeleted({ + downloadId: downloadItem.id, + deleted: true, + }); }} > diff --git a/packages/datagateway-download/src/downloadStatus/hooks/useDownloadFormatter.ts b/packages/datagateway-download/src/downloadStatus/hooks/useDownloadFormatter.ts new file mode 100644 index 000000000..79700714f --- /dev/null +++ b/packages/datagateway-download/src/downloadStatus/hooks/useDownloadFormatter.ts @@ -0,0 +1,57 @@ +import type { + Download, + DownloadStatus, + FormattedDownload, +} from 'datagateway-common'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +/** + * A function that given a {@link Download} object, returns the formatted version + * with all server side values replaced with user-facing labels. + */ +type DownloadFormatter = (download: Download) => FormattedDownload; + +/** + * A map that maps {@link DownloadStatus} to the corresponding user-facing label. + */ +type DownloadStatusLabelMap = { + [Status in DownloadStatus]: string; +}; + +/** + * A React hook that provides a function for formatting {@link Download} objects, + * and a map for mapping {@link DownloadStatus} to the corresponding user-facing label. + */ +function useDownloadFormatter(): { + formatDownload: DownloadFormatter; + downloadStatusLabels: DownloadStatusLabelMap; +} { + const [t] = useTranslation(); + const statusLabels: DownloadStatusLabelMap = React.useMemo( + () => ({ + COMPLETE: t('downloadStatus.complete'), + EXPIRED: t('downloadStatus.expired'), + PAUSED: t('downloadStatus.paused'), + PREPARING: t('downloadStatus.preparing'), + RESTORING: t('downloadStatus.restoring'), + }), + [t] + ); + + const downloadFormatter = React.useCallback( + (download: Download): FormattedDownload => ({ + ...download, + formattedIsDeleted: download.isDeleted ? 'Yes' : 'No', + formattedStatus: statusLabels[download.status] ?? '', + }), + [statusLabels] + ); + + return { + formatDownload: downloadFormatter, + downloadStatusLabels: statusLabels, + }; +} + +export default useDownloadFormatter; diff --git a/packages/datagateway-download/src/downloadTab/__snapshots__/downloadTab.component.test.tsx.snap b/packages/datagateway-download/src/downloadTab/__snapshots__/downloadTab.component.test.tsx.snap deleted file mode 100644 index 6517355a0..000000000 --- a/packages/datagateway-download/src/downloadTab/__snapshots__/downloadTab.component.test.tsx.snap +++ /dev/null @@ -1,106 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DownloadTab renders correctly 1`] = ` - - - - - - - - - - - -
- - - - - - -

- - downloadTab.last_checked - : - - -

-
-
-
- - - -
-
-
-`; diff --git a/packages/datagateway-download/src/downloadTab/downloadTab.component.test.tsx b/packages/datagateway-download/src/downloadTab/downloadTab.component.test.tsx index 9d8e16c2a..d48f6725d 100644 --- a/packages/datagateway-download/src/downloadTab/downloadTab.component.test.tsx +++ b/packages/datagateway-download/src/downloadTab/downloadTab.component.test.tsx @@ -1,52 +1,79 @@ -import React from 'react'; -import { createShallow, createMount } from '@material-ui/core/test-utils'; -import DownloadTabs from './downloadTab.component'; -import { act } from 'react-dom/test-utils'; -import { flushPromises } from '../setupTests'; -import { DownloadSettingsContext } from '../ConfigProvider'; -import { createMemoryHistory } from 'history'; -import { Router } from 'react-router-dom'; -import { ReactWrapper } from 'enzyme'; +import { RenderResult } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { fetchDownloadCart } from 'datagateway-common'; +import { createMemoryHistory, History } from 'history'; +import * as React from 'react'; import { QueryClient, QueryClientProvider } from 'react-query'; +import { Router } from 'react-router-dom'; +import { DownloadSettingsContext } from '../ConfigProvider'; +import { + downloadDeleted, + fetchDownloads, + getDataUrl, + getFileSizeAndCount, + removeAllDownloadCartItems, + removeFromCart, + isCartMintable, +} from '../downloadApi'; +import { mockCartItems, mockDownloadItems, mockedSettings } from '../testData'; +import DownloadTabs from './downloadTab.component'; -// Create our mocked datagateway-download settings file. -const mockedSettings = { - facilityName: 'LILS', - apiUrl: 'https://example.com/api', - downloadApiUrl: 'https://example.com/downloadApi', - idsUrl: 'https://example.com/ids', - accessMethods: { - https: { - idsUrl: 'https://example.com/ids', - displayName: 'HTTPS', - description: 'Example description for HTTPS access method.', - }, - globus: { - idsUrl: 'https://example.com/ids', - displayName: 'Globus', - description: 'Example description for Globus access method.', - }, - }, -}; +jest.mock('datagateway-common', () => { + const og = jest.requireActual('datagateway-common'); + return { + __esModule: true, + ...og, + fetchDownloadCart: jest.fn(), + }; +}); +jest.mock('../downloadApi'); describe('DownloadTab', () => { - let shallow; - let mount; - let history; + let history: History; + let holder; + let user: ReturnType; beforeEach(() => { - shallow = createShallow(); - mount = createMount(); history = createMemoryHistory(); - }); + user = userEvent.setup(); - afterEach(() => { - mount.cleanUp(); + holder = document.createElement('div'); + holder.setAttribute('id', 'datagateway-download'); + document.body.appendChild(holder); + + (downloadDeleted as jest.Mock).mockImplementation(() => Promise.resolve()); + (fetchDownloads as jest.Mock).mockImplementation(() => + Promise.resolve(mockDownloadItems) + ); + (getDataUrl as jest.Mock).mockImplementation(() => '/getData'); + ( + fetchDownloadCart as jest.MockedFunction + ).mockResolvedValue(mockCartItems); + ( + removeAllDownloadCartItems as jest.MockedFunction< + typeof removeAllDownloadCartItems + > + ).mockResolvedValue(); + ( + removeFromCart as jest.MockedFunction + ).mockImplementation((entityType, entityIds) => { + return Promise.resolve( + mockCartItems.filter((item) => !entityIds.includes(item.entityId)) + ); + }); + + ( + getFileSizeAndCount as jest.MockedFunction + ).mockResolvedValue({ fileSize: 1, fileCount: 7 }); + ( + isCartMintable as jest.MockedFunction + ).mockResolvedValue(true); }); - const createWrapper = (): ReactWrapper => { + const renderComponent = (): RenderResult => { const queryClient = new QueryClient(); - return mount( + return render( @@ -57,119 +84,61 @@ describe('DownloadTab', () => { ); }; - it('renders correctly', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); - it('shows the appropriate table when clicking between tabs', async () => { - const wrapper = createWrapper(); + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + // go to downloads tab - expect( - wrapper.exists('[aria-label="downloadTab.download_cart_panel_arialabel"]') - ).toBe(true); - expect( - wrapper - .find('div[aria-label="downloadTab.download_cart_panel_arialabel"]') - .props().hidden - ).toBe(false); + await user.click(await screen.findByText('downloadTab.downloads_tab')); expect( - wrapper.exists( - '[aria-label="downloadTab.download_status_panel_arialabel"]' - ) - ).toBe(true); + await screen.findByLabelText('downloadTab.download_cart_panel_arialabel') + ).not.toBeVisible(); expect( - wrapper - .find('div[aria-label="downloadTab.download_status_panel_arialabel"]') - .props().hidden - ).toBe(true); - - // Click on the downloads tab and the refresh downloads button. - await act(async () => { - wrapper - .find('button[aria-label="downloadTab.downloads_tab_arialabel"]') - .simulate('click'); - - await flushPromises(); - wrapper.update(); - - expect( - wrapper - .find('div[aria-label="downloadTab.download_status_panel_arialabel"]') - .props().hidden - ).toBe(false); - - expect( - wrapper.exists( - '[aria-label="downloadTab.refresh_download_status_arialabel"]' - ) - ).toBe(true); - - wrapper - .find( - 'button[aria-label="downloadTab.refresh_download_status_arialabel"]' - ) - .simulate('click'); - - await flushPromises(); - wrapper.update(); - }); + await screen.findByLabelText( + 'downloadTab.download_status_panel_arialabel' + ) + ).toBeVisible(); // Return back to the cart tab. - await act(async () => { - wrapper - .find('button[aria-label="downloadTab.cart_tab_arialabel"]') - .simulate('click'); - await flushPromises(); - wrapper.update(); - - expect( - wrapper - .find('div[aria-label="downloadTab.download_status_panel_arialabel"]') - .props().hidden - ).toBe(true); - }); - }); - it('renders the selections tab on each mount', async () => { - let wrapper = createWrapper(); + await user.click(await screen.findByText('downloadTab.cart_tab')); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + expect( + await screen.findByLabelText('downloadTab.download_cart_panel_arialabel') + ).toBeVisible(); + expect( + await screen.findByLabelText( + 'downloadTab.download_status_panel_arialabel' + ) + ).not.toBeVisible(); + }); - // Navigate to downloads tab - await act(async () => { - wrapper - .find('button[aria-label="downloadTab.downloads_tab_arialabel"]') - .simulate('click'); + it('refreshes downloads when the refresh button is clicked', async () => { + renderComponent(); + + ( + fetchDownloads as jest.MockedFunction + ).mockImplementation( + () => + new Promise((_) => { + // do nothing, simulating pending promise + // to test refreshing state + }) + ); - await flushPromises(); - wrapper.update(); - }); + // go to downloads tab - // Recreate the wrapper and expect it to show the selections tab. - wrapper = createWrapper(); + await user.click(await screen.findByText('downloadTab.downloads_tab')); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.click( + screen.getByRole('button', { + name: 'downloadTab.refresh_download_status_arialabel', + }) + ); expect( - wrapper.exists('[aria-label="downloadTab.download_cart_panel_arialabel"]') - ).toBe(true); - expect( - wrapper - .find('div[aria-label="downloadTab.download_cart_panel_arialabel"]') - .props().hidden - ).toBe(false); + await screen.findByText('downloadTab.refreshing_downloads') + ).toBeInTheDocument(); }); }); diff --git a/packages/datagateway-download/src/downloadTab/downloadTab.component.tsx b/packages/datagateway-download/src/downloadTab/downloadTab.component.tsx index 2b880ef0d..4c9be5d5f 100644 --- a/packages/datagateway-download/src/downloadTab/downloadTab.component.tsx +++ b/packages/datagateway-download/src/downloadTab/downloadTab.component.tsx @@ -8,27 +8,21 @@ import { Grid, IconButton, CircularProgress, - Theme, -} from '@material-ui/core'; -import Tab from '@material-ui/core/Tab'; + styled, + Tab, +} from '@mui/material'; import DownloadCartTable from '../downloadCart/downloadCartTable.component'; import DownloadStatusTable from '../downloadStatus/downloadStatusTable.component'; -import RefreshIcon from '@material-ui/icons/Refresh'; +import RefreshIcon from '@mui/icons-material/Refresh'; import BlackTooltip from '../tooltip.component'; import { useTranslation } from 'react-i18next'; -import { StyleRules, createStyles, withStyles } from '@material-ui/core/styles'; -const paperStyles = (theme: Theme): StyleRules => - createStyles({ - root: { - flexGrow: 1, - backgroundColor: theme.palette.background.default, - }, - }); - -const StyledPaper = withStyles(paperStyles)(Paper); +const StyledPaper = styled(Paper)(({ theme }) => ({ + flexGrow: 1, + backgroundColor: theme.palette.background.default, +})); interface TabPanelProps { children?: React.ReactNode; @@ -52,9 +46,10 @@ function TabPanel(props: TabPanelProps): React.ReactElement { ); } -function a11yProps( - index: number -): { id: string; [ariaControls: string]: string } { +function a11yProps(index: number): { + id: string; + [ariaControls: string]: string; +} { return { id: `tab-${index}`, 'aria-controls': `tabpanel-${index}`, @@ -65,7 +60,7 @@ const DownloadTabs: React.FC = () => { // Set the initial tab. const [selectedTab, setSelectedTab] = React.useState(0); const [refreshDownloads, setRefreshDownloads] = React.useState(false); - const [lastChecked, setLastChecked] = React.useState(''); + const [lastCheckedTimestamp, setLastCheckedTimestamp] = React.useState(0); const [t] = useTranslation(); const handleChange = ( @@ -135,6 +130,7 @@ const DownloadTabs: React.FC = () => { 'downloadTab.refresh_download_status_arialabel' )} onClick={() => setRefreshDownloads(true)} + size="large" >
@@ -146,7 +142,8 @@ const DownloadTabs: React.FC = () => { {!refreshDownloads ? (

- {t('downloadTab.last_checked')}: {lastChecked} + {t('downloadTab.last_checked')}: {' '} + {new Date(lastCheckedTimestamp).toLocaleString()}

) : (

@@ -161,7 +158,7 @@ const DownloadTabs: React.FC = () => { setLastChecked(new Date().toLocaleString())} + setLastCheckedTimestamp={setLastCheckedTimestamp} /> diff --git a/packages/datagateway-download/src/index.test.tsx b/packages/datagateway-download/src/index.test.tsx index 9ed557642..701170051 100644 --- a/packages/datagateway-download/src/index.test.tsx +++ b/packages/datagateway-download/src/index.test.tsx @@ -2,7 +2,7 @@ import axios from 'axios'; import { MicroFrontendId, RegisterRouteType } from 'datagateway-common'; import LogoLight from 'datagateway-common/src/images/datagateway-logo.svg'; import LogoDark from 'datagateway-common/src/images/datgateway-white-text-blue-mark-logo.svg'; -import * as log from 'loglevel'; +import log from 'loglevel'; import { fetchSettings } from './'; jest.mock('loglevel'); diff --git a/packages/datagateway-download/src/index.tsx b/packages/datagateway-download/src/index.tsx index 53137c9b9..28c4af484 100644 --- a/packages/datagateway-download/src/index.tsx +++ b/packages/datagateway-download/src/index.tsx @@ -1,22 +1,22 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import './index.css'; -import './i18n'; -import App from './App'; import axios from 'axios'; -import jsrsasign from 'jsrsasign'; -import singleSpaReact from 'single-spa-react'; import { MicroFrontendId, MicroFrontendToken, PluginRoute, RegisterRouteType, } from 'datagateway-common'; +import LogoLight from 'datagateway-common/src/images/datagateway-logo.svg'; +import LogoDark from 'datagateway-common/src/images/datgateway-white-text-blue-mark-logo.svg'; +import jsrsasign from 'jsrsasign'; import log from 'loglevel'; +import React from 'react'; +import ReactDOM from 'react-dom'; +import singleSpaReact from 'single-spa-react'; +import App, { ErrorFallback } from './App'; import { DownloadSettings } from './ConfigProvider'; +import './i18n'; +import './index.css'; import { setSettings } from './settings'; -import LogoLight from 'datagateway-common/src/images/datagateway-logo.svg'; -import LogoDark from 'datagateway-common/src/images/datgateway-white-text-blue-mark-logo.svg'; function domElementGetter(): HTMLElement { // Make sure there is a div for us to render into @@ -31,8 +31,13 @@ function domElementGetter(): HTMLElement { const reactLifecycles = singleSpaReact({ React, ReactDOM, - rootComponent: App, + rootComponent: () => + document.getElementById('datagateway-download') ? : null, domElementGetter, + errorBoundary(error) { + log.error(`datagateway-download failed with error: ${error}`); + return ; + }, }); const render = (): void => { diff --git a/packages/datagateway-download/src/setupTests.ts b/packages/datagateway-download/src/setupTests.ts index da8e1bbfc..286876465 100644 --- a/packages/datagateway-download/src/setupTests.ts +++ b/packages/datagateway-download/src/setupTests.ts @@ -1,8 +1,10 @@ -import Enzyme from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; +/* eslint-disable @typescript-eslint/no-empty-function */ +import '@testing-library/jest-dom'; +import failOnConsole from 'jest-fail-on-console'; -// React 16 Enzyme adapter -Enzyme.configure({ adapter: new Adapter() }); +failOnConsole(); + +jest.setTimeout(20000); function noOp(): void { // required as work-around for enzyme/jest environment not implementing window.URL.createObjectURL method @@ -17,3 +19,32 @@ export const flushPromises = (): Promise => // Mock lodash.debounce to return the function we want to call. jest.mock('lodash.debounce', () => (fn: (args: unknown) => unknown) => fn); + +// MUI date pickers default to mobile versions during testing and so functions +// like .simulate('change') will not work, this workaround ensures desktop +// datepickers are used in tests instead +// https://github.com/mui/material-ui-pickers/issues/2073 +export const applyDatePickerWorkaround = (): void => { + // add window.matchMedia + // this is necessary for the date picker to be rendered in desktop mode. + // if this is not provided, the mobile mode is rendered, which might lead to unexpected behavior + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: (query: string) => ({ + media: query, + // this is the media query that @material-ui/pickers uses to determine if a device is a desktop device + matches: query === '(pointer: fine)', + onchange: () => {}, + addEventListener: () => {}, + removeEventListener: () => {}, + addListener: () => {}, + removeListener: () => {}, + dispatchEvent: () => false, + }), + }); +}; + +export const cleanupDatePickerWorkaround = (): void => { + // @ts-expect-error this is a workaround + delete window.matchMedia; +}; diff --git a/packages/datagateway-download/src/testData.ts b/packages/datagateway-download/src/testData.ts new file mode 100644 index 000000000..5e229ddb1 --- /dev/null +++ b/packages/datagateway-download/src/testData.ts @@ -0,0 +1,359 @@ +import { + Datafile, + Dataset, + Download, + DownloadCartItem, + FacilityCycle, + FormattedDownload, + Investigation, +} from 'datagateway-common'; +import type { DownloadSettings } from './ConfigProvider'; + +export const mockDownloadItems: Download[] = [ + { + createdAt: '2020-02-25T15:05:29Z', + downloadItems: [{ entityId: 1, entityType: 'investigation', id: 1 }], + email: 'test1@email.com', + facilityName: 'LILS', + fileName: 'test-file-1', + fullName: 'Person 1', + id: 1, + isDeleted: false, + isEmailSent: true, + isTwoLevel: false, + preparedId: 'test-prepared-id', + sessionId: 'test-session-id', + size: 1000, + status: 'COMPLETE', + transport: 'https', + userName: 'test user', + }, + { + createdAt: '2020-02-26T15:05:35Z', + downloadItems: [{ entityId: 2, entityType: 'investigation', id: 2 }], + email: 'test2@email.com', + facilityName: 'LILS', + fileName: 'test-file-2', + fullName: 'Person 2', + id: 2, + isDeleted: false, + isEmailSent: true, + isTwoLevel: false, + preparedId: 'test-prepared-id', + sessionId: 'test-session-id', + size: 2000, + status: 'PREPARING', + transport: 'globus', + userName: 'test user', + }, + { + createdAt: '2020-02-27T15:57:20Z', + downloadItems: [{ entityId: 3, entityType: 'investigation', id: 3 }], + email: 'test3@email.com', + facilityName: 'LILS', + fileName: 'test-file-3', + fullName: 'Person 3', + id: 3, + isDeleted: false, + isEmailSent: true, + isTwoLevel: false, + preparedId: 'test-prepared-id', + sessionId: 'test-session-id', + size: 3000, + status: 'RESTORING', + transport: 'https', + userName: 'test user', + }, + { + createdAt: '2020-02-28T15:57:28Z', + downloadItems: [{ entityId: 4, entityType: 'investigation', id: 4 }], + email: 'test4@email.com', + facilityName: 'LILS', + fileName: 'test-file-4', + fullName: 'Person 4', + id: 4, + isDeleted: true, + isEmailSent: true, + isTwoLevel: false, + preparedId: 'test-prepared-id', + sessionId: 'test-session-id', + size: 4000, + status: 'EXPIRED', + transport: 'globus', + userName: 'test user', + }, + { + createdAt: '2020-03-01T15:57:28Z[UTC]', + downloadItems: [{ entityId: 5, entityType: 'investigation', id: 5 }], + email: 'test5@email.com', + facilityName: 'LILS', + fileName: 'test-file-5', + fullName: 'Person 5', + id: 5, + isDeleted: false, + isEmailSent: true, + isTwoLevel: false, + preparedId: 'test-prepared-id', + sessionId: 'test-session-id', + size: 5000, + status: 'PAUSED', + transport: 'globus', + userName: 'test user', + }, +]; + +export const mockFormattedDownloadItems: FormattedDownload[] = [ + { + createdAt: '2020-02-25T15:05:29Z', + downloadItems: [{ entityId: 1, entityType: 'investigation', id: 1 }], + email: 'test1@email.com', + facilityName: 'LILS', + fileName: 'test-file-1', + fullName: 'Person 1', + id: 1, + isDeleted: false, + formattedIsDeleted: 'No', + isEmailSent: true, + isTwoLevel: false, + preparedId: 'test-prepared-id', + sessionId: 'test-session-id', + size: 1000, + status: 'COMPLETE', + formattedStatus: 'downloadStatus.complete', + transport: 'https', + userName: 'test user', + }, + { + createdAt: '2020-02-26T15:05:35Z', + downloadItems: [{ entityId: 2, entityType: 'investigation', id: 2 }], + email: 'test2@email.com', + facilityName: 'LILS', + fileName: 'test-file-2', + fullName: 'Person 2', + id: 2, + isDeleted: false, + formattedIsDeleted: 'No', + isEmailSent: true, + isTwoLevel: false, + preparedId: 'test-prepared-id', + sessionId: 'test-session-id', + size: 2000, + status: 'PREPARING', + formattedStatus: 'downloadStatus.preparing', + transport: 'globus', + userName: 'test user', + }, + { + createdAt: '2020-02-27T15:57:20Z', + downloadItems: [{ entityId: 3, entityType: 'investigation', id: 3 }], + email: 'test3@email.com', + facilityName: 'LILS', + fileName: 'test-file-3', + fullName: 'Person 3', + id: 3, + isDeleted: false, + formattedIsDeleted: 'No', + isEmailSent: true, + isTwoLevel: false, + preparedId: 'test-prepared-id', + sessionId: 'test-session-id', + size: 3000, + status: 'RESTORING', + formattedStatus: 'downloadStatus.restoring', + transport: 'https', + userName: 'test user', + }, + { + createdAt: '2020-02-28T15:57:28Z', + downloadItems: [{ entityId: 4, entityType: 'investigation', id: 4 }], + email: 'test4@email.com', + facilityName: 'LILS', + fileName: 'test-file-4', + fullName: 'Person 4', + id: 4, + isDeleted: true, + formattedIsDeleted: 'Yes', + isEmailSent: true, + isTwoLevel: false, + preparedId: 'test-prepared-id', + sessionId: 'test-session-id', + size: 4000, + status: 'EXPIRED', + formattedStatus: 'downloadStatus.expired', + transport: 'globus', + userName: 'test user', + }, + { + createdAt: '2020-03-01T15:57:28Z[UTC]', + downloadItems: [{ entityId: 5, entityType: 'investigation', id: 5 }], + email: 'test5@email.com', + facilityName: 'LILS', + fileName: 'test-file-5', + fullName: 'Person 5', + id: 5, + isDeleted: false, + formattedIsDeleted: 'No', + isEmailSent: true, + isTwoLevel: false, + preparedId: 'test-prepared-id', + sessionId: 'test-session-id', + size: 5000, + status: 'PAUSED', + formattedStatus: 'downloadStatus.paused', + transport: 'globus', + userName: 'test user', + }, +]; + +export const mockCartItems: DownloadCartItem[] = [ + { + entityId: 1, + entityType: 'investigation', + id: 1, + name: 'INVESTIGATION 1', + parentEntities: [], + }, + { + entityId: 2, + entityType: 'investigation', + id: 2, + name: 'INVESTIGATION 2', + parentEntities: [], + }, + { + entityId: 3, + entityType: 'dataset', + id: 3, + name: 'DATASET 1', + parentEntities: [], + }, + { + entityId: 4, + entityType: 'datafile', + id: 4, + name: 'DATAFILE 1', + parentEntities: [], + }, +]; + +export const mockFacilityCycles: FacilityCycle[] = [ + { + id: 12938, + name: 'studio toughness', + description: 'He decided water-skiing on a frozen lake wasn’t a good idea.', + startDate: '2006-01-20T16:30:17Z', + endDate: '2007-01-20T16:30:17Z', + }, + { + id: 402, + name: 'within cell interlinked', + description: 'He waited for the stop sign to turn to a go sign.', + startDate: '2017-03-17T14:03:11Z', + endDate: '2020-11-29T05:41:54Z', + }, +]; + +export const mockInvestigations: Investigation[] = [ + { + id: 58, + title: 'Happiness can be found in the depths of chocolate pudding.', + name: 'investigation news', + visitId: 'CqJN', + startDate: '2018-03-09T08:19:55Z', + endDate: '2018-03-29T08:19:55Z', + investigationInstruments: [ + { + id: 446, + instrument: { + id: 937, + name: 'instrument fame', + }, + }, + ], + investigationFacilityCycles: [ + { + id: 446, + facilityCycle: mockFacilityCycles[1], + }, + ], + }, + { + id: 993, + title: 'I ate a sock because people on the Internet told me to.', + name: 'investigation inn', + visitId: 'z0bLi1f3', + startDate: '2019-08-08T22:27:07Z', + endDate: '2019-09-08T22:27:07Z', + investigationInstruments: [ + { + id: 262, + instrument: { + id: 927, + name: 'instrument case', + }, + }, + ], + investigationFacilityCycles: [ + { + id: 262, + facilityCycle: mockFacilityCycles[1], + }, + ], + }, +]; + +export const mockDatasets: Dataset[] = [ + { + id: 856, + name: 'dataset modern', + investigation: mockInvestigations[0], + createTime: '2018-03-10T08:19:55Z', + modTime: '2018-03-10T09:19:55Z', + }, + { + id: 535, + name: 'dataset lazy', + investigation: mockInvestigations[1], + createTime: '2019-09-01T22:27:07Z', + modTime: '2019-09-02T22:27:07Z', + }, +]; + +export const mockDatafiles: Datafile[] = [ + { + id: 70, + name: 'datafile weekend', + modTime: '2018-03-10T08:19:55Z', + createTime: '2018-03-10T08:19:55Z', + dataset: mockDatasets[0], + }, +]; + +// Create our mocked datagateway-download settings file. +export const mockedSettings: DownloadSettings = { + facilityName: 'LILS', + apiUrl: 'https://example.com/api', + downloadApiUrl: 'https://example.com/downloadApi', + idsUrl: 'https://example.com/ids', + doiMinterUrl: 'https://example.com/doiMinter', + dataCiteUrl: 'https://example.com/dataCite', + fileCountMax: 5000, + totalSizeMax: 1000000000000, + accessMethods: { + https: { + idsUrl: 'https://example.com/ids', + displayName: 'HTTPS', + description: 'Example description for HTTPS access method.', + }, + globus: { + idsUrl: 'https://example.com/ids', + displayName: 'Globus', + description: 'Example description for Globus access method.', + }, + }, + uiFeatures: { + downloadProgress: false, + }, + routes: [], + helpSteps: [], +}; diff --git a/packages/datagateway-download/src/tooltip.component.tsx b/packages/datagateway-download/src/tooltip.component.tsx index 7999d606b..4fcb8e08d 100644 --- a/packages/datagateway-download/src/tooltip.component.tsx +++ b/packages/datagateway-download/src/tooltip.component.tsx @@ -1,21 +1,5 @@ import React from 'react'; -import { makeStyles, createStyles, Theme } from '@material-ui/core/styles'; -import Tooltip, { TooltipProps } from '@material-ui/core/Tooltip'; - -const useTooltipStyles: ( - fontSize?: string | undefined -) => Record<'tooltip', string> = (fontSize?: string) => { - const useStyles = makeStyles((theme: Theme) => - createStyles({ - tooltip: { - backgroundColor: theme.palette.common.black, - fontSize: fontSize ? fontSize : '0.875rem', - }, - }) - ); - - return useStyles(fontSize); -}; +import Tooltip, { TooltipProps } from '@mui/material/Tooltip'; interface BlackTooltipProps { fontSize?: string; @@ -26,12 +10,21 @@ const BlackTooltip: React.FC = ( props: BlackTooltipProps & TooltipProps ) => { const { fontSize, children, ...other } = props; - const classes = useTooltipStyles(fontSize); // Handle tooltip on disabled button elements by placing a span element. // https://material-ui.com/components/tooltips/#disabled-elements) return ( - + {children} ); diff --git a/packages/datagateway-download/tsconfig.json b/packages/datagateway-download/tsconfig.json index 4aea8e9b3..48b66a451 100644 --- a/packages/datagateway-download/tsconfig.json +++ b/packages/datagateway-download/tsconfig.json @@ -17,13 +17,10 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "react", + "jsx": "react-jsx", "noFallthroughCasesInSwitch": true }, "include": [ "src" ], - "exclude": [ - "**/?*test.*", - ] } diff --git a/packages/datagateway-search/cypress.config.ts b/packages/datagateway-search/cypress.config.ts new file mode 100644 index 000000000..d1d811276 --- /dev/null +++ b/packages/datagateway-search/cypress.config.ts @@ -0,0 +1,32 @@ +import { defineConfig } from 'cypress'; + +export default defineConfig({ + chromeWebSecurity: false, + video: false, + retries: { + runMode: 3, + openMode: 1, + }, + e2e: { + setupNodeEvents(on, config) { + on('task', { + failed: require('cypress-failed-log/src/failed')(), + }); + on('before:browser:launch', (browser, launchOptions) => { + if (browser.family === 'chromium' && browser.name !== 'electron') { + // Set pointer type to fine so that date inputs work properly + launchOptions.args.push('--blink-settings=primaryPointerType=4'); + } + + if (browser.family === 'firefox') { + // Set pointer type to fine so that date inputs work properly + launchOptions.preferences['ui.primaryPointerCapabilities'] = 4; + } + + // whatever you return here becomes the launchOptions + return launchOptions; + }); + }, + baseUrl: 'http://127.0.0.1:3000', + }, +}); diff --git a/packages/datagateway-search/cypress.json b/packages/datagateway-search/cypress.json deleted file mode 100644 index 75f6d8138..000000000 --- a/packages/datagateway-search/cypress.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "baseUrl": "http://127.0.0.1:3000", - "chromeWebSecurity": false, - "video": false, - "retries": { - "runMode": 3, - "openMode": 1 - } -} diff --git a/packages/datagateway-search/cypress/integration/app.spec.ts b/packages/datagateway-search/cypress/e2e/app.cy.ts similarity index 100% rename from packages/datagateway-search/cypress/integration/app.spec.ts rename to packages/datagateway-search/cypress/e2e/app.cy.ts diff --git a/packages/datagateway-search/cypress/e2e/search/datafileSearch.cy.ts b/packages/datagateway-search/cypress/e2e/search/datafileSearch.cy.ts new file mode 100644 index 000000000..0087af199 --- /dev/null +++ b/packages/datagateway-search/cypress/e2e/search/datafileSearch.cy.ts @@ -0,0 +1,527 @@ +describe('Datafile search tab', () => { + beforeEach(() => { + cy.login(); + cy.visit('/search/data/'); + + // only the datafile tab is tested here, so we want to hide investigation & dataset tabs + // open search type dropdown menu + cy.findByRole('button', { name: 'Types (3)' }).click(); + + cy.findByRole('listbox').within(() => { + cy.findByRole('checkbox', { name: 'Investigation checkbox' }).click(); + cy.findByRole('checkbox', { name: 'Dataset checkbox' }).click(); + }); + // close the dropdown menu + cy.get('body').type('{esc}'); + }); + + it('should perform search query and show search results correctly', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type( + 'dog AND big' + ); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + cy.findByRole('tab', { name: 'Datafile' }).within(() => { + cy.findByText('2').should('exist'); + }); + + // 3 rows, 2 for search results, 1 for the header row + cy.findAllByRole('row').should('have.length', 3); + + cy.findByRole('button', { name: 'Toggle Format filter panel' }).click(); + + cy.findAllByLabelText('Format filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { name: 'Add DATAFILEFORMAT 9 filter' }) + .should('exist') + .within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByText('1').should('exist'); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + + cy.findAllByLabelText('Parameter name filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { name: 'Add PARAMETERTYPE 23 filter' }) + .should('exist') + .within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByText('1').should('exist'); + }); + + cy.findByRole('button', { name: 'Add PARAMETERTYPE 46 filter' }) + .should('exist') + .within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByText('1').should('exist'); + }); + }); + + cy.findByRole('button', { name: 'Toggle Sample filter panel' }).click(); + + cy.findAllByLabelText('Sample filter panel').within(() => { + cy.findByRole('button', { name: 'Add SAMPLETYPE 55 filter' }) + .should('exist') + .within(() => { + cy.findByText('1').should('exist'); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Instrument filter panel', + }).click(); + cy.findAllByLabelText('Instrument filter panel').within(() => { + cy.findByRole('button', { name: 'Add INSTRUMENT 8 filter' }) + .should('exist') + .within(() => { + // shouldn't find a facet count + cy.findByText(/^[0-9]+$/).should('not.exist'); + }); + + cy.findByRole('button', { name: 'Add INSTRUMENT 9 filter' }) + .should('exist') + .within(() => { + cy.findByText(/^[0-9]+$/).should('not.exist'); + }); + }); + }); + + it('should be able to add/remove to/from download cart', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('+dog +big'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + // 3 rows, 2 for search results, 1 for the header row + cy.findAllByRole('row').should('have.length', 3); + + cy.findAllByRole('row') + .eq(1) + .within(() => { + cy.findByRole('checkbox').click(); + cy.findByRole('checkbox').should('be.checked'); + }); + + cy.findAllByRole('row') + .eq(1) + .within(() => { + cy.findByRole('checkbox').click(); + cy.findByRole('checkbox').should('not.be.checked'); + }); + }); + + it('should be able to open the details panel of a specific row', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('+dog +big'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + cy.findAllByRole('row').should('have.length', 3); + + cy.findAllByRole('row') + .eq(1) + .within(() => { + cy.findByRole('button', { name: 'Show details' }).click(); + }); + + cy.findByTestId('datafile-details-panel').within(() => { + cy.findByText('Datafile 1302').should('exist'); + cy.findByText('32.89 MB').should('exist'); + cy.findByText('/memory/dog/experience.jpg').should('exist'); + }); + }); + + it('should be able to filter search results by facets', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('dog'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + cy.findAllByRole('row').should('have.length', 24); + + // open the filter panel, then select some filters + cy.findByRole('button', { name: 'Toggle Format filter panel' }).click(); + + // select the filter we want + cy.findAllByLabelText('Format filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { + name: 'Add DATAFILEFORMAT 1 filter', + }) + .as('filter') + .click(); + cy.get('@filter').within(() => { + cy.findByRole('checkbox').should('be.checked'); + }); + }); + + // apply the filter + cy.findAllByRole('button', { name: 'Apply' }).click(); + + // the search result should be filtered + cy.findAllByRole('row').should('have.length', 4); + + // check that filter chips are displayed + cy.findByTestId('tabpanel-datafile').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByText('Format: DATAFILEFORMAT 1').should('exist'); + }); + }); + + // open the filter panel to check that the filter is selected + cy.findByRole('button', { name: 'Toggle Format filter panel' }).click(); + cy.findAllByLabelText('Format filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { + name: 'Remove DATAFILEFORMAT 1 filter', + }).within(() => { + cy.findByRole('checkbox').should('be.checked'); + }); + }); + + // open another filter panel to see the panel shows the updated list of filters + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findAllByLabelText('Parameter name filter panel') + .filter(':visible') + .within(() => { + // the filtered search results don't include this facet + cy.findByRole('button', { + name: 'Add PARAMETERTYPE 19 filter', + }).should('not.exist'); + + cy.findByRole('button', { + name: 'Add PARAMETERTYPE 23 filter', + }).within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByRole('checkbox').click(); + }); + }); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 2); + + // remove both filters, one by deselecting the filter, one via removing the chip + + // check that filter chips are displayed + cy.findByTestId('tabpanel-datafile').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'Parameter name: PARAMETERTYPE 23', + exact: false, + }).should('exist'); + cy.findByRole('button', { + name: 'Format: DATAFILEFORMAT 1', + exact: false, + }) + .should('exist') + .within(() => { + // remove the filter chip + cy.findByTestId('CancelIcon').click(); + }); + }); + }); + + cy.findAllByRole('row').should('have.length', 5); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findAllByLabelText('Parameter name filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { + name: 'Remove PARAMETERTYPE 23 filter', + }).click(); + }); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 24); + + // filter chips should not exist anymore + cy.findByTestId('tabpanel-datafile').within(() => { + cy.findByLabelText('Selected filters') + .children() + .should('have.length', 0); + }); + + cy.findAllByLabelText('Parameter name filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { name: 'Add PARAMETERTYPE 23 filter' }) + .should('exist') + .within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByText('4').should('exist'); + }); + + cy.findByRole('button', { name: 'Add PARAMETERTYPE 19 filter' }) + .should('exist') + .within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByText('3').should('exist'); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + + cy.findByRole('button', { + name: 'Toggle Format filter panel', + }).click(); + + cy.findAllByLabelText('Format filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { name: 'Add DATAFILEFORMAT 1 filter' }) + .should('exist') + .within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByText('3').should('exist'); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Format filter panel', + }).click(); + + cy.findByRole('button', { + name: 'Toggle Sample filter panel', + }).click(); + + // select the filter we want + cy.findAllByLabelText('Sample filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { + name: 'Add SAMPLETYPE 30 filter', + }) + .as('filter') + .click(); + cy.get('@filter').within(() => { + cy.findByRole('checkbox').should('be.checked'); + }); + }); + + // apply the filter + cy.findAllByRole('button', { name: 'Apply' }).click(); + + // the search result should be filtered + cy.findAllByRole('row').should('have.length', 7); + + // check that filter chips are displayed + cy.findByTestId('tabpanel-datafile').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'Sample: SAMPLETYPE 30', + exact: false, + }) + .should('exist') + .within(() => { + // remove the filter chip + cy.findByTestId('CancelIcon').click(); + }); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Instrument filter panel', + }).click(); + + // select the filter we want + cy.findAllByLabelText('Instrument filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { + name: 'Add INSTRUMENT 13 filter', + }) + .as('filter') + .click(); + cy.get('@filter').within(() => { + cy.findByRole('checkbox').should('be.checked'); + }); + }); + + // apply the filter + cy.findAllByRole('button', { name: 'Apply' }).click(); + + // the search result should be filtered + cy.findAllByRole('row').should('have.length', 12); + + // check that filter chips are displayed + cy.findByTestId('tabpanel-datafile').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByText('Instrument: INSTRUMENT 13').should('exist'); + }); + }); + }); + + it('should be able to filter search results by parameter filters', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('dog'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + cy.findAllByRole('row').should('have.length', 24); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findByText('Parameter filters') + .parent() + .within(() => { + cy.findByRole('button', { name: 'Add' }).click(); + }); + + cy.findByRole('button', { name: /Parameter name /i }).click(); + + // numeric parameter + cy.findByRole('option', { name: 'PARAMETERTYPE 33' }).click(); + + cy.findByRole('button', { name: /Parameter type /i }).click(); + + cy.findByRole('option', { name: 'Numeric' }).click(); + + cy.findByRole('spinbutton', { name: 'Minimum value' }).type('30'); + + cy.findByRole('spinbutton', { name: 'Maximum value' }).type('40'); + + cy.findByRole('button', { name: 'Add filter' }).click(); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 3); + + // check that filter chips are displayed & remove + cy.findByTestId('tabpanel-datafile').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'PARAMETERTYPE 33: 30 to 40', + exact: false, + }) + .should('exist') + .within(() => { + cy.findByTestId('CancelIcon').click(); + }); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findByText('Parameter filters') + .parent() + .within(() => { + cy.findByRole('button', { name: 'Add' }).click(); + }); + + cy.findByRole('button', { name: /Parameter name /i }).click(); + + // string parameter + cy.findByRole('option', { name: 'PARAMETERTYPE 23' }).click(); + + cy.findByRole('button', { name: /Parameter type /i }).click(); + + cy.findByRole('option', { name: 'String' }).click(); + + cy.findByRole('button', { name: /Parameter equals /i }).click(); + + cy.findByRole('option', { name: /value 23/i }).click(); + + cy.findByRole('button', { name: 'Add filter' }).click(); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 5); + + // check that filter chips are displayed & remove + cy.findByTestId('tabpanel-datafile').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'PARAMETERTYPE 23: value 23', + exact: false, + }) + .should('exist') + .within(() => { + cy.findByTestId('CancelIcon').click(); + }); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findByText('Parameter filters') + .parent() + .within(() => { + cy.findByRole('button', { name: 'Add' }).click(); + }); + + cy.findByRole('button', { name: /Parameter name /i }).click(); + + // datetime parameter + cy.findByRole('option', { name: 'PARAMETERTYPE 19' }).click(); + + cy.findByRole('button', { name: /Parameter type /i }).click(); + + cy.findByRole('option', { name: 'Date and time' }).click(); + + cy.findByRole('button', { name: /Parameter is in /i }).click(); + + cy.findByRole('option', { name: /Older/i }).click(); + + cy.findByRole('button', { name: 'Add filter' }).click(); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 2); + + // check that filter chips are displayed + cy.findByTestId('tabpanel-datafile').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'PARAMETERTYPE 19: Older', + exact: false, + }).should('exist'); + }); + }); + }); +}); diff --git a/packages/datagateway-search/cypress/e2e/search/datasetSearch.cy.ts b/packages/datagateway-search/cypress/e2e/search/datasetSearch.cy.ts new file mode 100644 index 000000000..53c989085 --- /dev/null +++ b/packages/datagateway-search/cypress/e2e/search/datasetSearch.cy.ts @@ -0,0 +1,520 @@ +describe('Dataset search tab', () => { + beforeEach(() => { + cy.login(); + cy.visit('/search/data/'); + + // only the dataset tab is tested here, so we want to hide investigation & datafile tabs + // open search type dropdown menu + cy.findByRole('button', { name: 'Types (3)' }).click(); + // uncheck investigation + cy.findByRole('listbox').within(() => { + cy.findByRole('checkbox', { name: 'Investigation checkbox' }).click(); + cy.findByRole('checkbox', { name: 'Datafile checkbox' }).click(); + }); + // close the dropdown menu + cy.get('body').type('{esc}'); + }); + + it('should perform search query and show search results correctly', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('last'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + cy.findByRole('tab', { name: 'Dataset' }).within(() => { + cy.findByText('7').should('exist'); + }); + + // 8 rows, 7 for search results, 1 for the header row + cy.findAllByRole('row').should('have.length', 8); + + cy.findByRole('button', { name: 'Toggle Type filter panel' }).click(); + + cy.findAllByLabelText('Type filter panel').within(() => { + cy.findByRole('button', { name: 'Add DATASETTYPE 1 filter' }) + .should('exist') + .within(() => { + cy.findByText('4').should('exist'); + }); + + cy.findByRole('button', { name: 'Add DATASETTYPE 2 filter' }) + .should('exist') + .within(() => { + cy.findByText('2').should('exist'); + }); + }); + + cy.findByRole('button', { name: 'Toggle Sample filter panel' }).click(); + + cy.findAllByLabelText('Sample filter panel').within(() => { + cy.findByRole('button', { name: 'Add SAMPLETYPE 18 filter' }) + .should('exist') + .within(() => { + cy.findByText('1').should('exist'); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + + cy.findAllByLabelText('Parameter name filter panel').within(() => { + cy.findByRole('button', { name: 'Add PARAMETERTYPE 1 filter' }) + .should('exist') + .within(() => { + cy.findByText('1').should('exist'); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Instrument filter panel', + }).click(); + cy.findAllByLabelText('Instrument filter panel').within(() => { + cy.findByRole('button', { name: 'Add INSTRUMENT 13 filter' }) + .should('exist') + .within(() => { + // shouldn't find a facet count + cy.findByText(/^[0-9]+$/).should('not.exist'); + }); + + cy.findByRole('button', { name: 'Add INSTRUMENT 1 filter' }) + .should('exist') + .within(() => { + cy.findByText(/^[0-9]+$/).should('not.exist'); + }); + }); + }); + + it('should be able to open the details panel of a specific row', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('last'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + // 8 rows, 7 for search results, 1 for the header row + cy.findAllByRole('row').should('have.length', 8); + + cy.findAllByRole('row') + .eq(1) + .within(() => { + cy.findByRole('button', { name: 'Show details' }).click(); + }); + + cy.findByTestId('dataset-details-panel').within(() => { + cy.findByText('DATASET 75').should('exist'); + cy.findByText('Group story magazine hotel stand', { + exact: false, + }).should('exist'); + }); + }); + + it('should be able to add/remove to/from download cart', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('last'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + // 8 rows, 7 for search results, 1 for the header row + cy.findAllByRole('row').should('have.length', 8); + + cy.findAllByRole('row') + .eq(1) + .within(() => { + cy.findByRole('checkbox').click(); + cy.findByRole('checkbox').should('be.checked'); + }); + + cy.findAllByRole('row') + .eq(1) + .within(() => { + cy.findByRole('checkbox').click(); + cy.findByRole('checkbox').should('not.be.checked'); + }); + }); + + it('should be able to filter search results by facets', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('last'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + cy.findAllByRole('row').should('have.length', 8); + + // open the filter panel, then select some filters + cy.findByRole('button', { name: 'Toggle Type filter panel' }).click(); + + // select the filter we want + cy.findAllByLabelText('Type filter panel').within(() => { + cy.findByRole('button', { + name: 'Add DATASETTYPE 1 filter', + }) + .as('filter') + .click(); + cy.get('@filter').within(() => { + cy.findByRole('checkbox').should('be.checked'); + }); + }); + + // apply the filter + cy.findAllByRole('button', { name: 'Apply' }).click(); + + // the search result should be filtered + cy.findAllByRole('row').should('have.length', 5); + + // check that filter chips are displayed + cy.findByTestId('tabpanel-dataset').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByText('Type: DATASETTYPE 1').should('exist'); + }); + }); + + // open the filter panel to check that the filter is selected + cy.findByRole('button', { name: 'Toggle Type filter panel' }).click(); + cy.findAllByLabelText('Type filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { + name: 'Remove DATASETTYPE 1 filter', + }).within(() => { + cy.findByRole('checkbox').should('be.checked'); + }); + }); + + // open another filter panel to see the panel shows the updated list of filters + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findAllByLabelText('Parameter name filter panel') + .filter(':visible') + .within(() => { + // the filtered search results don't include this facet + cy.findByRole('button', { + name: 'Add PARAMETERTYPE 1 filter', + }).should('not.exist'); + + cy.findByRole('button', { + name: 'Add PARAMETERTYPE 40 filter', + }).within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByRole('checkbox').click(); + }); + }); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 2); + + // remove both filters, one by deselecting the filter, one via removing the chip + + // check that filter chips are displayed + cy.findByTestId('tabpanel-dataset').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'Parameter name: PARAMETERTYPE 40', + exact: false, + }).should('exist'); + cy.findByRole('button', { + name: 'Type: DATASETTYPE 1', + exact: false, + }) + .should('exist') + .within(() => { + // remove the filter chip + cy.findByTestId('CancelIcon').click(); + }); + }); + }); + + cy.findAllByRole('row').should('have.length', 2); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findAllByLabelText('Parameter name filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { + name: 'Remove PARAMETERTYPE 40 filter', + }).click(); + }); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 8); + + // filter chips should not exist anymore + cy.findByTestId('tabpanel-dataset').within(() => { + cy.findByLabelText('Selected filters') + .children() + .should('have.length', 0); + }); + + cy.findAllByLabelText('Parameter name filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { name: 'Add PARAMETERTYPE 40 filter' }) + .should('exist') + .within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByText('1').should('exist'); + }); + + cy.findByRole('button', { name: 'Add PARAMETERTYPE 1 filter' }) + .should('exist') + .within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByText('1').should('exist'); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + + cy.findByRole('button', { + name: 'Toggle Type filter panel', + }).click(); + + cy.findAllByLabelText('Type filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { name: 'Add DATASETTYPE 1 filter' }) + .should('exist') + .within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByText('4').should('exist'); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Type filter panel', + }).click(); + + cy.findByRole('button', { + name: 'Toggle Sample filter panel', + }).click(); + + // select the filter we want + cy.findAllByLabelText('Sample filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { + name: 'Add SAMPLETYPE 18 filter', + }) + .as('filter') + .click(); + cy.get('@filter').within(() => { + cy.findByRole('checkbox').should('be.checked'); + }); + }); + + // apply the filter + cy.findAllByRole('button', { name: 'Apply' }).click(); + + // the search result should be filtered + cy.findAllByRole('row').should('have.length', 2); + + // check that filter chips are displayed + cy.findByTestId('tabpanel-dataset').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'Sample: SAMPLETYPE 18', + exact: false, + }) + .should('exist') + .within(() => { + // remove the filter chip + cy.findByTestId('CancelIcon').click(); + }); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Instrument filter panel', + }).click(); + + // select the filter we want + cy.findAllByLabelText('Instrument filter panel') + .filter(':visible') + .within(() => { + cy.findByRole('button', { + name: 'Add INSTRUMENT 13 filter', + }) + .as('filter') + .click(); + cy.get('@filter').within(() => { + cy.findByRole('checkbox').should('be.checked'); + }); + }); + + // apply the filter + cy.findAllByRole('button', { name: 'Apply' }).click(); + + // the search result should be filtered + cy.findAllByRole('row').should('have.length', 3); + + // check that filter chips are displayed + cy.findByTestId('tabpanel-dataset').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByText('Instrument: INSTRUMENT 13').should('exist'); + }); + }); + }); + + it('should be able to filter search results by parameter filters', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type( + 'last table' + ); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + cy.findAllByRole('row').should('have.length', 11); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findByText('Parameter filters') + .parent() + .within(() => { + cy.findByRole('button', { name: 'Add' }).click(); + }); + + cy.findByRole('button', { name: /Parameter name /i }).click(); + + // numeric parameter + cy.findByRole('option', { name: 'PARAMETERTYPE 1' }).click(); + + cy.findByRole('button', { name: /Parameter type /i }).click(); + + cy.findByRole('option', { name: 'Numeric' }).click(); + + cy.findByRole('spinbutton', { name: 'Minimum value' }).type('15'); + + cy.findByRole('spinbutton', { name: 'Maximum value' }).type('25'); + + cy.findByRole('button', { name: 'Add filter' }).click(); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 2); + + // check that filter chips are displayed & remove + cy.findByTestId('tabpanel-dataset').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'PARAMETERTYPE 1: 15 to 25', + exact: false, + }) + .should('exist') + .within(() => { + cy.findByTestId('CancelIcon').click(); + }); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findByText('Parameter filters') + .parent() + .within(() => { + cy.findByRole('button', { name: 'Add' }).click(); + }); + + cy.findByRole('button', { name: /Parameter name /i }).click(); + + // string parameter + cy.findByRole('option', { name: 'PARAMETERTYPE 40' }).click(); + + cy.findByRole('button', { name: /Parameter type /i }).click(); + + cy.findByRole('option', { name: 'String' }).click(); + + cy.findByRole('button', { name: /Parameter equals /i }).click(); + + cy.findByRole('option', { name: /value 40/i }).click(); + + cy.findByRole('button', { name: 'Add filter' }).click(); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 2); + + // check that filter chips are displayed & remove + cy.findByTestId('tabpanel-dataset').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'PARAMETERTYPE 40: value 40', + exact: false, + }) + .should('exist') + .within(() => { + cy.findByTestId('CancelIcon').click(); + }); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findByText('Parameter filters') + .parent() + .within(() => { + cy.findByRole('button', { name: 'Add' }).click(); + }); + + cy.findByRole('button', { name: /Parameter name /i }).click(); + + // datetime parameter + cy.findByRole('option', { name: 'PARAMETERTYPE 4' }).click(); + + cy.findByRole('button', { name: /Parameter type /i }).click(); + + cy.findByRole('option', { name: 'Date and time' }).click(); + + cy.findByRole('button', { name: /Parameter is in /i }).click(); + + cy.findByRole('option', { name: /Older/i }).click(); + + cy.findByRole('button', { name: 'Add filter' }).click(); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 2); + + // check that filter chips are displayed + cy.findByTestId('tabpanel-dataset').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'PARAMETERTYPE 4: Older', + exact: false, + }).should('exist'); + }); + }); + }); +}); diff --git a/packages/datagateway-search/cypress/e2e/search/investigationSearch.cy.ts b/packages/datagateway-search/cypress/e2e/search/investigationSearch.cy.ts new file mode 100644 index 000000000..a1df6b73e --- /dev/null +++ b/packages/datagateway-search/cypress/e2e/search/investigationSearch.cy.ts @@ -0,0 +1,519 @@ +describe('Investigation search tab', () => { + beforeEach(() => { + cy.login(); + cy.visit('/search/data/'); + + // only the investigation tab is tested here, so we want to hide dataset & datafile tabs + // open search type dropdown menu + cy.findByRole('button', { name: 'Types (3)' }).click(); + + cy.findByRole('listbox').within(() => { + cy.findByRole('checkbox', { name: 'Dataset checkbox' }).click(); + cy.findByRole('checkbox', { name: 'Datafile checkbox' }).click(); + }); + // close the dropdown menu + cy.get('body').type('{esc}'); + }); + + it('should perform search query and show search results correctly', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('dog'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + cy.findByRole('tab', { name: 'Investigation' }).within(() => { + cy.findByText('5').should('exist'); + }); + + // expecting 6 rows, 5 for search results, 1 for the header row + cy.findAllByRole('row').should('have.length', 6); + + cy.findByRole('button', { name: 'Toggle Type filter panel' }).click(); + cy.findAllByLabelText('Type filter panel').within(() => { + cy.findByRole('button', { name: 'Add INVESTIGATIONTYPE 2 filter' }) + .should('exist') + .within(() => { + cy.findByText('3').should('exist'); + }); + + cy.findByRole('button', { name: 'Add INVESTIGATIONTYPE 1 filter' }) + .should('exist') + .within(() => { + cy.findByText('2').should('exist'); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findAllByLabelText('Parameter name filter panel').within(() => { + cy.findByRole('button', { name: 'Add PARAMETERTYPE 2 filter' }) + .should('exist') + .within(() => { + cy.findByText('2').should('exist'); + }); + + cy.findByRole('button', { name: 'Add PARAMETERTYPE 11 filter' }) + .should('exist') + .within(() => { + cy.findByText('1').should('exist'); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Sample filter panel', + }).click(); + cy.findAllByLabelText('Sample filter panel').within(() => { + cy.findByRole('button', { name: 'Add SAMPLETYPE 38 filter' }) + .should('exist') + .within(() => { + cy.findByText('1').should('exist'); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Instrument filter panel', + }).click(); + cy.findAllByLabelText('Instrument filter panel').within(() => { + cy.findByRole('button', { name: 'Add INSTRUMENT 8 filter' }) + .should('exist') + .within(() => { + cy.findByText('2').should('exist'); + }); + + cy.findByRole('button', { name: 'Add INSTRUMENT 14 filter' }) + .should('exist') + .within(() => { + cy.findByText('1').should('exist'); + }); + }); + }); + + it('should be able to open the details panel of a specific row', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('dog'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + // 6 rows, 5 for search results, 1 for the header row + cy.findAllByRole('row').should('have.length', 6); + + cy.findAllByRole('row') + .eq(1) + .within(() => { + cy.findByRole('button', { name: 'Show details' }).click(); + }); + + cy.findByTestId('investigation-details-panel').within(() => { + cy.findByText('Majority about dog idea bag summer', { + exact: false, + }).should('exist'); + cy.findByText('INVESTIGATION 52').should('exist'); + }); + }); + + it('should be able to add/remove to/from download cart', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('dog'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + // 6 rows, 5 for search results, 1 for the header row + cy.findAllByRole('row').should('have.length', 6); + + cy.findAllByRole('row') + .eq(1) + .within(() => { + cy.findByRole('checkbox').click(); + cy.findByRole('checkbox').should('be.checked'); + }); + + cy.findAllByRole('row') + .eq(1) + .within(() => { + cy.findByRole('checkbox').click(); + cy.findByRole('checkbox').should('not.be.checked'); + }); + }); + + it('should be able to filter search results by facets', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('dog'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + cy.findAllByRole('row').should('have.length', 6); + + // open the filter panel, then select some filters + cy.findByRole('button', { name: 'Toggle Type filter panel' }).click(); + + // select the filter we want + cy.findAllByLabelText('Type filter panel').within(() => { + cy.findByRole('button', { + name: 'Add INVESTIGATIONTYPE 2 filter', + }) + .as('filter') + .click(); + cy.get('@filter').within(() => { + cy.findByRole('checkbox').should('be.checked'); + }); + }); + + // apply the filter + cy.findAllByRole('button', { name: 'Apply' }).click(); + + // the search result should be filtered + cy.findAllByRole('row').should('have.length', 4); + + // check that filter chips are displayed + cy.findByTestId('tabpanel-investigation').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByText('Type: INVESTIGATIONTYPE 2').should('exist'); + }); + }); + + // open the filter panel to check that the filter is selected + cy.findByRole('button', { name: 'Toggle Type filter panel' }).click(); + cy.findAllByLabelText('Type filter panel').within(() => { + cy.findByRole('button', { + name: 'Remove INVESTIGATIONTYPE 2 filter', + }).within(() => { + cy.findByRole('checkbox').should('be.checked'); + }); + }); + + // open another filter panel to see the panel shows the updated list of filters + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findAllByLabelText('Parameter name filter panel').within(() => { + // the filtered search results don't include this facet + cy.findByRole('button', { + name: 'Add PARAMETERTYPE 11 filter', + }).should('not.exist'); + + cy.findByRole('button', { + name: 'Add PARAMETERTYPE 2 filter', + }).within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByRole('checkbox').click(); + }); + }); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 2); + + // remove both filters, one by deselecting the filter, one via removing the chip + + // check that filter chips are displayed + cy.findByTestId('tabpanel-investigation').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'Parameter name: PARAMETERTYPE 2', + exact: false, + }).should('exist'); + cy.findByRole('button', { + name: 'Type: INVESTIGATIONTYPE 2', + exact: false, + }) + .should('exist') + .within(() => { + // remove the filter chip + cy.findByTestId('CancelIcon').click(); + }); + }); + }); + + cy.findAllByRole('row').should('have.length', 3); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findAllByLabelText('Parameter name filter panel').within(() => { + cy.findByRole('button', { + name: 'Remove PARAMETERTYPE 2 filter', + }).click(); + }); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 6); + + // filter chips should not exist anymore + cy.findByTestId('tabpanel-investigation').within(() => { + cy.findByLabelText('Selected filters') + .children() + .should('have.length', 0); + }); + + cy.findAllByLabelText('Parameter name filter panel').within(() => { + cy.findByRole('button', { name: 'Add PARAMETERTYPE 2 filter' }) + .should('exist') + .within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByText('2').should('exist'); + }); + + cy.findByRole('button', { name: 'Add PARAMETERTYPE 11 filter' }) + .should('exist') + .within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByText('1').should('exist'); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + + cy.findByRole('button', { + name: 'Toggle Type filter panel', + }).click(); + + cy.findAllByLabelText('Type filter panel').within(() => { + cy.findByRole('button', { name: 'Add INVESTIGATIONTYPE 2 filter' }) + .should('exist') + .within(() => { + cy.findByRole('checkbox').should('not.be.checked'); + cy.findByText('3').should('exist'); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Type filter panel', + }).click(); + + cy.findByRole('button', { + name: 'Toggle Sample filter panel', + }).click(); + + // select the filter we want + cy.findAllByLabelText('Sample filter panel').within(() => { + cy.findByRole('button', { + name: 'Add SAMPLETYPE 38 filter', + }) + .as('filter') + .click(); + cy.get('@filter').within(() => { + cy.findByRole('checkbox').should('be.checked'); + }); + }); + + // apply the filter + cy.findAllByRole('button', { name: 'Apply' }).click(); + + // the search result should be filtered + cy.findAllByRole('row').should('have.length', 2); + + // check that filter chips are displayed + cy.findByTestId('tabpanel-investigation').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'Sample: SAMPLETYPE 38', + exact: false, + }) + .should('exist') + .within(() => { + // remove the filter chip + cy.findByTestId('CancelIcon').click(); + }); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Instrument filter panel', + }).click(); + + // select the filter we want + cy.findAllByLabelText('Instrument filter panel').within(() => { + cy.findByRole('button', { + name: 'Add INSTRUMENT 8 filter', + }) + .as('filter') + .click(); + cy.get('@filter').within(() => { + cy.findByRole('checkbox').should('be.checked'); + }); + }); + + // apply the filter + cy.findAllByRole('button', { name: 'Apply' }).click(); + + // the search result should be filtered + cy.findAllByRole('row').should('have.length', 3); + + // check that filter chips are displayed + cy.findByTestId('tabpanel-investigation').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByText('Instrument: INSTRUMENT 8').should('exist'); + }); + }); + }); + + it('should be able to filter search results by parameter filters', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('dog'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + cy.findAllByRole('row').should('have.length', 6); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findByText('Parameter filters') + .parent() + .within(() => { + cy.findByRole('button', { name: 'Add' }).click(); + }); + + cy.findByRole('button', { name: /Parameter name /i }).click(); + + // numeric parameter + cy.findByRole('option', { name: 'PARAMETERTYPE 2' }).click(); + + cy.findByRole('button', { name: /Parameter type /i }).click(); + + cy.findByRole('option', { name: 'Numeric' }).click(); + + cy.findByRole('spinbutton', { name: 'Minimum value' }).type('5'); + + cy.findByRole('spinbutton', { name: 'Maximum value' }).type('10'); + + cy.findByRole('button', { name: 'Add filter' }).click(); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 2); + + // check that filter chips are displayed & remove + cy.findByTestId('tabpanel-investigation').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'PARAMETERTYPE 2: 5 to 10', + exact: false, + }) + .should('exist') + .within(() => { + cy.findByTestId('CancelIcon').click(); + }); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findByText('Parameter filters') + .parent() + .within(() => { + cy.findByRole('button', { name: 'Add' }).click(); + }); + + cy.findByRole('button', { name: /Parameter name /i }).click(); + + // string parameter + cy.findByRole('option', { name: 'PARAMETERTYPE 47' }).click(); + + cy.findByRole('button', { name: /Parameter type /i }).click(); + + cy.findByRole('option', { name: 'String' }).click(); + + cy.findByRole('button', { name: /Parameter equals /i }).click(); + + cy.findByRole('option', { name: /value 47/i }).click(); + + cy.findByRole('button', { name: 'Add filter' }).click(); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 2); + + // check that filter chips are displayed & remove + cy.findByTestId('tabpanel-investigation').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'PARAMETERTYPE 47: value 47', + exact: false, + }) + .should('exist') + .within(() => { + cy.findByTestId('CancelIcon').click(); + }); + }); + }); + + cy.findByRole('button', { + name: 'Toggle Parameter name filter panel', + }).click(); + cy.findByText('Parameter filters') + .parent() + .within(() => { + cy.findByRole('button', { name: 'Add' }).click(); + }); + + cy.findByRole('button', { name: /Parameter name /i }).click(); + + // datetime parameter + cy.findByRole('option', { name: 'PARAMETERTYPE 25' }).click(); + + cy.findByRole('button', { name: /Parameter type /i }).click(); + + cy.findByRole('option', { name: 'Date and time' }).click(); + + cy.findByRole('button', { name: /Parameter is in /i }).click(); + + cy.findByRole('option', { name: /Older/i }).click(); + + cy.findByRole('button', { name: 'Add filter' }).click(); + + cy.findByRole('button', { name: 'Apply' }).click(); + + cy.findAllByRole('row').should('have.length', 2); + + // check that filter chips are displayed + cy.findByTestId('tabpanel-investigation').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByRole('button', { + name: 'PARAMETERTYPE 25: Older', + exact: false, + }).should('exist'); + }); + }); + }); + + it('should link to an investigation', () => { + // type in search query + cy.findByRole('searchbox', { name: 'Search text input' }).type('dog'); + // uncheck my data + cy.findByRole('checkbox', { name: 'My data' }).click(); + // click on search button + cy.findByRole('button', { name: 'Submit search' }).click(); + + cy.get('[href="/browse/investigation/3/dataset"]'); + }); +}); diff --git a/packages/datagateway-search/cypress/integration/searchBoxContainer.spec.ts b/packages/datagateway-search/cypress/e2e/searchBoxContainer.cy.ts similarity index 81% rename from packages/datagateway-search/cypress/integration/searchBoxContainer.spec.ts rename to packages/datagateway-search/cypress/e2e/searchBoxContainer.cy.ts index dc0d8e74b..d5648c006 100644 --- a/packages/datagateway-search/cypress/integration/searchBoxContainer.spec.ts +++ b/packages/datagateway-search/cypress/e2e/searchBoxContainer.cy.ts @@ -41,23 +41,26 @@ describe('SearchBoxContainer Component', () => { cy.get('.MuiFormHelperText-root').contains('At least one required'); }); + // MUI v6 date pickers don't allow for invalid dates to be entered it('should display an error when an invalid start date is entered', () => { - cy.get('[aria-label="Start date input"]').type('2009-13-01'); + cy.get('[aria-label="Start date input"]').type('2009-12-00'); cy.get('.MuiFormHelperText-root').contains('Date format: yyyy-MM-dd.'); - cy.get('[aria-label="Start date input"]').clear(); + // cy.get('[aria-label="Start date input"]').clear(); + cy.get('[aria-label="Start date input"]').type('{ctrl}a{backspace}'); cy.get('.MuiFormHelperText-root').should('not.exist'); - cy.get('[aria-label="Start date input"]').type('2009-02-30'); + cy.get('[aria-label="Start date input"]').type('0000-02-28'); cy.get('.MuiFormHelperText-root').contains('Date format: yyyy-MM-dd.'); }); it('should display an error when an invalid end date is entered', () => { - cy.get('[aria-label="End date input"]').type('2009-13-01'); + cy.get('[aria-label="End date input"]').type('2009-12-00'); cy.get('.MuiFormHelperText-root').contains('Date format: yyyy-MM-dd.'); - cy.get('[aria-label="End date input"]').clear(); + // cy.get('[aria-label="End date input"]').clear(); + cy.get('[aria-label="End date input"]').type('{ctrl}a{backspace}'); cy.get('.MuiFormHelperText-root').should('not.exist'); - cy.get('[aria-label="End date input"]').type('2009-02-30'); + cy.get('[aria-label="End date input"]').type('0000-02-28'); cy.get('.MuiFormHelperText-root').contains('Date format: yyyy-MM-dd.'); }); @@ -84,9 +87,9 @@ describe('SearchBoxContainer Component', () => { //Should be able to close again cy.get('[aria-label="Close"]').click(); - cy.get('[aria-labelledby="advanced-search-dialog-title"') - .contains('Advanced Search Tips') - .should('not.exist'); + cy.get('[aria-labelledby="advanced-search-dialog-title"').should( + 'not.exist' + ); //Should be able to click on one of the links cy.get('[aria-label="Search options"]').click(); @@ -95,7 +98,7 @@ describe('SearchBoxContainer Component', () => { 'Advanced Search Tips' ); - cy.get('[data-testid="advanced-help-link"]').click(); + cy.findByRole('link', { name: 'neutron AND scattering' }).click(); cy.url().should('contain', '?searchText=neutron+AND+scattering'); }); }); diff --git a/packages/datagateway-search/cypress/e2e/searchPageContainer.cy.ts b/packages/datagateway-search/cypress/e2e/searchPageContainer.cy.ts new file mode 100644 index 000000000..2a2ee261c --- /dev/null +++ b/packages/datagateway-search/cypress/e2e/searchPageContainer.cy.ts @@ -0,0 +1,425 @@ +describe('SearchPageContainer Component', () => { + it('Should default back to 10 when any result is manually entered into the url', () => { + cy.login(); + + cy.visit('/search/data?view=card&searchText=&results=100&restrict=false'); + + cy.get('[aria-label="Submit search"]').click(); + + cy.get('[data-testid="card"]:visible', { timeout: 10000 }).should( + 'have.length', + 10 + ); + }); + + it('should be able to load results from a URL', () => { + cy.login(); + + cy.visit( + '/search/data/?view=card&searchText=test&startDate=2000-06-01&restrict=false' + ); + + //Should be in card view + cy.get('[aria-label="page view Display as table"]').should('exist'); + cy.get('[aria-label="page view Display as table"]').contains( + 'Display as table' + ); + + cy.get('[aria-label="Search table"]') + .contains('Investigation') + .contains('1') + .should('exist'); + cy.get('[aria-label="Search table"]') + .contains('Dataset') + .contains('5') + .should('exist'); + cy.get('[aria-label="Search table"]') + .contains('Datafile') + .contains('36') + .should('exist'); + }); + + describe('SearchPageContainer Components', () => { + beforeEach(() => { + cy.login(); + cy.clearDownloadCart(); + cy.visit('/search/data'); + + cy.get('#filled-search').type('dog'); + + cy.findByRole('checkbox', { name: 'My data' }).click(); + + cy.get('[aria-label="Submit search"]').click(); + }); + + it('should load correctly', () => { + cy.title().should('equal', 'DataGateway Search'); + + cy.get('#container-search-filters').should('exist'); + cy.get('#container-search-table').should('exist'); + + cy.location().should((loc) => { + expect(loc.search).to.eq('?searchText=dog'); + }); + + // check table DOI link is correct + + cy.get('[data-testid="investigation-search-table-doi-link"]') + .first() + .then(($doi) => { + const doi = $doi.text(); + + const url = `https://doi.org/${doi}`; + + cy.get('[data-testid="investigation-search-table-doi-link"]') + .first() + .should('have.attr', 'href', url); + }); + }); + + it('should be able to click clear filters button to clear filters', () => { + cy.url().then((unfilteredUrl) => { + cy.visit( + '/search/data?searchText=dog&restrict=false&filters={"Investigation.type.name":["INVESTIGATIONTYPE+2"],"InvestigationInstrument.instrument.name":["INSTRUMENT+14"]}' + ); + + cy.get('[aria-rowcount="1"]').should('exist'); + + cy.get('[aria-rowindex="1"] [aria-colindex="3"]').contains( + 'Prove begin boy those always dream write inside. Cold drop season bill treat her wife. Nearly represent fire debate fish. Skin understand risk.' + ); + + cy.get('[data-testid="clear-filters-button"]').click(); + cy.url().should('eq', unfilteredUrl); + }); + }); + + it('should be able to switch between tabs (and filters & pagination state should not be lost)', () => { + // visit url with pre-applied filters & pagination params + cy.visit( + '/search/data?view=card&page=2&results=20&searchText=&restrict=false&filters=%7B"Investigation.type.name"%3A%5B"INVESTIGATIONTYPE+3"%5D%7D' + ); + + cy.findByRole('tab', { name: 'Investigation' }).contains('23'); + + cy.findByTestId('tabpanel-investigation').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByText('Type: INVESTIGATIONTYPE 3').should('exist'); + }); + }); + + cy.get('[data-testid="card"]:visible') + .as('cards') + .should('have.length', 3); + + cy.findAllByRole('button', { name: /page 2/i, current: true }); + + cy.findByRole('tab', { name: 'Dataset' }).click(); + + cy.findByRole('tab', { name: 'Investigation' }).click(); + + cy.findByRole('tab', { name: 'Investigation' }).contains('23'); + + cy.findByTestId('tabpanel-investigation').within(() => { + cy.findByLabelText('Selected filters') + .should('exist') + .within(() => { + cy.findByText('Type: INVESTIGATIONTYPE 3').should('exist'); + }); + }); + + cy.get('[data-testid="card"]:visible') + .as('cards') + .should('have.length', 3); + + cy.findAllByRole('button', { name: /page 2/i, current: true }); + }); + + it('should be able to switch to card view', () => { + cy.get('[aria-label="page view Display as cards"]').click(); + //Should now be in card view + cy.get('[aria-label="page view Display as table"]').should('exist'); + cy.get('[aria-label="page view Display as table"]').contains( + 'Display as table' + ); + + cy.location().should((loc) => { + expect(loc.search).to.eq('?view=card&searchText=dog'); + }); + + // check card view DOI link is correct + cy.get('[data-testid="investigation-search-card-doi-link"]') + .first() + .then(($doi) => { + const doi = $doi.text(); + + const url = `https://doi.org/${doi}`; + + cy.get('[data-testid="investigation-search-card-doi-link"]') + .first() + .should('have.attr', 'href', url); + }); + + cy.get('[aria-label="page view Display as table"]').click(); + + //Should now be in table view + cy.get('[aria-label="page view Display as cards"]').should('exist'); + cy.get('[aria-label="page view Display as cards"]').contains( + 'Display as cards' + ); + + cy.location().should((loc) => { + expect(loc.search).to.eq('?view=table&searchText=dog'); + }); + }); + + it('should be able to scroll down and load more rows', () => { + cy.get('[aria-label="Search text input"').clear(); + cy.get('[aria-label="Submit search"]').click(); + + cy.findByRole('tab', { name: 'Datafile' }).within(() => { + cy.findByText('300+').should('exist'); + cy.findByText('300+').click(); + }); + cy.get('[data-testid="tabpanel-datafile"] [aria-label="grid"]').should( + 'be.visible' + ); + + cy.get('[aria-rowcount="300"]').should('exist'); + cy.get('[data-testid="tabpanel-datafile"] [aria-label="grid"]').scrollTo( + 'bottom' + ); + cy.get('[aria-rowindex="300"] > [aria-colindex="3"]') + .contains('Datafile 300') + .should('exist'); + cy.findByRole('tab', { name: 'Datafile' }).within(() => { + cy.findByText('600+').should('exist'); + }); + cy.get('[aria-rowcount="600"]').should('exist'); + cy.get('[aria-rowindex="301"] > [aria-colindex="3"]') + .contains('Datafile 301') + .should('exist'); + }); + + it('should be able to choose number of results to display', () => { + cy.get('[aria-label="Search text input"]').clear(); + + cy.get('[aria-label="Submit search"]').click(); + cy.get('[aria-label="page view Display as cards"]').click(); + + cy.findByRole('combobox', { + name: /Max Results/i, + }) + .as('maxResultsSelect') + .find('option:selected', { timeout: 10000 }) + .should('have.text', '10'); + cy.get('[data-testid="card"]:visible') + .as('cards') + .should('have.length', 10); + + cy.get('@maxResultsSelect').select('20'); + + cy.get('@maxResultsSelect') + .find('option:selected', { timeout: 10000 }) + .should('have.text', '20'); + cy.get('@cards').should('have.length', 20); + + cy.get('@maxResultsSelect').select('30'); + + cy.get('@maxResultsSelect') + .find('option:selected', { timeout: 10000 }) + .should('have.text', '30'); + + cy.get('@cards').should('have.length', 30); + }); + + it('should be able to change page in card view', () => { + cy.viewport('macbook-11'); + + cy.get('[aria-label="Search text input"]').clear(); + + cy.get('[aria-label="Submit search"]').click(); + + cy.findByRole('tab', { name: 'Dataset' }).click(); + + cy.get('[aria-label="page view Display as cards"]').click(); + + // we're testing cards in the middle of pages, as CI and SG-preprod can differ + // by around 1 result, so using first/last item per page is going to be + // wrong on one env or the other + + cy.get('[aria-label="Go to page 2"]', { timeout: 10000 }).first().click(); + cy.contains('[data-testid="card"]', 'DATASET 15'); + + cy.get('[aria-label="Go to next page"]', { timeout: 10000 }) + .first() + .click(); + cy.contains('[data-testid="card"]', 'DATASET 25'); + + cy.get('[aria-label="Go to last page"]', { timeout: 10000 }) + .first() + .click(); + cy.contains('[data-testid="card"]', 'DATASET 115'); + + cy.get('[aria-label="Go to previous page"]', { timeout: 10000 }) + .first() + .click(); + cy.contains('[data-testid="card"]', 'DATASET 105'); + + cy.get('[aria-label="Go to first page"]', { timeout: 10000 }) + .first() + .click(); + cy.contains('[data-testid="card"]', 'DATASET 5'); + }); + + it('should display selection alert banner correctly', () => { + cy.get( + `[data-testid="tabpanel-investigation"] [aria-rowindex="1"] [aria-colindex="1"]` + ).click(); + + cy.get('[aria-label="selection-alert"]').should('exist'); + cy.get('[aria-label="selection-alert-text"]') + .invoke('text') + .then((text) => { + expect(text.trim()).equal('1 item has been added to selection.'); + }); + + //Check can go to selection + cy.get('[aria-label="selection-alert-link"]').click(); + cy.location().should((loc) => { + expect(loc.pathname).to.equal('/download'); + }); + cy.go('back'); + + //Check can close banner + cy.get('[aria-label="selection-alert-close"]').click(); + cy.get('[aria-label="selection-alert"]').should('not.exist'); + }); + + it('should be able to deselect checkboxes', () => { + cy.get('#search-entities-menu').click(); + cy.get('[aria-label="Investigation checkbox"]').click(); + cy.get('[aria-label="Datafile checkbox"]').click(); + //Close drop down menu + cy.get('body').type('{esc}'); + + cy.get('[aria-label="Submit search"]').click(); + + cy.location().should((loc) => { + expect(loc.search).to.eq( + '?searchText=dog&datafile=false&investigation=false¤tTab=dataset' + ); + }); + + cy.get('[aria-label="Search table"]') + .contains('Investigation') + .should('not.exist'); + cy.get('[aria-label="Search table"]') + .contains('Datafile') + .should('not.exist'); + cy.get('[aria-label="Search table"]') + .contains('Dataset') + .contains('3') + .should('exist'); + }); + + it('should display number of items in cart correctly and go to the download page when clicked (Table)', () => { + // Check that the download cart has displayed correctly. + cy.get('[aria-label="Go to selections"]', { timeout: 10000 }).contains( + // matches empty string i.e. no badge + /^$/ + ); + + cy.get('[aria-label="select row 0"]', { timeout: 10000 }).eq(0).click(); + + cy.get('[aria-label="Go to selections"]', { timeout: 10000 }).contains( + /^1/ + ); + + cy.get('[aria-label="select row 1"]', { timeout: 10000 }).eq(0).click(); + + cy.get('[aria-label="Go to selections"]', { timeout: 10000 }).contains( + /^2/ + ); + + cy.get('[aria-label="Go to selections"]').click(); + cy.url().should('include', '/download'); + }); + + it('should display number of items in cart correctly and go to the download page when clicked (Card)', () => { + cy.get('[aria-label="page view Display as cards"]').click(); + // Check that the download cart has displayed correctly. + cy.get('[aria-label="Go to selections"]', { timeout: 10000 }).contains( + // matches empty string i.e. no badge + /^$/ + ); + + cy.get('[aria-label="card-button-1"]', { timeout: 10000 }).eq(0).click(); + + cy.get('[aria-label="Go to selections"]', { timeout: 10000 }).contains( + /^1/ + ); + + cy.get('[aria-label="card-button-1"]', { timeout: 10000 }).eq(1).click(); + + cy.get('[aria-label="Go to selections"]', { timeout: 10000 }).contains( + /^2/ + ); + + cy.get('[aria-label="Go to selections"]').click(); + cy.url().should('include', '/download'); + }); + + it('should be able to select a start & end date', () => { + cy.get('[aria-label="Start date input"]').type('2009-01-01'); + + cy.get('[aria-label="Submit search"]').click(); + + cy.location().should((loc) => { + expect(loc.search).to.contains('?searchText=dog&startDate=2009-01-01'); + }); + + cy.get('[aria-label="Search table"]') + .contains('Investigation') + .contains('2') + .should('exist'); + + cy.get('[aria-label="End date input"]').type('2013-01-01'); + + cy.get('[aria-label="Submit search"]').click(); + + cy.location().should((loc) => { + expect(loc.search).to.contains( + '?searchText=dog&startDate=2009-01-01&endDate=2013-01-01' + ); + }); + + cy.get('[aria-label="Search table"]') + .contains('Investigation') + .contains('1') + .should('exist'); + }); + + it('should be able to sort by different criteria', () => { + cy.get( + `[data-testid="tabpanel-investigation"] [aria-rowindex="1"] [aria-colindex="3"]` + ).contains('Majority about dog'); + + cy.findByLabelText('Sort by').click(); + + cy.findByRole('option', { name: 'Name' }).click(); + + cy.location().should((loc) => { + expect(loc.search).to.contains( + '?searchText=dog&sort=%7B%22name%22%3A%22asc%22%7D' + ); + }); + + cy.get( + `[data-testid="tabpanel-investigation"] [aria-rowindex="1"] [aria-colindex="3"]` + ).contains('Prove begin boy'); + }); + }); +}); diff --git a/packages/datagateway-search/cypress/integration/search/datafileSearch.spec.ts b/packages/datagateway-search/cypress/integration/search/datafileSearch.spec.ts deleted file mode 100644 index a47245ea3..000000000 --- a/packages/datagateway-search/cypress/integration/search/datafileSearch.spec.ts +++ /dev/null @@ -1,136 +0,0 @@ -describe('Datafile search tab', () => { - let facilityName: string; - - before(() => { - cy.readFile('server/e2e-settings.json').then((settings) => { - if (settings.facilityName) facilityName = settings.facilityName; - }); - }); - - beforeEach(() => { - cy.login(); - cy.visit('/search/data/'); - cy.intercept('**/investigations/count?where=%7B%22id*').as( - 'investigationsCount' - ); - cy.intercept('**/investigations?*').as('investigations'); - cy.intercept('**/datasets/count?where=%7B%22id*').as('datasetsCount'); - cy.intercept('**/datasets?*').as('datasets'); - cy.intercept('**/datafiles/count?where=%7B%22id*').as('datafilesCount'); - cy.intercept('**/datafiles?*').as('datafiles'); - cy.intercept(`**/topcat/user/cart/${facilityName}/cartItems`).as('topcat'); - }); - - it('should load correctly', () => { - cy.title().should('equal', 'DataGateway Search'); - - cy.get('#search-entities-menu').click(); - cy.get('[aria-label="Investigation checkbox"]').click(); - cy.get('[aria-label="Dataset checkbox"]').click(); - //Close drop down menu - cy.get('body').type('{esc}'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@datafiles', '@datafiles', '@datafilesCount'], { - timeout: 10000, - }); - - cy.get('#container-search-filters').should('exist'); - - cy.get('#container-search-table').should('exist'); - }); - - it('should be able to search by text', () => { - cy.clearDownloadCart(); - cy.get('[aria-label="Search text input"]') - .find('#filled-search') - .type('2106'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - - cy.get('[aria-label="Search table"]') - .contains('Datafile') - .contains('1') - .click() - .wait(['@datafiles', '@datafiles', '@datafilesCount'], { - timeout: 10000, - }); - - cy.get('[aria-rowcount="1"]').should('exist'); - - cy.get('[aria-rowindex="1"] [aria-colindex="3"]').contains('Datafile 2106'); - - // Check that "select all" and individual selection are equivalent - cy.get(`[aria-rowindex="1"] [aria-colindex="1"]`) - .click() - .wait('@topcat', { timeout: 10000 }); - cy.get('[aria-label="select all rows"]', { timeout: 10000 }).should( - 'be.checked' - ); - cy.get('[aria-label="select all rows"]') - .should('have.attr', 'data-indeterminate') - .and('eq', 'false'); - }); - - it('should be able to search by date range', () => { - cy.get('[aria-label="Start date input"]').type('2012-02-02'); - cy.get('[aria-label="End date input"]').type('2012-02-03'); - - cy.get('[aria-label="Submit search"]').click().wait('@datafilesCount', { - timeout: 10000, - }); - - cy.get('[aria-label="Search table"]') - .contains('Datafile') - .contains('9') - .click(); - - cy.get('[aria-rowcount="9"]').should('exist'); - - cy.get('[aria-rowindex="1"] [aria-colindex="3"]').contains('Datafile 1956'); - }); - - it('should be hidden if datafile checkbox is unchecked', () => { - cy.get('#search-entities-menu').click(); - cy.get('[aria-label="Datafile checkbox"]').click(); - //Close drop down menu - cy.get('body').type('{esc}'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - - cy.get('[aria-rowcount="50"]').should('exist'); - - cy.get('[aria-label="Search table"]') - .contains('Datafile') - .should('not.exist'); - }); - - it('should link to a parent dataset', () => { - cy.get('[aria-label="Search text input"]') - .find('#filled-search') - .type('1956'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - cy.get('[aria-label="Search table"]') - .contains('Datafile') - .contains('1') - .click() - .wait(['@datafiles', '@datafiles', '@datafilesCount'], { - timeout: 10000, - }); - cy.get('[href="/browse/investigation/41/dataset/41/datafile"]'); - }); -}); diff --git a/packages/datagateway-search/cypress/integration/search/datasetSearch.spec.ts b/packages/datagateway-search/cypress/integration/search/datasetSearch.spec.ts deleted file mode 100644 index 8f8654b91..000000000 --- a/packages/datagateway-search/cypress/integration/search/datasetSearch.spec.ts +++ /dev/null @@ -1,152 +0,0 @@ -describe('Dataset search tab', () => { - let facilityName: string; - - before(() => { - cy.readFile('server/e2e-settings.json').then((settings) => { - if (settings.facilityName) facilityName = settings.facilityName; - }); - }); - - beforeEach(() => { - cy.login(); - cy.visit('/search/data/'); - cy.intercept('**/investigations/count?where=%7B%22id*').as( - 'investigationsCount' - ); - cy.intercept('**/investigations?*').as('investigations'); - cy.intercept('**/datasets/count?where=%7B%22id*').as('datasetsCount'); - cy.intercept('**/datasets?*').as('datasets'); - cy.intercept('**/datafiles/count?where=%7B%22id*').as('datafilesCount'); - cy.intercept('**/datafiles?*').as('datafiles'); - cy.intercept(`**/topcat/user/cart/${facilityName}/cartItems`).as('topcat'); - }); - - it('should load correctly', () => { - cy.title().should('equal', 'DataGateway Search'); - - cy.get('#search-entities-menu').click(); - cy.get('[aria-label="Investigation checkbox"]').click(); - cy.get('[aria-label="Datafile checkbox"]').click(); - //Close drop down menu - cy.get('body').type('{esc}'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@datasets', '@datasets', '@datasetsCount'], { - timeout: 10000, - }); - - cy.get('#container-search-filters').should('exist'); - - cy.get('#container-search-table').should('exist'); - }); - - it('should be able to search by text', () => { - cy.clearDownloadCart(); - cy.get('[aria-label="Search text input"]') - .find('#filled-search') - .type('police'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 15000, - }); - - cy.get('[aria-label="Search table"]') - .contains('Dataset') - .contains('10') - .click() - .wait(['@datasets', '@datasets', '@datasetsCount'], { - timeout: 15000, - }); - - cy.get('[aria-rowcount="10"]').should('exist'); - - cy.get('[aria-rowindex="1"] [aria-colindex="3"]').contains('DATASET 7'); - - // Check that "select all" and individual selection are equivalent - let i = 1; - while (i < 11) { - cy.get(`[aria-rowindex="${i}"] [aria-colindex="1"]`) - .click() - .wait('@topcat', { timeout: 10000 }); - i++; - } - cy.get('[aria-label="select all rows"]', { timeout: 10000 }).should( - 'be.checked' - ); - cy.get('[aria-label="select all rows"]') - .should('have.attr', 'data-indeterminate') - .and('eq', 'false'); - }); - - it('should be able to search by date range', () => { - cy.get('[aria-label="Start date input"]').type('2003-01-01'); - cy.get('[aria-label="End date input"]').type('2004-01-01'); - - cy.get('[aria-label="Submit search"]').click(); - - cy.get('[aria-label="Search table"]') - .contains('Dataset') - .contains('4') - .click(); - - cy.get('[aria-rowcount="4"]').should('exist'); - - cy.get('[aria-rowindex="1"] [aria-colindex="3"]').contains('DATASET 12'); - }); - - it('should be hidden if dataset checkbox is unchecked', () => { - cy.get('#search-entities-menu').click(); - cy.get('[aria-label="Dataset checkbox"]').click(); - //Close drop down menu - cy.get('body').type('{esc}'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - - cy.get('[aria-rowcount="50"]').should('exist'); - - cy.get('[aria-label="Search table"]') - .contains('Dataset') - .should('not.exist'); - }); - - it('should link to a dataset', () => { - cy.get('[aria-label="Search text input"]') - .find('#filled-search') - .type('12'); - cy.get('[aria-label="Start date input"]').type('2003-01-01'); - cy.get('[aria-label="End date input"]').type('2004-01-01'); - - cy.get('[aria-label="Submit search"]').click(); - - cy.get('[aria-label="Search table"]') - .contains('Dataset') - .contains('1') - .click(); - - cy.get('[href="/browse/investigation/12/dataset/12/datafile"]'); - }); - - it('should link to a parent investigation', () => { - cy.get('[aria-label="Search text input"]') - .find('#filled-search') - .type('12'); - cy.get('[aria-label="Start date input"]').type('2003-01-01'); - cy.get('[aria-label="End date input"]').type('2004-01-01'); - - cy.get('[aria-label="Submit search"]').click(); - - cy.get('[aria-label="Search table"]') - .contains('Dataset') - .contains('1') - .click(); - - cy.get('[href="/browse/investigation/12/dataset"]'); - }); -}); diff --git a/packages/datagateway-search/cypress/integration/search/investigationSearch.spec.ts b/packages/datagateway-search/cypress/integration/search/investigationSearch.spec.ts deleted file mode 100644 index 7e19cdbe0..000000000 --- a/packages/datagateway-search/cypress/integration/search/investigationSearch.spec.ts +++ /dev/null @@ -1,147 +0,0 @@ -describe('Investigation search tab', () => { - let facilityName: string; - - before(() => { - cy.readFile('server/e2e-settings.json').then((settings) => { - if (settings.facilityName) facilityName = settings.facilityName; - }); - }); - - beforeEach(() => { - cy.login(); - cy.visit('/search/data/'); - cy.intercept('**/investigations/count?where=%7B%22id*').as( - 'investigationsCount' - ); - cy.intercept('**/investigations?*').as('investigations'); - cy.intercept('**/datasets/count?where=%7B%22id*').as('datasetsCount'); - cy.intercept('**/datasets?*').as('datasets'); - cy.intercept('**/datafiles/count?where=%7B%22id*').as('datafilesCount'); - cy.intercept('**/datafiles?*').as('datafiles'); - cy.intercept(`**/topcat/user/cart/${facilityName}/cartItems`).as('topcat'); - }); - - it('should load correctly', () => { - cy.title().should('equal', 'DataGateway Search'); - - cy.get('#search-entities-menu').click(); - cy.get('[aria-label="Dataset checkbox"]').click(); - cy.get('[aria-label="Datafile checkbox"]').click(); - //Close drop down menu - cy.get('body').type('{esc}'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - - cy.get('#container-search-filters').should('exist'); - - cy.get('#container-search-table').should('exist'); - }); - - it('should be able to search by title text', () => { - cy.clearDownloadCart(); - cy.get('[aria-label="Search text input"]') - .find('#filled-search') - .type('dog'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - - cy.get('[aria-rowcount="15"]').should('exist'); - - cy.get('[aria-rowindex="1"] [aria-colindex="6"]').contains('1-235-68516-0'); - - // Small wait to ensure rows are selected correctly - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(1000); - // Check that "select all" and individual selection are equivalent - let i = 1; - while (i < 16) { - cy.get(`[aria-rowindex="${i}"] [aria-colindex="1"]`).click(); - cy.wait('@topcat', { timeout: 10000 }); - i++; - } - - cy.get('[aria-label="select all rows"]', { timeout: 10000 }).should( - 'be.checked' - ); - cy.get('[aria-label="select all rows"]') - .should('have.attr', 'data-indeterminate') - .and('eq', 'false'); - }); - - it('should be able to search by instrument text', () => { - cy.get('[aria-label="Search text input"]') - .find('#filled-search') - .type('knowledge media'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigationsCount'], { - timeout: 10000, - }); - - cy.get('[aria-label="Search table"]') - .contains('Investigation') - .contains('19') - .click(); - - cy.get('[aria-rowcount="19"]').should('exist'); - - cy.get('[aria-rowindex="1"] [aria-colindex="6"]').contains('0-221-94355-2'); - }); - - it('should be able to search by date range', () => { - cy.get('[aria-label="Start date input"]').type('2001-01-01'); - cy.get('[aria-label="End date input"]').type('2001-12-31'); - - cy.get('[aria-label="Submit search"]').click(); - - cy.get('[aria-label="Search table"]') - .contains('Investigation') - .contains('12') - .click(); - - cy.get('[aria-rowcount="12"]').should('exist'); - - cy.get('[aria-rowindex="1"] [aria-colindex="6"]').contains('0-9634101-9-9'); - }); - - it('should be hidden if investigation checkbox is unchecked', () => { - cy.get('#search-entities-menu').click(); - cy.get('[aria-label="Investigation checkbox"]').click(); - //Close drop down menu - cy.get('body').type('{esc}'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@datasets', '@datasets', '@datasetsCount'], { - timeout: 10000, - }); - - cy.get('[aria-rowcount="50"]').should('exist'); - - cy.get('[aria-label="Search table"]') - .contains('Investigation') - .should('not.exist'); - }); - - it('should link to an investigation', () => { - cy.get('[aria-label="Search text input"]') - .find('#filled-search') - .type('dog'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigationsCount'], { - timeout: 10000, - }); - cy.get('[href="/browse/investigation/6/dataset"]'); - }); -}); diff --git a/packages/datagateway-search/cypress/integration/searchPageContainer.spec.ts b/packages/datagateway-search/cypress/integration/searchPageContainer.spec.ts deleted file mode 100644 index a061ea37d..000000000 --- a/packages/datagateway-search/cypress/integration/searchPageContainer.spec.ts +++ /dev/null @@ -1,435 +0,0 @@ -describe('SearchPageContainer Component', () => { - let facilityName: string; - - before(() => { - cy.readFile('server/e2e-settings.json').then((settings) => { - if (settings.facilityName) facilityName = settings.facilityName; - }); - }); - - it('Should default back to 10 when any result is manually entered into the url', () => { - cy.login(); - cy.visit('/search/data?view=card&results=100'); - cy.intercept('**/investigations/count?where=%7B%22id*').as( - 'investigationsCount' - ); - cy.intercept('**/investigations?*').as('investigations'); - cy.intercept('**/datasets/count?where=%7B%22id*').as('datasetsCount'); - cy.intercept('**/datasets?*').as('datasets'); - cy.intercept('**/datafiles/count?where=%7B%22id*').as('datafilesCount'); - cy.intercept('**/datafiles?*').as('datafiles'); - cy.intercept(`**/topcat/user/cart/${facilityName}/cartItems`).as('topcat'); - - cy.clearDownloadCart(); - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - - cy.get('[aria-label="card-buttons"]', { timeout: 10000 }).should( - 'have.length', - 10 - ); - }); - - describe('SearchPageContianer Components', () => { - beforeEach(() => { - cy.login(); - cy.visit('/search/data/'); - cy.intercept('**/investigations/count?where=%7B%22id*').as( - 'investigationsCount' - ); - cy.intercept('**/investigations?*').as('investigations'); - - cy.clearDownloadCart(); - cy.get('[aria-label="Search text input"]') - .find('#filled-search') - .type('dog'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - }); - - it('should load correctly', () => { - cy.title().should('equal', 'DataGateway Search'); - - cy.get('#container-search-filters').should('exist'); - cy.location().should((loc) => { - expect(loc.search).to.eq('?searchText=dog'); - }); - }); - - it('should display results correctly', () => { - cy.get('#container-search-table').should('exist'); - }); - - it('should have the correct url for the DOI link (Tableview) ', () => { - // DOI - - cy.get('[data-testid="investigation-search-table-doi-link"]') - .first() - .then(($doi) => { - const doi = $doi.text(); - - const url = `https://doi.org/${doi}`; - - cy.get('[data-testid="investigation-search-table-doi-link"]') - .first() - .should('have.attr', 'href', url); - }); - }); - - it('should be able to navigate through tabs without losing the filters (Table)', () => { - cy.title().should('equal', 'DataGateway Search'); - - cy.get('#container-search-filters').should('exist'); - cy.get('[aria-label="Filter by Title"]').type('ba'); - cy.contains('Visit ID').first().click(); - - cy.get('[id="simple-tab-dataset"]').click(); - cy.get('[id="simple-tab-investigation"]').click(); - - cy.get('[aria-rowcount="3"]').should('exist'); - - cy.get('[aria-rowindex="1"] [aria-colindex="3"]').contains( - 'Energy place money bad authority. Poor community technology against happy. Detail customer management together dog. Put name war sometimes rise sport your. Imagine across mother herself then.' - ); - }); - - it('should be able to click clear filters button to clear filters', () => { - cy.url().then((url) => { - cy.get('#container-search-filters').should('exist'); - cy.get('[aria-label="Filter by Title"]').type('ba'); - cy.wait( - ['@investigations', '@investigations', '@investigationsCount'], - { - timeout: 10000, - } - ); - - cy.get('[aria-rowcount="3"]').should('exist'); - - cy.get('[aria-rowindex="1"] [aria-colindex="3"]').contains( - 'Energy place money bad authority. Poor community technology against happy. Detail customer management together dog. Put name war sometimes rise sport your. Imagine across mother herself then.' - ); - - cy.get('[data-testid="clear-filters-button"]').click(); - cy.url().should('eq', url); - }); - }); - - it('should have the correct url for the DOI link (Cardview) ', () => { - // DOI - - cy.get('[aria-label="page view Display as cards"]').click(); - - cy.get('[data-testid="investigation-search-card-doi-link"]') - .first() - .then(($doi) => { - const doi = $doi.text(); - - const url = `https://doi.org/${doi}`; - - cy.get('[data-testid="investigation-search-card-doi-link"]') - .first() - .should('have.attr', 'href', url); - }); - }); - - it('should be able to switch between tabs', () => { - cy.get('[aria-label="Search table"]') - .contains('Dataset') - .contains('14') - .click(); - - cy.get('[aria-label="Search table"]') - .contains('Datafile') - .contains('300') - .click(); - - cy.get('[aria-label="Search table"]') - .contains('Investigation') - .contains('15') - .click(); - }); - - it('should be able to switch to card view', () => { - cy.get('[aria-label="page view Display as cards"]').click(); - //Should now be in card view - cy.get('[aria-label="page view Display as table"]').should('exist'); - cy.get('[aria-label="page view Display as table"]').contains( - 'Display as table' - ); - - cy.location().should((loc) => { - expect(loc.search).to.eq('?view=card&searchText=dog'); - }); - - cy.get('[aria-label="page view Display as table"]').click(); - - //Should now be in table view - cy.get('[aria-label="page view Display as cards"]').should('exist'); - cy.get('[aria-label="page view Display as cards"]').contains( - 'Display as cards' - ); - - cy.location().should((loc) => { - expect(loc.search).to.eq('?view=table&searchText=dog'); - }); - }); - - it('should be able to scroll down and load more rows', () => { - cy.get('[aria-label="Search table"]') - .contains('Datafile') - .contains('300') - .click(); - cy.get('[aria-rowcount="50"]').should('exist'); - cy.get('[aria-label="grid"]').scrollTo('bottom'); - cy.get('[aria-rowcount="75"]').should('exist'); - }); - - it('should be able to choose number of results to display', () => { - cy.login(); - cy.visit('/search/data/'); - cy.intercept('**/investigations/count?where=%7B%22id*').as( - 'investigationsCount' - ); - cy.intercept('**/investigations?*').as('investigations'); - - cy.clearDownloadCart(); - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - cy.get('[aria-label="page view Display as cards"]').click(); - cy.get('[aria-label="card-buttons"]', { timeout: 10000 }).should( - 'have.length', - 10 - ); - - cy.get('select[id="select-max-results"]', { - timeout: 10000, - }) - .select('20') - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - cy.get('[aria-label="card-buttons"]', { timeout: 10000 }).should( - 'have.length', - 20 - ); - - cy.get('select[id="select-max-results"]', { - timeout: 10000, - }) - .select('30') - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - cy.get('[aria-label="card-buttons"]', { timeout: 10000 }).should( - 'have.length', - 30 - ); - }); - - //This test appears to get a different number of results locally compared to the automated tests - //on github meaning the test fails - it.skip('should be able to change page in card view', () => { - cy.get('[aria-label="Search text input"]').find('#filled-search').clear(); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - - cy.get('[aria-label="page view Display as cards"]').click(); - - cy.get('[aria-label="Go to page 2"]', { timeout: 10000 }).first().click(); - cy.get('[data-testid="card"]') - .first() - .contains('Guy maintain us process official people suffer.'); - - cy.get('[aria-label="Go to next page"]', { timeout: 10000 }) - .first() - .click(); - cy.get('[data-testid="card"]') - .first() - .contains('Yourself smile either I pass significant.'); - - cy.get('[aria-label="Go to last page"]', { timeout: 10000 }) - .first() - .click(); - cy.get('[data-testid="card"]') - .first() - .contains('Window former upon writer help step account.'); - - cy.get('[aria-label="Go to previous page"]', { timeout: 10000 }) - .first() - .click(); - cy.get('[data-testid="card"]') - .first() - .contains('Someone statement Republican plan watch.'); - - cy.get('[aria-label="Go to first page"]', { timeout: 10000 }) - .first() - .click(); - cy.get('[data-testid="card"]') - .first() - .contains('Including spend increase ability music skill former.'); - }); - - it('should display selection alert banner correctly', () => { - cy.get(`[aria-rowindex="1"] [aria-colindex="1"]`) - .click() - .wait('@investigations', { timeout: 10000 }); - - cy.get('[aria-label="selection-alert"]').should('exist'); - cy.get('[aria-label="selection-alert-text"]') - .invoke('text') - .then((text) => { - expect(text.trim()).equal('1 item has been added to selection.'); - }); - - //Check can go to selection - cy.get('[aria-label="selection-alert-link"]').click(); - cy.location().should((loc) => { - expect(loc.pathname).to.equal('/download'); - }); - cy.go('back'); - - //Check can close banner - cy.get('[aria-label="selection-alert-close"]').click(); - cy.get('[aria-label="selection-alert"]').should('not.exist'); - }); - - it('should be able to deselect checkboxes', () => { - cy.get('#search-entities-menu').click(); - cy.get('[aria-label="Investigation checkbox"]').click(); - cy.get('[aria-label="Datafile checkbox"]').click(); - //Close drop down menu - cy.get('body').type('{esc}'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - - cy.location().should((loc) => { - expect(loc.search).to.eq( - '?searchText=dog&datafile=false&investigation=false¤tTab=dataset' - ); - }); - - cy.get('[aria-label="Search table"]') - .contains('Investigation') - .should('not.exist'); - cy.get('[aria-label="Search table"]') - .contains('Datafile') - .should('not.exist'); - cy.get('[aria-label="Search table"]') - .contains('Dataset') - .contains('14') - .should('exist'); - }); - - it('should display number of items in cart correctly and go to the download page when clicked (Table)', () => { - // Check that the download cart has displayed correctly. - cy.get('[aria-label="Go to selections"]', { timeout: 10000 }).contains( - // matches empty string i.e. no badge - /^$/ - ); - - cy.get('[aria-label="select row 0"]', { timeout: 10000 }).eq(0).click(); - - cy.get('[aria-label="Go to selections"]', { timeout: 10000 }).contains( - /^1/ - ); - - cy.get('[aria-label="select row 1"]', { timeout: 10000 }).eq(0).click(); - - cy.get('[aria-label="Go to selections"]', { timeout: 10000 }).contains( - /^2/ - ); - - cy.get('[aria-label="Go to selections"]').click(); - cy.url().should('include', '/download'); - }); - - it('should display number of items in cart correctly and go to the download page when clicked (Card)', () => { - cy.get('[aria-label="page view Display as cards"]').click(); - // Check that the download cart has displayed correctly. - cy.get('[aria-label="Go to selections"]', { timeout: 10000 }).contains( - // matches empty string i.e. no badge - /^$/ - ); - - cy.get('[aria-label="card-button-1"]', { timeout: 10000 }).eq(0).click(); - - cy.get('[aria-label="Go to selections"]', { timeout: 10000 }).contains( - /^1/ - ); - - cy.get('[aria-label="card-button-1"]', { timeout: 10000 }).eq(1).click(); - - cy.get('[aria-label="Go to selections"]', { timeout: 10000 }).contains( - /^2/ - ); - - cy.get('[aria-label="Go to selections"]').click(); - cy.url().should('include', '/download'); - }); - - it('should be able to select a start date', () => { - cy.get('[aria-label="Start date input"]').type('2009-01-01'); - - cy.get('[aria-label="Submit search"]') - .click() - .wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - - cy.location().should((loc) => { - expect(loc.search).to.contains('?searchText=dog&startDate=2009-01-01'); - }); - - cy.get('[aria-label="Search table"]') - .contains('Investigation') - .contains('8') - .should('exist'); - }); - - it('should be able to load results from a URL', () => { - cy.visit( - '/search/data/?view=card&searchText=test&startDate=2009-01-01' - ).wait(['@investigations', '@investigations', '@investigationsCount'], { - timeout: 10000, - }); - - //Should be in card view - cy.get('[aria-label="page view Display as table"]').should('exist'); - cy.get('[aria-label="page view Display as table"]').contains( - 'Display as table' - ); - - cy.get('[aria-label="Search table"]') - .contains('Investigation') - .contains('4') - .should('exist'); - cy.get('[aria-label="Search table"]') - .contains('Dataset') - .contains('7') - .should('exist'); - cy.get('[aria-label="Search table"]') - .contains('Datafile') - .contains('300') - .should('exist'); - }); - }); -}); diff --git a/packages/datagateway-search/cypress/plugins/index.js b/packages/datagateway-search/cypress/plugins/index.js deleted file mode 100644 index 1f9707ae8..000000000 --- a/packages/datagateway-search/cypress/plugins/index.js +++ /dev/null @@ -1,21 +0,0 @@ -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) - -// eslint-disable-next-line -module.exports = (on, config) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config - on('task', { - failed: require('cypress-failed-log/src/failed')(), - }); -}; diff --git a/packages/datagateway-search/cypress/support/commands.js b/packages/datagateway-search/cypress/support/commands.js index c18937149..b42f406b1 100644 --- a/packages/datagateway-search/cypress/support/commands.js +++ b/packages/datagateway-search/cypress/support/commands.js @@ -25,6 +25,7 @@ // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) import jsrsasign from 'jsrsasign'; +import '@testing-library/cypress/add-commands'; const parseJwt = (token) => { const base64Url = token.split('.')[1]; @@ -55,30 +56,40 @@ export const readSciGatewayToken = () => { }; Cypress.Commands.add('login', () => { - return cy.readFile('server/e2e-settings.json').then((settings) => { - cy.request('POST', `${settings.apiUrl}/sessions`, { - username: '', - password: '', - mechanism: 'anon', - }).then((response) => { - const jwtHeader = { alg: 'HS256', typ: 'JWT' }; - const payload = { - sessionId: response.body.sessionID, - username: 'test', - }; - const jwt = jsrsasign.KJUR.jws.JWS.sign( - 'HS256', - jwtHeader, - payload, - 'shh' - ); - window.localStorage.setItem('scigateway:token', jwt); + cy.session('login', () => { + cy.request('datagateway-search-settings.json').then((response) => { + const settings = response.body; + cy.request({ + method: 'POST', + url: `${settings.icatUrl}/session`, + body: `json=${JSON.stringify({ + plugin: 'simple', + credentials: [{ username: 'root' }, { password: 'pw' }], + })}`, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }).then((response) => { + const jwtHeader = { alg: 'HS256', typ: 'JWT' }; + const payload = { + sessionId: response.body.sessionId, + username: 'dev', + }; + const jwt = jsrsasign.KJUR.jws.JWS.sign( + 'HS256', + jwtHeader, + payload, + 'shh' + ); + window.localStorage.setItem('scigateway:token', jwt); + }); }); }); }); Cypress.Commands.add('clearDownloadCart', () => { - return cy.readFile('server/e2e-settings.json').then((settings) => { + return cy.request('datagateway-search-settings.json').then((response) => { + const settings = response.body; cy.request({ method: 'DELETE', url: `${settings.downloadApiUrl}/user/cart/${settings.facilityName}/cartItems`, diff --git a/packages/datagateway-search/cypress/support/index.js b/packages/datagateway-search/cypress/support/e2e.js similarity index 100% rename from packages/datagateway-search/cypress/support/index.js rename to packages/datagateway-search/cypress/support/e2e.js diff --git a/packages/datagateway-search/cypress/support/index.d.ts b/packages/datagateway-search/cypress/support/index.d.ts index cafb746f3..d36c3ef79 100644 --- a/packages/datagateway-search/cypress/support/index.d.ts +++ b/packages/datagateway-search/cypress/support/index.d.ts @@ -1,6 +1,7 @@ declare namespace Cypress { interface Chainable { login(): Cypress.Chainable; + clearDownloadCart(): Cypress.Chainable; } } diff --git a/packages/datagateway-search/cypress/tsconfig.json b/packages/datagateway-search/cypress/tsconfig.json index d38e7a12f..745ee041a 100644 --- a/packages/datagateway-search/cypress/tsconfig.json +++ b/packages/datagateway-search/cypress/tsconfig.json @@ -3,8 +3,16 @@ "strict": true, "baseUrl": "../node_modules", "target": "es5", - "lib": ["es5", "dom"], - "types": ["cypress"] + "lib": [ + "es5", + "dom" + ], + "types": [ + "cypress", + "@testing-library/cypress" + ] }, - "include": ["**/*"] + "include": [ + "**/*" + ] } diff --git a/packages/datagateway-search/package.json b/packages/datagateway-search/package.json index 81ea8f6a0..fe086b12b 100644 --- a/packages/datagateway-search/package.json +++ b/packages/datagateway-search/package.json @@ -1,50 +1,64 @@ { "name": "datagateway-search", - "version": "1.1.3", + "version": "2.0.0", "private": true, "dependencies": { - "@date-io/date-fns": "^1.3.13", - "@material-ui/core": "^4.11.3", - "@material-ui/icons": "^4.11.2", - "@material-ui/pickers": "^3.3.10", - "@types/jest": "^27.4.0", - "@types/node": "^17.0.17", - "@types/react": "^17.0.2", - "@types/react-dom": "^17.0.1", - "axios": "^0.26.0", - "connected-react-router": "^6.9.1", - "custom-event-polyfill": "^1.0.7", - "datagateway-common": "^1.1.3", - "date-fns": "^2.28.0", - "history": "^4.10.1", - "i18next": "^21.6.13", - "i18next-browser-languagedetector": "^6.1.2", - "i18next-http-backend": "^1.3.2", - "loglevel": "^1.8.0", - "react": "^16.13.1", - "react-app-polyfill": "^3.0.0", - "react-dom": "^16.11.0", - "react-i18next": "^11.15.4", - "react-query": "^3.18.1", - "react-redux": "^7.1.0", - "react-router": "^5.0.1", - "react-router-dom": "^5.3.0", + "@craco/craco": "7.1.0", + "@date-io/date-fns": "2.17.0", + "@emotion/react": "11.11.1", + "@emotion/styled": "11.11.0", + "@mui/icons-material": "5.11.0", + "@mui/material": "5.11.0", + "@mui/x-date-pickers": "6.11.2", + "@types/history": "4.7.11", + "@types/jest": "29.5.2", + "@types/jsrsasign": "10.5.2", + "@types/lodash.isequal": "4.5.8", + "@types/node": "20.11.5", + "@types/react": "17.0.39", + "@types/react-dom": "17.0.11", + "@types/react-router-dom": "5.3.3", + "@types/react-virtualized": "9.21.10", + "@types/redux-logger": "3.0.8", + "axios": "1.6.1", + "connected-react-router": "6.9.1", + "custom-event-polyfill": "1.0.7", + "datagateway-common": "^2.0.0", + "date-fns": "2.30.0", + "eslint-config-prettier": "8.10.0", + "eslint-plugin-cypress": "2.15.1", + "eslint-plugin-prettier": "4.2.1", + "history": "4.10.1", + "i18next": "22.0.3", + "i18next-browser-languagedetector": "7.2.0", + "i18next-http-backend": "2.4.2", + "jsrsasign": "11.0.0", + "lodash.isequal": "4.5.0", + "loglevel": "1.9.1", + "prettier": "2.8.0", + "react": "17.0.2", + "react-app-polyfill": "3.0.0", + "react-dom": "17.0.2", + "react-i18next": "12.3.1", + "react-query": "3.39.2", + "react-redux": "8.1.3", + "react-router-dom": "5.3.0", "react-scripts": "5.0.0", - "react-virtualized": "^9.22.3", - "redux": "^4.1.2", - "redux-logger": "^3.0.6", - "redux-mock-store": "^1.5.4", - "redux-thunk": "^2.4.1", - "resize-observer-polyfill": "^1.5.1", - "single-spa-react": "^4.3.1", - "tslib": "^2.3.0", - "typescript": "4.5.3", - "url-search-params-polyfill": "^8.1.1" + "react-virtualized": "9.22.3", + "redux": "4.2.0", + "redux-logger": "3.0.6", + "redux-mock-store": "1.5.4", + "redux-thunk": "2.4.1", + "resize-observer-polyfill": "1.5.1", + "single-spa-react": "4.6.1", + "tslib": "2.6.0", + "typescript": "5.3.3", + "url-search-params-polyfill": "8.2.4" }, "scripts": { "start": "craco start", "build": "craco build", - "serve:build": "yarn build & serve -l 5001 build", + "serve:build": "yarn build && serve -l 5001 build", "test": "craco test --env=jsdom --coverage --watchAll=false", "test:watch": "craco test --env=jsdom --watch", "build:e2e": "cross-env REACT_APP_E2E_TESTING=true GENERATE_SOURCEMAP=false craco build", @@ -53,7 +67,7 @@ "e2e": "start-server-and-test e2e:serve http://localhost:3000 cy:run", "cy:open": "cypress open", "cy:run": "cypress run", - "lint:js": "eslint --ext=tsx --ext=ts --ext=js --ext=jsx --fix ./src && yarn build", + "lint:js": "eslint --max-warnings=0 --ext=tsx --ext=ts --ext=js --ext=jsx --fix ./src ./cypress && tsc --noEmit", "eject": "react-scripts eject", "pre-commit": "lint-staged" }, @@ -70,8 +84,8 @@ ] }, "jest": { - "snapshotSerializers": [ - "enzyme-to-json/serializer" + "transformIgnorePatterns": [ + "node_modules/(?!axios)" ], "collectCoverageFrom": [ "src/**/*.{tsx,js,jsx}", @@ -92,34 +106,25 @@ ] }, "devDependencies": { - "@craco/craco": "^6.4.3", - "@types/enzyme": "^3.10.10", - "@types/jsrsasign": "^9.0.3", - "@types/react-redux": "^7.1.16", - "@types/react-router": "^5.1.17", - "@types/react-router-dom": "^5.3.3", - "@types/react-virtualized": "^9.21.10", - "@types/redux-logger": "^3.0.8", - "@types/redux-mock-store": "^1.0.3", - "@typescript-eslint/eslint-plugin": "^5.5.0", - "@typescript-eslint/parser": "^5.13.0", - "babel-eslint": "10.1.0", - "cross-env": "^7.0.3", - "cypress": "9.5.1", - "cypress-failed-log": "^2.9.1", - "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.15.6", - "enzyme-to-json": "^3.6.1", - "eslint": "^8.9.0", - "eslint-config-prettier": "^8.3.0", - "eslint-config-react-app": "^7.0.0", - "eslint-plugin-cypress": "^2.12.1", - "eslint-plugin-prettier": "^3.3.1", - "express": "^4.17.1", - "jsrsasign": "^10.5.8", - "lint-staged": "^10.5.4", - "prettier": "^2.2.1", - "serve": "^13.0.2", - "start-server-and-test": "^1.14.0" + "@babel/eslint-parser": "7.23.3", + "@testing-library/cypress": "8.0.7", + "@testing-library/jest-dom": "6.4.1", + "@testing-library/react": "12.1.3", + "@testing-library/react-hooks": "8.0.1", + "@testing-library/user-event": "14.5.2", + "@types/react-redux": "7.1.22", + "@types/redux-mock-store": "1.0.3", + "@typescript-eslint/eslint-plugin": "5.62.0", + "@typescript-eslint/parser": "5.62.0", + "cross-env": "7.0.3", + "cypress": "13.6.4", + "cypress-failed-log": "2.10.0", + "eslint": "8.56.0", + "eslint-config-react-app": "7.0.0", + "express": "4.19.2", + "jest-fail-on-console": "3.1.1", + "lint-staged": "13.3.0", + "serve": "14.2.0", + "start-server-and-test": "2.0.0" } } diff --git a/packages/datagateway-search/public/index.html b/packages/datagateway-search/public/index.html index ea43bea38..487d2de4b 100644 --- a/packages/datagateway-search/public/index.html +++ b/packages/datagateway-search/public/index.html @@ -23,12 +23,12 @@

diff --git a/packages/datagateway-search/public/res/default.json b/packages/datagateway-search/public/res/default.json index d28d28acb..b0aa0d3ae 100644 --- a/packages/datagateway-search/public/res/default.json +++ b/packages/datagateway-search/public/res/default.json @@ -39,8 +39,10 @@ "cancel": "Cancel", "clear": "Clear" }, - "limited_results_message": "Only the top {{maxNumResults}} results will be displayed for each type" + "limited_results_message": "Only the top {{maxNumResults}} results will be displayed for each type", + "my_data_tooltip": "If this is enabled, only the data generated by you will be shown." }, + "selectedFilters": "Selected filters", "searchPageTable": { "tabs_arialabel": "Search table", "header": "Search", @@ -76,9 +78,9 @@ "end_date": "End Date", "start_date": "Start Date", "visit_id": "Experiment Part", - "pid": "Part DOI", + "pid": "DOI", "summary": "Summary", - "doi": "DOI", + "doi": "Part DOI", "size": "Size", "calculate": "Calculate", "datasets": "View Datasets", @@ -95,6 +97,9 @@ "name_other": "Samples", "no_samples": "No samples" }, + "parameters": { + "label": "Investigation Parameters" + }, "publications": { "label": "Publications", "reference_one": "Reference", @@ -157,10 +162,101 @@ } } }, + "facetDimensionLabel": { + "Investigation.type.name": "Type", + "InvestigationParameter.type.name": "Parameter name", + "Sample.sample.type.name": "Sample", + "InvestigationInstrument.instrument.name": "Instrument", + "Dataset.type.name": "Type", + "Dataset.sample.type.name": "Sample", + "DatasetParameter.type.name": "Parameter name", + "Datafile.datafileFormat.name": "Format", + "DatafileParameter.type.name": "Parameter name", + "Datafile.sample.type.name": "Sample" + }, + "parameterFilters": { + "title": "Parameter filters", + "addFilter": "Add", + "selectedParameterFilterList": "Selected parameter filters", + "noFilters": "No parameter filters", + "creator": { + "close": "Close new parameter filter", + "title": "New parameter filter", + "loading": "Loading…", + "message": { + "parameterNameNotSelected": "Parameter name not selected", + "parameterTypeNotSelected": "Parameter type not selected", + "parameterNameAndTypeNotSelected": "Parameter name and type not selected" + }, + "labels": { + "parameterNameSelect": "Parameter name", + "parameterValueTypeSelect": "Parameter type", + "parameterDateTimeSelect": "Parameter is in", + "parameterStringSelect": "Parameter equals", + "parameterNumericRange": { + "min": "Minimum value", + "max": "Maximum value", + "unit": "Unit of value" + } + }, + "addFilter": "Add filter", + "removeFilter": "Remove {{filterLabel} filter" + }, + "valueType": { + "dateTime": "Date and time", + "numeric": "Numeric", + "string": "String" + } + }, + "datafileparameter": { + "type": { + "name": "Parameter Name" + } + }, + "sample": { + "type": { + "name": "Sample Name" + } + }, + "dataset": { + "type": { + "name": "Type" + } + }, + "check_boxes": { + "my_data": "My data" + }, + "sort": { + "label": "Sort by", + "_score": "Score", + "date_desc": "Date (Newest)", + "date_asc": "Date (Oldest)", + "name_asc": "Name", + "size_desc": "Largest", + "size_asc": "Smallest" + }, + "filter": { + "parameter": { + "value_type": "Type", + "name": "Parameter", + "min": "Min", + "max": "Max", + "units": "Units", + "apply": "Apply" + } + }, + "facetPanel": { + "title": "Filters", + "apply": "Apply", + "noFilters": "No filters available" + }, "buttons": { "add_to_cart": "Add to selection", + "cart_loading_tooltip": "Loading selection information...", + "cart_loading_failed_tooltip": "Selection information failed to load, please reload the page or try again later", "remove_from_cart": "Remove from selection", - "download": "Download" + "download": "Download", + "unable_to_download_tooltip": "Unable to download - this item is empty" }, "selec_alert": { "added_one": "{{count}} item has been added to selection.", @@ -171,7 +267,8 @@ "warning_message_session_token": "Please remember that your selection will be lost after 2 hours of inactivity on this site" }, "loading": { - "filter_message": "No results found with current filters applied, please modify filter settings and try again." + "filter_message": "No results found with current filters applied, please modify filter settings and try again.", + "abort_message": "Search aborted for taking too long, please try more specific search terms." }, "advanced_filters": { "show": "Show Advanced Filters", @@ -204,29 +301,54 @@ "search_options_arialabel": "Search options", "close_button_arialabel": "Close", "title": "Advanced Search Tips", - "description": "When you search for a word e.g. 'calibration', we will search for any records containing this word. But, sometimes you may wish to be more specific. Here we show you how.", - "exact_phrase": { - "title": "Search by an exact phrase", - "description": "Use quotation marks around a phrase to search for a precise sequence of words e.g. <2>\"neutron scattering\"<2>.", + "description": "Searching the metadata catalogue using one or more words should be intuitive, with the most relevant matches appearing first. However, there is a powerful syntax that supports more advanced use cases, which are described below.", + "terms": { + "title": "Terms", + "description": "By default, all words in the search text are treated as separate terms. Results must contain at least one term to be returned, and they can occur in any order in the result. When using the default relevancy based sorting, results containing the most terms will appear first. For example, <10>neutron scattering will return results containing both terms first, then results containing only one or the other.", + "link1": "?searchText=neutron+scattering" + }, + "phrases": { + "title": "Phrases", + "description": "Use quotation marks around a multiple terms to create a phrase. Results must contain the entire phrase, with the words in order. For example, <7>\"neutron scattering\".", "link1": "?searchText=\"neutron+scattering\"" }, "logic_operators": { - "title": "Using logic operators", - "description": "Find all data containing 'neutron' and 'scattering' with <1>'neutron AND scattering'.

Find all data containing either neutron or scattering with '<4>neutron OR scattering'.

Find all data that contains the phrase 'scattering' but exclude those containing 'elastic' with '<7>scattering NOT elastic'.

Use brackets around phrases to construct more complicated searches e.g. '<10>scattering NOT (elastic OR neutron)'.", - "link1": "?searchText=neutron+AND+scattering", - "link2": "?searchText=neutron+OR+scattering", - "link3": "?searchText=scattering+NOT+elastic", - "link4": "?searchText=scattering+NOT+%28elastic+OR+neutron%29" + "title": "Logic operators", + "description": "OR is the default behaviour for multiple terms: <6>neutron OR scattering is equivalent to <10>neutron scattering.

AND requires both terms on either side of the keyword must be present in the result: <22>neutron AND scattering.

+ requires the next term be present in the result: <34>+neutron +scattering.

NOT or - requires the next term not be present in the result: <48>-neutron NOT scattering.

Finally, brackets can be used to build complicated logic: <55>(+neutron -photon) AND (scattering OR diffraction).", + "link1": "?searchText=neutron+OR+scattering", + "link2": "?searchText=neutron+scattering", + "link3": "?searchText=neutron+AND+scattering", + "link4": "?searchText=%2Bneutron+%2Bscattering", + "link5": "?searchText=-neutron+NOT+scattering", + "link6": "?searchText=(%2Bneutron+-photon)+AND+(scattering+OR+diffraction)" + }, + "synonyms": { + "title": "Synonyms", + "description": "Results do not need to have the exact term searched for in order to match. If the root word is the same, then the results should appear. <5>Scattering, <8>scattered, <11>scatters etc. are all treated as if the user searched for <15>scatter. Additionally, some common scientific terminology has additional support. Chemical symbols, amino acid codes and the PaNET ontology of techniques are all supported, so that searching for <18>xas li is equivalent to searching for <22>x-ray absorption spectoscopy lithium.", + "link1": "?searchText=Scattering", + "link2": "?searchText=scattered", + "link3": "?searchText=scatters", + "link4": "?searchText=scatter", + "link5": "?searchText=xas+li", + "link6": "?searchText=x-ray+absorption+spectoscopy+lithium" }, "wildcards": { "title": "Using wildcards", - "description": "Use wildcards to take the place of one or more characters in a phrase.

A question mark '?' can be used to search for a phrase with one or more character missing e.g. '<2>te?t' will return results containing 'test' or 'text'.

An asterix '*' can be used to replace zero or more characters e.g. '<4>*ium' will return results containing words like 'sodium' and 'vanadium'.", + "description": "To take the place of one character, use ?. To represent any number (0 or more) characters, use *. For example, <7>te?t would return results containing test or text, and <11>te*t would also return testament.

Note that the use of wildcards can prevent the synonym functionality described above. <19>scatterin? will not result in matches, as we match against the root word which is scatter. <23>scatter* however would work. Furthermore, use of wildcards (especially leading wildcards) can take longer than an otherwise identical search, so they should be used sparingly.", "link1": "?searchText=te%3Ft", - "link2": "?searchText=*ium" + "link2": "?searchText=te*t", + "link3": "?searchText=scatterin%3F", + "link4": "?searchText=scatter*" + }, + "special_characters": { + "title": "Special characters", + "description": "In addition to whitespace, there are other characters used to split terms based on context. A . character is treated as a separator only when between a mixture of letters and numbers, but is preserved when in-between two letters or two numbers. - is always treated as a separator. This can make searching for file extension difficult, as a searching for <9>1234.dat will match any result containing the term 1234 or dat, but not for example abcd.dat as that is treated as one single term.

When building a phrase, special characters in the phrase will not perform their special function and instead are treated as white space. This can be a useful way of effectively ignoring slashes in a file path, but will also prevent wildcards from working.", + "link1": "?searchText=1234.dat" }, - "limited_search_results": { - "title": "Limited results", - "description": "Due to technical and performance reasons, only the top {{maxNumResults}} results will be displayed for each entity type i.e. Investigation, Dataset or Datafile. If you find your search gives {{maxNumResults}} results, try using a more specific query to find what you are looking for." + "fields": { + "title": "Fields", + "description": "By default, terms are applied to several fields of the metadata. However more specific searches are possible based on the list of supported fields below (note that not all fields will always have a value and the fields differ between entities). For example, to find results that mention calibration in their summary but not their title, search for <16>summary:calibration -title:calibration

Investigation<22><0>title<1>summary<2>name<3>type.name<4>visitId<5>facility.name<6>doi Dataset<24><0>name<1>description<2>type.name<3>visitId<4>sample.name<5>sample.type.name<6>doi Datafile<26><0>name<1>description<2>location<3>datafileFormat.name<4>visitId<5>sample.name<6>sample.type.name<7>doi ", + "link1": "?searchText=summary%3Acalibration+-title%3Acalibration" }, "footer": "Further information on searching can be found <2>here." } diff --git a/packages/datagateway-search/server/e2e-test-server.js b/packages/datagateway-search/server/e2e-test-server.js index eb329abb3..5fc39ff49 100644 --- a/packages/datagateway-search/server/e2e-test-server.js +++ b/packages/datagateway-search/server/e2e-test-server.js @@ -1,51 +1,61 @@ -var express = require('express'); -var path = require('path'); -var serveStatic = require('serve-static'); -var axios = require('axios'); -var fs = require('fs') +const express = require('express'); +const path = require('path'); +const serveStatic = require('serve-static'); +const axios = require('axios'); +const fs = require('fs'); -var app = express(); +const app = express(); app.use( express.json(), serveStatic(path.resolve('./build'), { index: ['index.html', 'index.htm'] }) ); -app.get('/datagateway-search-settings.json', function(req, res) { - res.sendFile(path.resolve('./server/e2e-settings.json')); +app.get('/datagateway-search-settings.json', function (req, res) { + // detect if the E2E test is runnFing inside CI + // If so, use the settings file specific to E2E + // Otherwise, use the same settings file that is also for running the app normally (yarn start etc). + const isCiEnv = process.env.CI; + res.sendFile( + path.resolve( + isCiEnv + ? './server/e2e-settings.json' + : './public/datagateway-search-settings.json' + ) + ); }); -app.get(/\/sessions|investigations|datasets|datafiles/, function(req, res) { +app.get(/\/sessions|investigations|datasets|datafiles/, function (req, res) { fs.readFile('server/e2e-settings.json').then((settings) => { axios - .get(settings.apiUrl + req.url, { - headers: req.headers, - }) - .then(apiRes => { - res.json(apiRes.data); - }) - .catch(error => { - res.status(error.response.status).end(); - }); + .get(settings.apiUrl + req.url, { + headers: req.headers, + }) + .then((apiRes) => { + res.json(apiRes.data); + }) + .catch((error) => { + res.status(error.response.status).end(); + }); }); }); -app.post(/\/sessions|investigations|datasets|datafiles/, function(req, res) { +app.post(/\/sessions|investigations|datasets|datafiles/, function (req, res) { fs.readFile('server/e2e-settings.json').then((settings) => { axios .post(settings.apiUrl + req.url, req.body, { headers: req.headers, }) - .then(apiRes => { + .then((apiRes) => { res.json(apiRes.data); }) - .catch(error => { + .catch((error) => { res.status(error.response.status).end(); }); }); }); -app.get('/*', function(req, res) { +app.get('/*', function (req, res) { res.sendFile(path.resolve('./build/index.html')); }); diff --git a/packages/datagateway-search/src/App.test.tsx b/packages/datagateway-search/src/App.test.tsx index a50a3b0c0..76b626f48 100644 --- a/packages/datagateway-search/src/App.test.tsx +++ b/packages/datagateway-search/src/App.test.tsx @@ -1,22 +1,26 @@ import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; -import { createMount } from '@material-ui/core/test-utils'; -import { mount as enzymeMount } from 'enzyme'; -import * as log from 'loglevel'; -import { Provider } from 'react-redux'; +import log from 'loglevel'; +import { render, screen, waitFor } from '@testing-library/react'; +import { configureApp, settingsLoaded } from './state/actions'; -jest.mock('loglevel'); +jest.mock('loglevel').mock('./state/actions', () => ({ + ...jest.requireActual('./state/actions'), + configureApp: jest.fn(), +})); describe('App', () => { - let mount: typeof enzymeMount; + beforeEach(() => { + jest.restoreAllMocks(); + jest.clearAllMocks(); - beforeAll(() => { - mount = createMount(); - }); - - afterAll(() => { - mount.cleanUp(); + // pretend app is configured successfully + (configureApp as jest.MockedFn).mockReturnValue( + async (dispatch) => { + dispatch(settingsLoaded()); + } + ); }); it('renders without crashing', () => { @@ -25,17 +29,44 @@ describe('App', () => { ReactDOM.unmountComponentAtNode(div); }); - it('catches errors using componentDidCatch and shows fallback UI', () => { - const wrapper = mount(); - const error = new Error('test'); - wrapper.find(Provider).simulateError(error); + it('shows loading screen when configuring app', async () => { + (configureApp as jest.MockedFn).mockReturnValue( + () => + new Promise((_) => { + // never resolve the promise to pretend the app is still being configured + }) + ); + + render(); + + expect(await screen.findByText('Loading...')).toBeInTheDocument(); + expect(screen.queryByText('page')).toBeNull(); + }); + + it('catches errors using componentDidCatch and shows fallback UI', async () => { + const error = 'test SearchPageContainer error'; + + // throw an error in function used by searchPageContainer + jest + .spyOn(window.localStorage.__proto__, 'removeItem') + .mockImplementation(() => { + throw new Error(error); + }); + + jest.spyOn(console, 'error').mockImplementation(() => { + // suppress console error + }); + + render(); - expect(wrapper.exists('.error')).toBe(true); + await waitFor(() => { + // check that the error is logged + expect(log.error).toHaveBeenCalledWith( + `datagateway_search failed with error: Error: ${error}` + ); + }); - expect(log.error).toHaveBeenCalled(); - const mockLog = (log.error as jest.Mock).mock; - expect(mockLog.calls).toContainEqual([ - `datagateway_search failed with error: ${error}`, - ]); + // check that fallback UI is shown + expect(await screen.findByText('app.error')).toBeInTheDocument(); }); }); diff --git a/packages/datagateway-search/src/App.tsx b/packages/datagateway-search/src/App.tsx index ead617270..89b44063b 100644 --- a/packages/datagateway-search/src/App.tsx +++ b/packages/datagateway-search/src/App.tsx @@ -1,7 +1,3 @@ -import { - createGenerateClassName, - StylesProvider, -} from '@material-ui/core/styles'; import { ConnectedRouter, routerMiddleware } from 'connected-react-router'; import { DGCommonMiddleware, @@ -18,7 +14,7 @@ import { Action, // eslint-disable-next-line import/no-extraneous-dependencies } from 'history'; -import * as log from 'loglevel'; +import log from 'loglevel'; import React from 'react'; import { batch, connect, Provider } from 'react-redux'; import { AnyAction, applyMiddleware, compose, createStore, Store } from 'redux'; @@ -80,15 +76,6 @@ history.listen = (fn) => { const middleware = [thunk, routerMiddleware(history), DGCommonMiddleware]; -const generateClassName = createGenerateClassName({ - productionPrefix: 'dgws', - - // Only set disable when we are in production and not running e2e tests; - // ensures class selectors are working on tests. - disableGlobal: - process.env.NODE_ENV === 'production' && !process.env.REACT_APP_E2E_TESTING, -}); - if (process.env.NODE_ENV === `development`) { /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ const logger = (createLogger as any)({ collapsed: true }); @@ -121,6 +108,7 @@ document.addEventListener(MicroFrontendId, (e) => { class App extends React.Component { store: Store; + public constructor(props: unknown) { super(props); this.state = { hasError: false }; @@ -187,19 +175,17 @@ class App extends React.Component { - - - - Finished loading - } - > - - - - - + + + Finished loading + } + > + + + + diff --git a/packages/datagateway-search/src/__mocks__/loglevel.ts b/packages/datagateway-search/src/__mocks__/loglevel.ts new file mode 100644 index 000000000..01d81f572 --- /dev/null +++ b/packages/datagateway-search/src/__mocks__/loglevel.ts @@ -0,0 +1,3 @@ +// TODO: move __mocks__ folder back to package root once facebook/create-react-app#7539 is fixed + +export default jest.createMockFromModule('loglevel'); diff --git a/packages/datagateway-search/src/__snapshots__/searchBoxContainer.component.test.tsx.snap b/packages/datagateway-search/src/__snapshots__/searchBoxContainer.component.test.tsx.snap deleted file mode 100644 index b1eae7494..000000000 --- a/packages/datagateway-search/src/__snapshots__/searchBoxContainer.component.test.tsx.snap +++ /dev/null @@ -1,212 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`SearchBoxContainer - Tests renders searchBoxContainer correctly 1`] = ` -
- - - - - - - - - - - - - - -
- - - For example - - "instrument calibration" - - or - - - neutron AND scattering - - . - - - - -
-
- - - - searchBox.limited_results_message {maxNumResults:{tabs:{datasetTab:false,datafileTab:false,investigationTab:false},selectAllSetting:true,settingsLoaded:false,sideLayout:false,searchableEntities:[investigation,dataset,datafile],maxNumResults:300}} - -
-
-
-
-`; - -exports[`SearchBoxContainerSide - Tests renders searchBoxContainerSide correctly 1`] = ` - -`; diff --git a/packages/datagateway-search/src/__snapshots__/searchPageCardView.component.test.tsx.snap b/packages/datagateway-search/src/__snapshots__/searchPageCardView.component.test.tsx.snap deleted file mode 100644 index e34a5cfa8..000000000 --- a/packages/datagateway-search/src/__snapshots__/searchPageCardView.component.test.tsx.snap +++ /dev/null @@ -1,4788 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`SearchPageCardView renders correctly when request received 1`] = ` - - - - - - -
- - - - -
- - -
- - - -
-
-
- - - tabs.investigation - - - } - onChange={[Function]} - selected={true} - textColor="inherit" - value="investigation" - > - - - tabs.investigation - - - } - onChange={[Function]} - selected={true} - textColor="inherit" - value="investigation" - > - - - - - - - - - - tabs.dataset - - - } - onChange={[Function]} - selected={false} - textColor="inherit" - value="dataset" - > - - - tabs.dataset - - - } - onChange={[Function]} - selected={false} - textColor="inherit" - value="dataset" - > - - - - - - - - - - tabs.datafile - - - } - onChange={[Function]} - selected={false} - textColor="inherit" - value="datafile" - > - - - tabs.datafile - - - } - onChange={[Function]} - selected={false} - textColor="inherit" - value="datafile" - > - - - - - - - -
- - - - - -
-
-
-
-
- - -
- -
- - - - - - - - - -
-
-
-
-
-
-
-
-
-
-
-
-
- - - -
-
-
-
-
-
-
-`; diff --git a/packages/datagateway-search/src/__snapshots__/searchPageContainer.component.test.tsx.snap b/packages/datagateway-search/src/__snapshots__/searchPageContainer.component.test.tsx.snap deleted file mode 100644 index 279e77345..000000000 --- a/packages/datagateway-search/src/__snapshots__/searchPageContainer.component.test.tsx.snap +++ /dev/null @@ -1,1423 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`SearchPageContainer - Tests renders searchPageContainer correctly 1`] = ` - - - - - - - - - - - - Search data - - - - - - - - - - - -`; diff --git a/packages/datagateway-search/src/__snapshots__/searchPageTable.component.test.tsx.snap b/packages/datagateway-search/src/__snapshots__/searchPageTable.component.test.tsx.snap deleted file mode 100644 index d7f8ce281..000000000 --- a/packages/datagateway-search/src/__snapshots__/searchPageTable.component.test.tsx.snap +++ /dev/null @@ -1,5543 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`SearchPageTable renders correctly when request received 1`] = ` - - - - - - -
- - - - -
- - -
- - - -
-
-
- - 0 - - } - id="investigation-badge" - max={999} - showZero={true} - > - - tabs.investigation - - - } - onChange={[Function]} - selected={true} - textColor="inherit" - value="investigation" - > - - 0 - - } - id="investigation-badge" - max={999} - showZero={true} - > - - tabs.investigation - - - } - onChange={[Function]} - selected={true} - textColor="inherit" - value="investigation" - > - - - - - - - - - - tabs.dataset - - - } - onChange={[Function]} - selected={false} - textColor="inherit" - value="dataset" - > - - - tabs.dataset - - - } - onChange={[Function]} - selected={false} - textColor="inherit" - value="dataset" - > - - - - - - - - - - tabs.datafile - - - } - onChange={[Function]} - selected={false} - textColor="inherit" - value="datafile" - > - - - tabs.datafile - - - } - onChange={[Function]} - selected={false} - textColor="inherit" - value="datafile" - > - - - - - - - -
- - - - - -
-
-
-
-
- - -
- -
- - - - - - - - - -
-
-
-
-
-
-
-
-
-
-
-
-
- - - -
-
-
-
-
-
-
-`; diff --git a/packages/datagateway-search/src/card/__snapshots__/datasetSearchCardView.component.test.tsx.snap b/packages/datagateway-search/src/card/__snapshots__/datasetSearchCardView.component.test.tsx.snap deleted file mode 100644 index c47ae51e9..000000000 --- a/packages/datagateway-search/src/card/__snapshots__/datasetSearchCardView.component.test.tsx.snap +++ /dev/null @@ -1,141 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Dataset - Card View renders correctly 1`] = ` -Object { - "buttons": Array [ - [Function], - ], - "data": Array [ - Object { - "createTime": "2019-07-23", - "endDate": "2019-07-25", - "id": 1, - "investigation": Object { - "doi": "doi 1", - "endDate": "2019-06-11", - "facility": Object { - "id": 7, - "name": "facility name", - }, - "id": 2, - "investigationInstruments": Array [ - Object { - "id": 3, - "instrument": Object { - "id": 4, - "name": "LARMOR", - }, - }, - ], - "name": "Investigation test name", - "size": 1, - "startDate": "2019-06-10", - "studyInvestigations": Array [ - Object { - "id": 5, - "investigation": Object { - "id": 2, - "name": "Investigation test name", - "title": "Investigation test title", - "visitId": "1", - }, - "study": Object { - "createTime": "2019-06-10", - "id": 6, - "modTime": "2019-06-10", - "name": "study name", - "pid": "study pid", - }, - }, - ], - "summary": "foo bar", - "title": "Investigation test title", - "visitId": "1", - }, - "modTime": "2019-07-23", - "name": "Dataset test name", - "size": 1, - "startDate": "2019-07-24", - }, - ], - "description": Object { - "dataKey": "description", - "filterComponent": [Function], - "label": "datasets.details.description", - }, - "filters": Object {}, - "information": Array [ - Object { - "content": [Function], - "dataKey": "datafileCount", - "disableSort": true, - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.datafile_count", - }, - Object { - "content": [Function], - "dataKey": "investigation.title", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.investigation", - }, - Object { - "dataKey": "createTime", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.create_time", - }, - Object { - "dataKey": "modTime", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "datasets.modified_time", - }, - ], - "loadedCount": true, - "loadedData": true, - "moreInformation": [Function], - "onFilter": [Function], - "onPageChange": [Function], - "onResultsChange": [Function], - "onSort": [Function], - "page": null, - "results": null, - "sort": Object {}, - "title": Object { - "content": [Function], - "dataKey": "name", - "filterComponent": [Function], - "label": "datasets.name", - }, - "totalDataCount": 1, -} -`; diff --git a/packages/datagateway-search/src/card/__snapshots__/investigationSearchCardView.component.test.tsx.snap b/packages/datagateway-search/src/card/__snapshots__/investigationSearchCardView.component.test.tsx.snap deleted file mode 100644 index edecd9d12..000000000 --- a/packages/datagateway-search/src/card/__snapshots__/investigationSearchCardView.component.test.tsx.snap +++ /dev/null @@ -1,171 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Investigation - Card View renders correctly 1`] = ` -Object { - "buttons": Array [ - [Function], - ], - "data": Array [ - Object { - "createTime": "2019-07-23", - "doi": "doi 1", - "endDate": "2019-07-25", - "id": 1, - "investigationInstruments": Array [ - Object { - "id": 3, - "instrument": Object { - "id": 4, - "name": "LARMOR", - }, - }, - ], - "modTime": "2019-07-23", - "name": "Investigation test name", - "size": 1, - "startDate": "2019-07-24", - "studyInvestigations": Array [ - Object { - "id": 5, - "investigation": Object { - "id": 2, - "name": "Investigation test name", - "title": "Investigation test title", - "visitId": "1", - }, - "study": Object { - "createTime": "2019-06-10", - "id": 6, - "modTime": "2019-06-10", - "name": "study name", - "pid": "study pid", - }, - }, - ], - "title": "Test 1", - "visitId": "1", - }, - ], - "description": Object { - "dataKey": "summary", - "filterComponent": [Function], - "label": "investigations.details.summary", - }, - "filters": Object {}, - "information": Array [ - Object { - "content": [Function], - "dataKey": "doi", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.doi", - }, - Object { - "dataKey": "visitId", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.visit_id", - }, - Object { - "dataKey": "name", - "disableSort": true, - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.details.name", - }, - Object { - "content": [Function], - "dataKey": "datasetCount", - "disableSort": true, - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.dataset_count", - }, - Object { - "content": [Function], - "dataKey": "investigationInstruments.instrument.name", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.instrument", - "noTooltip": true, - }, - Object { - "dataKey": "startDate", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.details.start_date", - }, - Object { - "dataKey": "endDate", - "filterComponent": [Function], - "icon": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], - }, - }, - "label": "investigations.details.end_date", - }, - ], - "loadedCount": true, - "loadedData": true, - "moreInformation": [Function], - "onFilter": [Function], - "onPageChange": [Function], - "onResultsChange": [Function], - "onSort": [Function], - "page": null, - "results": null, - "sort": Object {}, - "title": Object { - "content": [Function], - "dataKey": "title", - "filterComponent": [Function], - "label": "investigations.title", - }, - "totalDataCount": 1, -} -`; diff --git a/packages/datagateway-search/src/card/datasetSearchCardView.component.test.tsx b/packages/datagateway-search/src/card/datasetSearchCardView.component.test.tsx index ccd9edc4d..b1e1c29e9 100644 --- a/packages/datagateway-search/src/card/datasetSearchCardView.component.test.tsx +++ b/packages/datagateway-search/src/card/datasetSearchCardView.component.test.tsx @@ -1,126 +1,113 @@ -import { Link, ListItemText } from '@material-ui/core'; -import { createMount } from '@material-ui/core/test-utils'; import { - AdvancedFilter, dGCommonInitialState, - useDatasetsPaginated, - useDatasetCount, - Dataset, - useLuceneSearch, - useAllFacilityCycles, - useDatasetSizes, - useDatasetsDatafileCount, - CardView, - DLSDatasetDetailsPanel, - ISISDatasetDetailsPanel, - DatasetDetailsPanel, + SearchResponse, + SearchResult, + SearchResultSource, + FACILITY_NAME, } from 'datagateway-common'; -import { ReactWrapper } from 'enzyme'; -import React from 'react'; +import * as React from 'react'; import { Provider } from 'react-redux'; -import { Router } from 'react-router'; +import { Router } from 'react-router-dom'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { StateType } from '../state/app.types'; import DatasetSearchCardView from './datasetSearchCardView.component'; import { QueryClient, QueryClientProvider } from 'react-query'; -// this is a dependency of react-router so we already have it -// eslint-disable-next-line import/no-extraneous-dependencies -import { createMemoryHistory, History } from 'history'; +import { createMemoryHistory, MemoryHistory } from 'history'; import { initialState as dgSearchInitialState } from '../state/reducers/dgsearch.reducer'; - -jest.mock('datagateway-common', () => { - const originalModule = jest.requireActual('datagateway-common'); - - return { - __esModule: true, - ...originalModule, - useDatasetCount: jest.fn(), - useDatasetsPaginated: jest.fn(), - useLuceneSearch: jest.fn(), - useDatasetsDatafileCount: jest.fn(), - useDatasetSizes: jest.fn(), - useAllFacilityCycles: jest.fn(), - }; -}); +import type { RenderResult } from '@testing-library/react'; +import { render, screen, waitFor, within } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import axios, { AxiosResponse } from 'axios'; describe('Dataset - Card View', () => { - let mount; - let mockStore; let state: StateType; - let cardData: Dataset[]; - let history: History; - - const createWrapper = (hierarchy?: string): ReactWrapper => { - return mount( - + let cardData: SearchResultSource; + let searchResult: SearchResult; + let searchResponse: SearchResponse; + let history: MemoryHistory; + let queryClient: QueryClient; + + function renderComponent({ hierarchy = '' } = {}): RenderResult { + return render( + - - + + ); + } + + const mockAxiosGet = (url: string): Promise> => { + if (/\/datasets$/.test(url)) { + return Promise.resolve({ + data: [], + }); + } + if (/\/search\/documents$/.test(url)) { + if (/\/datasets$/.test(url)) { + return Promise.resolve({ + data: [], + }); + } + // lucene search query + return Promise.resolve({ + data: searchResponse, + }); + } + return Promise.reject({ + message: `Endpoint not mocked ${url}`, + }); }; beforeEach(() => { - mount = createMount(); - cardData = [ - { - id: 1, - name: 'Dataset test name', - size: 1, - modTime: '2019-07-23', - createTime: '2019-07-23', - startDate: '2019-07-24', - endDate: '2019-07-25', - investigation: { - id: 2, - title: 'Investigation test title', - name: 'Investigation test name', - summary: 'foo bar', - visitId: '1', - doi: 'doi 1', - size: 1, - investigationInstruments: [ - { - id: 3, - instrument: { - id: 4, - name: 'LARMOR', - }, - }, - ], - studyInvestigations: [ - { - id: 5, - study: { - id: 6, - pid: 'study pid', - name: 'study name', - modTime: '2019-06-10', - createTime: '2019-06-10', - }, - investigation: { - id: 2, - title: 'Investigation test title', - name: 'Investigation test name', - visitId: '1', - }, - }, - ], - startDate: '2019-06-10', - endDate: '2019-06-11', - facility: { - id: 7, - name: 'facility name', - }, + cardData = { + id: 1, + name: 'Dataset test name', + startDate: 1563922800000, + endDate: 1564009200000, + fileSize: 10, + fileCount: 9, + investigationinstrument: [ + { + 'instrument.id': 4, + 'instrument.name': 'LARMOR', }, + ], + investigationfacilitycycle: [ + { + 'facilityCycle.id': 6, + }, + ], + 'investigation.id': 2, + 'investigation.title': 'Investigation test title', + 'investigation.name': 'Investigation test name', + 'investigation.startDate': 1560121200000, + }; + searchResult = { + score: 1, + id: 1, + source: cardData, + }; + searchResponse = { + results: [searchResult], + }; + history = createMemoryHistory({ + initialEntries: [ + { + pathname: '/search/data', + search: '?currentTab=dataset', + }, + ], + }); + queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false }, }, - ]; - history = createMemoryHistory(); + }); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -128,397 +115,271 @@ describe('Dataset - Card View', () => { }) ); - (useDatasetCount as jest.Mock).mockReturnValue({ - data: 1, - isLoading: false, - }); - (useDatasetsPaginated as jest.Mock).mockReturnValue({ - data: cardData, - isLoading: false, - }); - (useLuceneSearch as jest.Mock).mockReturnValue({ - data: [], - }); - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [], - }); - (useDatasetsDatafileCount as jest.Mock).mockImplementation((datasets) => - (datasets - ? 'pages' in datasets - ? datasets.pages.flat() - : datasets - : [] - ).map(() => ({ - data: 1, - isFetching: false, - isSuccess: true, - })) - ); - (useDatasetSizes as jest.Mock).mockImplementation((datasets) => - (datasets - ? 'pages' in datasets - ? datasets.pages.flat() - : datasets - : [] - ).map(() => ({ - data: 1, - isFetching: false, - isSuccess: true, - })) - ); + (axios.get as jest.Mock).mockImplementation(mockAxiosGet); window.scrollTo = jest.fn(); }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('CardView').props()).toMatchSnapshot(); - }); + it('disables the search query if dataset search is disabled', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append('dataset', 'false'); + history.replace({ search: `?${searchParams.toString()}` }); - it('calls the correct data fetching hooks on load', () => { - (useLuceneSearch as jest.Mock).mockReturnValue({ - data: [1], - }); + renderComponent(); - createWrapper(); + expect( + screen.queryByTestId('dataset-search-card-view') + ).toBeInTheDocument(); - expect(useLuceneSearch).toHaveBeenCalledWith('Dataset', { - searchText: '', - startDate: null, - endDate: null, - maxCount: 300, - }); + // wait for queries to finish fetching + await waitFor(() => !queryClient.isFetching()); - expect(useDatasetCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: [1] }, - }), - }, - ]); - expect(useDatasetsPaginated).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: [1] }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - investigation: { investigationInstruments: 'instrument' }, - }), - }, - ]); - expect(useDatasetsDatafileCount).toHaveBeenCalledWith(cardData); - expect(useDatasetSizes).toHaveBeenCalledWith(undefined); + expect( + queryClient.getQueryState(['search', 'Dataset'], { exact: false })?.status + ).toBe('idle'); + + expect(screen.queryAllByTestId('card')).toHaveLength(0); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('renders correctly', async () => { + renderComponent(); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: 'test' } }); + const cards = await screen.findAllByTestId('card'); + expect(cards).toHaveLength(1); - expect(history.location.search).toBe( - `?filters=${encodeURIComponent( - '{"name":{"value":"test","type":"include"}}' - )}` - ); + const card = cards[0]; - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: '' } }); + expect(within(card).getByText('Dataset test name')).toBeInTheDocument(); + expect( + within(card).getByText('entity_card.no_description') + ).toBeInTheDocument(); + expect( + within(card).getByRole('button', { name: 'card-more-info-expand' }) + ).toBeInTheDocument(); + expect(within(card).getByText('datasets.size:')).toBeInTheDocument(); + expect(within(card).getByText('10 B')).toBeInTheDocument(); + expect( + within(card).getByText('datasets.datafile_count:') + ).toBeInTheDocument(); + expect(within(card).getByText('9')).toBeInTheDocument(); + expect( + within(card).getByRole('button', { name: 'buttons.add_to_cart' }) + ).toBeInTheDocument(); + expect( + within(card).getByRole('button', { name: 'buttons.download' }) + ).toBeInTheDocument(); + }); + + it('renders generic link correctly', async () => { + renderComponent(); - expect(history.location.search).toBe('?'); + expect( + await screen.findByRole('link', { name: 'Dataset test name' }) + ).toHaveAttribute('href', '/browse/investigation/2/dataset/1/datafile'); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it("renders DLS link correctly and doesn't allow for download", async () => { + renderComponent({ + hierarchy: FACILITY_NAME.dls, + }); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '2019-08-06' } }); + const cards = await screen.findAllByTestId('card'); + const card = cards[0]; - expect(history.location.search).toBe( - `?filters=${encodeURIComponent('{"modTime":{"endDate":"2019-08-06"}}')}` + expect( + within(card).getByRole('link', { name: 'Dataset test name' }) + ).toHaveAttribute( + 'href', + '/browse/proposal/Investigation test name/investigation/2/dataset/1/datafile' ); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '' } }); + expect(within(card).getByText('10 B')).toBeInTheDocument(); + expect(within(card).getByText('9')).toBeInTheDocument(); - expect(history.location.search).toBe('?'); + expect( + within(card).getByRole('button', { name: 'buttons.add_to_cart' }) + ).toBeInTheDocument(); + expect( + within(card).queryByRole('button', { name: 'buttons.download' }) + ).toBeNull(); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('renders ISIS link & file sizes correctly', async () => { + renderComponent({ hierarchy: FACILITY_NAME.isis }); - const button = wrapper.find(ListItemText).first(); - expect(button.text()).toEqual('datasets.name'); - button.simulate('click'); + const cards = await screen.findAllByTestId('card'); + const card = cards[0]; - expect(history.location.search).toBe( - `?sort=${encodeURIComponent('{"name":"asc"}')}` + expect( + within(card).getByRole('link', { name: 'Dataset test name' }) + ).toHaveAttribute( + 'href', + '/browse/instrument/4/facilityCycle/6/investigation/2/dataset/1' ); + expect(within(card).getByText('10 B')).toBeInTheDocument(); }); - it('renders fine with incomplete data', () => { - (useDatasetCount as jest.Mock).mockReturnValue({}); - (useDatasetsPaginated as jest.Mock).mockReturnValue({}); + it('does not render ISIS link when instrumentId cannot be found', async () => { + delete cardData.investigationinstrument; - expect(() => createWrapper()).not.toThrowError(); - }); + renderComponent({ hierarchy: FACILITY_NAME.isis }); - it('renders generic link & pending count correctly', () => { - (useDatasetsDatafileCount as jest.Mock).mockImplementation(() => [ - { - isFetching: true, - }, - ]); - const wrapper = createWrapper(); + const cards = await screen.findAllByTestId('card'); + const card = cards[0]; - expect(wrapper.find(CardView).find('a').first().prop('href')).toEqual( - `/browse/investigation/2/dataset/1/datafile` - ); - expect(wrapper.find(CardView).find('a').first().text()).toEqual( - 'Dataset test name' - ); + expect(within(card).getByText('Dataset test name')).toBeInTheDocument(); expect( - wrapper - .find(CardView) - .first() - .find('[data-testid="card-info-data-datasets.datafile_count"]') - .text() - ).toEqual('Calculating...'); + within(card).queryByRole('link', { name: 'Dataset test name' }) + ).toBeNull(); }); - it("renders DLS link correctly and doesn't allow for download", () => { - const wrapper = createWrapper('dls'); - - expect(wrapper.find(CardView).find('a').first().prop('href')).toEqual( - '/browse/proposal/Investigation test name/investigation/2/dataset/1/datafile' - ); - expect(wrapper.find(CardView).find('a').first().text()).toEqual( - 'Dataset test name' - ); - expect(wrapper.exists('#add-to-cart-btn-dataset-1')).toBe(true); - expect(wrapper.exists('#download-btn-dataset-1')).toBe(false); - }); - - it('renders ISIS link & file sizes correctly', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 6, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], + it('does not render ISIS link when facilityCycleId cannot be found', async () => { + delete cardData.investigationfacilitycycle; + renderComponent({ + hierarchy: FACILITY_NAME.isis, }); - const wrapper = createWrapper('isis'); + const cards = await screen.findAllByTestId('card'); + const card = cards[0]; - expect(useDatasetSizes).toHaveBeenCalledWith(cardData); - expect(useDatasetsDatafileCount).toHaveBeenCalledWith(undefined); - - expect(wrapper.find(CardView).find('a').first().prop('href')).toEqual( - `/browse/instrument/4/facilityCycle/6/investigation/2/dataset/1` - ); - expect(wrapper.find(CardView).find('a').first().text()).toEqual( - 'Dataset test name' - ); + expect(within(card).getByText('Dataset test name')).toBeInTheDocument(); expect( - wrapper - .find(CardView) - .first() - .find('[data-testid="card-info-data-datasets.size"]') - .text() - ).toEqual('1 B'); + within(card).queryByRole('link', { name: 'Dataset test name' }) + ).toBeNull(); }); - it('does not render ISIS link when instrumentId cannot be found', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], - }); - delete cardData[0].investigation?.investigationInstruments; + it('displays only the dataset name when there is no generic investigation to link to', async () => { + delete cardData['investigation.id']; + delete cardData['investigation.name']; + delete cardData['investigation.title']; + delete cardData['investigation.startDate']; - (useDatasetsPaginated as jest.Mock).mockReturnValue({ - data: cardData, - fetchNextPage: jest.fn(), + renderComponent({ + hierarchy: 'data', }); - const wrapper = createWrapper('isis'); - - expect(wrapper.find(CardView).first().find('a')).toHaveLength(0); - expect( - wrapper.find(CardView).first().find('[aria-label="card-title"]').text() - ).toEqual('Dataset test name'); - }); - it('does not render ISIS link when facilityCycleId cannot be found', () => { - const wrapper = createWrapper('isis'); + const cards = await screen.findAllByTestId('card'); + const card = cards[0]; - expect(wrapper.find(CardView).first().find('a')).toHaveLength(0); + expect(within(card).getByText('Dataset test name')).toBeInTheDocument(); expect( - wrapper.find(CardView).first().find('[aria-label="card-title"]').text() - ).toEqual('Dataset test name'); + within(card).queryByRole('link', { name: 'Dataset test name' }) + ).toBeNull(); }); - it('does not render ISIS link when facilityCycleId has incompatible dates', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 2, - name: 'facility cycle name', - startDate: '2020-06-11', - endDate: '2000-06-10', - }, - ], + it('displays only the dataset name when there is no DLS investigation to link to', async () => { + delete cardData['investigation.id']; + delete cardData['investigation.name']; + delete cardData['investigation.title']; + delete cardData['investigation.startDate']; + + renderComponent({ + hierarchy: FACILITY_NAME.dls, }); - const wrapper = createWrapper('isis'); + const cards = await screen.findAllByTestId('card'); + const card = cards[0]; - expect(wrapper.find(CardView).first().find('a')).toHaveLength(0); + expect(within(card).getByText('Dataset test name')).toBeInTheDocument(); expect( - wrapper.find(CardView).first().find('[aria-label="card-title"]').text() - ).toEqual('Dataset test name'); + within(card).queryByRole('link', { name: 'Dataset test name' }) + ).toBeNull(); }); - it('displays only the dataset name when there is no generic investigation to link to', () => { - delete cardData[0].investigation; - (useDatasetsPaginated as jest.Mock).mockReturnValue({ - data: cardData, - fetchNextPage: jest.fn(), - }); + it('displays only the dataset name when there is no ISIS investigation to link to', async () => { + delete cardData['investigation.id']; + delete cardData['investigation.name']; + delete cardData['investigation.title']; + delete cardData['investigation.startDate']; - const wrapper = createWrapper('data'); + renderComponent({ hierarchy: FACILITY_NAME.isis }); - expect(wrapper.find(CardView).first().find('a')).toHaveLength(0); + const cards = await screen.findAllByTestId('card'); + const card = cards[0]; + + expect(within(card).getByText('Dataset test name')).toBeInTheDocument(); expect( - wrapper.find(CardView).first().find('[aria-label="card-title"]').text() - ).toEqual('Dataset test name'); + within(card).queryByRole('link', { name: 'Dataset test name' }) + ).toBeNull(); }); - it('displays only the dataset name when there is no DLS investigation to link to', () => { - delete cardData[0].investigation; - (useDatasetsPaginated as jest.Mock).mockReturnValue({ - data: cardData, - fetchNextPage: jest.fn(), - }); + it('displays generic details panel when expanded', async () => { + const user = userEvent.setup(); + + renderComponent(); - const wrapper = createWrapper('dls'); + expect(screen.queryByTestId('dataset-details-panel')).toBeNull(); + + await user.click( + await screen.findByRole('button', { name: 'card-more-info-expand' }) + ); - expect(wrapper.find(CardView).first().find('a')).toHaveLength(0); expect( - wrapper.find(CardView).first().find('[aria-label="card-title"]').text() - ).toEqual('Dataset test name'); + await screen.findByTestId('dataset-details-panel') + ).toBeInTheDocument(); }); - it('displays only the dataset name when there is no ISIS investigation to link to', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], - }); - delete cardData[0].investigation; - (useDatasetsPaginated as jest.Mock).mockReturnValue({ - data: cardData, - fetchNextPage: jest.fn(), + it('displays correct details panel for ISIS when expanded', async () => { + const user = userEvent.setup(); + + renderComponent({ + hierarchy: FACILITY_NAME.isis, }); - const wrapper = createWrapper('isis'); + expect(screen.queryByTestId('isis-dataset-details-panel')).toBeNull(); + + await user.click( + await screen.findByRole('button', { name: 'card-more-info-expand' }) + ); - expect(wrapper.find(CardView).first().find('a')).toHaveLength(0); expect( - wrapper.find(CardView).first().find('[aria-label="card-title"]').text() - ).toEqual('Dataset test name'); + await screen.findByTestId('isis-dataset-details-panel') + ).toBeInTheDocument(); }); - it('displays generic details panel when expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(DatasetDetailsPanel).exists()).toBeFalsy(); - wrapper - .find('[aria-label="card-more-info-expand"]') - .first() - .simulate('click'); - - expect(wrapper.find(DatasetDetailsPanel).exists()).toBeTruthy(); - }); + it('can navigate using the details panel for ISIS when there are facility cycles', async () => { + const user = userEvent.setup(); - it('displays correct details panel for ISIS when expanded', () => { - const wrapper = createWrapper('isis'); - expect(wrapper.find(ISISDatasetDetailsPanel).exists()).toBeFalsy(); - wrapper - .find('[aria-label="card-more-info-expand"]') - .first() - .simulate('click'); + renderComponent({ + hierarchy: FACILITY_NAME.isis, + }); - expect(wrapper.find(ISISDatasetDetailsPanel).exists()).toBeTruthy(); - }); + await user.click( + await screen.findByRole('button', { name: 'card-more-info-expand' }) + ); - it('can navigate using the details panel for ISIS when there are facility cycles', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], - }); + const panel = await screen.findByTestId('isis-dataset-details-panel'); - const wrapper = createWrapper('isis'); - expect(wrapper.find(ISISDatasetDetailsPanel).exists()).toBeFalsy(); - wrapper - .find('[aria-label="card-more-info-expand"]') - .first() - .simulate('click'); + expect(panel).toBeInTheDocument(); - expect(wrapper.find(ISISDatasetDetailsPanel).exists()).toBeTruthy(); + await user.click( + within(panel).getByRole('tab', { name: 'datasets.details.datafiles' }) + ); - wrapper.find('#dataset-datafiles-tab').first().simulate('click'); expect(history.location.pathname).toBe( - '/browse/instrument/4/facilityCycle/4/investigation/2/dataset/1' + '/browse/instrument/4/facilityCycle/6/investigation/2/dataset/1/datafile' ); }); - it('displays correct details panel for DLS when expanded', () => { - const wrapper = createWrapper('dls'); - expect(wrapper.find(DLSDatasetDetailsPanel).exists()).toBeFalsy(); - wrapper - .find('[aria-label="card-more-info-expand"]') - .first() - .simulate('click'); + it('displays correct details panel for DLS when expanded', async () => { + const user = userEvent.setup(); - expect(wrapper.find(DLSDatasetDetailsPanel).exists()).toBeTruthy(); + renderComponent({ + hierarchy: 'dls', + }); + + expect(screen.queryByTestId('dls-dataset-details-panel')).toBeNull(); + + await user.click( + await screen.findByRole('button', { name: 'card-more-info-expand' }) + ); + + expect( + await screen.findByTestId('dls-dataset-details-panel') + ).toBeInTheDocument(); }); }); diff --git a/packages/datagateway-search/src/card/datasetSearchCardView.component.tsx b/packages/datagateway-search/src/card/datasetSearchCardView.component.tsx index 0248f353e..03568e54a 100644 --- a/packages/datagateway-search/src/card/datasetSearchCardView.component.tsx +++ b/packages/datagateway-search/src/card/datasetSearchCardView.component.tsx @@ -1,249 +1,204 @@ -import React from 'react'; import { - ConfirmationNumber, CalendarToday, + ConfirmationNumber, Fingerprint, -} from '@material-ui/icons'; + Save, +} from '@mui/icons-material'; import { + AddToCartButton, CardView, - Dataset, + DatasetDetailsPanel, + DLSDatasetDetailsPanel, + DownloadButton, + formatBytes, + ISISDatasetDetailsPanel, parseSearchToQuery, - useDateFilter, - useDatasetCount, - useDatasetsPaginated, - usePushFilter, + SearchFilter, + SearchResponse, + SearchResultSource, + tableLink, + useLuceneSearchInfinite, + usePushDatasetFilter, usePushPage, usePushResults, useSort, - useTextFilter, - useAllFacilityCycles, - useLuceneSearch, - FacilityCycle, - tableLink, - useDatasetsDatafileCount, - useDatasetSizes, - formatCountOrSize, - AddToCartButton, - DownloadButton, - ISISDatasetDetailsPanel, - DLSDatasetDetailsPanel, - DatasetDetailsPanel, + buildDatafileTableUrlForDataset, + buildDatasetLandingUrl, + buildDatasetTableUrlForInvestigation, + buildInvestigationLandingUrl, + FACILITY_NAME, } from 'datagateway-common'; +import React from 'react'; import { useTranslation } from 'react-i18next'; -import { useHistory, useLocation } from 'react-router-dom'; -import { createStyles, makeStyles, Theme } from '@material-ui/core'; +import { Grid, Paper, styled, Typography } from '@mui/material'; import { useSelector } from 'react-redux'; +import { useHistory, useLocation } from 'react-router-dom'; import { StateType } from '../state/app.types'; +import FacetPanel from '../facet/components/facetPanel/facetPanel.component'; +import { facetClassificationFromSearchResponses } from '../facet/facet'; +import SelectedFilterChips from '../facet/components/selectedFilterChips.component'; +import useFacetFilters from '../facet/useFacetFilters'; +import { useSearchResultCounter } from '../searchTabs/useSearchResultCounter'; interface DatasetCardViewProps { hierarchy: string; } -const useStyles = makeStyles((theme: Theme) => - createStyles({ - actionButtons: { - display: 'flex', - flexDirection: 'column', - '& button': { - marginTop: theme.spacing(1), - margin: 'auto', - }, - }, - }) -); +const ActionButtonDiv = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + '& button': { + margin: 'auto', + marginTop: theme.spacing(1), + }, +})); -const DatasetCardView = (props: DatasetCardViewProps): React.ReactElement => { +const DatasetCardView: React.FC = (props) => { + const [t] = useTranslation(); const { hierarchy } = props; - const { data: facilityCycles } = useAllFacilityCycles(hierarchy === 'isis'); - const location = useLocation(); const { push } = useHistory(); - const queryParams = React.useMemo(() => parseSearchToQuery(location.search), [ - location.search, - ]); - const { startDate, endDate } = queryParams; - const searchText = queryParams.searchText ? queryParams.searchText : ''; - - const maxNumResults = useSelector( - (state: StateType) => state.dgsearch.maxNumResults + const queryParams = React.useMemo( + () => parseSearchToQuery(location.search), + [location.search] ); - - const { data: luceneData } = useLuceneSearch('Dataset', { - searchText, + const { startDate, endDate, - maxCount: maxNumResults, - }); - - const [t] = useTranslation(); + page, + results, + sort, + filters, + restrict, + dataset, + currentTab, + } = queryParams; + const searchText = queryParams.searchText ? queryParams.searchText : ''; - const { filters, sort, page, results } = React.useMemo( - () => parseSearchToQuery(location.search), - [location.search] + const minNumResults = useSelector( + (state: StateType) => state.dgsearch.minNumResults ); - const textFilter = useTextFilter(filters); - const dateFilter = useDateFilter(filters); - const handleSort = useSort(); - const pushFilter = usePushFilter(); - const pushPage = usePushPage(); - const pushResults = usePushResults(); - - const { data: totalDataCount, isLoading: countLoading } = useDatasetCount([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: luceneData || [] }, - }), - }, - ]); - const { isLoading: dataLoading, data } = useDatasetsPaginated([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: luceneData || [] }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - investigation: { investigationInstruments: 'instrument' }, - }), - }, - ]); - - const dlsLinkURL = ( - datasetData: Dataset, - linkType = 'dataset' - ): string | null => { - if (datasetData.investigation) { - return linkType === 'investigation' - ? `/browse/proposal/${datasetData.investigation.name}/investigation/${datasetData.investigation.id}/dataset` - : `/browse/proposal/${datasetData.investigation.name}/investigation/${datasetData.investigation.id}/dataset/${datasetData.id}/datafile`; - } - return null; - }; - - const dlsLink = React.useCallback( - ( - datasetData: Dataset, - linkType = 'dataset' - ): React.ReactElement | string => { - const linkURL = dlsLinkURL(datasetData, linkType); - - if (datasetData.investigation && linkURL) { - return linkType === 'investigation' - ? tableLink(linkURL, datasetData.investigation.title) - : tableLink(linkURL, datasetData.name); - } - return linkType === 'investigation' ? '' : datasetData.name; - }, - [] + const maxNumResults = useSelector( + (state: StateType) => state.dgsearch.maxNumResults ); - const isisLinkURL = React.useCallback( - (datasetData: Dataset, linkType = 'dataset') => { - let instrumentId; - let facilityCycleId; - if (datasetData.investigation?.investigationInstruments?.length) { - instrumentId = - datasetData.investigation?.investigationInstruments[0].instrument?.id; - } else { - return null; - } - - if (facilityCycles?.length && datasetData.investigation?.startDate) { - const filteredFacilityCycles: FacilityCycle[] = facilityCycles?.filter( - (facilityCycle: FacilityCycle) => - datasetData.investigation?.startDate && - facilityCycle.startDate && - facilityCycle.endDate && - datasetData.investigation.startDate >= facilityCycle.startDate && - datasetData.investigation.startDate <= facilityCycle.endDate - ); - if (filteredFacilityCycles.length) { - facilityCycleId = filteredFacilityCycles[0].id; - } + const { data, isLoading, isFetching, hasNextPage, fetchNextPage, refetch } = + useLuceneSearchInfinite( + 'Dataset', + { + searchText, + startDate, + endDate, + sort, + minCount: minNumResults, + maxCount: maxNumResults, + restrict, + facets: [ + { target: 'Dataset' }, + { + target: 'DatasetParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], + }, + currentTab === 'dataset' ? filters : {}, + { + enabled: dataset, + // this select removes the facet count for the InvestigationInstrument.instrument.name + // facet since the number is confusing for datafiles + select: (data) => ({ + ...data, + pages: data.pages.map((searchResponse) => ({ + ...searchResponse, + dimensions: { + ...searchResponse.dimensions, + ...(searchResponse.dimensions?.[ + 'InvestigationInstrument.instrument.name' + ] + ? { + 'InvestigationInstrument.instrument.name': Object.keys( + searchResponse.dimensions?.[ + 'InvestigationInstrument.instrument.name' + ] + ).reduce( + ( + accumulator: { [key: string]: undefined }, + current: string + ) => { + accumulator[current] = undefined; + return accumulator; + }, + {} + ), + } + : {}), + }, + })), + }), } + ); + + const { + selectedFacetFilters, + addFacetFilter, + removeFacetFilter, + applyFacetFilters, + haveUnappliedFilters, + } = useFacetFilters(); + + useSearchResultCounter({ + isFetching, + dataSearchType: 'Dataset', + searchResponses: data?.pages, + hasMore: hasNextPage, + }); - if (facilityCycleId) { - return linkType === 'investigation' - ? `/browse/instrument/${instrumentId}/facilityCycle/${facilityCycleId}/investigation/${datasetData.investigation.id}` - : `/browse/instrument/${instrumentId}/facilityCycle/${facilityCycleId}/investigation/${datasetData.investigation.id}/dataset/${datasetData.id}`; - } - return null; - }, - [facilityCycles] - ); + function mapSource(response: SearchResponse): SearchResultSource[] { + return response.results?.map((result) => result.source) ?? []; + } - const isisLink = React.useCallback( - (datasetData: Dataset, linkType = 'dataset') => { - const linkURL = isisLinkURL(datasetData, linkType); + function mapIds(response: SearchResponse): number[] { + return response.results?.map((result) => result.id) ?? []; + } - if (datasetData.investigation && linkURL) { - return linkType === 'investigation' - ? tableLink(linkURL, datasetData.investigation.title) - : tableLink(linkURL, datasetData.name); - } else return linkType === 'investigation' ? '' : datasetData.name; - }, - [isisLinkURL] - ); + const { paginatedSource, aggregatedIds, aborted } = React.useMemo(() => { + if (data) { + const aggregatedIds = data.pages + .map((response) => mapIds(response)) + .flat(); + const minResult = (page ? page - 1 : 0) * (results ?? 10); + const maxResult = (page ?? 1) * (results ?? 10); - const genericLinkURL = React.useCallback( - (datasetData: Dataset, linkType = 'dataset'): string | null => { - if (datasetData.investigation) { - return linkType === 'investigation' - ? `/browse/investigation/${datasetData.investigation.id}/dataset` - : `/browse/investigation/${datasetData.investigation.id}/dataset/${datasetData.id}/datafile`; + if (hasNextPage && aggregatedIds.length < maxResult) { + fetchNextPage(); } - return null; - }, - [] - ); - - const genericLink = React.useCallback( - ( - datasetData: Dataset, - linkType = 'dataset' - ): React.ReactElement | string => { - const linkURL = genericLinkURL(datasetData, linkType); - if (datasetData.investigation && linkURL) { - return linkType === 'investigation' - ? tableLink(linkURL, datasetData.investigation.title) - : tableLink(linkURL, datasetData.name); - } - return linkType === 'investigation' ? '' : datasetData.name; - }, - [genericLinkURL] - ); - - const hierarchyLinkURL = React.useMemo(() => { - if (hierarchy === 'dls') { - return dlsLinkURL; - } else if (hierarchy === 'isis') { - return isisLinkURL; - } else { - return genericLinkURL; - } - }, [genericLinkURL, hierarchy, isisLinkURL]); - - const hierarchyLink = React.useMemo(() => { - if (hierarchy === 'dls') { - return dlsLink; - } else if (hierarchy === 'isis') { - return isisLink; + const aggregatedSource = data.pages + .map((response) => mapSource(response)) + .flat(); + return { + paginatedSource: aggregatedSource.slice(minResult, maxResult), + aggregatedIds: aggregatedIds, + aborted: data.pages[data.pages.length - 1].aborted, + }; } else { - return genericLink; + return { + paginatedSource: [], + aggregatedIds: [], + aborted: false, + }; } - }, [dlsLink, genericLink, hierarchy, isisLink]); + }, [data, fetchNextPage, hasNextPage, page, results]); - // hierarchy === 'isis' ? data : undefined is a 'hack' to only perform - // the correct calculation queries for each facility - const datasetCountQueries = useDatasetsDatafileCount( - hierarchy !== 'isis' ? data : undefined - ); - const sizeQueries = useDatasetSizes(hierarchy === 'isis' ? data : undefined); + const handleSort = useSort(); + const pushFilter = usePushDatasetFilter(); + const pushPage = usePushPage(); + const pushResults = usePushResults(); const title = React.useMemo( () => ({ @@ -251,159 +206,279 @@ const DatasetCardView = (props: DatasetCardViewProps): React.ReactElement => { label: t('datasets.name'), // Provide both the dataKey (for tooltip) and content to render. dataKey: 'name', - content: (dataset: Dataset) => { - return hierarchyLink(dataset); + content: (dataset: SearchResultSource) => { + if (!dataset['investigation.id'] || !dataset['investigation.name']) + return dataset.name; + const formattedDataset = { + id: dataset.id, + name: dataset.name, + investigation: { + id: dataset['investigation.id'], + name: dataset['investigation.name'], + instrumentId: + dataset.investigationinstrument?.[0]?.['instrument.id'], + facilityCycleId: + dataset.investigationfacilitycycle?.[0]?.['facilityCycle.id'], + }, + }; + const url = + hierarchy === FACILITY_NAME.isis + ? buildDatasetLandingUrl(formattedDataset) + : buildDatafileTableUrlForDataset({ + dataset: formattedDataset, + facilityName: hierarchy, + }); + return url ? tableLink(url, dataset.name) : dataset.name; }, - filterComponent: textFilter, + disableSort: true, }), - [hierarchyLink, t, textFilter] + [hierarchy, t] ); const description = React.useMemo( () => ({ label: t('datasets.details.description'), dataKey: 'description', - filterComponent: textFilter, + disableSort: true, }), - [t, textFilter] + [t] ); const information = React.useMemo( () => [ { - icon: ConfirmationNumber, - label: - hierarchy === 'isis' - ? t('datasets.size') - : t('datasets.datafile_count'), - dataKey: hierarchy === 'isis' ? 'size' : 'datafileCount', - content: (dataset: Dataset): string => { - const index = data?.findIndex((item) => item.id === dataset.id); - if (typeof index === 'undefined') return 'Unknown'; - const query = - hierarchy === 'isis' - ? sizeQueries[index] - : datasetCountQueries[index]; - return formatCountOrSize(query, hierarchy === 'isis'); - }, + icon: Save, + label: t('datasets.size'), + dataKey: 'size', + content: (dataset: SearchResultSource): string => + formatBytes(dataset.fileSize), disableSort: true, }, + ...(hierarchy !== FACILITY_NAME.isis + ? [ + { + icon: ConfirmationNumber, + label: t('datasets.datafile_count'), + dataKey: 'fileCount', + disableSort: true, + }, + ] + : []), { icon: Fingerprint, label: t('datasets.investigation'), dataKey: 'investigation.title', // eslint-disable-next-line @typescript-eslint/no-explicit-any - content: (dataset: Dataset): any => { - return hierarchyLink(dataset, 'investigation'); + content: (dataset: SearchResultSource): any => { + if ( + !dataset['investigation.id'] || + !dataset['investigation.name'] || + !dataset['investigation.title'] + ) + return ''; + + const investigation = { + id: dataset['investigation.id'], + name: dataset['investigation.name'], + instrumentId: + dataset.investigationinstrument?.[0]?.['instrument.id'], + facilityCycleId: + dataset.investigationfacilitycycle?.[0]?.['facilityCycle.id'], + }; + + const url = + hierarchy === FACILITY_NAME.isis + ? buildInvestigationLandingUrl(investigation) + : buildDatasetTableUrlForInvestigation({ + investigation, + facilityName: hierarchy, + }); + return url + ? tableLink(url, dataset['investigation.title']) + : dataset['investigation.title']; }, - filterComponent: textFilter, + disableSort: true, }, { icon: CalendarToday, label: t('datasets.create_time'), dataKey: 'createTime', - filterComponent: dateFilter, + disableSort: true, }, { icon: CalendarToday, label: t('datasets.modified_time'), dataKey: 'modTime', - filterComponent: dateFilter, + disableSort: true, }, ], - [ - data, - datasetCountQueries, - dateFilter, - hierarchy, - hierarchyLink, - sizeQueries, - t, - textFilter, - ] + [hierarchy, t] ); const moreInformation = React.useCallback( - (dataset: Dataset) => { - const datasetsURL = hierarchyLinkURL(dataset); - - if (hierarchy === 'isis') { - return ( - { - push(datasetsURL); - } - : undefined - } - /> - ); - } else if (hierarchy === 'dls') - return ; - else return ; + (dataset: SearchResultSource) => { + switch (hierarchy) { + case FACILITY_NAME.isis: + let datasetsUrl: string | null = null; + if (dataset['investigation.id'] && dataset['investigation.name']) { + const formattedDataset = { + id: dataset.id, + name: dataset.name, + investigation: { + id: dataset['investigation.id'], + name: dataset['investigation.name'], + instrumentId: + dataset.investigationinstrument?.[0]?.['instrument.id'], + facilityCycleId: + dataset.investigationfacilitycycle?.[0]?.['facilityCycle.id'], + }, + }; + datasetsUrl = buildDatafileTableUrlForDataset({ + dataset: formattedDataset, + facilityName: hierarchy, + }); + } + return ( + { + if (datasetsUrl) push(datasetsUrl); + }} + /> + ); + + case FACILITY_NAME.dls: + return ; + + default: + return ; + } }, - [hierarchy, hierarchyLinkURL, push] + [hierarchy, push] ); - const classes = useStyles(); - const buttons = React.useMemo( () => hierarchy !== 'dls' ? [ - (dataset: Dataset) => ( -
+ (dataset: SearchResultSource) => ( + dataset.id) ?? []} + allIds={aggregatedIds} entityId={dataset.id} /> -
+ ), ] : [ - (dataset: Dataset) => ( + (dataset: SearchResultSource) => ( dataset.id) ?? []} + allIds={aggregatedIds} entityId={dataset.id} /> ), ], - - [classes.actionButtons, data, hierarchy, sizeQueries] + [hierarchy, aggregatedIds] ); + const removeFilterChip = ( + dimension: string, + filterValue: SearchFilter + ): void => { + removeFacetFilter({ dimension, filterValue, applyImmediately: true }); + }; + + if (currentTab !== 'dataset') return null; + return ( - + + + {data?.pages && ( + + addFacetFilter({ + dimension, + filterValue, + applyImmediately: false, + }) + } + onRemoveFilter={(dimension, filterValue) => + removeFacetFilter({ + dimension, + filterValue, + applyImmediately: false, + }) + } + onApplyFacetFilters={() => { + applyFacetFilters(); + refetch(); + }} + /> + )} + + + + + +
+ {aborted ? ( + + + {t('loading.abort_message')} + + + ) : ( + + )} +
+
+
+
+
); }; diff --git a/packages/datagateway-search/src/card/investigationSearchCardView.component.test.tsx b/packages/datagateway-search/src/card/investigationSearchCardView.component.test.tsx index 75166aef7..16c86bd0a 100644 --- a/packages/datagateway-search/src/card/investigationSearchCardView.component.test.tsx +++ b/packages/datagateway-search/src/card/investigationSearchCardView.component.test.tsx @@ -1,115 +1,104 @@ -import React from 'react'; -import { createMount } from '@material-ui/core/test-utils'; +import * as React from 'react'; import { dGCommonInitialState, - useAllFacilityCycles, - useLuceneSearch, - useInvestigationCount, - useInvestigationsPaginated, - useInvestigationsDatasetCount, - useInvestigationSizes, - Investigation, + SearchResponse, + SearchResult, + SearchResultSource, + FACILITY_NAME, StateType, - AdvancedFilter, - CardView, - InvestigationDetailsPanel, - ISISInvestigationDetailsPanel, - DLSVisitDetailsPanel, } from 'datagateway-common'; import InvestigationSearchCardView from './investigationSearchCardView.component'; import { QueryClient, QueryClientProvider } from 'react-query'; import { Provider } from 'react-redux'; -import { Router } from 'react-router'; -import { ReactWrapper } from 'enzyme'; +import { Router } from 'react-router-dom'; import thunk from 'redux-thunk'; import configureStore from 'redux-mock-store'; - -// this is a dependency of react-router so we already have it -// eslint-disable-next-line import/no-extraneous-dependencies -import { createMemoryHistory, History } from 'history'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen, waitFor, within } from '@testing-library/react'; +import { createMemoryHistory, MemoryHistory } from 'history'; import { initialState as dgSearchInitialState } from '../state/reducers/dgsearch.reducer'; -import { Link, ListItemText } from '@material-ui/core'; - -jest.mock('datagateway-common', () => { - const originalModule = jest.requireActual('datagateway-common'); - - return { - __esModule: true, - ...originalModule, - useAllFacilityCycles: jest.fn(), - useLuceneSearch: jest.fn(), - useInvestigationCount: jest.fn(), - useInvestigationsPaginated: jest.fn(), - useInvestigationsDatasetCount: jest.fn(), - useInvestigationSizes: jest.fn(), - }; -}); +import userEvent from '@testing-library/user-event'; +import axios, { AxiosResponse } from 'axios'; describe('Investigation - Card View', () => { - let mount; - let mockStore; let state: StateType; - let cardData: Investigation[]; - let history: History; - - const createWrapper = (hierarchy?: string): ReactWrapper => { - return mount( - + let cardData: SearchResultSource; + let searchResult: SearchResult; + let searchResponse: SearchResponse; + let history: MemoryHistory; + let queryClient: QueryClient; + + function renderComponent({ hierarchy = '' } = {}): RenderResult { + return render( + - - + + ); + } + + const mockAxiosGet = (url: string): Promise> => { + if (/\/investigations$/.test(url)) { + return Promise.resolve({ + data: [], + }); + } + if (/\/search\/documents$/.test(url)) { + // lucene search query + return Promise.resolve({ + data: searchResponse, + }); + } + return Promise.reject({ + message: `Endpoint not mocked ${url}`, + }); }; beforeEach(() => { - mount = createMount(); - cardData = [ - { - id: 1, - name: 'Investigation test name', - size: 1, - modTime: '2019-07-23', - createTime: '2019-07-23', - startDate: '2019-07-24', - endDate: '2019-07-25', - title: 'Test 1', - visitId: '1', - doi: 'doi 1', - investigationInstruments: [ - { - id: 3, - instrument: { - id: 4, - name: 'LARMOR', - }, - }, - ], - studyInvestigations: [ - { - id: 5, - study: { - id: 6, - pid: 'study pid', - name: 'study name', - modTime: '2019-06-10', - createTime: '2019-06-10', - }, - investigation: { - id: 2, - title: 'Investigation test title', - name: 'Investigation test name', - visitId: '1', - }, - }, - ], + cardData = { + id: 1, + name: 'Investigation test name', + startDate: 1563922800000, + endDate: 1564009200000, + fileSize: 10, + fileCount: 9, + title: 'Test 1', + visitId: '1', + doi: 'doi 1', + investigationinstrument: [ + { + 'instrument.id': 4, + 'instrument.name': 'LARMOR', + }, + ], + investigationfacilitycycle: [ + { + 'facilityCycle.id': 6, + }, + ], + }; + searchResult = { + score: 1, + id: 1, + source: cardData, + }; + searchResponse = { + results: [searchResult], + }; + history = createMemoryHistory({ + initialEntries: [ + { search: 'searchText=test search¤tTab=investigation' }, + ], + }); + queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false }, }, - ]; - history = createMemoryHistory(); + }); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -117,385 +106,208 @@ describe('Investigation - Card View', () => { }) ); - (useInvestigationCount as jest.Mock).mockReturnValue({ - data: 1, - isLoading: false, - }); - (useInvestigationsPaginated as jest.Mock).mockReturnValue({ - data: cardData, - isLoading: false, - }); - (useLuceneSearch as jest.Mock).mockReturnValue({ - data: [], - }); - - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [], - }); - - (useInvestigationsDatasetCount as jest.Mock).mockImplementation( - (investigations) => - (investigations - ? 'pages' in investigations - ? investigations.pages.flat() - : investigations - : [] - ).map(() => ({ - data: 1, - isFetching: false, - isSuccess: true, - })) - ); - - (useInvestigationSizes as jest.Mock).mockImplementation((investigations) => - (investigations - ? 'pages' in investigations - ? investigations.pages.flat() - : investigations - : [] - ).map(() => ({ - data: 1, - isFetching: false, - isSuccess: true, - })) - ); - + (axios.get as jest.Mock).mockImplementation(mockAxiosGet); window.scrollTo = jest.fn(); }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - //The below tests are modified from datasetSearchCardView + it('disables the search query if investigation search is disabled', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append('investigation', 'false'); + history.replace({ search: `?${searchParams.toString()}` }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('CardView').props()).toMatchSnapshot(); - }); + renderComponent(); - it('calls the correct data fetching hooks on load', () => { - (useLuceneSearch as jest.Mock).mockReturnValue({ - data: [1], - }); + expect( + screen.queryByTestId('investigation-search-card-view') + ).toBeInTheDocument(); - createWrapper(); + // wait for queries to finish fetching + await waitFor(() => !queryClient.isFetching()); - expect(useLuceneSearch).toHaveBeenCalledWith('Investigation', { - searchText: '', - startDate: null, - endDate: null, - maxCount: 300, - }); + expect( + queryClient.getQueryState(['search', 'Investigation'], { exact: false }) + ?.status + ).toBe('idle'); - expect(useInvestigationCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: [1] }, - }), - }, - ]); - expect(useInvestigationsPaginated).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: [1] }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - investigationInstruments: 'instrument', - }), - }, - ]); - expect(useInvestigationsDatasetCount).toHaveBeenCalledWith(cardData); - expect(useInvestigationSizes).toHaveBeenCalledWith(undefined); + expect(screen.queryAllByTestId('card')).toHaveLength(0); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); - - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: 'test' } }); + it('renders correctly', async () => { + renderComponent(); - expect(history.location.search).toBe( - `?filters=${encodeURIComponent( - '{"title":{"value":"test","type":"include"}}' - )}` - ); - - advancedFilter - .find('input') - .first() - .simulate('change', { target: { value: '' } }); + const cards = await screen.findAllByTestId('card'); + expect(cards).toHaveLength(1); - expect(history.location.search).toBe('?'); + const card = cards[0]; + expect(within(card).getByText('Test 1')).toBeInTheDocument(); + expect( + within(card).getByText('entity_card.no_description') + ).toBeInTheDocument(); + expect( + within(card).getByRole('button', { name: 'card-more-info-expand' }) + ).toBeInTheDocument(); + expect(within(card).getByText('investigations.size:')).toBeInTheDocument(); + expect( + within(card).getByRole('button', { name: 'buttons.add_to_cart' }) + ).toBeInTheDocument(); + expect( + within(card).getByRole('button', { name: 'buttons.download' }) + ).toBeInTheDocument(); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('renders generic link correctly', async () => { + renderComponent(); - const advancedFilter = wrapper.find(AdvancedFilter); - advancedFilter.find(Link).simulate('click'); - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '2019-08-06' } }); + const card = (await screen.findAllByTestId('card'))[0]; - expect(history.location.search).toBe( - `?filters=${encodeURIComponent('{"endDate":{"endDate":"2019-08-06"}}')}` + expect(within(card).getByRole('link', { name: 'Test 1' })).toHaveAttribute( + 'href', + '/browse/investigation/1/dataset' ); - - advancedFilter - .find('input') - .last() - .simulate('change', { target: { value: '' } }); - - expect(history.location.search).toBe('?'); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it("renders DLS link correctly and doesn't allow for cart selection or download", async () => { + renderComponent({ + hierarchy: FACILITY_NAME.dls, + }); - const button = wrapper.find(ListItemText).first(); - expect(button.text()).toEqual('investigations.title'); - button.simulate('click'); + const card = (await screen.findAllByTestId('card'))[0]; - expect(history.location.search).toBe( - `?sort=${encodeURIComponent('{"title":"asc"}')}` + expect(within(card).getByRole('link', { name: 'Test 1' })).toHaveAttribute( + 'href', + '/browse/proposal/Investigation test name/investigation/1/dataset' ); - }); - - it('renders fine with incomplete data', () => { - (useInvestigationCount as jest.Mock).mockReturnValue({}); - (useInvestigationsPaginated as jest.Mock).mockReturnValue({}); - expect(() => createWrapper()).not.toThrowError(); + expect( + within(card).queryByRole('button', { name: 'buttons.add_to_cart' }) + ).toBeNull(); + expect( + within(card).queryByRole('button', { name: 'buttons.download' }) + ).toBeNull(); }); - it('renders generic link & pending count correctly', () => { - (useInvestigationsDatasetCount as jest.Mock).mockImplementation(() => [ - { - isFetching: true, - }, - ]); - const wrapper = createWrapper(); + it('renders ISIS link & file sizes correctly', async () => { + renderComponent({ hierarchy: FACILITY_NAME.isis }); + + const card = (await screen.findAllByTestId('card'))[0]; - expect(wrapper.find(CardView).find('a').first().prop('href')).toEqual( - `/browse/investigation/1/dataset` - ); - expect(wrapper.find(CardView).find('a').first().text()).toEqual('Test 1'); expect( - wrapper - .find(CardView) - .first() - .find('[data-testid="card-info-data-investigations.dataset_count"]') - .text() - ).toEqual('Calculating...'); + within(card).getByRole('link', { + name: 'Test 1', + }) + ).toHaveAttribute( + 'href', + '/browse/instrument/4/facilityCycle/6/investigation/1/dataset' + ); + + expect(within(card).getByText('10 B')).toBeInTheDocument(); }); - it("renders DLS link correctly and doesn't allow for cart selection or download", () => { - const wrapper = createWrapper('dls'); + it('displays DOI and renders the expected Link ', async () => { + renderComponent(); - expect(wrapper.find(CardView).find('a').first().prop('href')).toEqual( - '/browse/proposal/Investigation test name/investigation/1/dataset' + const card = (await screen.findAllByTestId('card'))[0]; + + expect(within(card).getByRole('link', { name: 'doi 1' })).toHaveAttribute( + 'href', + 'https://doi.org/doi 1' ); - expect(wrapper.find(CardView).find('a').first().text()).toEqual('Test 1'); - expect(wrapper.exists('#add-to-cart-btn-1')).toBe(false); - expect(wrapper.exists('#download-btn-1')).toBe(false); }); - it('renders ISIS link & file sizes correctly', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 6, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], - }); + it('does not render ISIS link when instrumentId cannot be found', async () => { + delete cardData.investigationinstrument; - const wrapper = createWrapper('isis'); + renderComponent({ hierarchy: FACILITY_NAME.isis }); - expect(useInvestigationSizes).toHaveBeenCalledWith(cardData); - expect(useInvestigationsDatasetCount).toHaveBeenCalledWith(undefined); + const card = (await screen.findAllByTestId('card'))[0]; - expect(wrapper.find(CardView).find('a').first().prop('href')).toEqual( - `/browse/instrument/4/facilityCycle/6/investigation/1/dataset` - ); - expect(wrapper.find(CardView).find('a').first().text()).toEqual('Test 1'); - expect( - wrapper - .find(CardView) - .first() - .find('[data-testid="card-info-data-investigations.size"]') - .text() - ).toEqual('1 B'); + expect(within(card).queryByRole('link', { name: 'Test 1' })).toBeNull(); + expect(within(card).getByText('Test 1')).toBeInTheDocument(); }); - it('displays DOI and renders the expected Link ', () => { - const wrapper = createWrapper(); - expect( - wrapper - .find('[data-testid="investigation-search-card-doi-link"]') - .first() - .text() - ).toEqual('doi 1'); + it('displays generic details panel when expanded', async () => { + const user = userEvent.setup(); - expect( - wrapper - .find('[data-testid="investigation-search-card-doi-link"]') - .first() - .prop('href') - ).toEqual('https://doi.org/doi 1'); - }); + renderComponent(); - it('does not render ISIS link when instrumentId cannot be found', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], - }); - delete cardData[0].investigationInstruments; + expect(screen.queryByTestId('investigation-details-panel')).toBeNull(); - (useInvestigationsPaginated as jest.Mock).mockReturnValue({ - data: cardData, - fetchNextPage: jest.fn(), - }); - const wrapper = createWrapper('isis'); + await user.click( + await screen.findByRole('button', { name: 'card-more-info-expand' }) + ); - expect(wrapper.find(CardView).first().find('a')).toHaveLength(1); expect( - wrapper.find(CardView).first().find('[aria-label="card-title"]').text() - ).toEqual('Test 1'); + await screen.findByTestId('investigation-details-panel') + ).toBeInTheDocument(); }); - it('displays only the dataset name when there is no generic investigation to link to', () => { - delete cardData[0].investigation; - (useInvestigationsPaginated as jest.Mock).mockReturnValue({ - data: cardData, - fetchNextPage: jest.fn(), - }); + it('displays correct details panel for ISIS when expanded', async () => { + cardData.investigationinstrument = []; + cardData.investigationfacilitycycle = []; - const wrapper = createWrapper('data'); + const user = userEvent.setup(); - expect(wrapper.find(CardView).first().find('a')).toHaveLength(2); - expect( - wrapper.find(CardView).first().find('[aria-label="card-title"]').text() - ).toEqual('Test 1'); - }); + renderComponent({ hierarchy: FACILITY_NAME.isis }); - it('displays only the dataset name when there is no DLS investigation to link to', () => { - delete cardData[0].investigation; - (useInvestigationsPaginated as jest.Mock).mockReturnValue({ - data: cardData, - fetchNextPage: jest.fn(), - }); + expect(screen.queryByTestId('isis-investigation-details-panel')).toBeNull(); - const wrapper = createWrapper('dls'); + await user.click( + await screen.findByRole('button', { name: 'card-more-info-expand' }) + ); - expect(wrapper.find(CardView).first().find('a')).toHaveLength(2); expect( - wrapper.find(CardView).first().find('[aria-label="card-title"]').text() - ).toEqual('Test 1'); + await screen.findByTestId('isis-investigation-details-panel') + ).toBeInTheDocument(); }); - it('displays only the dataset name when there is no ISIS investigation to link to', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], - }); - delete cardData[0].investigation; - (useInvestigationsPaginated as jest.Mock).mockReturnValue({ - data: cardData, - fetchNextPage: jest.fn(), - }); + it('can navigate using the details panel for ISIS when there are facility cycles', async () => { + const user = userEvent.setup(); - const wrapper = createWrapper('isis'); + renderComponent({ + hierarchy: FACILITY_NAME.isis, + }); - expect(wrapper.find(CardView).first().find('a')).toHaveLength(2); - expect( - wrapper.find(CardView).first().find('[aria-label="card-title"]').text() - ).toEqual('Test 1'); - }); + expect(screen.queryByTestId('isis-investigation-details-panel')).toBeNull(); - it('displays generic details panel when expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(InvestigationDetailsPanel).exists()).toBeFalsy(); - wrapper - .find('[aria-label="card-more-info-expand"]') - .first() - .simulate('click'); + await user.click( + await screen.findByRole('button', { name: 'card-more-info-expand' }) + ); - expect(wrapper.find(InvestigationDetailsPanel).exists()).toBeTruthy(); - }); + const panel = await screen.findByTestId('isis-investigation-details-panel'); + expect(panel).toBeInTheDocument(); - it('displays correct details panel for ISIS when expanded', () => { - const wrapper = createWrapper('isis'); - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeFalsy(); - wrapper - .find('[aria-label="card-more-info-expand"]') - .first() - .simulate('click'); + await user.click( + within(panel).getByRole('tab', { + name: 'investigations.details.datasets', + }) + ); - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeTruthy(); + await waitFor(() => { + expect(history.location.pathname).toBe( + '/browse/instrument/4/facilityCycle/6/investigation/1/dataset' + ); + }); }); - it('can navigate using the details panel for ISIS when there are facility cycles', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], - }); + it('displays correct details panel for DLS when expanded', async () => { + const user = userEvent.setup(); - const wrapper = createWrapper('isis'); - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeFalsy(); - wrapper - .find('[aria-label="card-more-info-expand"]') - .first() - .simulate('click'); + renderComponent({ + hierarchy: FACILITY_NAME.dls, + }); - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeTruthy(); + expect(screen.queryByTestId('dls-visit-details-panel')).toBeNull(); - wrapper.find('#investigation-datasets-tab').first().simulate('click'); - expect(history.location.pathname).toBe( - '/browse/instrument/4/facilityCycle/4/investigation/1/dataset' + await user.click( + await screen.findByRole('button', { name: 'card-more-info-expand' }) ); - }); - - it('displays correct details panel for DLS when expanded', () => { - const wrapper = createWrapper('dls'); - expect(wrapper.find(DLSVisitDetailsPanel).exists()).toBeFalsy(); - wrapper - .find('[aria-label="card-more-info-expand"]') - .first() - .simulate('click'); - expect(wrapper.find(DLSVisitDetailsPanel).exists()).toBeTruthy(); + expect( + await screen.findByTestId('dls-visit-details-panel') + ).toBeInTheDocument(); }); }); diff --git a/packages/datagateway-search/src/card/investigationSearchCardView.component.tsx b/packages/datagateway-search/src/card/investigationSearchCardView.component.tsx index affb10241..8bb8146bc 100644 --- a/packages/datagateway-search/src/card/investigationSearchCardView.component.tsx +++ b/packages/datagateway-search/src/card/investigationSearchCardView.component.tsx @@ -1,212 +1,181 @@ import { + Assessment, CalendarToday, - ConfirmationNumber, Fingerprint, Public, - Assessment, -} from '@material-ui/icons'; + Save, +} from '@mui/icons-material'; import { + AddToCartButton, + ArrowTooltip, + buildDatasetTableUrlForInvestigation, CardView, - formatCountOrSize, + DLSVisitDetailsPanel, + DownloadButton, + formatBytes, + FACILITY_NAME, Investigation, + InvestigationDetailsPanel, + ISISInvestigationDetailsPanel, parseSearchToQuery, - useDateFilter, - useInvestigationCount, - useInvestigationsDatasetCount, - useInvestigationsPaginated, - usePushFilter, + SearchFilter, + SearchResponse, + SearchResultSource, + tableLink, + useLuceneSearchInfinite, + usePushInvestigationFilter, usePushPage, usePushResults, useSort, - useTextFilter, - useAllFacilityCycles, - tableLink, - FacilityCycle, - useInvestigationSizes, - useLuceneSearch, - nestedValue, - ArrowTooltip, - AddToCartButton, - DownloadButton, - InvestigationDetailsPanel, - ISISInvestigationDetailsPanel, - DLSVisitDetailsPanel, } from 'datagateway-common'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { useHistory, useLocation } from 'react-router-dom'; import { - Typography, + Grid, Link as MuiLink, - makeStyles, - createStyles, - Theme, -} from '@material-ui/core'; + Paper, + styled, + Typography, +} from '@mui/material'; import { useSelector } from 'react-redux'; +import { useHistory, useLocation } from 'react-router-dom'; import { StateType } from '../state/app.types'; +import useFacetFilters from '../facet/useFacetFilters'; +import FacetPanel from '../facet/components/facetPanel/facetPanel.component'; +import { facetClassificationFromSearchResponses } from '../facet/facet'; +import SelectedFilterChips from '../facet/components/selectedFilterChips.component'; +import { useSearchResultCounter } from '../searchTabs/useSearchResultCounter'; interface InvestigationCardProps { hierarchy: string; } -const useStyles = makeStyles((theme: Theme) => - createStyles({ - actionButtons: { - display: 'flex', - flexDirection: 'column', - '& button': { - marginTop: theme.spacing(1), - margin: 'auto', - }, - }, - }) -); +const ActionButtonDiv = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + '& button': { + margin: 'auto', + marginTop: theme.spacing(1), + }, +})); -const InvestigationCardView = ( - props: InvestigationCardProps -): React.ReactElement => { +const InvestigationCardView: React.FC = (props) => { const { hierarchy } = props; const [t] = useTranslation(); const location = useLocation(); const { push } = useHistory(); - const queryParams = React.useMemo(() => parseSearchToQuery(location.search), [ - location.search, - ]); - const { filters, sort, page, results, startDate, endDate } = queryParams; - const searchText = queryParams.searchText ? queryParams.searchText : ''; - - const { data: facilityCycles } = useAllFacilityCycles(hierarchy === 'isis'); - - const dlsLinkURL = (investigationData: Investigation): string => - `/browse/proposal/${investigationData.name}/investigation/${investigationData.id}/dataset`; - - const isisLinkURL = React.useCallback( - (investigationData: Investigation) => { - let instrumentId; - let facilityCycleId; - if (investigationData.investigationInstruments?.length) { - instrumentId = - investigationData.investigationInstruments[0].instrument?.id; - } else { - return null; - } - - if (investigationData.startDate && facilityCycles?.length) { - const filteredFacilityCycles: FacilityCycle[] = facilityCycles?.filter( - (facilityCycle: FacilityCycle) => - investigationData.startDate && - facilityCycle.startDate && - facilityCycle.endDate && - investigationData.startDate >= facilityCycle.startDate && - investigationData.startDate <= facilityCycle.endDate - ); - if (filteredFacilityCycles.length) { - facilityCycleId = filteredFacilityCycles[0].id; - } - } - - if (facilityCycleId) - return `/browse/instrument/${instrumentId}/facilityCycle/${facilityCycleId}/investigation/${investigationData.id}/dataset`; - else return null; - }, - [facilityCycles] - ); - - const isisLink = React.useCallback( - (investigationData: Investigation) => { - const linkURL = isisLinkURL(investigationData); - - if (linkURL) return tableLink(linkURL, investigationData.title); - else return investigationData.title; - }, - [isisLinkURL] + const queryParams = React.useMemo( + () => parseSearchToQuery(location.search), + [location.search] ); + const { + filters, + sort, + page, + results, + startDate, + endDate, + restrict, + investigation, + currentTab, + } = queryParams; + const searchText = queryParams.searchText ? queryParams.searchText : ''; - const genericLinkURL = (investigationData: Investigation): string => - `/browse/investigation/${investigationData.id}/dataset`; - - const hierarchyLinkURL = React.useMemo(() => { - if (hierarchy === 'dls') { - return dlsLinkURL; - } else if (hierarchy === 'isis') { - return isisLinkURL; - } else { - return genericLinkURL; - } - }, [hierarchy, isisLinkURL]); - - const hierarchyLink = React.useMemo(() => { - if (hierarchy === 'dls') { - const dlsLink = (investigationData: Investigation): React.ReactElement => - tableLink(dlsLinkURL(investigationData), investigationData.title); - - return dlsLink; - } else if (hierarchy === 'isis') { - return isisLink; - } else { - const genericLink = ( - investigationData: Investigation - ): React.ReactElement => - tableLink(genericLinkURL(investigationData), investigationData.title); - - return genericLink; - } - }, [hierarchy, isisLink]); - - const textFilter = useTextFilter(filters); - const dateFilter = useDateFilter(filters); const handleSort = useSort(); - const pushFilter = usePushFilter(); + const pushFilter = usePushInvestigationFilter(); const pushPage = usePushPage(); const pushResults = usePushResults(); + const minNumResults = useSelector( + (state: StateType) => state.dgsearch.minNumResults + ); + const maxNumResults = useSelector( (state: StateType) => state.dgsearch.maxNumResults ); - const { data: luceneData } = useLuceneSearch('Investigation', { - searchText, - startDate, - endDate, - maxCount: maxNumResults, - }); + const { data, isLoading, isFetching, hasNextPage, fetchNextPage, refetch } = + useLuceneSearchInfinite( + 'Investigation', + { + searchText, + startDate, + endDate, + sort, + minCount: minNumResults, + maxCount: maxNumResults, + restrict, + facets: [ + { target: 'Investigation' }, + { + target: 'InvestigationParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'Sample', + dimensions: [{ dimension: 'sample.type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], + }, + currentTab === 'investigation' ? filters : {}, + { enabled: investigation } + ); + + function mapSource(response: SearchResponse): SearchResultSource[] { + return response.results?.map((result) => result.source) ?? []; + } + + function mapIds(response: SearchResponse): number[] { + return response.results?.map((result) => result.id) ?? []; + } const { - data: totalDataCount, - isLoading: countLoading, - } = useInvestigationCount([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: luceneData || [] }, - }), - }, - ]); - const { isLoading: dataLoading, data } = useInvestigationsPaginated([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: luceneData || [] }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - investigationInstruments: 'instrument', - }), - }, - ]); + selectedFacetFilters, + addFacetFilter, + removeFacetFilter, + applyFacetFilters, + haveUnappliedFilters, + } = useFacetFilters(); - // hierarchy === 'isis' ? data : undefined is a 'hack' to only perform - // the correct calculation queries for each facility - const datasetCountQueries = useInvestigationsDatasetCount( - hierarchy !== 'isis' ? data : undefined - ); - const sizeQueries = useInvestigationSizes( - hierarchy === 'isis' ? data : undefined - ); + useSearchResultCounter({ + isFetching, + dataSearchType: 'Investigation', + searchResponses: data?.pages, + hasMore: hasNextPage, + }); + + const { paginatedSource, aggregatedIds, aborted } = React.useMemo(() => { + if (data) { + const aggregatedIds = data.pages + .map((response) => mapIds(response)) + .flat(); + const minResult = (page ? page - 1 : 0) * (results ?? 10); + const maxResult = (page ?? 1) * (results ?? 10); + if (hasNextPage && aggregatedIds.length < maxResult) { + fetchNextPage(); + } + const aggregatedSource = data.pages + .map((response) => mapSource(response)) + .flat(); + return { + paginatedSource: aggregatedSource.slice(minResult, maxResult), + aggregatedIds: aggregatedIds, + aborted: data.pages[data.pages.length - 1].aborted, + }; + } else { + return { + paginatedSource: [], + aggregatedIds: [], + aborted: false, + }; + } + }, [data, fetchNextPage, hasNextPage, page, results]); const title = React.useMemo( () => ({ @@ -214,22 +183,35 @@ const InvestigationCardView = ( label: t('investigations.title'), // Provide both the dataKey (for tooltip) and content to render. dataKey: 'title', - content: (investigation: Investigation) => { - return hierarchyLink(investigation); + content: (investigation: SearchResultSource) => { + const url = buildDatasetTableUrlForInvestigation({ + investigation: { + id: investigation.id, + name: investigation.name, + instrumentId: + investigation.investigationinstrument?.[0]?.['instrument.id'], + facilityCycleId: + investigation.investigationfacilitycycle?.[0]?.[ + 'facilityCycle.id' + ], + }, + facilityName: hierarchy, + }); + if (!investigation.title) return ''; + return url ? tableLink(url, investigation.title) : investigation.title; }, - filterComponent: textFilter, + disableSort: true, }), - // [t, textFilter, view] - [hierarchyLink, t, textFilter] + [hierarchy, t] ); const description = React.useMemo( () => ({ label: t('investigations.details.summary'), dataKey: 'summary', - filterComponent: textFilter, + disableSort: true, }), - [t, textFilter] + [t] ); const information = React.useMemo( @@ -250,48 +232,39 @@ const InvestigationCardView = ( icon: Public, label: t('investigations.doi'), dataKey: 'doi', - filterComponent: textFilter, + disableSort: true, }, { icon: Fingerprint, label: t('investigations.visit_id'), dataKey: 'visitId', - filterComponent: textFilter, + disableSort: true, }, { icon: Fingerprint, label: t('investigations.details.name'), dataKey: 'name', - filterComponent: textFilter, disableSort: true, }, { - icon: ConfirmationNumber, - label: - hierarchy === 'isis' - ? t('investigations.size') - : t('investigations.dataset_count'), - dataKey: hierarchy === 'isis' ? 'size' : 'datasetCount', - content: (investigation: Investigation): string => { - const index = data?.findIndex((item) => item.id === investigation.id); - if (typeof index === 'undefined') return 'Unknown'; - const query = - hierarchy === 'isis' - ? sizeQueries[index] - : datasetCountQueries[index]; - return formatCountOrSize(query, hierarchy === 'isis'); - }, + icon: Save, + label: t('investigations.size'), + dataKey: 'size', + content: (investigation: Investigation): string => + formatBytes(investigation.fileSize), disableSort: true, }, { icon: Assessment, label: t('investigations.instrument'), dataKey: 'investigationInstruments.instrument.name', - content: function Content(investigation: Investigation) { - const instrument = nestedValue( - investigation, - 'investigationInstruments[0].instrument.name' - ); + content: function Content(investigation: SearchResultSource) { + const investigationInstrument = + investigation.investigationinstrument?.[0]; + const instrument = + investigationInstrument?.['instrument.fullName'] ?? + investigationInstrument?.['instrument.name'] ?? + 'Unknown'; return ( {instrument} @@ -299,105 +272,185 @@ const InvestigationCardView = ( ); }, noTooltip: true, - filterComponent: textFilter, + disableSort: true, }, { + content: function (investigation: Investigation): string { + return investigation.startDate + ? new Date(investigation.startDate).toLocaleDateString() + : 'Unknown'; + }, icon: CalendarToday, label: t('investigations.details.start_date'), dataKey: 'startDate', - filterComponent: dateFilter, + disableSort: true, }, { + content: function (investigation: Investigation): string { + return investigation.endDate + ? new Date(investigation.endDate).toLocaleDateString() + : 'Unknown'; + }, icon: CalendarToday, label: t('investigations.details.end_date'), dataKey: 'endDate', - filterComponent: dateFilter, + disableSort: true, }, ], - [ - data, - datasetCountQueries, - dateFilter, - hierarchy, - sizeQueries, - t, - textFilter, - ] + [t] ); const moreInformation = React.useCallback( - (investigation: Investigation) => { - if (hierarchy === 'isis') { - const datasetsURL = hierarchyLinkURL(investigation); - return ( - { - push(datasetsURL); - } - : undefined - } - /> - ); - } else if (hierarchy === 'dls') - return ; - else return ; + (investigation: SearchResultSource) => { + switch (hierarchy) { + case FACILITY_NAME.isis: + const url = buildDatasetTableUrlForInvestigation({ + investigation: { + id: investigation.id, + name: investigation.name, + instrumentId: + investigation.investigationinstrument?.[0]?.['instrument.id'], + facilityCycleId: + investigation.investigationfacilitycycle?.[0]?.[ + 'facilityCycle.id' + ], + }, + facilityName: FACILITY_NAME.isis, + }); + return ( + { + if (url) push(url); + }} + /> + ); + + case FACILITY_NAME.dls: + return ; + + default: + return ; + } }, - [hierarchy, hierarchyLinkURL, push] + [hierarchy, push] ); - const classes = useStyles(); + const removeFilterChip = ( + dimension: string, + filterValue: SearchFilter + ): void => { + removeFacetFilter({ dimension, filterValue, applyImmediately: true }); + }; const buttons = React.useMemo( () => hierarchy !== 'dls' ? [ - (investigation: Investigation) => ( -
+ (investigation: SearchResultSource) => ( + investigation.id) ?? []} + allIds={aggregatedIds} entityId={investigation.id} /> -
+ ), ] : [], - [classes.actionButtons, data, hierarchy, sizeQueries] + [aggregatedIds, hierarchy] ); + if (currentTab !== 'investigation') return null; + return ( - + + + {data?.pages && ( + + addFacetFilter({ + dimension, + filterValue, + applyImmediately: false, + }) + } + onRemoveFilter={(dimension, filterValue) => + removeFacetFilter({ + dimension, + filterValue, + applyImmediately: false, + }) + } + onApplyFacetFilters={() => { + applyFacetFilters(); + refetch(); + }} + /> + )} + + + + + +
+ {aborted ? ( + + + {t('loading.abort_message')} + + + ) : ( + + )} +
+
+
+
+
); }; diff --git a/packages/datagateway-search/src/facet/components/facetPanel/facetPanel.component.test.tsx b/packages/datagateway-search/src/facet/components/facetPanel/facetPanel.component.test.tsx new file mode 100644 index 000000000..49ecfc1ec --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/facetPanel.component.test.tsx @@ -0,0 +1,487 @@ +import * as React from 'react'; +import { render, screen, within } from '@testing-library/react'; +import FacetPanel from './facetPanel.component'; +import { FacetClassification } from '../../facet'; +import userEvent from '@testing-library/user-event'; +import { DatasearchType } from 'datagateway-common'; + +describe('facetPanel', () => { + const TEST_FACET_CLASSIFICATION: FacetClassification = { + 'investigation.type.name': { + experiment: 300, + calibration: 200, + }, + 'investigationparameter.type.name': { + bcat_inv_str: 299, + run_number_range: 400, + }, + }; + const TEST_ENTITY_NAME: DatasearchType = 'Investigation'; + const TEST_IDS = [123, 456, 789]; + + it('renders facets as list of accordions that expands to reveal filters', async () => { + const user = userEvent.setup(); + + render( + + ); + + expect( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.investigation.type.name filter panel', + }) + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.investigationparameter.type.name filter panel', + }) + ).toBeInTheDocument(); + + // open investigation type filter panel + await user.click( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.investigation.type.name filter panel', + }) + ); + + const investigationTypeFilterPanel = screen.getByLabelText( + 'facetDimensionLabel.investigation.type.name filter panel' + ); + expect(investigationTypeFilterPanel).toBeVisible(); + + const experimentFilterItem = within(investigationTypeFilterPanel).getByRole( + 'button', + { name: 'Add experiment filter' } + ); + expect( + within(experimentFilterItem).getByText('experiment') + ).toBeInTheDocument(); + expect(within(experimentFilterItem).getByText('300')).toBeInTheDocument(); + + const calibrationFilterItem = within( + investigationTypeFilterPanel + ).getByRole('button', { name: 'Add calibration filter' }); + expect( + within(calibrationFilterItem).getByText('calibration') + ).toBeInTheDocument(); + expect(within(calibrationFilterItem).getByText('200')).toBeInTheDocument(); + + // close investigation type filter panel + await user.click( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.investigation.type.name filter panel', + }) + ); + + expect( + screen.getByLabelText( + 'facetDimensionLabel.investigation.type.name filter panel' + ) + ).not.toBeVisible(); + + // open investigation parameter type filter panel + await user.click( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.investigationparameter.type.name filter panel', + }) + ); + + const investigationParamFilterPanel = screen.getByLabelText( + 'facetDimensionLabel.investigationparameter.type.name filter panel' + ); + expect(investigationParamFilterPanel).toBeVisible(); + + const bcatInvStrFilterItem = within( + investigationParamFilterPanel + ).getByRole('button', { name: 'Add bcat_inv_str filter' }); + expect( + within(bcatInvStrFilterItem).getByText('bcat_inv_str') + ).toBeInTheDocument(); + expect(within(bcatInvStrFilterItem).getByText('299')).toBeInTheDocument(); + + const runNumberRangeFilterItem = within( + investigationParamFilterPanel + ).getByRole('button', { name: 'Add run_number_range filter' }); + expect( + within(runNumberRangeFilterItem).getByText('run_number_range') + ).toBeInTheDocument(); + expect( + within(runNumberRangeFilterItem).getByText('400') + ).toBeInTheDocument(); + + // close investigation type filter panel + await user.click( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.investigationparameter.type.name filter panel', + }) + ); + + expect( + screen.getByLabelText( + 'facetDimensionLabel.investigationparameter.type.name filter panel' + ) + ).not.toBeVisible(); + }); + + it('highlights selected filters', async () => { + const user = userEvent.setup(); + + render( + + ); + + // open investigation type filter panel + await user.click( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.investigation.type.name filter panel', + }) + ); + + const experimentFilterItem = within( + screen.getByLabelText( + 'facetDimensionLabel.investigation.type.name filter panel' + ) + ).getByRole('button', { name: 'Remove experiment filter' }); + expect(experimentFilterItem).toHaveAttribute('aria-selected', 'true'); + expect(within(experimentFilterItem).getByRole('checkbox')).toBeChecked(); + + // open investigation parameter type filter panel + await user.click( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.investigationparameter.type.name filter panel', + }) + ); + + const bcatInvStrFilterItem = within( + screen.getByLabelText( + 'facetDimensionLabel.investigationparameter.type.name filter panel' + ) + ).getByRole('button', { name: 'Remove bcat_inv_str filter' }); + expect(bcatInvStrFilterItem).toHaveAttribute('aria-selected', 'true'); + expect(within(bcatInvStrFilterItem).getByRole('checkbox')).toBeChecked(); + }); + + it('reflects the changes when a filter is added', async () => { + const user = userEvent.setup(); + const onAddFilter = jest.fn(); + const onApplyFacetFilters = jest.fn(); + + const { rerender } = render( + + ); + + // apply button should not be visible when no changes are made to filters + expect( + screen.queryByRole('button', { name: 'facetPanel.apply' }) + ).toBeNull(); + + // open investigation type filter panel + await user.click( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.investigation.type.name filter panel', + }) + ); + await user.click( + within( + screen.getByLabelText( + 'facetDimensionLabel.investigation.type.name filter panel' + ) + ).getByRole('button', { name: 'Add calibration filter' }) + ); + + rerender( + + ); + + expect(onAddFilter).toHaveBeenLastCalledWith( + 'investigation.type.name', + 'calibration' + ); + + const investigationFilterPanel = within( + screen.getByLabelText( + 'facetDimensionLabel.investigation.type.name filter panel' + ) + ); + expect( + investigationFilterPanel.queryByRole('button', { + name: 'Add calibration filter', + }) + ).toBeNull(); + expect( + investigationFilterPanel.getByRole('button', { + name: 'Remove calibration filter', + }) + ).toBeInTheDocument(); + + // apply the filter + await user.click(screen.getByRole('button', { name: 'facetPanel.apply' })); + expect(onApplyFacetFilters).toHaveBeenCalledTimes(1); + }); + + it('reflects the changes when a filter is removed', async () => { + const user = userEvent.setup(); + const onRemoveFilter = jest.fn(); + const onApplyFacetFilters = jest.fn(); + + const { rerender } = render( + + ); + + // apply button should not be visible when no changes are made to filters + expect( + screen.queryByRole('button', { name: 'facetPanel.apply' }) + ).toBeNull(); + + // open investigation type filter panel + await user.click( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.investigation.type.name filter panel', + }) + ); + + const experimentFilterItem = within( + screen.getByLabelText( + 'facetDimensionLabel.investigation.type.name filter panel' + ) + ).getByRole('button', { name: 'Remove experiment filter' }); + await user.click(experimentFilterItem); + + // pretend the selected filters are updated + rerender( + + ); + + expect(onRemoveFilter).toHaveBeenLastCalledWith( + 'investigation.type.name', + 'experiment' + ); + + expect( + within( + screen.getByLabelText( + 'facetDimensionLabel.investigation.type.name filter panel' + ) + ).queryByRole('button', { name: 'Remove experiment filter' }) + ).toBeNull(); + expect( + within( + screen.getByLabelText( + 'facetDimensionLabel.investigation.type.name filter panel' + ) + ).getByRole('button', { name: 'Add experiment filter' }) + ).toBeInTheDocument(); + + // apply the filter + await user.click(screen.getByRole('button', { name: 'facetPanel.apply' })); + expect(onApplyFacetFilters).toHaveBeenCalledTimes(1); + }); + + describe('shows parameter filter', () => { + it('for investigation parameters', async () => { + const user = userEvent.setup(); + + render( + + ); + + // open investigation parameter type filter panel + await user.click( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.investigationparameter.type.name filter panel', + }) + ); + + expect(screen.getByTestId('parameter-filters')).toBeInTheDocument(); + }); + + it('for dataset parameters', async () => { + const user = userEvent.setup(); + + render( + + ); + + // open dataset parameter type filter panel + await user.click( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.datasetparameter.type.name filter panel', + }) + ); + + expect(screen.getByTestId('parameter-filters')).toBeInTheDocument(); + }); + + it('for datafile parameters', async () => { + const user = userEvent.setup(); + + render( + + ); + + // open datafile parameter type filter panel + await user.click( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.datafileparameter.type.name filter panel', + }) + ); + + expect(screen.getByTestId('parameter-filters')).toBeInTheDocument(); + }); + }); + + it('shows selected parameter filters in the parameter name filter panel', async () => { + const user = userEvent.setup(); + + render( + + ); + + // open datafile parameter type filter panel + await user.click( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.investigationparameter.type.name filter panel', + }) + ); + + const selectedParameterFilterList = screen.getByRole('list', { + name: 'parameterFilters.selectedParameterFilterList', + }); + const listItems = within(selectedParameterFilterList).getAllByRole( + 'listitem' + ); + + expect(selectedParameterFilterList).toBeInTheDocument(); + expect(listItems).toHaveLength(1); + expect( + within(listItems[0]).getByText('bcat_inv_str: Test Label') + ).toBeInTheDocument(); + }); +}); diff --git a/packages/datagateway-search/src/facet/components/facetPanel/facetPanel.component.tsx b/packages/datagateway-search/src/facet/components/facetPanel/facetPanel.component.tsx new file mode 100644 index 000000000..ed51d06cb --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/facetPanel.component.tsx @@ -0,0 +1,242 @@ +import React from 'react'; +import { + Accordion as MuiAccordion, + AccordionDetails, + AccordionSummary as MuiAccordionSummary, + Box, + Button, + Divider, + List, + styled, + Typography, +} from '@mui/material'; +import { ExpandMore } from '@mui/icons-material'; +import ToggleableFilterItem from './toggleableFilterItem.component'; +import { FacetClassification } from '../../facet'; +import { useTranslation } from 'react-i18next'; +import { DatasearchType, FiltersType, SearchFilter } from 'datagateway-common'; +import ParameterFilters from './parameterFilters/parameterFilters.component'; + +const PanelContainer = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'start', + padding: theme.spacing(2), + overflow: 'auto', + height: '100%', +})); + +const Accordion = styled(MuiAccordion)(({ theme }) => ({ + border: `1px solid ${theme.palette.divider}`, + width: '100%', + '&:not(:last-child)': { + borderBottom: 0, + }, + '&:before': { + display: 'none', + }, +})); + +const AccordionSummary = styled(MuiAccordionSummary)(({ theme }) => ({ + backgroundColor: + theme.palette.mode === 'dark' + ? theme.palette.grey[900] + : theme.palette.grey[50], + minHeight: 0, + paddingTop: theme.spacing(1), + paddingBottom: theme.spacing(1), + paddingLeft: theme.spacing(1.5), + paddingRight: theme.spacing(1.5), + '& .MuiAccordionSummary-content': { + margin: 0, + }, +})); + +interface FacetPanelProps { + /** + * Facet classifications on the search result set. + */ + facetClassification: FacetClassification; + + /** + * The currently selected filters. + */ + selectedFacetFilters: FiltersType; + + /** + * Called when a filter is added by the user. The dimension and the value of the filter is passed. + * For example, `dimension` can be "investigation.type.name" and `filterValue` can be `"experiment"`, + * which indicates that the user wishes to only see investigations with type `"experiment"`. + * + * @param dimension The dimension of the added filter. For example investigation.type.name (Investigation type) + * @param filterValue The value of the added filter. + */ + onAddFilter: (dimension: string, filterValue: SearchFilter) => void; + + /** + * Called when a filter is removed by the user. + * + * @param dimension The dimension of the removed filter. For example investigation.type.name (Investigation type) + * @param filterValue The value of the removed filter. + * @see FacetPanelProps.onAddFilter + */ + onRemoveFilter: (dimension: string, filterValue: SearchFilter) => void; + + /** + * Called when the selected filters are applied by the user. The search data should refresh + * to reflect the applied filters. + */ + onApplyFacetFilters: () => void; + + /** + * Whether the apply button for applying filters should be shown. + */ + showApplyButton: boolean; + + /** + * Aggregated IDs of the search result rows. + */ + allIds: number[]; + + entityName: DatasearchType; +} + +/** + * Allows users to narrow down the search result by applying filters + * based on the facet classification of the search result set. + * + * For example, users can filter the search result by investigation type + * or datafile format (txt? log? nexus file?) + * + * When filters are added/removed via {@link FacetPanelProps.onAddFilter} or {@link FacetPanelProps.onRemoveFilter}, + * the data should not be updated until the user *applies* them via {@link FacetPanelProps.onApplyFacetFilters}. + */ +function FacetPanel({ + facetClassification, + selectedFacetFilters, + onAddFilter, + onRemoveFilter, + onApplyFacetFilters, + allIds, + entityName, + showApplyButton, +}: FacetPanelProps): JSX.Element { + const [t] = useTranslation(); + + const classifications = Object.entries(facetClassification); + + return ( + + + {t('facetPanel.title')} + {showApplyButton && ( + + )} + + + {classifications.length > 0 ? ( + + {/* For each facet classification on the search data, + render a new Accordion that expands to show the available filter values on that facet (dimension). */} + {classifications.map(([dimension, classifications]) => ( + + } + aria-controls={`${dimension}-filter-panel`} + aria-label={`Toggle ${t( + `facetDimensionLabel.${dimension}` + )} filter panel`} + > + {t(`facetDimensionLabel.${dimension}`)} + + + + {Object.entries(classifications).map( + ([classificationLabel, count]) => { + const selectedFilterValue = + selectedFacetFilters[dimension]; + const isItemSelected = + Array.isArray(selectedFilterValue) && + selectedFilterValue.includes(classificationLabel); + + return ( + { + if (selected) { + onAddFilter(dimension, classificationLabel); + } else { + onRemoveFilter(dimension, classificationLabel); + } + }} + count={count} + /> + ); + } + )} + + {areParameterFiltersAvailable(dimension) && ( + <> + + + + + + )} + + + ))} + + ) : ( + + {t('facetPanel.noFilters')} + + )} + + ); +} + +/** + * Given a facet dimension, determine whether parameter filters are available for it. + * Parameter filters only apply to InvestigationParameter, DatasetParameter and DatafileParameter dimensions. + * + * This is used to check whether the parameter filters UI should be shown. + * + * @see ParameterFilters + */ +function areParameterFiltersAvailable(dimension: string): boolean { + const l = dimension.toLocaleLowerCase(); + return ( + l === 'investigationparameter.type.name' || + l === 'datasetparameter.type.name' || + l === 'datafileparameter.type.name' + ); +} + +export default FacetPanel; diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/newParameterFilterCreator.component.test.tsx b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/newParameterFilterCreator.component.test.tsx new file mode 100644 index 000000000..357c70243 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/newParameterFilterCreator.component.test.tsx @@ -0,0 +1,420 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; +import { Provider } from 'react-redux'; +import createMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { DatasearchType, dGCommonInitialState } from 'datagateway-common'; +import { QueryClient, QueryClientProvider } from 'react-query'; +import NewParameterFilterCreator from './newParameterFilterCreator.component'; +import axios, { AxiosResponse } from 'axios'; + +describe('NewParameterFilterCreator', () => { + const TEST_ENTITY_NAME: DatasearchType = 'Investigation'; + const TEST_PARAMETER_NAMES = ['bcat_inv_str', 'run_number_range']; + const TEST_IDS = [123, 456, 789]; + + function Wrapper({ + children, + }: React.PropsWithChildren): React.ReactElement { + return ( + + + {children} + + + ); + } + + beforeEach(() => { + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + if (/\/facet\/documents$/.test(url)) { + return Promise.resolve({ + data: { + results: [], + dimensions: { + investigationparameters: { + 'PARAMETER STRING VALUE': 123, + 'PARAMETER STRING VALUE 2': 456, + }, + }, + }, + }); + } + return Promise.reject(`Endpoint not mocked: ${url}`); + }); + }); + + it('shows parameter name and value type dropdown and a disabled add filter button initially', () => { + render( + , + { + wrapper: Wrapper, + } + ); + + expect( + screen.getByRole('button', { + // have to use regex with case-insensitive option here instead of regular string + // because for some reason even though testing-library *says* it can't find the element by string + // in the actual error message it shows the matching element with the exact same label and casing + // but somehow this works + name: /parameterFilters.creator.labels.parameterNameSelect /i, + }) + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterValueTypeSelect /i, + }) + ).toBeInTheDocument(); + + const addFilterButton = screen.getByRole('button', { + name: 'parameterFilters.creator.addFilter', + }); + expect(addFilterButton).toBeInTheDocument(); + expect(addFilterButton).toBeDisabled(); + }); + + it('shows help message when neither parameter name nor parameter value type is selected', () => { + render( + , + { + wrapper: Wrapper, + } + ); + + expect( + screen.getByText( + 'parameterFilters.creator.message.parameterNameAndTypeNotSelected' + ) + ).toBeInTheDocument(); + }); + + it("shows help message when parameter name is selected but parameter value type isn't", async () => { + const user = userEvent.setup(); + + render( + , + { + wrapper: Wrapper, + } + ); + + await user.click( + screen.getByRole('button', { + // have to use regex with case-insensitive option here instead of regular string + // because for some reason even though testing-library *says* it can't find the element by string + // in the actual error message it shows the matching element with the exact same label and casing + // but somehow this works + name: /parameterFilters.creator.labels.parameterNameSelect /i, + }) + ); + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterNameSelect', + }), + screen.getByRole('option', { name: 'bcat_inv_str' }) + ); + + expect( + await screen.findByText( + 'parameterFilters.creator.message.parameterTypeNotSelected' + ) + ).toBeInTheDocument(); + }); + + it("shows help message when parameter type is selected but parameter name isn't", async () => { + const user = userEvent.setup(); + + render( + , + { + wrapper: Wrapper, + } + ); + + await user.click( + screen.getByRole('button', { + // have to use regex with case-insensitive option here instead of regular string + // because for some reason even though testing-library *says* it can't find the element by string + // in the actual error message it shows the matching element with the exact same label and casing + // but somehow this works + name: /parameterFilters.creator.labels.parameterValueTypeSelect /i, + }) + ); + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterValueTypeSelect', + }), + screen.getByRole('option', { + name: 'parameterFilters.valueType.dateTime', + }) + ); + + expect( + await screen.findByText( + 'parameterFilters.creator.message.parameterNameNotSelected' + ) + ).toBeInTheDocument(); + }); + + it('shows appropriate parameter value selector depending on the selected parameter type', async () => { + const user = userEvent.setup(); + + render( + , + { + wrapper: Wrapper, + } + ); + + // select parameter name + await user.click( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterNameSelect /i, + }) + ); + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterNameSelect', + }), + screen.getByRole('option', { name: 'bcat_inv_str' }) + ); + // select parameter value type + await user.click( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterValueTypeSelect /i, + }) + ); + + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterValueTypeSelect', + }), + screen.getByRole('option', { + name: 'parameterFilters.valueType.dateTime', + }) + ); + expect( + screen.getByTestId('parameter-date-time-selector') + ).toBeInTheDocument(); + + await user.click( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterValueTypeSelect /i, + }) + ); + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterValueTypeSelect', + }), + screen.getByRole('option', { + name: 'parameterFilters.valueType.numeric', + }) + ); + expect( + screen.getByTestId('parameter-numeric-range-selector') + ).toBeInTheDocument(); + + await user.click( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterValueTypeSelect /i, + }) + ); + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterValueTypeSelect', + }), + screen.getByRole('option', { + name: 'parameterFilters.valueType.string', + }) + ); + expect(screen.getByTestId('parameter-facet-list')).toBeInTheDocument(); + }); + + it('calls onAddFilter callback when a filter is added', async () => { + const user = userEvent.setup(); + const onAddFilter = jest.fn(); + + render( + , + { + wrapper: Wrapper, + } + ); + + // select parameter name + await user.click( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterNameSelect /i, + }) + ); + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterNameSelect', + }), + screen.getByRole('option', { name: 'bcat_inv_str' }) + ); + // select parameter value type + await user.click( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterValueTypeSelect /i, + }) + ); + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterValueTypeSelect', + }), + screen.getByRole('option', { + name: 'parameterFilters.valueType.string', + }) + ); + + await user.click( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterStringSelect /i, + }) + ); + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterStringSelect', + }), + screen.getByRole('option', { + name: 'Filter by PARAMETER STRING VALUE', + }) + ); + + const addFilterButton = screen.getByRole('button', { + name: 'parameterFilters.creator.addFilter', + }); + expect(addFilterButton).toBeEnabled(); + await user.click(addFilterButton); + + expect(onAddFilter).toHaveBeenCalledWith('InvestigationParameter', { + key: `InvestigationParameter.stringValue.bcat_inv_str`, + label: 'PARAMETER STRING VALUE', + filter: [ + { field: 'stringValue', value: 'PARAMETER STRING VALUE' }, + { field: 'type.name', value: 'bcat_inv_str' }, + ], + }); + }); + + it('resets parameter filter when requested by the parameter value selector', async () => { + const user = userEvent.setup(); + const onAddFilter = jest.fn(); + + render( + , + { + wrapper: Wrapper, + } + ); + + // select parameter name + await user.click( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterNameSelect /i, + }) + ); + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterNameSelect', + }), + screen.getByRole('option', { name: 'run_number_range' }) + ); + // select parameter value type + await user.click( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterValueTypeSelect /i, + }) + ); + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterValueTypeSelect', + }), + screen.getByRole('option', { + name: 'parameterFilters.valueType.numeric', + }) + ); + + // insert valid numeric range so that a filter object can be created + await user.type( + screen.getByRole('spinbutton', { + name: 'parameterFilters.creator.labels.parameterNumericRange.min', + }), + '1' + ); + await user.type( + screen.getByRole('spinbutton', { + name: 'parameterFilters.creator.labels.parameterNumericRange.max', + }), + '1' + ); + + expect( + screen.getByRole('button', { name: 'parameterFilters.creator.addFilter' }) + ).toBeEnabled(); + + // now insert invalid numeric range, the creator should reset the filter value and disable the add filter button + await user.type( + screen.getByRole('spinbutton', { + name: 'parameterFilters.creator.labels.parameterNumericRange.min', + }), + '11' + ); + + expect( + screen.getByRole('button', { name: 'parameterFilters.creator.addFilter' }) + ).toBeDisabled(); + expect(onAddFilter).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/newParameterFilterCreator.component.tsx b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/newParameterFilterCreator.component.tsx new file mode 100644 index 000000000..a1e79c14f --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/newParameterFilterCreator.component.tsx @@ -0,0 +1,195 @@ +import React from 'react'; +import { + Button, + Divider, + IconButton, + MenuItem, + Stack, + TextField, + Typography, +} from '@mui/material'; +import { useTranslation } from 'react-i18next'; +import { type DatasearchType, SearchFilter } from 'datagateway-common'; +import { + PARAMETER_VALUE_TYPE, + ParameterValueType, +} from './parameterFilterTypes'; +import type ParameterValueSelectorProps from './valueSelectors/parameterValueSelectorProps'; +import ParameterNumericRange from './valueSelectors/parameterNumericRange.component'; +import ParameterFacetList from './valueSelectors/parameterFacetList.component'; +import ParameterDateTimeSelector from './valueSelectors/parameterDateTimeSelector.component'; +import { Close } from '@mui/icons-material'; + +interface NewParameterFilterCreatorProps { + allIds: number[]; + entityName: DatasearchType; + parameterNames: string[]; + onAddFilter: (filterKey: string, filterValue: SearchFilter) => void; + onClose: () => void; +} + +const PARAMETER_VALUE_SELECTOR: Record< + ParameterValueType, + (props: ParameterValueSelectorProps) => JSX.Element +> = { + [PARAMETER_VALUE_TYPE.dateTime]: ParameterDateTimeSelector, + [PARAMETER_VALUE_TYPE.string]: ParameterFacetList, + [PARAMETER_VALUE_TYPE.numeric]: ParameterNumericRange, +}; + +/** + * Allows the user to construct a new parameter filter. + * The creator first shows 2 dropdowns, one for selecting parameter to be filtered by, and the other one for selecting the type of the filter value. + * Based on the type of the filter value, the creator shows different options that the user can filter the parameter with. + * For example, if the user selects "number" for the type of the filter value, the creator will let the user specify the range of the filter value. + * The resulting filter selects only the parameters whose values are within the number range. + */ +function NewParameterFilterCreator({ + allIds, + entityName, + parameterNames, + onAddFilter, + onClose, +}: NewParameterFilterCreatorProps): JSX.Element { + const [t] = useTranslation(); + + const [parameterName, setParameterName] = React.useState(''); + const [valueType, setValueType] = React.useState(''); + // the search filter object being built by this creator, + // which varies depending on the parameter name, type, and parameter value that the user chooses. + const [filterValue, setFilterValue] = React.useState( + null + ); + + const resetFilterValue = React.useCallback(() => { + setFilterValue(null); + }, []); + + function addFilter(): void { + if (filterValue) { + onAddFilter(`${entityName}Parameter`, filterValue); + } + } + + function changeParameterName(selectedName: string): void { + setParameterName(selectedName); + } + + function changeValueType(selectedValue: string): void { + if (selectedValue in PARAMETER_VALUE_TYPE || selectedValue === '') { + // at the moment the typescript type checker doesn't perform type narrowing + // in control flows for arbitrary expressions like variables + // therefore a cast has to be performed here to tell the type checker that this is valid + // see: + // https://github.com/microsoft/TypeScript/issues/10530 + // https://stackoverflow.com/questions/64616994/typescript-type-narrowing-not-working-for-in-when-key-is-stored-in-a-variable + setValueType(selectedValue as ParameterValueType | ''); + // changing the value type changes the size of the Popover + // so send resize event to force trigger the Popover to correctly position + // this is primarily a problem with the Numeric type as it has 3 fields + window.dispatchEvent(new Event('resize')); + } + } + + function renderValueSelector(): JSX.Element { + if (!parameterName || !valueType) { + // cannot render value selector because users haven't selected all the required options + + let helpMessage = ''; + if (!parameterName && !valueType) { + // both parameter name and parameter type are not selected + helpMessage = t( + 'parameterFilters.creator.message.parameterNameAndTypeNotSelected' + ); + } else if (!parameterName) { + // parameter type selected but parameter name is not selected + helpMessage = t( + 'parameterFilters.creator.message.parameterNameNotSelected' + ); + } else if (!valueType) { + // parameter name selected but parameter type is not selected + helpMessage = t( + 'parameterFilters.creator.message.parameterTypeNotSelected' + ); + } + + return {helpMessage}; + } + + const ParameterValueSelector = PARAMETER_VALUE_SELECTOR[valueType]; + return ( + + ); + } + + return ( + + + + {t('parameterFilters.creator.title')} + + + + + + + changeParameterName(e.target.value)} + label={t('parameterFilters.creator.labels.parameterNameSelect')} + > + {parameterNames.map((param) => ( + + {param} + + ))} + + changeValueType(e.target.value)} + > + {Object.values(PARAMETER_VALUE_TYPE).map((value) => ( + + {t(`parameterFilters.valueType.${value}`)} + + ))} + + + + {renderValueSelector()} + + + ); +} + +export default NewParameterFilterCreator; diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFacetsFromSearchResponse.test.ts b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFacetsFromSearchResponse.test.ts new file mode 100644 index 000000000..409a87829 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFacetsFromSearchResponse.test.ts @@ -0,0 +1,38 @@ +import parameterFacetsFromSearchResponse from './parameterFacetsFromSearchResponse'; +import { ParameterValueFacet } from './parameterFilterTypes'; + +describe('parameterFacetsFromSearchResponse', () => { + it('extract facets on parameters from search result dimensions (facets)', () => { + expect( + parameterFacetsFromSearchResponse({ + dimensions: { + investigationparameters: { + bcat_inv_str: 123, + run_number_range: { + from: 1, + to: 10, + count: 234, + }, + }, + }, + }) + ).toEqual([ + { + label: 'bcat_inv_str', + count: 123, + }, + { + label: 'run_number_range', + from: 1, + to: 10, + count: 234, + }, + ]); + }); + + it('returns an empty array if the search result object does not contain facets', () => { + expect(parameterFacetsFromSearchResponse({ results: [] })).toEqual< + ParameterValueFacet[] + >([]); + }); +}); diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFacetsFromSearchResponse.ts b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFacetsFromSearchResponse.ts new file mode 100644 index 000000000..8d6df9d41 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFacetsFromSearchResponse.ts @@ -0,0 +1,23 @@ +import type { SearchResponse } from 'datagateway-common'; +import type { ParameterValueFacet } from './parameterFilterTypes'; + +function parameterFacetsFromSearchResponse( + response: SearchResponse +): ParameterValueFacet[] { + if (!response.dimensions) return []; + + return Object.values(response.dimensions).flatMap((labelValues) => + Object.entries(labelValues).map(([label, value]) => + typeof value === 'object' + ? { + label, + count: value.count, + from: value.from, + to: value.to, + } + : { label, count: value } + ) + ); +} + +export default parameterFacetsFromSearchResponse; diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilterItem.component.test.tsx b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilterItem.component.test.tsx new file mode 100644 index 000000000..b59397c99 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilterItem.component.test.tsx @@ -0,0 +1,48 @@ +import * as React from 'react'; +import { NestedFilter } from 'datagateway-common'; +import { render, screen } from '@testing-library/react'; +import ParameterFilterItem from './parameterFilterItem.component'; +import userEvent from '@testing-library/user-event'; + +describe('ParameterFilterItem', () => { + const TEST_PARAMETER_FILTER: NestedFilter = { + filter: [], + key: 'investigationparameter.stringValue.bcat_inv_str', + label: 'Team ROQ - RAL', + }; + + it('shows the label of the given parameter filter and a remove button to remove the filter', () => { + render( + + ); + + expect( + screen.getByText('bcat_inv_str: Team ROQ - RAL') + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { + name: 'parameterFilters.removeFilter {filterLabel:bcat_inv_str: Team ROQ - RAL}', + }) + ); + }); + + it('calls onRemove callback when the remove button is clicked', async () => { + const user = userEvent.setup(); + const onRemove = jest.fn(); + + render( + + ); + + await user.click( + screen.getByRole('button', { + name: 'parameterFilters.removeFilter {filterLabel:bcat_inv_str: Team ROQ - RAL}', + }) + ); + + expect(onRemove).toHaveBeenCalledWith(TEST_PARAMETER_FILTER); + }); +}); diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilterItem.component.tsx b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilterItem.component.tsx new file mode 100644 index 000000000..7ee157a12 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilterItem.component.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { NestedFilter } from 'datagateway-common'; +import { IconButton, ListItem, ListItemText } from '@mui/material'; +import { Close } from '@mui/icons-material'; +import { useTranslation } from 'react-i18next'; + +interface ParameterFilterItemProps { + filter: NestedFilter; + onRemove: (removedFilter: NestedFilter) => void; +} + +/** + * Shows a parameter filter in a formatted user-friendly way. + * @constructor + */ +function ParameterFilterItem({ + filter, + onRemove, +}: ParameterFilterItemProps): JSX.Element { + const [t] = useTranslation(); + const userLabel = `${filter.key.split('.').at(-1)}: ${filter.label}`; + + return ( + onRemove(filter)} + > + + + } + > + + + ); +} + +export default ParameterFilterItem; diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilterTypes.ts b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilterTypes.ts new file mode 100644 index 000000000..4aabe35ed --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilterTypes.ts @@ -0,0 +1,42 @@ +/** + * Defines different types of parameter values. + */ +const PARAMETER_VALUE_TYPE = { + dateTime: 'dateTime', + numeric: 'numeric', + string: 'string', +} as const; + +/** + * Union of all possible types of parameter values. + */ +type ParameterValueType = keyof typeof PARAMETER_VALUE_TYPE; + +interface NewParameterValueFilter { + name: string; + + /** + * Allow empty string for initial value (i.e. when the user hasn't selected any type). + */ + valueType: ParameterValueType | ''; +} + +interface ParameterValueFilter { + name: string; + valueType: ParameterValueType; +} + +interface ParameterValueFacet { + label: string; + count?: number; + from?: number; + to?: number; +} + +export { PARAMETER_VALUE_TYPE }; +export type { + ParameterValueType, + ParameterValueFilter, + ParameterValueFacet, + NewParameterValueFilter, +}; diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilters.component.test.tsx b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilters.component.test.tsx new file mode 100644 index 000000000..c9e9cbb78 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilters.component.test.tsx @@ -0,0 +1,340 @@ +import * as React from 'react'; +import { render, screen, within } from '@testing-library/react'; +import ParameterFilters from './parameterFilters.component'; +import { DatasearchType, dGCommonInitialState } from 'datagateway-common'; +import { QueryClient, QueryClientProvider } from 'react-query'; +import userEvent from '@testing-library/user-event'; +import { Provider } from 'react-redux'; +import createMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import axios, { AxiosResponse } from 'axios'; + +describe('ParameterFilters', () => { + const TEST_ENTITY_NAME: DatasearchType = 'Investigation'; + const TEST_PARAMETER_NAMES = ['bcat_inv_str', 'run_number_range']; + const TEST_IDS = [123, 456, 789]; + + function Wrapper({ + children, + }: React.PropsWithChildren): React.ReactElement { + return ( + + + {children} + + + ); + } + + beforeEach(() => { + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + if (/\/facet\/documents$/.test(url)) { + return Promise.resolve({ + data: { + results: [], + dimensions: { + investigationparameters: { + 'PARAMETER STRING VALUE': 123, + 'PARAMETER STRING VALUE 2': 456, + }, + }, + }, + }); + } + return Promise.reject(`Endpoint not mocked: ${url}`); + }); + }); + + it('shows selected parameter filters as a list and has a button to add a new filter', () => { + render( + , + { + wrapper: Wrapper, + } + ); + + const selectedParameterFilterList = screen.getByRole('list', { + name: 'parameterFilters.selectedParameterFilterList', + }); + const parameterFilterItems = within( + selectedParameterFilterList + ).getAllByRole('listitem'); + + // verify that the list of selected parameter filters are shown + expect(selectedParameterFilterList).toBeInTheDocument(); + expect(parameterFilterItems).toHaveLength(1); + for (const item of parameterFilterItems) { + expect(item).toBeInTheDocument(); + } + + // the add filter button should be shown + expect( + screen.getByRole('button', { name: 'parameterFilters.addFilter' }) + ).toBeInTheDocument(); + }); + + it('shows an empty message when no parameter filters are selected', () => { + render( + , + { + wrapper: Wrapper, + } + ); + + expect( + screen.queryByRole('list', { + name: 'parameterFilters.selectedParameterFilterList', + }) + ).toBeNull(); + expect(screen.getByText('parameterFilters.noFilters')).toBeInTheDocument(); + }); + + it('shows/closes UI for creating new parameter filter', async () => { + const user = userEvent.setup(); + + render( + , + { + wrapper: Wrapper, + } + ); + + expect(screen.queryByTestId('new-parameter-filter')).toBeNull(); + + await user.click( + screen.getByRole('button', { name: 'parameterFilters.addFilter' }) + ); + expect(screen.getByTestId('new-parameter-filter')).toBeInTheDocument(); + + await user.click( + screen.getByRole('button', { name: 'parameterFilters.creator.close' }) + ); + expect(screen.queryByTestId('new-parameter-filter')).toBeNull(); + }); + + it('updates parameter filter list when a new parameter filter is added', async () => { + const user = userEvent.setup(); + const onAddParameterFilter = jest.fn(); + + const { rerender } = render( + , + { + wrapper: Wrapper, + } + ); + + expect( + screen.queryByRole('list', { + name: 'parameterFilters.selectedParameterFilterList', + }) + ).toBeNull(); + expect(screen.getByText('parameterFilters.noFilters')).toBeInTheDocument(); + + // click on add filter button + await user.click( + screen.getByRole('button', { name: 'parameterFilters.addFilter' }) + ); + // open parameter name dropdown + await user.click( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterNameSelect /i, + }) + ); + // select bcat_inv_str as parameter name + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterNameSelect', + }), + screen.getByRole('option', { name: 'bcat_inv_str' }) + ); + // open parameter value type dropdown + await user.click( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterValueTypeSelect /i, + }) + ); + // select string as value type + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterValueTypeSelect', + }), + screen.getByRole('option', { + name: 'parameterFilters.valueType.string', + }) + ); + // open parameter string value dropdown + await user.click( + await screen.findByRole('button', { + name: /parameterFilters.creator.labels.parameterStringSelect /i, + }) + ); + // select PARAMETER STRING VALUE as the filter value + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterStringSelect', + }), + screen.getByRole('option', { name: 'Filter by PARAMETER STRING VALUE' }) + ); + // click the add filter button + await user.click( + screen.getByRole('button', { + name: 'parameterFilters.creator.addFilter', + }) + ); + + expect(onAddParameterFilter).toHaveBeenCalledWith( + 'InvestigationParameter', + { + key: `InvestigationParameter.stringValue.bcat_inv_str`, + label: 'PARAMETER STRING VALUE', + filter: [ + { field: 'stringValue', value: 'PARAMETER STRING VALUE' }, + { field: 'type.name', value: 'bcat_inv_str' }, + ], + } + ); + + // rerender component to pretend the filter is added + rerender( + + ); + + const selectedParameterFilterList = screen.getByRole('list', { + name: 'parameterFilters.selectedParameterFilterList', + }); + const parameterFilterItems = within( + selectedParameterFilterList + ).getAllByRole('listitem'); + + expect(selectedParameterFilterList).toBeInTheDocument(); + expect(parameterFilterItems).toHaveLength(1); + expect( + within(parameterFilterItems[0]).getByText( + 'bcat_inv_str: PARAMETER STRING VALUE' + ) + ).toBeInTheDocument(); + }); + + it('updates parameter filter list when a parameter filter is removed', async () => { + const user = userEvent.setup(); + const onRemoveParameterFilter = jest.fn(); + + const { rerender } = render( + , + { + wrapper: Wrapper, + } + ); + + const selectedParameterFilterList = screen.getByRole('list', { + name: 'parameterFilters.selectedParameterFilterList', + }); + const parameterFilterItems = within( + selectedParameterFilterList + ).getAllByRole('listitem'); + + expect(parameterFilterItems).toHaveLength(1); + + await user.click( + within(parameterFilterItems[0]).getByRole('button', { + name: 'parameterFilters.removeFilter {filterLabel:bcat_inv_str: PARAMETER STRING VALUE}', + }) + ); + + expect(onRemoveParameterFilter).toHaveBeenCalledWith( + 'InvestigationParameter', + { + filter: [], + key: 'InvestigationParameter.stringValue.bcat_inv_str', + label: 'PARAMETER STRING VALUE', + } + ); + + rerender( + + ); + + expect( + screen.queryByRole('list', { + name: 'parameterFilters.selectedParameterFilterList', + }) + ).toBeNull(); + expect(screen.getByText('parameterFilters.noFilters')).toBeInTheDocument(); + }); +}); diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilters.component.tsx b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilters.component.tsx new file mode 100644 index 000000000..55d054a53 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/parameterFilters.component.tsx @@ -0,0 +1,154 @@ +import React from 'react'; +import { + Box, + IconButton, + List, + Popover, + Stack, + Typography, +} from '@mui/material'; +import { Add } from '@mui/icons-material'; +import type { + DatasearchType, + NestedFilter, + SearchFilter, +} from 'datagateway-common'; +import ParameterFilterItem from './parameterFilterItem.component'; +import NewParameterFilterCreator from './newParameterFilterCreator.component'; +import { useTranslation } from 'react-i18next'; + +interface ParameterFiltersProps { + entityName: DatasearchType; + parameterNames: string[]; + allIds: number[]; + selectedFilters: SearchFilter[]; + onAddParameterFilter: (filterKey: string, filterValue: SearchFilter) => void; + onRemoveParameterFilter: ( + filterKey: string, + filterValue: SearchFilter + ) => void; +} + +/** + * A UI component that allows users to filter search results based on the parameter value of each item. + * For example, the user can filter investigations so that the value of a certain parameter of each investigation returned + * matches the range specified by the applied parameter filter. + */ +const ParameterFilters = ({ + entityName, + parameterNames, + allIds, + selectedFilters, + onAddParameterFilter, + onRemoveParameterFilter, +}: ParameterFiltersProps): React.ReactElement => { + const [t] = useTranslation(); + + const [isNewFilterPopoverVisible, setIsNewFilterPopoverVisible] = + React.useState(false); + const [popoverAnchor, setPopoverAnchor] = React.useState( + null + ); + + function openNewParameterFilterCreator( + event: React.MouseEvent + ): void { + setIsNewFilterPopoverVisible(true); + setPopoverAnchor(event.currentTarget); + } + + function closeNewParameterFilterCreator(): void { + setIsNewFilterPopoverVisible(false); + setPopoverAnchor(null); + } + + function addNewParameterFilter( + filterKey: string, + filterValue: SearchFilter + ): void { + onAddParameterFilter(filterKey, filterValue); + closeNewParameterFilterCreator(); + } + + function removeParameterFilter(filterValue: SearchFilter): void { + onRemoveParameterFilter(`${entityName}Parameter`, filterValue); + } + + const selectedParameterFilters = selectedFilters.filter( + (filter): filter is NestedFilter => + typeof filter !== 'string' && 'filter' in filter + ); + + return ( + + + + {t('parameterFilters.title')} + + + + + + {selectedParameterFilters.length > 0 ? ( + + {selectedParameterFilters.map((filter) => ( + + ))} + + ) : ( + + {t('parameterFilters.noFilters')} + + )} + + + + + ); +}; + +ParameterFilters.whyDidYouRender = true; + +export default ParameterFilters; diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterDateTimeSelector.component.test.tsx b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterDateTimeSelector.component.test.tsx new file mode 100644 index 000000000..bae094578 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterDateTimeSelector.component.test.tsx @@ -0,0 +1,173 @@ +import * as React from 'react'; +import axios, { AxiosResponse } from 'axios'; +import { QueryClient, QueryClientProvider } from 'react-query'; +import { render, screen, within } from '@testing-library/react'; +import ParameterDateTimeSelector from './parameterDateTimeSelector.component'; +import { DatasearchType, dGCommonInitialState } from 'datagateway-common'; +import userEvent from '@testing-library/user-event'; +import { Provider } from 'react-redux'; +import createMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; + +describe('ParameterDateTimeSelector', () => { + const TEST_ENTITY_NAME: DatasearchType = 'Investigation'; + const TEST_PARAMETER_NAME = 'bcat_inv_str'; + const TEST_IDS = [123, 456, 789]; + + let user: ReturnType; + + function Wrapper({ + children, + }: React.PropsWithChildren): React.ReactElement { + return ( + + + {children} + + + ); + } + + beforeEach(() => { + user = userEvent.setup(); + + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + if (/\/facet\/documents$/.test(url)) { + return Promise.resolve({ + data: { + results: [], + dimensions: { + investigationparameters: { + '2020': { + count: 123, + from: 10, + to: 20, + }, + '2021': { + count: 456, + from: 20, + to: 30, + }, + }, + }, + }, + }); + } + return Promise.reject(`Endpoint not mocked: ${url}`); + }); + }); + + it('displays the list of available date time value options in a dropdown menu', async () => { + render( + , + { wrapper: Wrapper } + ); + + await user.click( + await screen.findByRole('button', { + name: /parameterFilters.creator.labels.parameterDateTimeSelect /i, + }) + ); + + expect( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterDateTimeSelect', + }) + ).toBeInTheDocument(); + + const option2020 = screen.getByRole('option', { name: 'Filter by 2020' }); + expect(option2020).toBeInTheDocument(); + expect(within(option2020).getByText('123')).toBeInTheDocument(); + + const option2021 = screen.getByRole('option', { name: 'Filter by 2021' }); + expect(option2021).toBeInTheDocument(); + expect(within(option2021).getByText('456')).toBeInTheDocument(); + }); + + it('shows loading when loading the list of available date time options', () => { + axios.get = jest.fn().mockImplementation( + () => + new Promise((resolve) => { + // never resolve the promise to pretend it is loading + }) + ); + + render( + , + { wrapper: Wrapper } + ); + + expect(screen.getByRole('progressbar')).toBeInTheDocument(); + expect( + screen.getByText('parameterFilters.creator.loading') + ).toBeInTheDocument(); + }); + + it('calls onNewFilter and shows the selected option when an option is selected ', async () => { + const onNewFilter = jest.fn(); + + render( + , + { wrapper: Wrapper } + ); + + await user.click( + await screen.findByRole('button', { + name: /parameterFilters.creator.labels.parameterDateTimeSelect /i, + }) + ); + + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterDateTimeSelect', + }), + screen.getByRole('option', { name: 'Filter by 2020' }) + ); + + expect(onNewFilter).toHaveBeenCalledWith({ + key: `InvestigationParameter.dateTimeValue.bcat_inv_str`, + label: '2020', + filter: [ + { + from: 10, + to: 20, + key: '2020', + field: 'dateTimeValue', + }, + { + field: 'type.name', + value: 'bcat_inv_str', + }, + ], + }); + expect( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterDateTimeSelect 2020/i, + }) + ).toBeInTheDocument(); + }); +}); diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterDateTimeSelector.component.tsx b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterDateTimeSelector.component.tsx new file mode 100644 index 000000000..f2737469c --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterDateTimeSelector.component.tsx @@ -0,0 +1,143 @@ +import React from 'react'; +import { + CircularProgress, + ListItemText, + MenuItem, + Stack, + TextField, + Typography, +} from '@mui/material'; +import { + type FacetRequest, + type FiltersType, + useLuceneFacet, +} from 'datagateway-common'; +import type { ParameterValueFacet } from '../parameterFilterTypes'; +import parameterFacetsFromSearchResponse from '../parameterFacetsFromSearchResponse'; +import ParameterValueSelectorProps from './parameterValueSelectorProps'; +import { useTranslation } from 'react-i18next'; +import { ExtraSmallChip } from '../../toggleableFilterItem.component'; + +function ParameterDateTimeSelector({ + entityName, + parameterName, + allIds, + onNewFilter, +}: ParameterValueSelectorProps): JSX.Element { + const [t] = useTranslation(); + + const facetRequests: FacetRequest[] = React.useMemo(() => { + const currentYear = new Date().getFullYear(); + return [ + { + target: `${entityName}Parameter`, + dimensions: [ + { + dimension: 'dateTimeValue', + ranges: [ + { + key: `${currentYear}`, + from: new Date(currentYear, 0).getTime(), + to: Date.now(), + }, + { + key: `${currentYear - 1}`, + from: new Date(currentYear - 1, 0).getTime(), + to: new Date(currentYear, 0).getTime(), + }, + { + key: `${currentYear - 2}`, + from: new Date(currentYear - 2, 0).getTime(), + to: new Date(currentYear - 1, 0).getTime(), + }, + { + key: `${currentYear - 3}`, + from: new Date(currentYear - 3, 0).getTime(), + to: new Date(currentYear - 2, 0).getTime(), + }, + { + key: 'Older', + to: new Date(currentYear - 3, 0).getTime(), + }, + ], + }, + ], + }, + ]; + }, [entityName]); + + const { data: facets, isLoading: isLoadingFacets } = useLuceneFacet( + entityName, + facetRequests, + { + [`${entityName.toLowerCase()}.id`]: allIds, + 'type.name': parameterName, + } as FiltersType, + { + select: parameterFacetsFromSearchResponse, + } + ); + + const [selectedFacet, setSelectedFacet] = + React.useState(null); + + function selectFacet(facet: ParameterValueFacet): void { + setSelectedFacet(facet); + onNewFilter({ + key: `${entityName}Parameter.dateTimeValue.${parameterName}`, + label: facet.label, + filter: [ + { + from: facet.from, + to: facet.to, + key: facet.label, + field: 'dateTimeValue', + }, + { + field: 'type.name', + value: parameterName, + }, + ], + }); + } + + if (isLoadingFacets) { + return ( + + + + {t('parameterFilters.creator.loading')} + + + ); + } + + if (facets) { + return ( + + {facets.map((facet, index) => ( + selectFacet(facet)} + aria-label={`Filter by ${facet.label}`} + > + {facet.label} + + + ))} + + ); + } + + return <>; +} + +export default ParameterDateTimeSelector; diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterFacetList.component.test.tsx b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterFacetList.component.test.tsx new file mode 100644 index 000000000..26a4253e0 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterFacetList.component.test.tsx @@ -0,0 +1,161 @@ +import { DatasearchType, dGCommonInitialState } from 'datagateway-common'; +import * as React from 'react'; +import { Provider } from 'react-redux'; +import createMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { QueryClient, QueryClientProvider } from 'react-query'; +import userEvent from '@testing-library/user-event'; +import axios, { AxiosResponse } from 'axios'; +import { render, screen, within } from '@testing-library/react'; +import ParameterFacetList from './parameterFacetList.component'; + +describe('ParameterFacetList', () => { + const TEST_ENTITY_NAME: DatasearchType = 'Investigation'; + const TEST_PARAMETER_NAME = 'bcat_inv_str'; + const TEST_IDS = [123, 456, 789]; + + let user: ReturnType; + + function Wrapper({ + children, + }: React.PropsWithChildren): React.ReactElement { + return ( + + + {children} + + + ); + } + + beforeEach(() => { + user = userEvent.setup(); + + axios.get = jest + .fn() + .mockImplementation((url: string): Promise> => { + if (/\/facet\/documents$/.test(url)) { + return Promise.resolve({ + data: { + results: [], + dimensions: { + investigationparameters: { + 'PARAMETER STRING VALUE': 123, + 'PARAMETER STRING VALUE 2': 456, + }, + }, + }, + }); + } + return Promise.reject(`Endpoint not mocked: ${url}`); + }); + }); + + it('displays the list of available parameter string values in a dropdown menu', async () => { + render( + , + { wrapper: Wrapper } + ); + + await user.click( + await screen.findByRole('button', { + name: /parameterFilters.creator.labels.parameterStringSelect /i, + }) + ); + + expect( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterStringSelect', + }) + ).toBeInTheDocument(); + + const option1 = screen.getByRole('option', { + name: 'Filter by PARAMETER STRING VALUE', + }); + expect(option1).toBeInTheDocument(); + expect(within(option1).getByText('123')).toBeInTheDocument(); + + const option2 = screen.getByRole('option', { + name: 'Filter by PARAMETER STRING VALUE 2', + }); + expect(option2).toBeInTheDocument(); + expect(within(option2).getByText('456')).toBeInTheDocument(); + }); + + it('shows loading when loading the list of available string values', () => { + axios.get = jest.fn().mockImplementation( + () => + new Promise((resolve) => { + // never resolve the promise to pretend it is loading + }) + ); + + render( + , + { wrapper: Wrapper } + ); + + expect(screen.getByRole('progressbar')).toBeInTheDocument(); + expect( + screen.getByText('parameterFilters.creator.loading') + ).toBeInTheDocument(); + }); + + it('calls onNewFilter and shows the selected option when an option is selected ', async () => { + const onNewFilter = jest.fn(); + + render( + , + { wrapper: Wrapper } + ); + + await user.click( + await screen.findByRole('button', { + name: /parameterFilters.creator.labels.parameterStringSelect /i, + }) + ); + + await user.selectOptions( + screen.getByRole('listbox', { + name: 'parameterFilters.creator.labels.parameterStringSelect', + }), + screen.getByRole('option', { name: 'Filter by PARAMETER STRING VALUE' }) + ); + + expect(onNewFilter).toHaveBeenCalledWith({ + key: `InvestigationParameter.stringValue.bcat_inv_str`, + label: 'PARAMETER STRING VALUE', + filter: [ + { field: 'stringValue', value: 'PARAMETER STRING VALUE' }, + { field: 'type.name', value: 'bcat_inv_str' }, + ], + }); + expect( + screen.getByRole('button', { + name: /parameterFilters.creator.labels.parameterStringSelect PARAMETER STRING VALUE/i, + }) + ).toBeInTheDocument(); + }); +}); diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterFacetList.component.tsx b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterFacetList.component.tsx new file mode 100644 index 000000000..7a79a158d --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterFacetList.component.tsx @@ -0,0 +1,102 @@ +import React from 'react'; +import { + CircularProgress, + ListItemText, + MenuItem, + Stack, + TextField, + Typography, +} from '@mui/material'; +import { + type FacetRequest, + type FiltersType, + useLuceneFacet, +} from 'datagateway-common'; +import type { ParameterValueFacet } from '../parameterFilterTypes'; +import parameterFacetsFromSearchResponse from '../parameterFacetsFromSearchResponse'; +import ParameterValueSelectorProps from './parameterValueSelectorProps'; +import { useTranslation } from 'react-i18next'; +import { ExtraSmallChip } from '../../toggleableFilterItem.component'; + +function ParameterFacetList({ + entityName, + parameterName, + allIds, + onNewFilter, +}: ParameterValueSelectorProps): JSX.Element { + const [t] = useTranslation(); + + const facetRequests: FacetRequest[] = [ + { + target: `${entityName}Parameter`, + dimensions: [{ dimension: 'stringValue' }], + }, + ]; + + const { data: facets, isLoading: isLoadingFacets } = useLuceneFacet( + entityName, + facetRequests, + { + [`${entityName.toLowerCase()}.id`]: allIds, + 'type.name': parameterName, + } as FiltersType, + { + select: parameterFacetsFromSearchResponse, + } + ); + + const [selectedFacet, setSelectedFacet] = + React.useState(null); + + function selectFacet(facet: ParameterValueFacet): void { + setSelectedFacet(facet); + onNewFilter({ + key: `${entityName}Parameter.stringValue.${parameterName}`, + label: facet.label, + filter: [ + { field: 'stringValue', value: facet.label }, + { field: 'type.name', value: parameterName }, + ], + }); + } + + if (isLoadingFacets) { + return ( + + `{' '} + + {t('parameterFilters.creator.loading')} + + + ); + } + + if (facets) { + return ( + + {facets.map((facet, index) => ( + selectFacet(facet)} + aria-label={`Filter by ${facet.label}`} + > + {facet.label} + + + ))} + + ); + } + + return <>; +} + +export default ParameterFacetList; diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterNumericRange.component.test.tsx b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterNumericRange.component.test.tsx new file mode 100644 index 000000000..81012d139 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterNumericRange.component.test.tsx @@ -0,0 +1,175 @@ +import { DatasearchType } from 'datagateway-common'; +import * as React from 'react'; +import userEvent from '@testing-library/user-event'; +import { render, screen } from '@testing-library/react'; +import ParameterNumericRange from './parameterNumericRange.component'; + +describe('ParameterNumericRange', () => { + const TEST_ENTITY_NAME: DatasearchType = 'Investigation'; + const TEST_PARAMETER_NAME = 'bcat_inv_str'; + const TEST_IDS = [123, 456, 789]; + + let user: ReturnType; + + beforeEach(() => { + user = userEvent.setup(); + }); + + it('shows min, max, and unit text field', () => { + render( + + ); + + expect( + screen.getByRole('spinbutton', { + name: 'parameterFilters.creator.labels.parameterNumericRange.min', + }) + ).toBeInTheDocument(); + expect( + screen.getByRole('spinbutton', { + name: 'parameterFilters.creator.labels.parameterNumericRange.max', + }) + ).toBeInTheDocument(); + expect( + screen.getByRole('textbox', { + name: 'parameterFilters.creator.labels.parameterNumericRange.unit', + }) + ).toBeInTheDocument(); + }); + + it('constructs new filter object and pass it to onNewFilter when min and max are set', async () => { + const onNewFilter = jest.fn(); + + render( + + ); + + await user.type( + screen.getByRole('spinbutton', { + name: 'parameterFilters.creator.labels.parameterNumericRange.min', + }), + '1' + ); + await user.type( + screen.getByRole('spinbutton', { + name: 'parameterFilters.creator.labels.parameterNumericRange.max', + }), + '10' + ); + + expect(onNewFilter).toHaveBeenLastCalledWith({ + label: '1 to 10', + key: `InvestigationParameter.numericValue.bcat_inv_str`, + filter: [ + { + field: 'numericValue', + from: 1, + to: 10, + key: '1 to 10', + }, + { field: 'type.name', value: 'bcat_inv_str' }, + ], + }); + }); + + it('constructs new filter object and pass it to onNewFilter when min, max and unit are set', async () => { + const onNewFilter = jest.fn(); + + render( + + ); + + await user.type( + screen.getByRole('spinbutton', { + name: 'parameterFilters.creator.labels.parameterNumericRange.min', + }), + '1' + ); + await user.type( + screen.getByRole('spinbutton', { + name: 'parameterFilters.creator.labels.parameterNumericRange.max', + }), + '10' + ); + await user.type( + screen.getByRole('textbox', { + name: 'parameterFilters.creator.labels.parameterNumericRange.unit', + }), + 'cm' + ); + + expect(onNewFilter).toHaveBeenLastCalledWith({ + label: '1 to 10 (cm)', + key: `InvestigationParameter.numericValue.bcat_inv_str`, + filter: [ + { + field: 'numericValue', + from: 1, + to: 10, + units: 'cm', + key: '1 to 10 (cm)', + }, + { field: 'type.name', value: 'bcat_inv_str' }, + ], + }); + }); + + it('resets filters when the numeric range becomes invalid', async () => { + const onNewFilter = jest.fn(); + const onResetFilter = jest.fn(); + + render( + + ); + + await user.type( + screen.getByRole('spinbutton', { + name: 'parameterFilters.creator.labels.parameterNumericRange.min', + }), + '1' + ); + await user.type( + screen.getByRole('spinbutton', { + name: 'parameterFilters.creator.labels.parameterNumericRange.max', + }), + '10' + ); + + expect(onNewFilter).toHaveBeenCalledTimes(2); + // 1: initial call from useEffect + // 2: max === '' when typing '1' to min box -> call from useEffect + expect(onResetFilter).toHaveBeenCalledTimes(2); + + await user.clear( + screen.getByRole('spinbutton', { + name: 'parameterFilters.creator.labels.parameterNumericRange.min', + }) + ); + + expect(onResetFilter).toHaveBeenCalledTimes(3); + }); +}); diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterNumericRange.component.tsx b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterNumericRange.component.tsx new file mode 100644 index 000000000..b843394b3 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterNumericRange.component.tsx @@ -0,0 +1,122 @@ +import React from 'react'; +import { Stack, TextField } from '@mui/material'; +import { useTranslation } from 'react-i18next'; +import type ParameterValueSelectorProps from './parameterValueSelectorProps'; + +function ParameterNumericRange({ + entityName, + parameterName, + onNewFilter, + onResetFilter, +}: ParameterValueSelectorProps): JSX.Element { + const [t] = useTranslation(); + + const [units, setUnits] = React.useState(''); + const [min, setMin] = React.useState(''); + const [max, setMax] = React.useState(''); + + const applyRange = React.useCallback(() => { + const minNum = Number(min); + const maxNum = Number(max); + + if (minNum > maxNum || maxNum < minNum) { + onResetFilter(); + return; + } + + const label = + units === '' ? `${min} to ${max}` : `${min} to ${max} (${units})`; + const filter = + units === '' + ? { + field: 'numericValue', + from: Number(min), + to: Number(max), + key: label, + } + : { + units, + field: 'numericValue', + from: Number(min), + to: Number(max), + key: label, + }; + + onNewFilter({ + label, + key: `${entityName}Parameter.numericValue.${parameterName}`, + filter: [filter, { field: 'type.name', value: parameterName }], + }); + }, [entityName, max, min, onNewFilter, onResetFilter, parameterName, units]); + + React.useEffect(() => { + if (min === '' || max === '') { + onResetFilter(); + } else if (!Number.isNaN(Number(min)) && !Number.isNaN(Number(max))) { + applyRange(); + } + }, [min, max, applyRange, onResetFilter]); + + const onUnitsChange = (event: React.ChangeEvent<{ value: string }>): void => { + setUnits(event.target.value); + }; + + const onMinChange = (event: React.ChangeEvent<{ value: string }>): void => { + setMin(event.target.value); + }; + + const onMaxChange = (event: React.ChangeEvent<{ value: string }>): void => { + setMax(event.target.value); + }; + + return ( + + + + + + ); +} + +export default ParameterNumericRange; diff --git a/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterValueSelectorProps.ts b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterValueSelectorProps.ts new file mode 100644 index 000000000..df66e61c4 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/parameterFilters/valueSelectors/parameterValueSelectorProps.ts @@ -0,0 +1,22 @@ +import type { DatasearchType, SearchFilter } from 'datagateway-common'; + +interface ParameterValueSelectorProps { + entityName: DatasearchType; + parameterName: string; + allIds: number[]; + + /** + * Called when the selector creates a new filter from the value selected. + * @param newFilter The search filter created based on the selected value. + * When performing a search with the filter, only parameters that match the selected value will be selected. + */ + onNewFilter: (newFilter: SearchFilter) => void; + + /** + * Called when the selector wants to reset the filter created previously. + * This can happen, for example, when the selector is now in an invalid state, and the previous filter should not be used. + */ + onResetFilter: () => void; +} + +export default ParameterValueSelectorProps; diff --git a/packages/datagateway-search/src/facet/components/facetPanel/toggleableFilterItem.component.test.tsx b/packages/datagateway-search/src/facet/components/facetPanel/toggleableFilterItem.component.test.tsx new file mode 100644 index 000000000..8002a63f7 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/toggleableFilterItem.component.test.tsx @@ -0,0 +1,81 @@ +import * as React from 'react'; +import { render, screen, within } from '@testing-library/react'; +import ToggleableFilterItem from './toggleableFilterItem.component'; +import userEvent from '@testing-library/user-event'; + +const testClassificationLabel = 'experiment'; +const testCount = 123; + +describe('toggleableFilterItem', () => { + it('renders the given classification label as a toggleable filter', () => { + render( + + ); + + const item = screen.getByRole('button', { name: 'Add experiment filter' }); + expect(item).toBeInTheDocument(); + expect(item).toHaveAttribute('aria-selected', 'false'); + expect(within(item).getByText('experiment')).toBeInTheDocument(); + expect(within(item).getByText('123')).toBeInTheDocument(); + + const checkbox = within(item).getByRole('checkbox', { + name: 'Add experiment filter', + }); + expect(checkbox).toBeInTheDocument(); + expect(checkbox).not.toBeChecked(); + }); + + it('renders as selected if selected is true', () => { + render( + + ); + + const item = screen.getByRole('button', { + name: 'Remove experiment filter', + }); + expect(item).toBeInTheDocument(); + expect(item).toHaveAttribute('aria-selected', 'true'); + + const checkbox = within(item).getByRole('checkbox', { + name: 'Remove experiment filter', + }); + expect(checkbox).toBeInTheDocument(); + expect(checkbox).toBeChecked(); + }); + + it('calls the given callback when toggled', async () => { + const user = userEvent.setup(); + const onSelect = jest.fn(); + + render( + + ); + + await user.click( + screen.getByRole('button', { + name: 'Add experiment filter', + }) + ); + expect(onSelect).toHaveBeenLastCalledWith('experiment', true); + + await user.click( + screen.getByRole('checkbox', { name: 'Add experiment filter' }) + ); + expect(onSelect).toHaveBeenLastCalledWith('experiment', true); + }); +}); diff --git a/packages/datagateway-search/src/facet/components/facetPanel/toggleableFilterItem.component.tsx b/packages/datagateway-search/src/facet/components/facetPanel/toggleableFilterItem.component.tsx new file mode 100644 index 000000000..b39adc9ac --- /dev/null +++ b/packages/datagateway-search/src/facet/components/facetPanel/toggleableFilterItem.component.tsx @@ -0,0 +1,73 @@ +import { + Box, + Checkbox, + Chip, + chipClasses, + ListItemButton, + ListItemIcon, + ListItemText, + styled, +} from '@mui/material'; +import React, { ComponentProps } from 'react'; + +const StyledChip = styled(Chip)(() => ({ + cursor: 'unset', + height: '20px', + [`& .${chipClasses.label}`]: { paddingLeft: '6px', paddingRight: '6px' }, +})); + +export const ExtraSmallChip: React.FC< + Omit, 'size'> +> = (props) => ; + +interface ToggleableFilterItemProps { + classificationLabel: string; + count: number | undefined; + selected: boolean; + onSelect: (classificationLabel: string, selected: boolean) => void; +} + +function ToggleableFilterItem({ + classificationLabel, + count, + selected, + onSelect, +}: ToggleableFilterItemProps): JSX.Element { + return ( + onSelect(classificationLabel, !selected)} + > + + + + + + + {classificationLabel} + + {count && } + + + + ); +} + +export default ToggleableFilterItem; diff --git a/packages/datagateway-search/src/facet/components/selectedFilterChips.component.test.tsx b/packages/datagateway-search/src/facet/components/selectedFilterChips.component.test.tsx new file mode 100644 index 000000000..0a2226711 --- /dev/null +++ b/packages/datagateway-search/src/facet/components/selectedFilterChips.component.test.tsx @@ -0,0 +1,72 @@ +import * as React from 'react'; +import { FiltersType } from 'datagateway-common'; +import { render, screen, within } from '@testing-library/react'; +import SelectedFilterChips from './selectedFilterChips.component'; +import userEvent from '@testing-library/user-event'; + +const testFilters: FiltersType = { + 'unrelated.dimension': { + type: 'type', + value: 'asd', + }, + 'unrelated.dimension.2': [{ label: 'asd', key: 'key', filter: [] }], + 'investigation.type.name': ['experiment'], + 'investigationparameter.type.name': ['bcat_123'], +}; + +describe('selectedFilterChips', () => { + it('renders the given filters as chips', () => { + render( + + ); + + expect( + screen.getByText( + 'facetDimensionLabel.investigation.type.name: experiment' + ) + ).toBeInTheDocument(); + expect( + screen.getByText( + 'facetDimensionLabel.investigationparameter.type.name: bcat_123' + ) + ).toBeInTheDocument(); + }); + + it('calls the given callback function when chip is removed', async () => { + const user = userEvent.setup(); + const onRemoveFilter = jest.fn(); + + render( + + ); + + await user.click( + within( + screen.getByRole('button', { + name: 'facetDimensionLabel.investigation.type.name: experiment', + }) + ).getByTestId('CancelIcon') + ); + + expect(onRemoveFilter).toHaveBeenLastCalledWith( + 'investigation.type.name', + 'experiment' + ); + + await user.click( + within( + screen.getByRole('button', { + name: 'facetDimensionLabel.investigationparameter.type.name: bcat_123', + }) + ).getByTestId('CancelIcon') + ); + + expect(onRemoveFilter).toHaveBeenLastCalledWith( + 'investigationparameter.type.name', + 'bcat_123' + ); + }); +}); diff --git a/packages/datagateway-search/src/facet/components/selectedFilterChips.component.tsx b/packages/datagateway-search/src/facet/components/selectedFilterChips.component.tsx new file mode 100644 index 000000000..f161322cc --- /dev/null +++ b/packages/datagateway-search/src/facet/components/selectedFilterChips.component.tsx @@ -0,0 +1,71 @@ +import React from 'react'; +import { FiltersType, SearchFilter } from 'datagateway-common'; +import { Chip, Stack } from '@mui/material'; +import { useTranslation } from 'react-i18next'; + +interface SelectedFilterChipsProps { + /** + * The filters to be displayed by {@link SelectedFilterChips} + */ + filters: FiltersType; + + /** + * Called when the user removes a filter chip. + */ + onRemoveFilter: (facetDimension: string, filterValue: SearchFilter) => void; +} + +/** + * Displays the given filters as a row of removable chips. + */ +function SelectedFilterChips({ + filters, + onRemoveFilter, +}: SelectedFilterChipsProps): JSX.Element { + const [t] = useTranslation(); + + return ( + + {Object.entries(filters).flatMap(([filterKey, filterValue], i) => { + if (!Array.isArray(filterValue)) return []; + + return filterValue.flatMap((value, j) => { + if (typeof value === 'string') { + return [ + { + onRemoveFilter(filterKey, value); + }} + sx={i === 0 && j === 0 ? { ml: 1 } : {}} + />, + ]; + } + + if ('filter' in value) { + return [ + { + onRemoveFilter(filterKey, value); + }} + sx={i === 0 && j === 0 ? { ml: 1 } : {}} + />, + ]; + } + + return []; + }); + })} + + ); +} + +export default SelectedFilterChips; diff --git a/packages/datagateway-search/src/facet/doc.ts b/packages/datagateway-search/src/facet/doc.ts new file mode 100644 index 000000000..932283f45 --- /dev/null +++ b/packages/datagateway-search/src/facet/doc.ts @@ -0,0 +1,56 @@ +/** + * This package contains everything related to faceting of search data. + * + * # What is faceting? + * Faceting, or faceted search, is a technique of searching that allows the users to filter/narrow data + * based on classifications of items in the data. + * + * For example, faceted search can be performed on a list of phones to find a specific brand of phone, + * or phones within a specified price range. The brand and the price of the phones are called *facets*, + * hence the term "faceted search" - searches are classified by different facets. Facets can also be: + * + * - the storage capacity of the phone + * - the display size of the phone + * - the type of the charging port (USB-C? micro USB?) + * + * ## datagateway-search + * In the context of datagateway-search, search data can be faceted based on different facets (also called dimensions). + * For example, search results for Investigations can be filtered based on the investigation type. + * + * What filters are available depends on what is returned in the search response ({@link SearchResponse}). + * The `dimensions` property contains dimensions that the results can be filtered on. + * For example, the dimensions of a search response for searching through investigations can look like this: + * + * ``` + * { + * dimensions: { + * 'Investigation.type.name': { + * calibration: 100, + * experiment: 234, + * } + * } + * } + * ``` + * + * The dimensions object indicates that there are 100 investigations that are of type 'calibration', and 234 that are of type 'experiment'. + * 'Investigation.type.name' can be seen as a path that drills down to the InvestigationType entity, which has a `name` field: + * + * ``` + * Investigation entity { + * `type` field: InvestigationType (1..1) { + * name: string + * } + * } + * ``` + * + * This link provides the schema for the Investigation entity. https://repo.icatproject.org/site/icat/server/5.0.0/schema.html#Investigation + * + * Based on that dimensions object, the search results can be filtered by `Investigation.type.name` (investigation type). + * For example, "only show investigations that have type "calibration"). + * This filtering operation can be done through `FacetPanel`. + * + * @see https://repo.icatproject.org/site/icat/server/5.0.0/schema.html + * @see https://en.wikipedia.org/wiki/Faceted_search + * @see https://www.algolia.com/blog/ux/faceted-search-an-overview/ + */ +export {}; diff --git a/packages/datagateway-search/src/facet/facet.ts b/packages/datagateway-search/src/facet/facet.ts new file mode 100644 index 000000000..e132a877b --- /dev/null +++ b/packages/datagateway-search/src/facet/facet.ts @@ -0,0 +1,160 @@ +import { SearchResponse } from 'datagateway-common'; + +/** + * Stores the result of performing faceted search on a search result set. + * It maps names of the facets used for the search (field names of the targeted/faceted entity) to + * a map that classifies the search result set in that facet. + * + * For example, let's say a list of entity called `Phone` is faceted. + * The result is stored as `FacetDimensions`. Here is an example of the `FacetDimensions`: + * ``` + * { // FacetResults + * "Phone.color": { // FacetValues, classifies the list of phones by Phone.color field. + * "black": 100, + * "white": 99, + * } + * // Nested field (Phone.manufacturer is a "Manufacturer" entity) + * "Phone.manufacturer.name": { // FacetDimensionValues, classifies the list of phones by `Phone.manufacturer.name` field. + * "sungsam": 23, + * "orange": 176, + * } + * } + * ``` + * + * The example tells us: + * - In the list, there are 100 `Phone` with the `color` field being to `"black"`, 99 for `"white"`. + * - In the list, there are 23 `Phone`s manufactured by sungsam, 176 manufactured by orange. + */ +type FacetClassification = Record; + +/** + * Describes the search result set under a certain facet. + * Maps the values of facet (field name of the targeted entity) + * to the number of entities whose field has that value. + * + * For example, let's say FacetDimensionValues contains values of a facet dimension + * called "colors" on the "Phone" entity. In this case, FacetDimensionValues can look like this: + * ``` + * { + * "black": 100, + * "white": 99, + * } + * ``` + * It shows that there are 100 `Phone` entities whose `color` field has the value `"black"`, + * and 99 `Phone`s whose `color` field has the value `"white"`. + * In English, it means that there are 100 black phones and 99 white phones. + */ +type FacetClassificationValues = Record; + +/** + * Combines facet objects in each {@link SearchResponse} in the given array into one + * facet objects. + * + * Example: + * ``` + * const response = [ + * { + * dimensions: { + * 'Investigation.type.name': { + * type1: 2, + * type2: 4, + * } + * }, + * ... + * }, + * { + * dimensions: { + * 'Investigation.type.name': { + * type1: 4, + * type3: 3, + * }, + * 'InvestigationParameter.type.name': { + * param: 6 + * } + * }, + * ... + * } + * ] + * + * const facets = facetClassificationFromSearchResponses(responses) + * { + * dimensions: { + * 'Investigation.type.name': { + * type1: 6, + * type2: 4, + * type3: 3, + * }, + * 'InvestigationParameter.type.name': { + * param: 6 + * } + * } + * } + * ``` + * + * @param responses + */ +function facetClassificationFromSearchResponses( + responses: SearchResponse[] +): FacetClassification { + return responses.reduce((facets, searchResponse) => { + if (!searchResponse.dimensions) return facets; + + // combine the facet object of this search response with other ones + // object shape example: + // { + // 'Investigation.type.name': { + // type1: 2, + // type2: 3, + // }, + // 'InvestigationParameter.type.name': { + // ... + // } + // } + for (const [dimension, classifications] of Object.entries( + searchResponse.dimensions + )) { + if (!(dimension in facets)) { + // classification doesn't exist yet under this dimension + // in the result object + // create a blank object so that the classifications can be written into this object + facets[dimension] = {}; + } + + // "classifications" object example + // { + // type1: 2, + // type2: 3, + // type3: { + // count: 4 + // } + // } + + const otherClassifications = facets[dimension]; + for (const [classification, value] of Object.entries(classifications)) { + // the number of search items under this classification + const classificationCount = + typeof value === 'object' ? value.count : value; + + if ( + classification in otherClassifications && + typeof classificationCount !== 'undefined' && + typeof otherClassifications[classification] !== 'undefined' + ) { + // combine count with other existing classifications + // type-cast as number since we check for not undefined above but TS isn't happy + (otherClassifications[classification] as number) += + classificationCount; + } else { + // classification under this dimension doesn't exist yet + // add this to the final object + otherClassifications[classification] = classificationCount; + } + } + } + + return facets; + }, {}); +} + +export type { FacetClassification, FacetClassificationValues }; +export { facetClassificationFromSearchResponses }; diff --git a/packages/datagateway-search/src/facet/useFacetFilters.test.tsx b/packages/datagateway-search/src/facet/useFacetFilters.test.tsx new file mode 100644 index 000000000..992e1cfb6 --- /dev/null +++ b/packages/datagateway-search/src/facet/useFacetFilters.test.tsx @@ -0,0 +1,329 @@ +import * as React from 'react'; +import { act, renderHook } from '@testing-library/react-hooks'; +import useFacetFilters from './useFacetFilters'; +import { createMemoryHistory, MemoryHistory } from 'history'; +import { Router } from 'react-router-dom'; + +describe('useFacetFilters', () => { + let history: MemoryHistory; + + function Wrapper({ children }: { children: React.ReactNode }): JSX.Element { + return {children}; + } + + beforeEach(() => { + history = createMemoryHistory(); + }); + + it('stores the currently selected filters', () => { + const { result, rerender } = renderHook(() => useFacetFilters(), { + wrapper: Wrapper, + }); + // should be empty initially + expect(result.current.selectedFacetFilters).toEqual({}); + + const searchParam = new URLSearchParams(); + searchParam.append( + 'filters', + JSON.stringify({ + 'investigation.type.name': ['experiment'], + }) + ); + history.push({ search: `?${searchParam.toString()}` }); + + rerender(); + + expect(result.current.selectedFacetFilters).toEqual({ + 'investigation.type.name': ['experiment'], + }); + }); + + it('adds filter without applying the changes', async () => { + const { result, waitFor } = renderHook(() => useFacetFilters(), { + wrapper: Wrapper, + }); + + act(() => { + result.current.addFacetFilter({ + dimension: 'investigation.type.name', + filterValue: 'experiment', + applyImmediately: false, + }); + }); + + await waitFor(() => { + expect(result.current.selectedFacetFilters).toEqual({ + 'investigation.type.name': ['experiment'], + }); + expect(history.location.search).toEqual(''); + }); + + act(() => { + result.current.addFacetFilter({ + dimension: 'investigation.type.name', + filterValue: 'calibration', + applyImmediately: false, + }); + }); + + await waitFor(() => { + expect(result.current.selectedFacetFilters).toEqual({ + 'investigation.type.name': ['experiment', 'calibration'], + }); + expect(history.location.search).toEqual(''); + }); + + act(() => { + result.current.addFacetFilter({ + dimension: 'investigationparameter.type.name', + filterValue: 'run_number_after', + applyImmediately: false, + }); + }); + + await waitFor(() => { + expect(result.current.selectedFacetFilters).toEqual({ + 'investigation.type.name': ['experiment', 'calibration'], + 'investigationparameter.type.name': ['run_number_after'], + }); + expect(history.location.search).toEqual(''); + }); + }); + + it('adds filters and apply the changes immediately when applyImmediately set to true', async () => { + const { result, waitFor } = renderHook(() => useFacetFilters(), { + wrapper: Wrapper, + }); + + act(() => { + result.current.addFacetFilter({ + dimension: 'investigation.type.name', + filterValue: 'experiment', + applyImmediately: true, + }); + }); + + await waitFor(() => { + const selectedFilters = { + 'investigation.type.name': ['experiment'], + }; + + const searchParams = new URLSearchParams(); + searchParams.append('filters', JSON.stringify(selectedFilters)); + + expect(result.current.selectedFacetFilters).toEqual(selectedFilters); + expect(history.location.search).toEqual(`?${searchParams.toString()}`); + }); + + act(() => { + result.current.addFacetFilter({ + dimension: 'investigationparameter.type.name', + filterValue: 'bcat_inv_str', + applyImmediately: true, + }); + }); + + await waitFor(() => { + const selectedFilters = { + 'investigation.type.name': ['experiment'], + 'investigationparameter.type.name': ['bcat_inv_str'], + }; + + const searchParams = new URLSearchParams(); + searchParams.append('filters', JSON.stringify(selectedFilters)); + + expect(result.current.selectedFacetFilters).toEqual(selectedFilters); + expect(history.location.search).toEqual(`?${searchParams.toString()}`); + }); + }); + + it('removes filters without applying the changes', async () => { + const searchParams = new URLSearchParams(); + searchParams.append( + 'filters', + JSON.stringify({ + 'investigation.type.name': ['experiment'], + 'investigationparameter.type.name': [ + 'bcat_inv_str', + 'run_number_after', + ], + }) + ); + + const searchParamStr = `?${searchParams.toString()}`; + history.replace({ search: searchParamStr }); + + const { result, waitFor } = renderHook(() => useFacetFilters(), { + wrapper: Wrapper, + }); + + // try to remove something not in the filter + act(() => { + result.current.removeFacetFilter({ + dimension: 'investigation.type.name', + filterValue: 'calibration', + applyImmediately: false, + }); + }); + // nothing should be changed + await waitFor(() => { + expect(result.current.selectedFacetFilters).toEqual({ + 'investigation.type.name': ['experiment'], + 'investigationparameter.type.name': [ + 'bcat_inv_str', + 'run_number_after', + ], + }); + expect(history.location.search).toEqual(searchParamStr); + }); + + act(() => { + result.current.removeFacetFilter({ + dimension: 'investigation.type.name', + filterValue: 'experiment', + applyImmediately: false, + }); + }); + await waitFor(() => { + expect(result.current.selectedFacetFilters).toEqual({ + 'investigationparameter.type.name': [ + 'bcat_inv_str', + 'run_number_after', + ], + }); + expect(history.location.search).toEqual(searchParamStr); + }); + + act(() => { + result.current.removeFacetFilter({ + dimension: 'investigationparameter.type.name', + filterValue: 'bcat_inv_str', + applyImmediately: false, + }); + }); + await waitFor(() => { + expect(result.current.selectedFacetFilters).toEqual({ + 'investigationparameter.type.name': ['run_number_after'], + }); + expect(history.location.search).toEqual(searchParamStr); + }); + }); + + it('removes filters and apply the changes immediately when applyImmediately set to true', async () => { + const searchParams = new URLSearchParams(); + searchParams.append( + 'filters', + JSON.stringify({ + 'investigation.type.name': ['experiment'], + 'investigationparameter.type.name': [ + 'bcat_inv_str', + 'run_number_after', + ], + }) + ); + + const searchParamStr = `?${searchParams.toString()}`; + history.replace({ search: searchParamStr }); + + const { result, waitFor } = renderHook(() => useFacetFilters(), { + wrapper: Wrapper, + }); + + // try to remove something not in the filter + act(() => { + result.current.removeFacetFilter({ + dimension: 'investigation.type.name', + filterValue: 'calibration', + applyImmediately: true, + }); + }); + // nothing should be changed + await waitFor(() => { + expect(result.current.selectedFacetFilters).toEqual({ + 'investigation.type.name': ['experiment'], + 'investigationparameter.type.name': [ + 'bcat_inv_str', + 'run_number_after', + ], + }); + expect(history.location.search).toEqual(searchParamStr); + }); + + act(() => { + result.current.removeFacetFilter({ + dimension: 'investigation.type.name', + filterValue: 'experiment', + applyImmediately: true, + }); + }); + + await waitFor(() => { + const selectedFilters = { + 'investigationparameter.type.name': [ + 'bcat_inv_str', + 'run_number_after', + ], + }; + + const searchParams = new URLSearchParams(); + searchParams.append('filters', JSON.stringify(selectedFilters)); + + expect(result.current.selectedFacetFilters).toEqual(selectedFilters); + expect(history.location.search).toEqual(`?${searchParams.toString()}`); + }); + }); + + it('applies the update filters to the URL when requested', async () => { + const searchParams = new URLSearchParams(); + searchParams.append( + 'filters', + JSON.stringify({ + 'investigation.type.name': ['experiment'], + 'investigationparameter.type.name': [ + 'bcat_inv_str', + 'run_number_after', + ], + }) + ); + history.replace({ search: `?${searchParams.toString()}` }); + + const { result, waitFor } = renderHook(() => useFacetFilters(), { + wrapper: Wrapper, + }); + + act(() => { + result.current.addFacetFilter({ + dimension: 'investigation.type.name', + filterValue: 'calibration', + applyImmediately: false, + }); + }); + act(() => { + result.current.removeFacetFilter({ + dimension: 'investigationparameter.type.name', + filterValue: 'bcat_inv_str', + applyImmediately: false, + }); + }); + act(() => { + result.current.applyFacetFilters(); + }); + + const newSearchParams = new URLSearchParams(); + newSearchParams.append( + 'filters', + JSON.stringify({ + 'investigation.type.name': ['experiment', 'calibration'], + 'investigationparameter.type.name': ['run_number_after'], + }) + ); + + await waitFor(() => { + expect(history.location.search).toEqual(`?${newSearchParams.toString()}`); + expect(result.current.selectedFacetFilters).toEqual({ + 'investigation.type.name': ['experiment', 'calibration'], + 'investigationparameter.type.name': ['run_number_after'], + }); + }); + }); +}); diff --git a/packages/datagateway-search/src/facet/useFacetFilters.ts b/packages/datagateway-search/src/facet/useFacetFilters.ts new file mode 100644 index 000000000..237a3f26e --- /dev/null +++ b/packages/datagateway-search/src/facet/useFacetFilters.ts @@ -0,0 +1,130 @@ +import React from 'react'; +import { + FiltersType, + parseSearchToQuery, + SearchFilter, +} from 'datagateway-common'; +import { useHistory, useLocation } from 'react-router-dom'; +import isEqual from 'lodash.isequal'; + +function useFacetFilters(): { + selectedFacetFilters: FiltersType; + addFacetFilter: (options: { + dimension: string; + filterValue: SearchFilter; + applyImmediately: boolean; + }) => void; + removeFacetFilter: (options: { + dimension: string; + filterValue: SearchFilter; + applyImmediately: boolean; + }) => void; + applyFacetFilters: () => void; + haveUnappliedFilters: boolean; +} { + const location = useLocation(); + const { push } = useHistory(); + const { filters } = React.useMemo( + () => parseSearchToQuery(location.search), + [location.search] + ); + + const [isImmediateUpdateRequired, setIsImmediateUpdateRequired] = + React.useState(false); + const [selectedFacetFilters, setSelectedFacetFilters] = + React.useState({}); + + const haveUnappliedFilters = !isEqual(filters, selectedFacetFilters); + + const addFacetFilter = ({ + dimension, + filterValue, + applyImmediately, + }: { + dimension: string; + filterValue: SearchFilter; + applyImmediately: boolean; + }): void => { + const filterKey = dimension; + + setSelectedFacetFilters((prevFilter) => { + const prevFilterValue = prevFilter[filterKey]; + if (!prevFilterValue) { + return { + ...prevFilter, + [filterKey]: [filterValue], + }; + } + if (Array.isArray(prevFilterValue)) { + return { + ...prevFilter, + [filterKey]: [...prevFilterValue, filterValue], + }; + } + return prevFilter; + }); + setIsImmediateUpdateRequired(applyImmediately); + }; + + const removeFacetFilter = ({ + dimension, + filterValue, + applyImmediately, + }: { + dimension: string; + filterValue: SearchFilter; + applyImmediately: boolean; + }): void => { + const filterKey = dimension; + + setSelectedFacetFilters((prevFilter) => { + const prevFilterValue = prevFilter[filterKey]; + if (!Array.isArray(prevFilterValue)) { + return prevFilter; + } + + // new facet filters excluding the filter that should be removed + const dimensionFilters = prevFilterValue?.filter( + (value) => !isEqual(value, filterValue) + ); + + if (dimensionFilters && dimensionFilters.length > 0) { + return { + ...prevFilter, + [filterKey]: dimensionFilters, + }; + } + + const { [filterKey]: _, ...rest } = prevFilter; + return rest; + }); + setIsImmediateUpdateRequired(applyImmediately); + }; + + const applyFacetFilters = React.useCallback((): void => { + const searchParams = new URLSearchParams(location.search); + searchParams.set('filters', JSON.stringify(selectedFacetFilters)); + push({ search: `?${searchParams.toString()}` }); + }, [location.search, push, selectedFacetFilters]); + + React.useEffect(() => { + setSelectedFacetFilters(filters); + }, [filters]); + + React.useEffect(() => { + if (isImmediateUpdateRequired) { + applyFacetFilters(); + setIsImmediateUpdateRequired(false); + } + }, [applyFacetFilters, isImmediateUpdateRequired]); + + return { + selectedFacetFilters, + addFacetFilter, + removeFacetFilter, + applyFacetFilters, + haveUnappliedFilters, + }; +} + +export default useFacetFilters; diff --git a/packages/datagateway-search/src/index.test.tsx b/packages/datagateway-search/src/index.test.tsx index c2e080a18..d38f8ccaf 100644 --- a/packages/datagateway-search/src/index.test.tsx +++ b/packages/datagateway-search/src/index.test.tsx @@ -2,7 +2,7 @@ import axios from 'axios'; import { MicroFrontendId, RegisterRouteType } from 'datagateway-common'; import LogoLight from 'datagateway-common/src/images/datagateway-logo.svg'; import LogoDark from 'datagateway-common/src/images/datgateway-white-text-blue-mark-logo.svg'; -import * as log from 'loglevel'; +import log from 'loglevel'; import { fetchSettings } from './'; jest.mock('loglevel'); diff --git a/packages/datagateway-search/src/index.tsx b/packages/datagateway-search/src/index.tsx index 1cf68f0ca..ca3f3595d 100644 --- a/packages/datagateway-search/src/index.tsx +++ b/packages/datagateway-search/src/index.tsx @@ -7,13 +7,14 @@ import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; -import * as log from 'loglevel'; +import log from 'loglevel'; import singleSpaReact from 'single-spa-react'; import axios from 'axios'; import jsrsasign from 'jsrsasign'; import { SearchSettings, setSettings } from './settings'; import { MicroFrontendId, + MicroFrontendToken, PluginRoute, RegisterRouteType, } from 'datagateway-common'; @@ -35,7 +36,7 @@ function domElementGetter(): HTMLElement { const reactLifecycles = singleSpaReact({ React, ReactDOM, - rootComponent: App, + rootComponent: () => (document.getElementById(pluginName) ? : null), domElementGetter, }); @@ -157,47 +158,25 @@ if ( if (settingsResult) { const apiUrl = settingsResult.apiUrl; axios - .post( - `${settingsResult.icatUrl}/session`, - `json=${JSON.stringify({ - plugin: 'simple', - credentials: [{ username: 'root' }, { password: 'pw' }], - })}`, - { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - } - ) + .post(`${apiUrl}/sessions`, { + username: 'root', + password: 'pw', + mechanism: 'simple', + }) .then((response) => { - axios - .get(`${apiUrl}/sessions`, { - headers: { - Authorization: `Bearer ${response.data.sessionId}`, - }, - }) - .then(() => { - const jwtHeader = { alg: 'HS256', typ: 'JWT' }; - const payload = { - sessionId: response.data.sessionId, - username: 'dev', - }; - const jwt = jsrsasign.KJUR.jws.JWS.sign( - 'HS256', - jwtHeader, - payload, - 'shh' - ); - - window.localStorage.setItem('scigateway:token', jwt); - }) - .catch((error) => { - log.error( - `datagateway-api cannot verify ICAT session id: ${error.message}. - This is likely caused if datagateway-api is pointing to a - different ICAT than the one used by the IDS/TopCAT` - ); - }); + const jwtHeader = { alg: 'HS256', typ: 'JWT' }; + const payload = { + sessionId: response.data.sessionID, + username: 'dev', + }; + const jwt = jsrsasign.KJUR.jws.JWS.sign( + 'HS256', + jwtHeader, + payload, + 'shh' + ); + + window.localStorage.setItem(MicroFrontendToken, jwt); }) .catch((error) => log.error(`Can't log in to ICAT: ${error.message}`) @@ -205,4 +184,6 @@ if ( } }); } +} else { + log.setDefaultLevel(log.levels.ERROR); } diff --git a/packages/datagateway-search/src/search/__snapshots__/advancedHelpDialogue.component.test.tsx.snap b/packages/datagateway-search/src/search/__snapshots__/advancedHelpDialogue.component.test.tsx.snap deleted file mode 100644 index 4854ebd9a..000000000 --- a/packages/datagateway-search/src/search/__snapshots__/advancedHelpDialogue.component.test.tsx.snap +++ /dev/null @@ -1,280 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Advanced help dialogue component tests renders correctly 1`] = ` - - See all - - - search options - - . - - - - Advanced Search Tips - - - - - - - advanced_search_help.description - - - - advanced_search_help.exact_phrase.title - - - - Use quotation marks around a phrase to search for a precise sequence of words e.g. - - - "neutron scattering" - - . - - - - - - advanced_search_help.logic_operators.title - - - - Find all data containing 'neutron' and 'scattering' with ' - - neutron AND scattering - - '. Find all data containing either neutron or scattering with ' - - - neutron OR scattering - - '. Find all data that contains the phrase 'scattering' but exclude those containing 'elastic' with ' - - - scattering NOT elastic - - '. Use brackets around phrases to construct more complicated searches e.g. ' - - - scattering NOT (elastic OR neutron) - - '. - - - - - - advanced_search_help.wildcards.title - - - - Use wildcards to take the place of one or more characters in a phrase. A question mark '?' can be used to search for a phrase with one or more character missing e.g. ' - - - te?t - - ' will return results containing 'test' or 'text'. An asterix '*' can be used to replace zero or more characters e.g. ' - - *ium - - ' will return results containing words like 'sodium' and 'vanadium'. - - - - - - advanced_search_help.limited_search_results.title - - - advanced_search_help.limited_search_results.description {maxNumResults:{tabs:{datasetTab:false,datafileTab:false,investigationTab:false},selectAllSetting:true,settingsLoaded:false,sideLayout:false,searchableEntities:[investigation,dataset,datafile],maxNumResults:300}} - - - - - Further information on searching can be found - - - here - - . - - - - -`; diff --git a/packages/datagateway-search/src/search/__snapshots__/searchButton.component.test.tsx.snap b/packages/datagateway-search/src/search/__snapshots__/searchButton.component.test.tsx.snap index b4f81a885..00d67e774 100644 --- a/packages/datagateway-search/src/search/__snapshots__/searchButton.component.test.tsx.snap +++ b/packages/datagateway-search/src/search/__snapshots__/searchButton.component.test.tsx.snap @@ -1,9 +1,19 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Search Button component tests renders correctly 1`] = ` -
- -
+ +
+ +
+
`; diff --git a/packages/datagateway-search/src/search/__snapshots__/searchTextBox.component.test.tsx.snap b/packages/datagateway-search/src/search/__snapshots__/searchTextBox.component.test.tsx.snap index 53d563433..437f2fc0c 100644 --- a/packages/datagateway-search/src/search/__snapshots__/searchTextBox.component.test.tsx.snap +++ b/packages/datagateway-search/src/search/__snapshots__/searchTextBox.component.test.tsx.snap @@ -1,30 +1,43 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Search text box component tests renders correctly 1`] = ` -
- +
- searchBox.search_text - - - searchBox.search_text - - } - multiline={false} - onChange={[Function]} - type="search" - value="test" - /> -
+ +
+ + +
+
+ `; diff --git a/packages/datagateway-search/src/search/advancedHelpDialogue.component.test.tsx b/packages/datagateway-search/src/search/advancedHelpDialogue.component.test.tsx index c3abd94af..11031cbf0 100644 --- a/packages/datagateway-search/src/search/advancedHelpDialogue.component.test.tsx +++ b/packages/datagateway-search/src/search/advancedHelpDialogue.component.test.tsx @@ -1,30 +1,44 @@ -import React from 'react'; -import { createMount, createShallow } from '@material-ui/core/test-utils'; +import * as React from 'react'; import AdvancedHelpDialogue from './advancedHelpDialogue.component'; -import { Provider, useSelector } from 'react-redux'; +import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; import { dGCommonInitialState } from 'datagateway-common'; -import { initialState as dgSearchInitialState } from '../state/reducers/dgsearch.reducer'; import configureStore from 'redux-mock-store'; -import { ReactWrapper } from 'enzyme'; -import { StateType } from '../state/app.types'; import { MemoryRouter } from 'react-router-dom'; +import type { RenderResult } from '@testing-library/react'; +import { + render, + screen, + waitForElementToBeRemoved, +} from '@testing-library/react'; + +import { initialState as dgSearchInitialState } from '../state/reducers/dgsearch.reducer'; +import { StateType } from '../state/app.types'; +import userEvent from '@testing-library/user-event'; jest.mock('react-redux', () => ({ ...jest.requireActual('react-redux'), useSelector: jest.fn(), })); -describe('Advanced help dialogue component tests', () => { - let shallow; - let mount; - let mockStore; +function renderComponent({ + initialState, +}: { + initialState: StateType; +}): RenderResult { + return render( + + + + + + ); +} + +describe('Advanced help dialogue', () => { let state: StateType; beforeEach(() => { - shallow = createShallow(); - mount = createMount(); - mockStore = configureStore([thunk]); state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, @@ -33,46 +47,39 @@ describe('Advanced help dialogue component tests', () => { ); }); - const createWrapper = (): ReactWrapper => { - return mount( - - - - - - ); - }; + it('is hidden initially', () => { + renderComponent({ initialState: state }); + expect( + screen.queryByRole('dialog', { name: 'Advanced Search Tips' }) + ).toBeNull(); + }); - it('renders correctly', () => { - useSelector.mockImplementation(() => { - return dgSearchInitialState; - }); + it('opens when search options link is clicked and closes when the close button is clicked', async () => { + const user = userEvent.setup(); - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); + renderComponent({ initialState: state }); + + await user.click( + screen.getByRole('button', { + name: 'advanced_search_help.search_options_arialabel', + }) + ); - it('can open and close help dialogue', () => { - const wrapper = createWrapper(); - wrapper - .find('[aria-label="advanced_search_help.search_options_arialabel"]') - .first() - .simulate('click'); expect( - wrapper - .find('[aria-labelledby="advanced-search-dialog-title"]') - .first() - .prop('open') - ).toBe(true); - wrapper - .find('[aria-label="advanced_search_help.close_button_arialabel"]') - .first() - .simulate('click'); + screen.getByRole('dialog', { name: 'Advanced Search Tips' }) + ).toBeInTheDocument(); + + await user.click( + screen.getByRole('button', { + name: 'advanced_search_help.close_button_arialabel', + }) + ); + + await waitForElementToBeRemoved( + screen.getByRole('dialog', { name: 'Advanced Search Tips' }) + ); expect( - wrapper - .find('[aria-labelledby="advanced-search-dialog-title"]') - .first() - .prop('open') - ).toBe(false); + screen.queryByRole('dialog', { name: 'Advanced Search Tips' }) + ).toBeNull(); }); }); diff --git a/packages/datagateway-search/src/search/advancedHelpDialogue.component.tsx b/packages/datagateway-search/src/search/advancedHelpDialogue.component.tsx index 375785a63..0aa5e0aba 100644 --- a/packages/datagateway-search/src/search/advancedHelpDialogue.component.tsx +++ b/packages/datagateway-search/src/search/advancedHelpDialogue.component.tsx @@ -1,72 +1,47 @@ import React from 'react'; import { - createStyles, - makeStyles, + Dialog, + DialogContent, + DialogTitle, + IconButton, + Link, + styled, Theme, - withStyles, -} from '@material-ui/core/styles'; -import Dialog from '@material-ui/core/Dialog'; -import MuiDialogTitle from '@material-ui/core/DialogTitle'; -import MuiDialogContent from '@material-ui/core/DialogContent'; -import IconButton from '@material-ui/core/IconButton'; -import CloseIcon from '@material-ui/icons/Close'; -import Typography from '@material-ui/core/Typography'; -import { Link, Paper } from '@material-ui/core'; + Typography, +} from '@mui/material'; +import CloseIcon from '@mui/icons-material/Close'; import { Trans, useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; -import { StateType } from '../state/app.types'; import { Link as RouterLink } from 'react-router-dom'; -const useStyles = makeStyles((theme: Theme) => { - return createStyles({ - root: { - margin: 0, - padding: theme.spacing(2), - }, - advancedButton: { - fontSize: '14px', - fontWeight: 'bold', - }, - closeButton: { - position: 'absolute', - right: theme.spacing(1), - top: theme.spacing(1), - color: theme.palette.grey[500], - }, - paper: { - margin: theme.spacing(2), - padding: theme.spacing(2), - // eslint-disable-next-line @typescript-eslint/no-explicit-any - backgroundColor: (theme as any).colours?.paper, - }, - dialogueBackground: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - backgroundColor: (theme as any).colours?.background, - }, - }); -}); +const Section = styled('section')(({ theme }) => ({ + marginTop: theme.spacing(4), + marginBottom: theme.spacing(4), +})); -const DialogueContent = withStyles((theme: Theme) => ({ - root: { - padding: theme.spacing(2), - }, -}))(MuiDialogContent); +const SectionTitle = ({ + children, +}: { + children: React.ReactNode; +}): JSX.Element => ( + + {children} + +); -const DialogueHeading = withStyles((theme: Theme) => ({ - root: { - padding: theme.spacing(2), - }, -}))(MuiDialogTitle); +const SectionText = ({ + children, +}: { + children: React.ReactNode; +}): JSX.Element => ( + + {children} + +); const AdvancedHelpDialogue = (): React.ReactElement => { const [open, setOpen] = React.useState(false); - const classes = useStyles(); const [t] = useTranslation(); - const maxNumResults = useSelector( - (state: StateType) => state.dgsearch.maxNumResults - ); - const handleClickOpen = (): void => { setOpen(true); }; @@ -80,7 +55,11 @@ const AdvancedHelpDialogue = (): React.ReactElement => { See all{' '} @@ -91,151 +70,362 @@ const AdvancedHelpDialogue = (): React.ReactElement => { onClose={handleClose} aria-labelledby="advanced-search-dialog-title" open={open} - PaperProps={{ className: classes.dialogueBackground }} + sx={{ padding: 2 }} + PaperProps={{ + sx: { + backgroundColor: (theme: Theme) => + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (theme as any).colours?.background, + }, + }} > - - Advanced Search Tips + + Advanced Search Tips - - - {t('advanced_search_help.description')} - - - - {t('advanced_search_help.exact_phrase.title')} - - - - Use quotation marks around a phrase to search for a precise - sequence of words e.g.{' '} - - "neutron scattering" - - . - - - - - - {t('advanced_search_help.logic_operators.title')} - - - - Find all data containing 'neutron' and - 'scattering' with ' - - neutron AND scattering - - '. Find all data containing either neutron or scattering with - '{' '} - + + + {t('advanced_search_help.description')} + +
+ {t('advanced_search_help.terms.title')} + + + By default, all words in the search text are treated as separate{' '} + terms. Results must contain at least one{' '} + term to be returned, and they can occur in any + order in the result. When using the default relevancy based + sorting, results containing the most terms will + appear first. For example,{' '} + + neutron scattering + {' '} + will return results containing both terms + first, then results containing only one or the other. + + +
+
+ + {t('advanced_search_help.phrases.title')} + + + + Use quotation marks around a multiple terms to + create a phrase. Results must contain the + entire + phrase, with the words in order. For example, + + "neutron scattering" + + . + + +
+
+ + {t('advanced_search_help.logic_operators.title')} + + + - neutron OR scattering - - '. Find all data that contains the phrase 'scattering' - but exclude those containing 'elastic' with '{' '} - OR is the default behaviour for multiple{' '} + terms:{' '} + + neutron OR scattering + {' '} + is equivalent to{' '} + + neutron scattering + + .

AND requires both{' '} + terms on either side of the keyword must be + present in the result:{' '} + + neutron AND scattering + + .

+ requires the next{' '} + term be present in the result:{' '} + + +neutron +scattering + + .

NOT or -{' '} + requires the next term not be present in the + result:{' '} + + -neutron NOT scattering + + . +

Finally, brackets can be used to build complicated + logic:{' '} + + (+neutron -photon) AND (scattering OR diffraction) + + . +
+
+
+
+ + {t('advanced_search_help.synonyms.title')} + + + + Results do not need to have the exact term{' '} + searched for in order to match. If the root word is the same, + then the results should appear.{' '} + + Scattering + + ,{' '} + + scattered + + ,{' '} + + scatters + {' '} + etc. are all treated as if the user searched for{' '} + + scatter + + . Additionally, some common scientific terminology has + additional support. Chemical symbols, amino acid codes and the + PaNET ontology of techniques are all supported, so that + searching for{' '} + + xas li + {' '} + is equivalent to searching for{' '} + + x-ray absorption spectroscopy lithium + + . + + +
+
+ + {t('advanced_search_help.wildcards.title')} + + + + To take the place of one character, use ?. To + represent any number (0 or more) characters, use{' '} + *. For example,{' '} + + te?t + {' '} + would return results containing test or text, and{' '} + + te*t + {' '} + would also return testament. +

Note that the use of wildcards can prevent the + synonym functionality described above.{' '} + + scatterin? + {' '} + will not result in matches, as we match against the root word + which is scatter.{' '} + + scatter* + {' '} + however would work. Furthermore, use of wildcards (especially + leading wildcards) can take longer than an otherwise identical + search, so they should be used sparingly. +
+
+
+
+ + {t('advanced_search_help.special_characters.title')} + + + - scattering NOT elastic - - '. Use brackets around phrases to construct more complicated - searches e.g. '{' '} + In addition to whitespace, there are other characters used to + split terms based on context. A{' '} + . character is treated as a separator only when + between a mixture of letters and numbers, but is preserved when + in-between two letters or two numbers. - is + always treated as a separator. This can make searching for file + extension difficult, as a searching for{' '} + + 1234.dat + {' '} + will match any result containing the term 1234 + or dat, but not for example abcd.dat as that is treated as one + single term. +

When building a phrase, special + characters in the phrase will not perform their + special function and instead are treated as white space. This + can be a useful way of effectively ignoring slashes in a file + path, but will also prevent wildcards from working. +
+
+
+
+ + {t('advanced_search_help.fields.title')} + + + + By default, terms are applied to several{' '} + fields of the metadata. However more specific + searches are possible based on the list of supported{' '} + fields below (note that not all{' '} + fields will always have a value and the{' '} + fields differ between entities). For example, + to find results that mention calibration in their summary but + not their title, search for{' '} + + summary:calibration -title:calibration + +

Investigation +
    +
  • title
  • +
  • summary
  • +
  • name
  • +
  • type.name
  • +
  • visitId
  • +
  • facility.name
  • +
  • doi
  • +
+ Dataset +
    +
  • name
  • +
  • description
  • +
  • type.name
  • +
  • visitId
  • +
  • sample.name
  • +
  • sample.type.name
  • +
  • doi
  • +
+ Datafile +
    +
  • name
  • +
  • description
  • +
  • location
  • +
  • datafileFormat.name
  • +
  • visitId
  • +
  • sample.name
  • +
  • sample.type.name
  • +
  • doi
  • +
+
+
+
+ + + Further information on searching can be found{' '} - scattering NOT (elastic OR neutron) + here - '. - -
-
- - - {t('advanced_search_help.wildcards.title')} - - - - Use wildcards to take the place of one or more characters in a - phrase. A question mark '?' can be used to search for a - phrase with one or more character missing e.g. '{' '} - - te?t - - ' will return results containing 'test' or - 'text'. An asterix '*' can be used to replace zero - or more characters e.g. ' - - *ium - - ' will return results containing words like 'sodium' - and 'vanadium'. + . - - - - - {t('advanced_search_help.limited_search_results.title')} - - - {t('advanced_search_help.limited_search_results.description', { - maxNumResults, - })} - - - - - Further information on searching can be found{' '} - - here - - . - - +
+ ); diff --git a/packages/datagateway-search/src/search/checkBoxes.component.test.tsx b/packages/datagateway-search/src/search/checkBoxes.component.test.tsx index 61dfedf07..0a07290d2 100644 --- a/packages/datagateway-search/src/search/checkBoxes.component.test.tsx +++ b/packages/datagateway-search/src/search/checkBoxes.component.test.tsx @@ -1,196 +1,175 @@ -import React from 'react'; -import { StateType } from '../state/app.types'; +import * as React from 'react'; +import type { StateType } from '../state/app.types'; import { Provider } from 'react-redux'; -import { createMount } from '@material-ui/core/test-utils'; import configureStore from 'redux-mock-store'; import CheckBoxesGroup from './checkBoxes.component'; import thunk from 'redux-thunk'; import { initialState } from '../state/reducers/dgsearch.reducer'; -import { createMemoryHistory, History } from 'history'; +import { createMemoryHistory, type History } from 'history'; import { Router } from 'react-router-dom'; +import { render, type RenderResult, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; jest.mock('loglevel'); describe('Checkbox component tests', () => { - let mount; + let user: ReturnType; let state: StateType; - let mockStore; - let testStore; + const mockStore = configureStore([thunk]); + let testStore: ReturnType; let history: History; - let pushSpy; + let pushSpy: jest.SpyInstance; - const createWrapper = (h: History = history): ReactWrapper => { - return mount( + function renderComponent(): RenderResult { + return render( - + ); - }; + } beforeEach(() => { - mount = createMount(); + user = userEvent.setup(); history = createMemoryHistory(); pushSpy = jest.spyOn(history, 'push'); state = JSON.parse(JSON.stringify({ dgsearch: initialState })); state.dgsearch = { + ...state.dgsearch, tabs: { datasetTab: true, datafileTab: true, investigationTab: true, }, - requestReceived: false, - searchData: { - dataset: [], - datafile: [], - investigation: [], - }, searchableEntities: ['investigation', 'dataset', 'datafile'], settingsLoaded: true, }; - mockStore = configureStore([thunk]); testStore = mockStore(state); }); - it('renders correctly', () => { - history.replace('/?searchText=&investigation=false'); - const wrapper = createWrapper(); + afterEach(() => { + jest.clearAllMocks(); + }); - expect(wrapper.find('#search-entities-menu').last().text()).toEqual( - 'searchBox.checkboxes.types (2)' - ); + it('renders a dropdown button that expands to show search type checkboxes', async () => { + history.replace('/?searchText=&investigation=false'); + renderComponent(); - wrapper - .find('#search-entities-menu') - .find('[role="button"]') - .simulate('mousedown', { button: 0 }); + // open the dropdown + await user.click(await screen.findByRole('button')); - const investigationCheckbox = wrapper.find( - '[aria-label="searchBox.checkboxes.investigation_arialabel"]' - ); - expect(investigationCheckbox.exists()); - investigationCheckbox.find('input').forEach((node) => { - expect(node.props().checked).toEqual(false); + const investigationCheckbox = await screen.findByRole('checkbox', { + name: 'searchBox.checkboxes.investigation_arialabel', }); + expect(investigationCheckbox).not.toBeChecked(); - const datasetCheckbox = wrapper.find( - '[aria-label="searchBox.checkboxes.dataset_arialabel"]' - ); - expect(datasetCheckbox.exists()); - datasetCheckbox.find('input').forEach((node) => { - expect(node.props().checked).toEqual(true); + const datasetCheckbox = await screen.findByRole('checkbox', { + name: 'searchBox.checkboxes.dataset_arialabel', }); + expect(datasetCheckbox).toBeChecked(); - const datafileCheckbox = wrapper.find( - '[aria-label="searchBox.checkboxes.datafile_arialabel"]' - ); - expect(datafileCheckbox.exists()).toEqual(true); - datafileCheckbox.find('input').forEach((node) => { - expect(node.props().checked).toEqual(true); + const datafileCheckbox = await screen.findByRole('checkbox', { + name: 'searchBox.checkboxes.datafile_arialabel', }); + expect(datafileCheckbox).toBeChecked(); }); - it('renders correctly when datafiles are not searchable', () => { + it('renders correctly when datafiles are not searchable', async () => { state.dgsearch.searchableEntities = ['investigation', 'dataset']; history.replace('/?searchText=&investigation=false'); - const wrapper = createWrapper(); - - expect(wrapper.find('#search-entities-menu').last().text()).toEqual( - 'searchBox.checkboxes.types (1)' - ); + renderComponent(); - wrapper - .find('#search-entities-menu') - .find('[role="button"]') - .simulate('mousedown', { button: 0 }); + // open the dropdown + await user.click(await screen.findByRole('button')); - const investigationCheckbox = wrapper.find( - '[aria-label="searchBox.checkboxes.investigation_arialabel"]' - ); - expect(investigationCheckbox.exists()); - investigationCheckbox.find('input').forEach((node) => { - expect(node.props().checked).toEqual(false); + const investigationCheckbox = await screen.findByRole('checkbox', { + name: 'searchBox.checkboxes.investigation_arialabel', }); + expect(investigationCheckbox).not.toBeChecked(); - const datasetCheckbox = wrapper.find( - '[aria-label="searchBox.checkboxes.dataset_arialabel"]' - ); - expect(datasetCheckbox.exists()); - datasetCheckbox.find('input').forEach((node) => { - expect(node.props().checked).toEqual(true); + const datasetCheckbox = await screen.findByRole('checkbox', { + name: 'searchBox.checkboxes.dataset_arialabel', }); + expect(datasetCheckbox).toBeChecked(); expect( - wrapper - .find('[aria-label="searchBox.checkboxes.datafile_arialabel"]') - .exists() - ).toEqual(false); + screen.queryByRole('checkbox', { + name: 'searchBox.checkboxes.datafile_arialabel', + }) + ).toBeNull(); }); - it('renders an error message when nothing is selected', () => { + it('renders an error message when nothing is selected', async () => { history.replace( '/?searchText=&investigation=false&dataset=false&datafile=false' ); - const wrapper = createWrapper(); - expect( - wrapper.find('#search-entities-checkbox-label').first().text() - ).toContain('searchBox.checkboxes.types'); + renderComponent(); - expect(wrapper.find('.MuiFormHelperText-root').last().text()).toEqual( - 'searchBox.checkboxes.types_error' - ); + expect( + await screen.findByText('searchBox.checkboxes.types_error') + ).toBeInTheDocument(); }); - it('pushes URL with new dataset value when user clicks checkbox', () => { + it('pushes URL with new dataset value when user clicks checkbox', async () => { history.replace('/?searchText=&investigation=false'); - const wrapper = createWrapper(); + renderComponent(); - wrapper - .find('#search-entities-menu') - .find('[role="button"]') - .simulate('mousedown', { button: 0 }); - - wrapper - .find('[aria-label="searchBox.checkboxes.dataset_arialabel"]') - .simulate('click'); + await user.click( + screen.getByRole('button', { + name: 'searchBox.checkboxes.types (2)', + }) + ); + await user.click( + screen.getByRole('checkbox', { + name: 'searchBox.checkboxes.dataset_arialabel', + }) + ); - expect(pushSpy).toHaveBeenCalledWith('?dataset=false&investigation=false'); + expect(pushSpy).toHaveBeenCalledWith( + '?searchText=&dataset=false&investigation=false' + ); }); - it('pushes URL with new datafile value when user clicks checkbox', () => { + it('pushes URL with new datafile value when user clicks checkbox', async () => { history.replace('/?searchText=&investigation=false'); - const wrapper = createWrapper(); - - wrapper - .find('#search-entities-menu') - .find('[role="button"]') - .simulate('mousedown', { button: 0 }); + renderComponent(); - wrapper - .find('[aria-label="searchBox.checkboxes.datafile_arialabel"]') - .simulate('click'); + await user.click( + screen.getByRole('button', { + name: 'searchBox.checkboxes.types (2)', + }) + ); + await user.click( + screen.getByRole('checkbox', { + name: 'searchBox.checkboxes.datafile_arialabel', + }) + ); - expect(pushSpy).toHaveBeenCalledWith('?datafile=false&investigation=false'); + expect(pushSpy).toHaveBeenCalledWith( + '?searchText=&datafile=false&investigation=false' + ); }); - it('pushes URL with new investigation value when user clicks checkbox', () => { + it('pushes URL with new investigation value when user clicks checkbox', async () => { history.replace('/?searchText=&investigation=false'); - const wrapper = createWrapper(); + renderComponent(); - wrapper - .find('#search-entities-menu') - .find('[role="button"]') - .simulate('mousedown', { button: 0 }); - - wrapper - .find('[aria-label="searchBox.checkboxes.investigation_arialabel"]') - .simulate('click'); + await user.click( + screen.getByRole('button', { + name: 'searchBox.checkboxes.types (2)', + }) + ); + await user.click( + screen.getByRole('checkbox', { + name: 'searchBox.checkboxes.investigation_arialabel', + }) + ); - expect(pushSpy).toHaveBeenCalledWith('?'); + expect(pushSpy).toHaveBeenCalledWith('?searchText='); }); }); diff --git a/packages/datagateway-search/src/search/checkBoxes.component.tsx b/packages/datagateway-search/src/search/checkBoxes.component.tsx index 1b21969db..353cce35d 100644 --- a/packages/datagateway-search/src/search/checkBoxes.component.tsx +++ b/packages/datagateway-search/src/search/checkBoxes.component.tsx @@ -1,46 +1,26 @@ import React from 'react'; -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'; -import FormControl from '@material-ui/core/FormControl'; -import Checkbox from '@material-ui/core/Checkbox'; -import { connect } from 'react-redux'; -import { StateType } from '../state/app.types'; -import { useTranslation } from 'react-i18next'; -import { parseSearchToQuery, usePushSearchToggles } from 'datagateway-common'; -import { useLocation } from 'react-router-dom'; import { + Theme, + FormControl, + Checkbox, FormHelperText, InputLabel, ListItemText, MenuItem, Select, -} from '@material-ui/core'; - -const useStyles = makeStyles((theme: Theme) => - createStyles({ - root: { - display: 'flex', - }, - formControl: { - margin: theme.spacing(1), - minWidth: 120, - maxWidth: 300, - }, - formLabel: { - margin: 'auto', - marginRight: theme.spacing(2), - }, - select: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - color: (theme as any).colours?.contrastGrey, - }, - }) -); + SelectChangeEvent, +} from '@mui/material'; +import { connect } from 'react-redux'; +import { StateType } from '../state/app.types'; +import { useTranslation } from 'react-i18next'; +import { parseSearchToQuery, usePushSearchToggles } from 'datagateway-common'; +import { useLocation } from 'react-router-dom'; const ITEM_HEIGHT = 48; const ITEM_PADDING_TOP = 8; const MenuProps = { PaperProps: { - style: { + sx: { maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, width: 250, }, @@ -60,7 +40,6 @@ interface SearchToggle { } const CheckboxesGroup = (props: CheckBoxStoreProps): React.ReactElement => { - const classes = useStyles(); const [t] = useTranslation(); const { searchableEntities } = props; @@ -99,7 +78,7 @@ const CheckboxesGroup = (props: CheckBoxStoreProps): React.ReactElement => { ariaLabel: t('searchBox.checkboxes.datafile_arialabel'), }); - const handleChange = (event: React.ChangeEvent<{ value: unknown }>): void => { + const handleChange = (event: SelectChangeEvent): void => { const newValues = event.target.value as string[]; pushSearchToggles( @@ -112,11 +91,13 @@ const CheckboxesGroup = (props: CheckBoxStoreProps): React.ReactElement => { const error = searchToggles.filter((toggle) => toggle.value).length === 0; return ( -
+
{error && ( { {error && ( - + {t('searchBox.checkboxes.types_error')} )} diff --git a/packages/datagateway-search/src/search/datePicker.component.test.tsx b/packages/datagateway-search/src/search/datePicker.component.test.tsx index 7bb505121..b092f83ba 100644 --- a/packages/datagateway-search/src/search/datePicker.component.test.tsx +++ b/packages/datagateway-search/src/search/datePicker.component.test.tsx @@ -1,315 +1,357 @@ import React from 'react'; import { StateType } from '../state/app.types'; import { Provider } from 'react-redux'; -import { createMount } from '@material-ui/core/test-utils'; import configureStore from 'redux-mock-store'; import SelectDates from './datePicker.component'; import thunk from 'redux-thunk'; import { Router } from 'react-router-dom'; import { initialState } from '../state/reducers/dgsearch.reducer'; import { createMemoryHistory, History } from 'history'; +import { + applyDatePickerWorkaround, + cleanupDatePickerWorkaround, +} from '../setupTests'; +import { render, type RenderResult, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { UserEvent } from '@testing-library/user-event/setup/setup'; jest.mock('loglevel'); describe('DatePicker component tests', () => { - let mount; let state: StateType; - let mockStore; - let testStore; + const mockStore = configureStore([thunk]); + let testStore: ReturnType; let history: History; - let pushSpy; + let pushSpy: jest.SpyInstance; const testInitiateSearch = jest.fn(); - const createWrapper = (h: History = history): ReactWrapper => { - return mount( + const renderComponent = (h: History = history): RenderResult => + render( ); - }; beforeEach(() => { - mount = createMount(); + applyDatePickerWorkaround(); + history = createMemoryHistory(); pushSpy = jest.spyOn(history, 'push'); state = JSON.parse(JSON.stringify({ dgsearch: initialState })); state.dgsearch = { + ...state.dgsearch, tabs: { datasetTab: true, datafileTab: true, investigationTab: true, }, - requestReceived: false, - searchData: { - dataset: [], - datafile: [], - investigation: [], - }, settingsLoaded: true, sideLayout: false, }; - mockStore = configureStore([thunk]); testStore = mockStore(state); }); afterEach(() => { - testInitiateSearch.mockClear(); + jest.clearAllMocks(); + cleanupDatePickerWorkaround(); }); - it('renders correctly', () => { + it('renders correctly', async () => { history.replace( '/?searchText=&investigation=false&startDate=2021-10-26&endDate=2021-10-28' ); - const wrapper = createWrapper(); - const startDateInput = wrapper.find( - '[aria-label="searchBox.start_date_arialabel"]' - ); - expect(startDateInput.exists()); - expect(startDateInput.instance().value).toEqual('2021-10-26'); + renderComponent(); + const startDateInput = await screen.findByRole('textbox', { + name: 'searchBox.start_date_arialabel', + }); + expect(startDateInput).toBeInTheDocument(); + expect(startDateInput).toHaveValue('2021-10-26'); - const endDateInput = wrapper.find( - '[aria-label="searchBox.end_date_arialabel"]' - ); - expect(endDateInput.exists()); - expect(endDateInput.instance().value).toEqual('2021-10-28'); + const endDateInput = await screen.findByRole('textbox', { + name: 'searchBox.end_date_arialabel', + }); + expect(endDateInput).toBeInTheDocument(); + expect(endDateInput).toHaveValue('2021-10-28'); }); describe('Start date box', () => { - it('pushes URL with new start date value when user types number into Start Date input', () => { + let user: UserEvent; + + beforeEach(() => { + user = userEvent.setup(); + }); + + it('pushes URL with new start date value when user types number into Start Date input', async () => { history.replace('/?searchText=&investigation=false'); - const wrapper = createWrapper(); - const startDateInput = wrapper.find( - '[aria-label="searchBox.start_date_arialabel"]' - ); - startDateInput.instance().value = '2012 01 01'; - startDateInput.simulate('change'); + renderComponent(); + const startDateInput = await screen.findByRole('textbox', { + name: 'searchBox.start_date_arialabel', + }); + + await user.type(startDateInput, '2012-01-01'); expect(pushSpy).toHaveBeenCalledWith('?startDate=2012-01-01'); }); - it('initiates search with valid start and end dates', () => { + it('initiates search with valid start and end dates', async () => { history.replace( '/?searchText=&investigation=false&startDate=2012-01-01&endDate=2013-01-01' ); - const wrapper = createWrapper(); - const startDateInput = wrapper.find( - '[aria-label="searchBox.start_date_arialabel"]' - ); - startDateInput.simulate('keydown', { key: 'Enter' }); + renderComponent(); + const startDateInput = await screen.findByRole('textbox', { + name: 'searchBox.start_date_arialabel', + }); + + await user.type(startDateInput, '{enter}'); + expect(testInitiateSearch).toHaveBeenCalled(); }); - it('initiates search with valid start date and empty end date', () => { + it('initiates search with valid start date and empty end date', async () => { history.replace('/?searchText=&investigation=false&startDate=2012-01-01'); - const wrapper = createWrapper(); - const startDateInput = wrapper.find( - '[aria-label="searchBox.start_date_arialabel"]' - ); - startDateInput.simulate('keydown', { key: 'Enter' }); + renderComponent(); + const startDateInput = await screen.findByRole('textbox', { + name: 'searchBox.start_date_arialabel', + }); + + await user.type(startDateInput, '{enter}'); + expect(testInitiateSearch).toHaveBeenCalled(); }); - it('initiates search with valid end date and empty start date', () => { + it('initiates search with valid end date and empty start date', async () => { history.replace('/?searchText=&investigation=false&endDate=2012-01-01'); - const wrapper = createWrapper(); - const startDateInput = wrapper.find( - '[aria-label="searchBox.start_date_arialabel"]' - ); - startDateInput.simulate('keydown', { key: 'Enter' }); + renderComponent(); + const startDateInput = await screen.findByRole('textbox', { + name: 'searchBox.start_date_arialabel', + }); + + await user.type(startDateInput, '{enter}'); + expect(testInitiateSearch).toHaveBeenCalled(); }); - it('initiates search with empty start and end dates', () => { + it('initiates search with empty start and end dates', async () => { history.replace('/?searchText=&investigation=false'); - const wrapper = createWrapper(); + renderComponent(); + const startDateInput = await screen.findByRole('textbox', { + name: 'searchBox.start_date_arialabel', + }); + + await user.type(startDateInput, '{enter}'); - const startDateInput = wrapper.find( - '[aria-label="searchBox.start_date_arialabel"]' - ); - startDateInput.simulate('keydown', { key: 'Enter' }); expect(testInitiateSearch).toHaveBeenCalled(); }); - it('displays error message when an invalid date is entered', () => { + // In v6, date pickers don't allow invalid dates to be entered + it('displays error message when an invalid date is entered', async () => { history.replace('/?searchText=&investigation=false'); - const wrapper = createWrapper(); - const startDateInput = wrapper.find( - '[aria-label="searchBox.start_date_arialabel"]' - ); - startDateInput.instance().value = '2012 01 35'; - startDateInput.simulate('change'); + renderComponent(); + const startDateInput = await screen.findByRole('textbox', { + name: 'searchBox.start_date_arialabel', + }); - expect(wrapper.find('.MuiFormHelperText-filled').first().text()).toEqual( - 'searchBox.invalid_date_message' - ); + await user.type(startDateInput, '2012-01-00'); + + expect( + await screen.findByText('searchBox.invalid_date_message') + ).toBeInTheDocument(); }); - it('displays error message when a date after the maximum date is entered', () => { + it('displays error message when a date after the maximum date is entered', async () => { history.replace('/?searchText=&investigation=false'); - const wrapper = createWrapper(); - const startDateInput = wrapper.find( - '[aria-label="searchBox.start_date_arialabel"]' - ); - startDateInput.instance().value = '3000 01 01'; - startDateInput.simulate('change'); + renderComponent(); + const startDateInput = await screen.findByRole('textbox', { + name: 'searchBox.start_date_arialabel', + }); - expect(wrapper.find('.MuiFormHelperText-filled').first().text()).toEqual( - 'searchBox.invalid_date_range_message' - ); + await user.type(startDateInput, '3000-01-01'); + + expect( + await screen.findByText('searchBox.invalid_date_message') + ).toBeInTheDocument(); }); - it('displays error message when a date after the end date is entered', () => { + it('displays error message when a date after the end date is entered', async () => { history.replace('/?searchText=&investigation=false&endDate=2011-11-21'); - const wrapper = createWrapper(); - const startDateInput = wrapper.find( - '[aria-label="searchBox.start_date_arialabel"]' - ); - startDateInput.instance().value = '2012 01 01'; - startDateInput.simulate('change'); + renderComponent(); + const startDateInput = await screen.findByRole('textbox', { + name: 'searchBox.start_date_arialabel', + }); - expect(wrapper.find('.MuiFormHelperText-filled').first().text()).toEqual( + await user.type(startDateInput, '2012-01-01'); + + const errorMessages = await screen.findAllByText( 'searchBox.invalid_date_range_message' ); + expect(errorMessages).toHaveLength(2); + + for (const msg of errorMessages) { + expect(msg).toBeInTheDocument(); + } }); - it('invalid date in URL is ignored', () => { + it('invalid date in URL is ignored', async () => { history.replace('/?searchText=&investigation=false&startDate=2011-14-21'); - const wrapper = createWrapper(); - const startDateInput = wrapper.find( - '[aria-label="searchBox.start_date_arialabel"]' - ); - expect(startDateInput.instance().value).toEqual(''); + renderComponent(); + const startDateInput = await screen.findByRole('textbox', { + name: 'searchBox.start_date_arialabel', + }); + + expect(startDateInput).toHaveValue(''); }); }); describe('End date box', () => { - it('pushes URL with new end date value when user types number into Start Date input', () => { + let user: UserEvent; + + beforeEach(() => { + user = userEvent.setup(); + }); + + it('pushes URL with new end date value when user types number into Start Date input', async () => { history.replace('/?searchText=&investigation=false'); - const wrapper = createWrapper(); - const endDateInput = wrapper.find( - '[aria-label="searchBox.end_date_arialabel"]' - ); - endDateInput.instance().value = '2000 01 01'; - endDateInput.simulate('change'); + renderComponent(); + const endDateInput = await screen.findByRole('textbox', { + name: 'searchBox.end_date_arialabel', + }); + + await user.type(endDateInput, '2000 01 01'); + expect(pushSpy).toHaveBeenCalledWith('?endDate=2000-01-01'); }); - it('initiates search with valid start and end dates', () => { + it('initiates search with valid start and end dates', async () => { history.replace( '/?searchText=&investigation=false&startDate=2012-01-01&endDate=2013-01-01' ); - const wrapper = createWrapper(); - const endDateInput = wrapper.find( - '[aria-label="searchBox.end_date_arialabel"]' - ); - endDateInput.simulate('keydown', { key: 'Enter' }); + renderComponent(); + const endDateInput = await screen.findByRole('textbox', { + name: 'searchBox.end_date_arialabel', + }); + + await user.type(endDateInput, '{enter}'); + expect(testInitiateSearch).toHaveBeenCalled(); }); - it('initiates search with valid start date and empty end date', () => { + it('initiates search with valid start date and empty end date', async () => { history.replace('/?searchText=&investigation=false&startDate=2012-01-01'); - const wrapper = createWrapper(); - const endDateInput = wrapper.find( - '[aria-label="searchBox.end_date_arialabel"]' - ); - endDateInput.simulate('keydown', { key: 'Enter' }); + renderComponent(); + const endDateInput = await screen.findByRole('textbox', { + name: 'searchBox.end_date_arialabel', + }); + + await user.type(endDateInput, '{enter}'); + expect(testInitiateSearch).toHaveBeenCalled(); }); - it('initiates search with valid end date and empty start date', () => { + it('initiates search with valid end date and empty start date', async () => { history.replace('/?searchText=&investigation=false&endDate=2012-01-01'); - const wrapper = createWrapper(); - const endDateInput = wrapper.find( - '[aria-label="searchBox.end_date_arialabel"]' - ); - endDateInput.simulate('keydown', { key: 'Enter' }); + renderComponent(); + const endDateInput = await screen.findByRole('textbox', { + name: 'searchBox.end_date_arialabel', + }); + + await user.type(endDateInput, '{enter}'); + expect(testInitiateSearch).toHaveBeenCalled(); }); - it('initiates search with empty start and end dates', () => { + it('initiates search with empty start and end dates', async () => { history.replace('/?searchText=&investigation=false'); - const wrapper = createWrapper(); - const endDateInput = wrapper.find( - '[aria-label="searchBox.end_date_arialabel"]' - ); - endDateInput.simulate('keydown', { key: 'Enter' }); + renderComponent(); + const endDateInput = await screen.findByRole('textbox', { + name: 'searchBox.end_date_arialabel', + }); + + await user.type(endDateInput, '{enter}'); + expect(testInitiateSearch).toHaveBeenCalled(); }); - it('displays error message when an invalid date is entered', () => { + // In v6, date pickers don't allow invalid dates to be entered + it('displays error message when an invalid date is entered', async () => { history.replace('/?searchText=&investigation=false'); - const wrapper = createWrapper(); - const endDateInput = wrapper.find( - '[aria-label="searchBox.end_date_arialabel"]' - ); - endDateInput.instance().value = '2012 01 35'; - endDateInput.simulate('change'); + renderComponent(); + const endDateInput = await screen.findByRole('textbox', { + name: 'searchBox.end_date_arialabel', + }); - expect(wrapper.find('.MuiFormHelperText-filled').text()).toEqual( - 'searchBox.invalid_date_message' - ); + await user.type(endDateInput, '2012-01-00'); + + expect( + await screen.findByText('searchBox.invalid_date_message') + ).toBeInTheDocument(); }); - it('displays error message when a date before the minimum date is entered', () => { + it('displays error message when a date before the minimum date is entered', async () => { history.replace('/?searchText=&investigation=false'); - const wrapper = createWrapper(); - const endDateInput = wrapper.find( - '[aria-label="searchBox.end_date_arialabel"]' - ); - endDateInput.instance().value = '1203 01 01'; - endDateInput.simulate('change'); + renderComponent(); + const endDateInput = await screen.findByRole('textbox', { + name: 'searchBox.end_date_arialabel', + }); - expect(wrapper.find('.MuiFormHelperText-filled').last().text()).toEqual( - 'searchBox.invalid_date_range_message' - ); + await user.type(endDateInput, '1203-01-01'); + + expect( + await screen.findByText('searchBox.invalid_date_message') + ).toBeInTheDocument(); }); - it('displays error message when a date before the start date is entered', () => { + it('displays error message when a date before the start date is entered', async () => { history.replace('/?searchText=&investigation=false&startDate=2011-11-21'); - const wrapper = createWrapper(); - const endDateInput = wrapper.find( - '[aria-label="searchBox.end_date_arialabel"]' - ); - endDateInput.instance().value = '2010 01 01'; - endDateInput.simulate('change'); + renderComponent(); + const endDateInput = await screen.findByRole('textbox', { + name: 'searchBox.end_date_arialabel', + }); - expect(wrapper.find('.MuiFormHelperText-filled').last().text()).toEqual( + await user.type(endDateInput, '2010-01-01'); + + const errorMessages = await screen.findAllByText( 'searchBox.invalid_date_range_message' ); + expect(errorMessages).toHaveLength(2); + + for (const msg of errorMessages) { + expect(msg).toBeInTheDocument(); + } }); - it('invalid date in URL is ignored', () => { + it('invalid date in URL is ignored', async () => { history.replace('/?searchText=&investigation=false&endDate=2011-14-21'); - const wrapper = createWrapper(); - const endDateInput = wrapper.find( - '[aria-label="searchBox.end_date_arialabel"]' - ); - expect(endDateInput.instance().value).toEqual(''); + renderComponent(); + const endDateInput = await screen.findByRole('textbox', { + name: 'searchBox.end_date_arialabel', + }); + + expect(endDateInput).toHaveValue(''); }); }); }); diff --git a/packages/datagateway-search/src/search/datePicker.component.tsx b/packages/datagateway-search/src/search/datePicker.component.tsx index a42a86395..b1350b34a 100644 --- a/packages/datagateway-search/src/search/datePicker.component.tsx +++ b/packages/datagateway-search/src/search/datePicker.component.tsx @@ -1,15 +1,4 @@ import React, { useState } from 'react'; -import DateFnsUtils from '@date-io/date-fns'; -import { - KeyboardDatePicker, - MuiPickersUtilsProvider, -} from '@material-ui/pickers'; -import { - Theme, - createStyles, - makeStyles, - useTheme, -} from '@material-ui/core/styles'; import { connect } from 'react-redux'; import { StateType } from '../state/app.types'; import { useTranslation } from 'react-i18next'; @@ -18,9 +7,11 @@ import { usePushSearchEndDate, usePushSearchStartDate, } from 'datagateway-common'; -import { useLocation } from 'react-router'; -import { MaterialUiPickersDate } from '@material-ui/pickers/typings/date'; -import { isValid } from 'date-fns'; +import { useLocation } from 'react-router-dom'; +import { isBefore, isValid } from 'date-fns'; +import { TextField, TextFieldProps } from '@mui/material'; +import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; +import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers'; interface DatePickerProps { initiateSearch: () => void; @@ -32,17 +23,40 @@ interface DatePickerStoreProps { type DatePickerCombinedProps = DatePickerProps & DatePickerStoreProps; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - root: { - padding: theme.spacing(1, 0), - }, - }) -); +const CustomTextField: React.FC = (props) => { + const { invalidDateRange, t, sideLayout, ...inputProps } = + props.inputProps ?? {}; + const error = + // eslint-disable-next-line react/prop-types + (props.error || invalidDateRange) ?? undefined; + let helperText = t('searchBox.invalid_date_message'); + if (invalidDateRange) helperText = t('searchBox.invalid_date_range_message'); + return ( + + ); +}; export function SelectDates(props: DatePickerCombinedProps): JSX.Element { const { sideLayout, initiateSearch } = props; - const classes = useStyles(); const [t] = useTranslation(); @@ -84,7 +98,7 @@ export function SelectDates(props: DatePickerCombinedProps): JSX.Element { }; const handleChange = ( - date: MaterialUiPickersDate, + date: Date | null, dateName: 'startDate' | 'endDate' ): void => { //Only push date when valid (and not every keypress when typing) @@ -105,96 +119,69 @@ export function SelectDates(props: DatePickerCombinedProps): JSX.Element { } }; - //Obtain a contrast friendly button colour - const theme = useTheme(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const buttonColour = (theme as any).colours?.blue; + const invalidDateRange = startDate && endDate && isBefore(endDate, startDate); return (
- + <> - { - handleChange(date, 'startDate'); + handleChange(date as Date, 'startDate'); }} - onKeyDown={handleKeyDown} - animateYearScrolling - placeholder={t('searchBox.start_date')} - inputProps={{ 'aria-label': t('searchBox.start_date_arialabel') }} - KeyboardButtonProps={{ - 'aria-label': t('searchBox.start_date_button_arialabel'), + slots={{ + textField: CustomTextField, + }} + slotProps={{ + actionBar: { + actions: ['clear'], + }, + textField: { + inputProps: { + invalidDateRange, + sideLayout, + t: t, + placeholder: t('searchBox.start_date'), + 'aria-label': t('searchBox.start_date_arialabel'), + }, + onKeyDown: handleKeyDown, + }, }} - color="secondary" - style={sideLayout ? {} : { paddingRight: 6, width: '178px' }} - okLabel={ - - {t('searchBox.date_picker.ok')} - - } - cancelLabel={ - - {t('searchBox.date_picker.cancel')} - - } - clearLabel={ - - {t('searchBox.date_picker.clear')} - - } /> {sideLayout ?

: null} - { - handleChange(date, 'endDate'); + handleChange(date as Date, 'endDate'); + }} + slots={{ + textField: CustomTextField, }} - onKeyDown={handleKeyDown} - animateYearScrolling - placeholder={t('searchBox.end_date')} - inputProps={{ 'aria-label': t('searchBox.end_date_arialabel') }} - KeyboardButtonProps={{ - 'aria-label': t('searchBox.end_date_button_arialabel'), + slotProps={{ + actionBar: { + actions: ['clear'], + }, + textField: { + inputProps: { + invalidDateRange, + sideLayout, + t: t, + placeholder: t('searchBox.end_date'), + 'aria-label': t('searchBox.end_date_arialabel'), + }, + onKeyDown: handleKeyDown, + }, }} - color="secondary" - style={sideLayout ? {} : { width: '178px' }} - okLabel={ - - {t('searchBox.date_picker.ok')} - - } - cancelLabel={ - - {t('searchBox.date_picker.cancel')} - - } - clearLabel={ - - {t('searchBox.date_picker.clear')} - - } /> -
+
); } diff --git a/packages/datagateway-search/src/search/myDataCheckBox.component.tsx b/packages/datagateway-search/src/search/myDataCheckBox.component.tsx new file mode 100644 index 000000000..5bcd5f484 --- /dev/null +++ b/packages/datagateway-search/src/search/myDataCheckBox.component.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { Checkbox, FormControlLabel } from '@mui/material'; +import { ArrowTooltip } from 'datagateway-common'; + +interface MyDataCheckBoxProps { + checked: boolean; + onChange: (checked: boolean) => void; +} + +const MyDataCheckBox = ({ + checked, + onChange, +}: MyDataCheckBoxProps): React.ReactElement => { + const [t] = useTranslation(); + + const handleChange = (event: React.ChangeEvent): void => { + const restrict = event.target.checked; + onChange(restrict); + }; + + return ( + +
+ } + label={t('check_boxes.my_data')} + /> +
+
+ ); +}; + +export default MyDataCheckBox; diff --git a/packages/datagateway-search/src/search/myDataCheckbox.component.test.tsx b/packages/datagateway-search/src/search/myDataCheckbox.component.test.tsx new file mode 100644 index 000000000..915e2bc3c --- /dev/null +++ b/packages/datagateway-search/src/search/myDataCheckbox.component.test.tsx @@ -0,0 +1,57 @@ +import * as React from 'react'; +import MyDataCheckBox from './myDataCheckBox.component'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +describe('myDataCheckbox', () => { + it('renders correctly', async () => { + const user = userEvent.setup(); + + const { rerender } = render( + + ); + + const checkbox = screen.getByRole('checkbox', { + name: 'check_boxes.my_data', + }); + + expect(checkbox).toBeChecked(); + + // check if tooltip is working + await user.hover(checkbox); + expect( + await screen.findByText('searchBox.my_data_tooltip') + ).toBeInTheDocument(); + + rerender(); + + expect( + screen.getByRole('checkbox', { + name: 'check_boxes.my_data', + }) + ).not.toBeChecked(); + }); + + it('calls onChange callback when checkbox is toggled', async () => { + const user = userEvent.setup(); + const mockOnChange = jest.fn(); + + const { rerender } = render( + + ); + + await user.click( + screen.getByRole('checkbox', { name: 'check_boxes.my_data' }) + ); + + expect(mockOnChange).toHaveBeenLastCalledWith(false); + + rerender(); + + await user.click( + screen.getByRole('checkbox', { name: 'check_boxes.my_data' }) + ); + + expect(mockOnChange).toHaveBeenLastCalledWith(true); + }); +}); diff --git a/packages/datagateway-search/src/search/searchButton.component.test.tsx b/packages/datagateway-search/src/search/searchButton.component.test.tsx index b3a6c6de4..54d287733 100644 --- a/packages/datagateway-search/src/search/searchButton.component.test.tsx +++ b/packages/datagateway-search/src/search/searchButton.component.test.tsx @@ -1,37 +1,31 @@ import React from 'react'; -import { createShallow, createMount } from '@material-ui/core/test-utils'; +import { fireEvent, render } from '@testing-library/react'; import SearchButton from './searchButton.component'; -import Button from '@material-ui/core/Button'; jest.mock('loglevel'); describe('Search Button component tests', () => { - let shallow; - let mount; - const testInitiateSearch = jest.fn(); - beforeEach(() => { - shallow = createShallow({ untilSelector: 'div' }); - mount = createMount(); - }); - afterEach(() => { - testInitiateSearch.mockClear(); + jest.clearAllMocks(); }); it('renders correctly', () => { - const wrapper = shallow( -
- -
+ const wrapper = render( + ); - expect(wrapper).toMatchSnapshot(); + expect(wrapper.asFragment()).toMatchSnapshot(); }); - it('initiates search when user clicks button', () => { - const wrapper = mount(); - wrapper.find(Button).simulate('click'); + it('initiates search when user clicks button', async () => { + const wrapper = render( + + ); + const button = await wrapper.findByLabelText( + 'searchBox.search_button_arialabel' + ); + fireEvent.click(button); expect(testInitiateSearch).toHaveBeenCalled(); }); }); diff --git a/packages/datagateway-search/src/search/searchButton.component.tsx b/packages/datagateway-search/src/search/searchButton.component.tsx index 73e0c354b..783e66da1 100644 --- a/packages/datagateway-search/src/search/searchButton.component.tsx +++ b/packages/datagateway-search/src/search/searchButton.component.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import Button from '@material-ui/core/Button'; +import Button from '@mui/material/Button'; import { withTranslation, WithTranslation, @@ -26,6 +26,7 @@ const SearchButton = (props: SearchButtonCombinedProps): React.ReactElement => { aria-label={t('searchBox.search_button_arialabel')} size="large" fullWidth={true} + type="submit" > {t('searchBox.search_button')} diff --git a/packages/datagateway-search/src/search/searchTextBox.component.test.tsx b/packages/datagateway-search/src/search/searchTextBox.component.test.tsx index 577bccf6d..fb00577fb 100644 --- a/packages/datagateway-search/src/search/searchTextBox.component.test.tsx +++ b/packages/datagateway-search/src/search/searchTextBox.component.test.tsx @@ -1,33 +1,30 @@ import React from 'react'; import { StateType } from '../state/app.types'; import { Provider } from 'react-redux'; -import { createShallow, createMount } from '@material-ui/core/test-utils'; import configureStore from 'redux-mock-store'; import SearchTextBox from './searchTextBox.component'; import thunk from 'redux-thunk'; import { initialState } from '../state/reducers/dgsearch.reducer'; import { createMemoryHistory, History } from 'history'; import { Router } from 'react-router-dom'; +import { fireEvent, render, RenderResult } from '@testing-library/react'; jest.mock('loglevel'); describe('Search text box component tests', () => { - let shallow; - let mount; let state: StateType; - let mockStore; - let testStore; + const mockStore = configureStore([thunk]); + let testStore: ReturnType; let history: History; const testInitiateSearch = jest.fn(); const handleChange = jest.fn(); - const createWrapper = (h: History = history): ReactWrapper => { - return mount( + const createWrapper = (h: History = history): RenderResult => { + return render( { }; beforeEach(() => { - shallow = createShallow({ untilSelector: 'div' }); - mount = createMount(); history = createMemoryHistory(); state = JSON.parse(JSON.stringify({ dgsearch: initialState })); state.dgsearch = { + ...state.dgsearch, tabs: { datasetTab: true, datafileTab: true, investigationTab: true, }, - requestReceived: false, - searchData: { - dataset: [], - datafile: [], - investigation: [], - }, settingsLoaded: true, }; - mockStore = configureStore([thunk]); testStore = mockStore(state); }); afterEach(() => { - testInitiateSearch.mockClear(); + jest.clearAllMocks(); }); it('renders correctly', () => { - const wrapper = shallow( - - ); - expect(wrapper).toMatchSnapshot(); + const wrapper = createWrapper(); + expect(wrapper.asFragment()).toMatchSnapshot(); }); - it('initiates search when user presses enter key', () => { + it('initiates search when user presses enter key', async () => { const wrapper = createWrapper(); - wrapper - .find('[aria-label="searchBox.search_text_arialabel"] input') - .simulate('change', { target: { value: 'test' } }); - wrapper - .find('[aria-label="searchBox.search_text_arialabel"] input') - .simulate('keydown', { key: 'Enter' }); + const input = await wrapper.findByLabelText( + 'searchBox.search_text_arialabel' + ); + fireEvent.change(input, { target: { value: 'test' } }); + expect(handleChange).toHaveBeenCalled(); + expect(testInitiateSearch).not.toHaveBeenCalled(); + fireEvent.keyDown(input, { key: 'Enter' }); expect(testInitiateSearch).toHaveBeenCalled(); }); }); diff --git a/packages/datagateway-search/src/search/searchTextBox.component.tsx b/packages/datagateway-search/src/search/searchTextBox.component.tsx index dda224d58..051a69d5d 100644 --- a/packages/datagateway-search/src/search/searchTextBox.component.tsx +++ b/packages/datagateway-search/src/search/searchTextBox.component.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import TextField from '@material-ui/core/TextField'; +import TextField from '@mui/material/TextField'; import { useTranslation } from 'react-i18next'; interface SearchTextProps { @@ -25,6 +25,7 @@ const SearchTextBox = (props: SearchTextProps): React.ReactElement => { { fullWidth variant="outlined" color="secondary" - InputProps={{ + inputProps={{ 'aria-label': t('searchBox.search_text_arialabel'), }} /> diff --git a/packages/datagateway-search/src/search/sortSelect.component.test.tsx b/packages/datagateway-search/src/search/sortSelect.component.test.tsx new file mode 100644 index 000000000..bf4fc0255 --- /dev/null +++ b/packages/datagateway-search/src/search/sortSelect.component.test.tsx @@ -0,0 +1,93 @@ +import * as React from 'react'; +import { render, screen } from '@testing-library/react'; +import SortSelectComponent from './sortSelect.component'; +import { MemoryRouter, Router } from 'react-router-dom'; +import userEvent from '@testing-library/user-event'; +import { createMemoryHistory } from 'history'; + +describe('sortSelect', () => { + it('renders correctly', async () => { + const user = userEvent.setup(); + + render( + + + + ); + + // open the dropdown menu + await user.click(screen.getByRole('button', { name: /sort.label/ })); + + expect( + await screen.findByRole('option', { name: 'sort.date_desc' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('option', { name: 'sort.date_asc' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('option', { name: 'sort.name_asc' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('option', { name: 'sort.size_asc' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('option', { name: 'sort.size_desc' }) + ).toBeInTheDocument(); + }); + + it('updates URL correctly accordingly to selected sort', async () => { + const user = userEvent.setup(); + const history = createMemoryHistory(); + + render( + + + + ); + + // open the dropdown menu + await user.click(screen.getByRole('button', { name: /sort.label/ })); + await user.selectOptions(screen.getByRole('listbox'), [ + screen.getByRole('option', { name: 'sort.date_desc' }), + ]); + + expect(history.location.search).toBe( + `?${new URLSearchParams({ + sort: JSON.stringify({ date: 'desc' }), + }).toString()}` + ); + + // open the dropdown menu + await user.click(screen.getByRole('button', { name: /sort.label/ })); + await user.selectOptions(screen.getByRole('listbox'), [ + screen.getByRole('option', { name: 'sort.name_asc' }), + ]); + + expect(history.location.search).toBe( + `?${new URLSearchParams({ + sort: JSON.stringify({ name: 'asc' }), + }).toString()}` + ); + }); + + it('shows selected sort correctly on first render', () => { + const initialQuery = new URLSearchParams({ + sort: JSON.stringify({ fileSize: 'asc' }), + }); + + const history = createMemoryHistory(); + history.replace({ + search: `?${initialQuery.toString()}`, + }); + + render( + + + + ); + + expect( + screen.getByRole('button', { name: 'sort.label sort.size_asc' }) + ).toBeInTheDocument(); + }); +}); diff --git a/packages/datagateway-search/src/search/sortSelect.component.tsx b/packages/datagateway-search/src/search/sortSelect.component.tsx new file mode 100644 index 000000000..d5fa34530 --- /dev/null +++ b/packages/datagateway-search/src/search/sortSelect.component.tsx @@ -0,0 +1,87 @@ +import React from 'react'; +import type { SelectChangeEvent } from '@mui/material'; +import { InputLabel, MenuItem, Select, FormControl } from '@mui/material'; +import { useTranslation } from 'react-i18next'; +import { Order, parseSearchToQuery, useSingleSort } from 'datagateway-common'; +import { useLocation } from 'react-router-dom'; + +const ITEM_HEIGHT = 48; +const ITEM_PADDING_TOP = 8; +const MenuProps = { + PaperProps: { + style: { + maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, + width: 250, + }, + }, +}; + +const SortSelectComponent = (): React.ReactElement => { + const [t] = useTranslation(); + + const location = useLocation(); + const parsedSort = React.useMemo(() => { + const { sort } = parseSearchToQuery(location.search); + const keys = Object.keys(sort); + return keys.length === 0 ? '_score' : keys[0] + ' ' + sort[keys[0]]; + }, [location.search]); + const pushSort = useSingleSort(); + + const handleChange = (event: SelectChangeEvent): void => { + const sort = event.target.value.split(' '); + if (sort[0] === '_score') { + pushSort(sort[0], null, 'replace'); + } else { + pushSort(sort[0], sort[1] as Order, 'replace'); + } + }; + + return ( +
+ + + {t('sort.label')} + + + +
+ ); +}; + +export default SortSelectComponent; diff --git a/packages/datagateway-search/src/searchBoxContainer.component.test.tsx b/packages/datagateway-search/src/searchBoxContainer.component.test.tsx index 134c67dbf..01f646204 100644 --- a/packages/datagateway-search/src/searchBoxContainer.component.test.tsx +++ b/packages/datagateway-search/src/searchBoxContainer.component.test.tsx @@ -1,11 +1,15 @@ -import React from 'react'; -import { ReactWrapper } from 'enzyme'; +import * as React from 'react'; +import { Provider } from 'react-redux'; +import type { RenderResult } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import configureStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { MemoryRouter } from 'react-router-dom'; +import type { DeepPartial } from 'redux'; +import type { StateType } from './state/app.types'; -import { createShallow } from '@material-ui/core/test-utils'; import SearchBoxContainer from './searchBoxContainer.component'; import SearchBoxContainerSide from './searchBoxContainerSide.component'; -import { useSelector } from 'react-redux'; -import { initialState } from './state/reducers/dgsearch.reducer'; jest.mock('loglevel'); @@ -15,46 +19,163 @@ jest.mock('react-redux', () => ({ })); describe('SearchBoxContainer - Tests', () => { - let shallow; - - const testInitiateSearch = jest.fn(); + function renderComponent( + props?: Partial> + ): RenderResult { + return render( + + + + + + ); + } - const createWrapper = (path: string): ReactWrapper => { - return shallow(); - }; + let state: DeepPartial; beforeEach(() => { - shallow = createShallow({ untilSelector: 'Grid' }); - useSelector.mockImplementation(() => { - return initialState; - }); + state = { + dgsearch: { + sideLayout: false, + searchableEntities: ['investigation', 'dataset'], + }, + }; + }); + + it('renders searchBoxContainer correctly', async () => { + renderComponent(); + + // search text box should be visible + expect( + screen.getByRole('searchbox', { name: 'searchBox.search_text_arialabel' }) + ).toBeInTheDocument(); + + // search toggle dropdown should be visible + expect( + screen.getByRole('button', { name: 'searchBox.checkboxes.types (2)' }) + ).toBeInTheDocument(); + + // date select should be visible + expect( + screen.getByRole('textbox', { name: 'searchBox.start_date_arialabel' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('textbox', { name: 'searchBox.end_date_arialabel' }) + ).toBeInTheDocument(); + + // sort select should be visible + // default value is sort by score + expect( + screen.getByRole('button', { name: 'sort.label sort._score' }) + ).toBeInTheDocument(); + + // logged in anonymously so my data checkbox should be hidden + expect( + screen.queryByRole('checkbox', { name: 'check_boxes.my_data' }) + ).toBeNull(); + + // search button should be visible + expect( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ).toBeInTheDocument(); + + // link to example instrument calibration should be visible + expect( + screen.getByRole('link', { name: '"instrument calibration"' }) + ).toHaveAttribute('href', '/?searchText=%22instrument+calibration%22'); + + // link to example neutron and scattering should be visible + expect( + screen.getByRole('link', { name: 'neutron AND scattering' }) + ).toHaveAttribute('href', '/?searchText=neutron+AND+scattering'); }); - it('renders searchBoxContainer correctly', () => { - const wrapper = createWrapper('/'); + it('shows my data checkbox if user is logged in', () => { + renderComponent({ loggedInAnonymously: false }); - expect(wrapper).toMatchSnapshot(); + expect( + screen.getByRole('checkbox', { name: 'check_boxes.my_data' }) + ).toBeInTheDocument(); }); }); describe('SearchBoxContainerSide - Tests', () => { - let shallow; - - const testInitiateSearch = jest.fn(); + let state: DeepPartial; - const createWrapper = (path: string): ReactWrapper => { - return shallow( - + function renderComponent( + props?: Partial> + ): RenderResult { + return render( + + + + + ); - }; + } beforeEach(() => { - shallow = createShallow({ untilSelector: 'Grid' }); + state = { + dgsearch: { + sideLayout: true, + searchableEntities: ['investigation', 'dataset'], + }, + }; }); it('renders searchBoxContainerSide correctly', () => { - const wrapper = createWrapper('/'); + renderComponent(); + + // search box should be visible + expect( + screen.getByRole('searchbox', { name: 'searchBox.search_text_arialabel' }) + ).toBeInTheDocument(); + + // search toggle dropdown should be visible + expect( + screen.getByRole('button', { name: 'searchBox.checkboxes.types (2)' }) + ).toBeInTheDocument(); + + // date select should be visible + expect( + screen.getByRole('textbox', { name: 'searchBox.start_date_arialabel' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('textbox', { name: 'searchBox.end_date_arialabel' }) + ).toBeInTheDocument(); + + // logged in anonymously so my data checkbox should be hidden + expect( + screen.queryByRole('checkbox', { name: 'check_boxes.my_data' }) + ).toBeNull(); + + // search button should be visible + expect( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ).toBeInTheDocument(); + }); + + it('shows my data checkbox if user is logged in', () => { + renderComponent({ loggedInAnonymously: false }); - expect(wrapper).toMatchSnapshot(); + expect( + screen.getByRole('checkbox', { name: 'searchBox.my_data_tooltip' }) + ).toBeInTheDocument(); }); }); diff --git a/packages/datagateway-search/src/searchBoxContainer.component.tsx b/packages/datagateway-search/src/searchBoxContainer.component.tsx index c9edbb9d7..8899c6dc3 100644 --- a/packages/datagateway-search/src/searchBoxContainer.component.tsx +++ b/packages/datagateway-search/src/searchBoxContainer.component.tsx @@ -1,118 +1,134 @@ import React from 'react'; - -import { - Grid, - Typography, - Link, - makeStyles, - createStyles, - Theme, - Box, -} from '@material-ui/core'; - +import { Box, Grid, Link, styled, Theme, Typography } from '@mui/material'; import SelectDates from './search/datePicker.component'; import CheckboxesGroup from './search/checkBoxes.component'; import SearchButton from './search/searchButton.component'; import SearchTextBox from './search/searchTextBox.component'; -import { Trans, useTranslation } from 'react-i18next'; import AdvancedHelpDialogue from './search/advancedHelpDialogue.component'; -import { useSelector } from 'react-redux'; -import { StateType } from './state/app.types'; -import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined'; +import { Trans, useTranslation } from 'react-i18next'; import { Link as RouterLink } from 'react-router-dom'; +import SortSelectComponent from './search/sortSelect.component'; +import MyDataCheckBox from './search/myDataCheckBox.component'; +import { Location } from 'history'; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - infoIcon: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - color: (theme as any).colours?.contrastGrey, - }, - containerBox: { - maxWidth: '1920px', - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(2), - paddingBottom: theme.spacing(2), - margin: 'auto', - justifyContent: 'center', - }, - leftText: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - color: (theme as any).colours?.contrastGrey, - textAlign: 'left', - fontSize: '14px', - }, - rightText: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - color: (theme as any).colours?.contrastGrey, - textAlign: 'right', - fontSize: '14px', - marginLeft: 'auto', - }, - bold: { - fontWeight: 'bold', - }, - }) -); +const ContainerBox = styled(Box)(({ theme }) => ({ + maxWidth: '1920px', + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(2), + paddingBottom: theme.spacing(2), + margin: 'auto', + justifyContent: 'center', +})); interface SearchBoxContainerProps { searchText: string; + restrict: boolean; + loggedInAnonymously: boolean; initiateSearch: () => void; onSearchTextChange: (searchText: string) => void; + onMyDataCheckboxChange: (checked: boolean) => void; } const SearchBoxContainer = ( props: SearchBoxContainerProps ): React.ReactElement => { - const { searchText, initiateSearch, onSearchTextChange } = props; - const classes = useStyles(); + const { + searchText, + restrict, + loggedInAnonymously, + initiateSearch, + onSearchTextChange, + onMyDataCheckboxChange, + } = props; const [t] = useTranslation(); - const maxNumResults = useSelector( - (state: StateType) => state.dgsearch.maxNumResults - ); + function searchTextExampleLink(exampleSearchText: string) { + return (location: Location): Location => { + const searchParams = new URLSearchParams(location.search); + searchParams.set('searchText', exampleSearchText); + return { + ...location, + search: searchParams.toString(), + }; + }; + } return ( - - - - - + +
{ + event.preventDefault(); + }} + > + + + + - - - + + + - - - + + + - - + + + + + {/* Only show the "my data" search box if the user is logged in + because "my data" means data specific to a user, + which doesn't make sense if the user is not logged in. */} + {!loggedInAnonymously && ( + + + + )} + + + + - +
- + (theme as any).colours?.contrastGrey, + textAlign: 'left', + fontSize: '14px', + }} + > For example "instrument calibration" or{' '} neutron AND scattering @@ -120,28 +136,8 @@ const SearchBoxContainer = ( {' '} - -
-
- {' '} - - {t('searchBox.limited_results_message', { - maxNumResults, - })} - -
-
-
+ ); }; diff --git a/packages/datagateway-search/src/searchBoxContainerSide.component.tsx b/packages/datagateway-search/src/searchBoxContainerSide.component.tsx index e7b240e9f..c660e5f76 100644 --- a/packages/datagateway-search/src/searchBoxContainerSide.component.tsx +++ b/packages/datagateway-search/src/searchBoxContainerSide.component.tsx @@ -1,28 +1,47 @@ import React from 'react'; -import { Grid, Box } from '@material-ui/core'; +import { Grid, Box, FormControlLabel, Checkbox } from '@mui/material'; import SelectDates from './search/datePicker.component'; import CheckboxesGroup from './search/checkBoxes.component'; import SearchButton from './search/searchButton.component'; import SearchTextBox from './search/searchTextBox.component'; +import { ArrowTooltip } from 'datagateway-common'; +import { useTranslation } from 'react-i18next'; interface SearchBoxContainerProps { searchText: string; + restrict: boolean; + loggedInAnonymously: boolean; initiateSearch: () => void; onSearchTextChange: (searchText: string) => void; + onMyDataCheckboxChange: (checked: boolean) => void; } const SearchBoxContainerSide = ( props: SearchBoxContainerProps ): React.ReactElement => { - const { searchText, initiateSearch, onSearchTextChange } = props; + const { + searchText, + restrict, + loggedInAnonymously, + initiateSearch, + onSearchTextChange, + onMyDataCheckboxChange, + } = props; + + const [t] = useTranslation(); + + function toggleRestrict(event: React.ChangeEvent): void { + onMyDataCheckboxChange(event.target.checked); + } return ( @@ -43,9 +62,35 @@ const SearchBoxContainerSide = ( - + + + + {/* Only show the "my data" search box if the user is logged in + because "my data" means data specific to a user, + which doesn't make sense if the user is not logged in. */} + {!loggedInAnonymously && ( + + + + + } + label={t('check_boxes.my_data')} + /> + + + + )} + diff --git a/packages/datagateway-search/src/searchPageCardView.component.test.tsx b/packages/datagateway-search/src/searchPageCardView.component.test.tsx deleted file mode 100644 index f8fb309e6..000000000 --- a/packages/datagateway-search/src/searchPageCardView.component.test.tsx +++ /dev/null @@ -1,188 +0,0 @@ -import React from 'react'; -import { StateType } from './state/app.types'; -import { Provider } from 'react-redux'; -import { MemoryRouter, Router } from 'react-router'; - -import SearchPageCardView, { - SearchCardViewProps, -} from './searchPageCardView.component'; - -import { mount as enzymeMount, ReactWrapper } from 'enzyme'; -import { createMount } from '@material-ui/core/test-utils'; -import configureStore from 'redux-mock-store'; -import thunk from 'redux-thunk'; -import { initialState } from './state/reducers/dgsearch.reducer'; -import { dGCommonInitialState, CartProps } from 'datagateway-common'; -import axios from 'axios'; -import { QueryClientProvider, QueryClient } from 'react-query'; -import { Store } from 'redux'; -import DatasetCardView from './card/datasetSearchCardView.component'; -import DatafileSearchTable from './table/datafileSearchTable.component'; -import { createMemoryHistory, History } from 'history'; -import InvestigationCardView from './card/investigationSearchCardView.component'; - -jest.mock('datagateway-common', () => ({ - ...jest.requireActual('datagateway-common'), - __esModule: true, - // mock card view to opt out of rendering them in these tests as there's no need - CardView: jest.fn(() => 'MockedCardView'), -})); - -describe('SearchPageCardView', () => { - let mount: typeof enzymeMount; - let state: StateType; - let history: History; - let props: SearchCardViewProps & CartProps; - - const mockStore = configureStore([thunk]); - const onTabChange = jest.fn(); - const navigateToDownload = jest.fn(); - - const createWrapper = ( - store: Store = mockStore(state), - props: SearchCardViewProps & CartProps - ): ReactWrapper => { - return mount( - - - - - - - - ); - }; - - beforeEach(() => { - mount = createMount(); - history = createMemoryHistory({ - initialEntries: ['/search/data'], - }); - state = JSON.parse( - JSON.stringify({ - dgsearch: initialState, - dgcommon: dGCommonInitialState, - }) - ); - - props = { - onTabChange: onTabChange, - currentTab: 'investigation', - cartItems: [], - navigateToDownload: navigateToDownload, - }; - - (axios.get as jest.Mock).mockImplementation((url) => { - if (url.includes('count')) { - return Promise.resolve({ data: 0 }); - } else { - return Promise.resolve({ data: [] }); - } - }); - }); - - afterEach(() => { - onTabChange.mockClear(); - navigateToDownload.mockClear(); - }); - - it('renders correctly when request received', () => { - state.dgsearch = { - ...state.dgsearch, - tabs: { - datasetTab: true, - datafileTab: true, - investigationTab: true, - }, - }; - (axios.get as jest.Mock).mockImplementation((url) => { - if (url.includes('count')) { - return Promise.resolve({ data: 1 }); - } else { - return Promise.resolve({ data: Array(1) }); - } - }); - - const createWrapper = (store: Store = mockStore(state)): ReactWrapper => { - return mount( - - - - - - - - ); - }; - const testStore = mockStore(state); - const wrapper = createWrapper(testStore); - expect(wrapper).toMatchSnapshot(); - }); - - it('changes selected tab value on click of a new tab', () => { - history.replace('/search/data?view=card&page=2&results=20&searchText='); - state.dgsearch = { - ...state.dgsearch, - tabs: { - datasetTab: true, - datafileTab: true, - investigationTab: true, - }, - }; - - const testStore = mockStore(state); - const wrapper = createWrapper(testStore, props); - - expect(wrapper.exists(InvestigationCardView)).toBeTruthy(); - - wrapper - .find('[aria-controls="simple-tabpanel-dataset"]') - .first() - .simulate('click'); - - expect(onTabChange).toHaveBeenNthCalledWith(1, 'dataset'); - }); - - it('has the investigation search card view component when on the investigation tab', () => { - const updatedProps = { - ...props, - currentTab: 'investigation', - }; - - const testStore = mockStore(state); - const wrapper = createWrapper(testStore, updatedProps); - expect(wrapper.exists(InvestigationCardView)).toBeTruthy(); - }); - - it('has the dataset search card view component when on the dataset tab', () => { - const updatedProps = { - ...props, - currentTab: 'dataset', - }; - - // Mock to prevent error logging - const spy = jest.spyOn(console, 'error').mockImplementation(); - const testStore = mockStore(state); - const wrapper = createWrapper(testStore, updatedProps); - - expect(wrapper.exists(DatasetCardView)).toBeTruthy(); - spy.mockRestore(); - }); - - it('has the datafile search table component when on the datafile tab', () => { - const updatedProps = { - ...props, - currentTab: 'datafile', - }; - - // Mock to prevent error logging - const spy = jest.spyOn(console, 'error').mockImplementation(); - const testStore = mockStore(state); - const wrapper = createWrapper(testStore, updatedProps); - - expect(wrapper.exists(DatafileSearchTable)).toBeTruthy(); - spy.mockRestore(); - }); -}); diff --git a/packages/datagateway-search/src/searchPageCardView.component.tsx b/packages/datagateway-search/src/searchPageCardView.component.tsx deleted file mode 100644 index 81079cf37..000000000 --- a/packages/datagateway-search/src/searchPageCardView.component.tsx +++ /dev/null @@ -1,435 +0,0 @@ -import React from 'react'; -import AppBar from '@material-ui/core/AppBar'; -import Tabs from '@material-ui/core/Tabs'; -import Tab from '@material-ui/core/Tab'; -import Box from '@material-ui/core/Box'; -import { - Badge, - Paper, - Theme, - createStyles, - withStyles, - LinearProgress, -} from '@material-ui/core'; - -import { StyleRules } from '@material-ui/core/styles'; -import { StateType } from './state/app.types'; -import { connect } from 'react-redux'; -import DatafileSearchTable from './table/datafileSearchTable.component'; -import { useTranslation } from 'react-i18next'; -import { - parseSearchToQuery, - useDatafileCount, - useDatasetCount, - useInvestigationCount, - useLuceneSearch, - useUpdateQueryParam, - ViewCartButton, - CartProps, -} from 'datagateway-common'; -import InvestigationCardView from './card/investigationSearchCardView.component'; -import DatasetCardView from './card/datasetSearchCardView.component'; -import { useLocation } from 'react-router-dom'; -import { useIsFetching } from 'react-query'; -import { - getFilters, - getPage, - getResults, - getSorts, - storeFilters, - storePage, - storeResults, - storeSort, -} from './searchPageContainer.component'; - -const badgeStyles = (theme: Theme): StyleRules => - createStyles({ - badge: { - backgroundColor: '#CCCCCC', - //Increase contrast on high contrast modes by using black text - color: - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (theme as any).colours?.type === 'contrast' ? '#000000' : '#333333', - fontSize: '14px', - fontWeight: 'bold', - lineHeight: 'inherit', - top: '1em', - }, - }); - -const tabStyles = (theme: Theme): StyleRules => - createStyles({ - root: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - backgroundColor: (theme as any).colours?.tabsGrey, - //Fixes contrast issue for unselected tabs in darkmode - color: - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (theme as any).palette.type === 'dark' - ? '#FFFFFF' - : // eslint-disable-next-line @typescript-eslint/no-explicit-any - (theme as any).colours?.blue, - boxShadow: 'none', - }, - indicator: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - backgroundColor: (theme as any).colours?.blue, - }, - }); - -const boxStyles = (theme: Theme): StyleRules => - createStyles({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - root: { backgroundColor: (theme as any).colours?.tabsGrey }, - }); - -export interface SearchCardViewProps { - containerHeight: string; - hierarchy: string; - onTabChange: (currentTab: string) => void; - currentTab: string; -} - -interface SearchCardViewStoreProps { - maxNumResults: number; - datasetTab: boolean; - datafileTab: boolean; - investigationTab: boolean; -} - -interface TabPanelProps { - children?: React.ReactNode; - index: string; - value: string; -} - -function TabPanel(props: TabPanelProps): React.ReactElement { - const { children, value, index, ...other } = props; - - return ( - - ); -} - -function a11yProps(index: string): React.ReactFragment { - return { - id: `simple-tab-${index}`, - 'aria-controls': `simple-tabpanel-${index}`, - }; -} - -const StyledBadge = withStyles(badgeStyles)(Badge); -const StyledTabs = withStyles(tabStyles)(Tabs); -const StyledBox = withStyles(boxStyles)(Box); - -const SearchPageCardView = ( - props: SearchCardViewProps & SearchCardViewStoreProps & CartProps -): React.ReactElement => { - const { - maxNumResults, - investigationTab, - datasetTab, - datafileTab, - containerHeight, - hierarchy, - onTabChange, - currentTab, - cartItems, - navigateToDownload, - } = props; - const [t] = useTranslation(); - - const location = useLocation(); - const queryParams = React.useMemo(() => parseSearchToQuery(location.search), [ - location.search, - ]); - const { startDate, endDate } = queryParams; - const searchText = queryParams.searchText ? queryParams.searchText : ''; - - const { data: investigation } = useLuceneSearch('Investigation', { - searchText, - startDate, - endDate, - maxCount: maxNumResults, - }); - const { data: dataset } = useLuceneSearch('Dataset', { - searchText, - startDate, - endDate, - maxCount: maxNumResults, - }); - const { data: datafile } = useLuceneSearch('Datafile', { - searchText, - startDate, - endDate, - maxCount: maxNumResults, - }); - - const isFetchingNum = useIsFetching({ - predicate: (query) => - !query.queryHash.includes('InvestigationCount') && - !query.queryHash.includes('DatasetCount') && - !query.queryHash.includes('DatafileCount'), - }); - const loading = isFetchingNum > 0; - - const { filters, sort, page, results } = React.useMemo( - () => parseSearchToQuery(location.search), - [location.search] - ); - - const replaceFilters = useUpdateQueryParam('filters', 'replace'); - const replaceSorts = useUpdateQueryParam('sort', 'replace'); - const replacePage = useUpdateQueryParam('page', 'replace'); - const replaceResults = useUpdateQueryParam('results', 'replace'); - - const handleChange = ( - event: React.ChangeEvent, - newValue: string - ): void => { - storeFilters(filters, currentTab); - storeSort(sort, currentTab); - if (page) { - storePage(page, currentTab); - } - if (results) { - storeResults(results, currentTab); - } - - onTabChange(newValue); - - replaceFilters({}); - replaceSorts({}); - replacePage(null); - replaceResults(null); - }; - - React.useEffect(() => { - const filters = getFilters(currentTab); - const sorts = getSorts(currentTab); - const page = getPage(currentTab); - const results = getResults(currentTab); - if (filters) replaceFilters(filters); - if (sorts) replaceSorts(sorts); - if (page) replacePage(page); - if (results) replaceResults(results); - }, [currentTab, replaceFilters, replacePage, replaceResults, replaceSorts]); - - const { data: investigationDataCount } = useInvestigationCount( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: investigation || [] }, - }), - }, - ], - getFilters('investigation') ?? {}, - currentTab - ); - - const { data: datasetDataCount } = useDatasetCount( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: dataset || [] }, - }), - }, - ], - getFilters('dataset') ?? {}, - currentTab - ); - - const { data: datafileDataCount } = useDatafileCount( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: datafile || [] }, - }), - }, - ], - getFilters('datafile') ?? {}, - currentTab - ); - - const badgeDigits = (length?: number): 3 | 2 | 1 => { - return length ? (length >= 100 ? 3 : length >= 10 ? 2 : 1) : 1; - }; - - return ( -
- {/* Show loading progress if data is still being loaded */} - {loading && } - - - - {investigationTab ? ( - - - {t('tabs.investigation')} - - - } - value="investigation" - {...a11yProps('investigation')} - /> - ) : ( - - )} - {datasetTab ? ( - - - {t('tabs.dataset')} - - - } - value="dataset" - {...a11yProps('dataset')} - /> - ) : ( - - )} - {datafileTab ? ( - - - {t('tabs.datafile')} - - - } - value="datafile" - {...a11yProps('datafile')} - /> - ) : ( - - )} - - - - - - - - {currentTab === 'investigation' && ( - - - - )} - - {currentTab === 'dataset' && ( - - - - )} - - {currentTab === 'datafile' && ( - - - - - - )} -
- ); -}; - -const mapStateToProps = (state: StateType): SearchCardViewStoreProps => { - return { - maxNumResults: state.dgsearch.maxNumResults, - datasetTab: state.dgsearch.tabs.datasetTab, - datafileTab: state.dgsearch.tabs.datafileTab, - investigationTab: state.dgsearch.tabs.investigationTab, - }; -}; - -export default connect(mapStateToProps)(SearchPageCardView); diff --git a/packages/datagateway-search/src/searchPageContainer.component.test.tsx b/packages/datagateway-search/src/searchPageContainer.component.test.tsx index 0a2a8bdd5..1477b869d 100644 --- a/packages/datagateway-search/src/searchPageContainer.component.test.tsx +++ b/packages/datagateway-search/src/searchPageContainer.component.test.tsx @@ -1,40 +1,27 @@ -import React from 'react'; -import { ReactWrapper } from 'enzyme'; - +import * as React from 'react'; import thunk from 'redux-thunk'; import configureStore from 'redux-mock-store'; import { StateType } from './state/app.types'; import { initialState as dgSearchInitialState } from './state/reducers/dgsearch.reducer'; import { dGCommonInitialState, - useCart, - ClearFiltersButton, + readSciGatewayToken, + type DownloadCartItem, } from 'datagateway-common'; -import { createMemoryHistory, History } from 'history'; -import { createMount } from '@material-ui/core/test-utils'; -import { MemoryRouter, Router } from 'react-router-dom'; -import SearchPageContainer from './searchPageContainer.component'; -import { LinearProgress } from '@material-ui/core'; +import { createMemoryHistory, createPath, type History } from 'history'; +import { Router } from 'react-router-dom'; +import SearchPageContainer, { + usePushCurrentTab, +} from './searchPageContainer.component'; import { Provider } from 'react-redux'; import axios from 'axios'; -import { act } from 'react-dom/test-utils'; -import { flushPromises } from './setupTests'; -import { - setInvestigationTab, - setDatasetTab, - setDatafileTab, -} from './state/actions/actions'; import { QueryClient, QueryClientProvider } from 'react-query'; -import { - getFilters, - getPage, - getResults, - getSorts, - storeFilters, - storePage, - storeResults, - storeSort, -} from './searchPageContainer.component'; +import { render, type RenderResult, screen, act } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import type { DeepPartial } from 'redux'; +import { applyMiddleware, compose, createStore } from 'redux'; +import AppReducer from './state/reducers/app.reducer'; +import { renderHook } from '@testing-library/react-hooks'; jest.mock('loglevel'); @@ -48,47 +35,155 @@ jest.mock('datagateway-common', () => { originalModule.parseSearchToQuery(queryParams) ), useCart: jest.fn(() => originalModule.useCart()), + readSciGatewayToken: jest.fn(), }; }); +function generateURLSearchParams({ + sessionId = '', + query = {}, + minCount = '10', + maxCount = '100', + restrict = 'false', +}): URLSearchParams { + const params = new URLSearchParams(); + params.append('sessionId', sessionId); + params.append('query', JSON.stringify(query)); + params.append('minCount', minCount); + params.append('maxCount', maxCount); + params.append('restrict', restrict); + return params; +} + +describe('usePushCurrentTab', () => { + let localStorageSetItemMock: jest.SpyInstance; + let localStorageGetItemMock: jest.SpyInstance; + beforeEach(() => { + localStorageSetItemMock = jest.spyOn( + window.localStorage.__proto__, + 'setItem' + ); + localStorageGetItemMock = jest.spyOn( + window.localStorage.__proto__, + 'getItem' + ); + }); + + afterEach(() => { + localStorageSetItemMock.mockRestore(); + localStorageGetItemMock.mockRestore(); + }); + + it('returns callback that when called pushes a new tab to the url query', () => { + const history = createMemoryHistory(); + + const { result } = renderHook(() => usePushCurrentTab(), { + wrapper: ({ children }) => {children}, + }); + + act(() => { + result.current('dataset'); + }); + + expect(history.location.search).toEqual('?currentTab=dataset'); + }); + + it('returns callback that when called pushes a new tab to the url query, and stores and restores any stored search query params', () => { + const history = createMemoryHistory({ + initialEntries: [ + '/search/data?currentTab=investigation&filters={"title":{"value":"test","type":"include"}}&page=2&results=30', + ], + }); + + const { result } = renderHook(() => usePushCurrentTab(), { + wrapper: ({ children }) => {children}, + }); + + localStorageGetItemMock.mockImplementation((name) => { + if (name === 'datasetResults') return '20'; + if (name === 'datasetPage') return '3'; + if (name === 'datasetFilters') + return '{"name":{"value":"test2","type":"include"}}'; + }); + + act(() => { + result.current('dataset'); + }); + + expect(localStorageSetItemMock).toBeCalledWith( + 'investigationFilters', + '{"title":{"value":"test","type":"include"}}' + ); + expect(localStorageSetItemMock).toBeCalledWith('investigationPage', '2'); + expect(localStorageSetItemMock).toBeCalledWith( + 'investigationResults', + '30' + ); + + expect(history.location.search).toEqual( + '?page=3&results=20¤tTab=dataset&filters=%7B%22name%22%3A%7B%22value%22%3A%22test2%22%2C%22type%22%3A%22include%22%7D%7D' + ); + }); +}); + describe('SearchPageContainer - Tests', () => { - let state: StateType; - let mount; + let state: DeepPartial; let queryClient: QueryClient; let history: History; - let pushSpy; - - const localStorageGetItemMock = jest.spyOn( - window.localStorage.__proto__, - 'getItem' - ); - - const createWrapper = ( - h: History = history, - client: QueryClient = queryClient - ): ReactWrapper => { - const mockStore = configureStore([thunk]); - return mount( - - - + let holder: HTMLElement; + let cartItems: DownloadCartItem[]; + + function renderComponent(): RenderResult { + return render( + + + ); - }; + } beforeEach(() => { - mount = createMount(); + cartItems = []; queryClient = new QueryClient(); history = createMemoryHistory({ initialEntries: ['/search/data'], }); - pushSpy = jest.spyOn(history, 'push'); + // @ts-expect-error we need it this way + delete window.location; + // @ts-expect-error we need it this way + window.location = new URL(`http://localhost/search/data`); + + // below code keeps window.location in sync with history changes + // (needed because useUpdateQueryParam uses window.location not history) + const historyReplace = history.replace; + const historyReplaceSpy = jest.spyOn(history, 'replace'); + historyReplaceSpy.mockImplementation((args) => { + historyReplace(args); + if (typeof args === 'string') { + // @ts-expect-error we need it this way + window.location = new URL(`http://localhost${args}`); + } else { + // @ts-expect-error we need it this way + window.location = new URL(`http://localhost${createPath(args)}`); + } + }); + const historyPush = history.push; + const historyPushSpy = jest.spyOn(history, 'push'); + historyPushSpy.mockImplementation((args) => { + historyPush(args); + if (typeof args === 'string') { + // @ts-expect-error we need it this way + window.location = new URL(`http://localhost${args}`); + } else { + // @ts-expect-error we need it this way + window.location = new URL(`http://localhost${createPath(args)}`); + } + }); - window.localStorage.__proto__.removeItem = jest.fn(); - window.localStorage.__proto__.setItem = jest.fn(); + window.localStorage.clear(); const dGSearchInitialState = { tabs: { @@ -122,38 +217,85 @@ describe('SearchPageContainer - Tests', () => { }, }; + holder = document.createElement('div'); + holder.setAttribute('id', 'datagateway-search'); + document.body.appendChild(holder); + (axios.get as jest.Mock).mockImplementation((url) => { + if (url.includes('/user/cart')) { + return Promise.resolve({ data: { cartItems } }); + } + if (url.includes('count')) { return Promise.resolve({ data: 0 }); - } else { - return Promise.resolve({ data: [] }); } + + return Promise.resolve({ data: [] }); + }); + + ( + readSciGatewayToken as jest.MockedFn + ).mockReturnValue({ + sessionId: null, + username: 'test', }); }); afterEach(() => { + document.body.removeChild(holder); jest.clearAllMocks(); }); it('renders searchPageContainer correctly', () => { - const mockStore = configureStore([thunk]); - const wrapper = mount( - - - - - - - + const localStorageRemoveItemMock = jest.spyOn( + window.localStorage.__proto__, + 'removeItem' + ); + history.replace({ key: 'testKey', pathname: '/' }); + + renderComponent(); + + expect(screen.getByRole('link', { name: 'Search data' })).toHaveAttribute( + 'href', + '/search/data' ); - expect(wrapper).toMatchSnapshot(); + // check it clears all the localstorage stuff + expect(localStorageRemoveItemMock).toHaveBeenCalledWith( + 'investigationFilters' + ); + expect(localStorageRemoveItemMock).toHaveBeenCalledWith('datasetFilters'); + expect(localStorageRemoveItemMock).toHaveBeenCalledWith('datafileFilters'); + expect(localStorageRemoveItemMock).toHaveBeenCalledWith( + 'investigationPage' + ); + expect(localStorageRemoveItemMock).toHaveBeenCalledWith('datasetPage'); + expect(localStorageRemoveItemMock).toHaveBeenCalledWith( + 'investigationResults' + ); + expect(localStorageRemoveItemMock).toHaveBeenCalledWith('datasetResults'); }); - it('renders correctly at /search/data route', () => { - const wrapper = createWrapper(); + it('renders initial layout at /search/data route', () => { + renderComponent(); + + expect(screen.getByTestId('search-box-container')).toBeInTheDocument(); + + // logged in, so my_data checkbox should be visible & checked by default + expect( + screen.getByRole('checkbox', { name: 'check_boxes.my_data' }) + ).toBeChecked(); - expect(wrapper.exists('SearchBoxContainer')).toBeTruthy(); + // no search results yet, so view button, clear filter button and tabs should be hidden + expect( + screen.queryByRole('button', { name: 'page view app.view_cards' }) + ).toBeNull(); + expect( + screen.queryByRole('button', { name: 'app.clear_filters' }) + ).toBeNull(); + expect( + screen.queryByRole('tablist', { name: 'searchPageTable.tabs_arialabel' }) + ).toBeNull(); }); it('renders side layout correctly', () => { @@ -167,72 +309,100 @@ describe('SearchPageContainer - Tests', () => { }) ); - const wrapper = createWrapper(); + renderComponent(); - expect(wrapper.exists('SearchBoxContainerSide')).toBeTruthy(); + expect(screen.getByTestId('search-box-container-side')).toBeInTheDocument(); + // no search results yet, so view button, clear filter button and tabs should be hidden + expect( + screen.queryByRole('button', { name: 'page view app.view_cards' }) + ).toBeNull(); + expect( + screen.queryByRole('button', { name: 'app.clear_filters' }) + ).toBeNull(); + expect( + screen.queryByRole('tablist', { name: 'searchPageTable.tabs_arialabel' }) + ).toBeNull(); }); it('display search table container when search request sent', async () => { - const wrapper = createWrapper(); + const user = userEvent.setup(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.click( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ); - expect(wrapper.exists('#container-search-table')).toBeTruthy(); - expect(wrapper.exists(LinearProgress)).toBeFalsy(); + expect( + await screen.findByRole('tablist', { + name: 'searchPageTable.tabs_arialabel', + }) + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'page view app.view_cards' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'app.clear_filters' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('tab', { name: 'tabs.investigation' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('tab', { name: 'tabs.dataset' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('tab', { name: 'tabs.datafile' }) + ).toBeInTheDocument(); }); it('display loading bar when loading true', async () => { + const user = userEvent.setup(); (axios.get as jest.Mock).mockImplementation( () => - new Promise((resolve, reject) => { + new Promise((_) => { // do nothing, simulating pending promise // to test loading state }) ); - const wrapper = createWrapper(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.click( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ); - expect(wrapper.exists(LinearProgress)).toBeTruthy(); + expect(await screen.findByRole('progressbar')).toBeInTheDocument(); }); it('builds correct parameters for datafile request if date and search text properties are in use', () => { history.replace( - '/search/data?searchText=hello&startDate=2013-11-11&endDate=2016-11-11' + '/search/data?searchText=hello&dataset=false&investigation=false&startDate=2013-11-11&endDate=2016-11-11' ); - const wrapper = createWrapper(); + renderComponent(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Datafile', lower: '201311110000', - text: 'hello', upper: '201611112359', + text: 'hello', + facets: [ + { target: 'Datafile' }, + { + target: 'DatafileParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + }), } ); }); @@ -242,24 +412,32 @@ describe('SearchPageContainer - Tests', () => { '/search/data?searchText=hello&datafile=false&investigation=false&startDate=2013-11-11&endDate=2016-11-11' ); - const wrapper = createWrapper(); + renderComponent(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Dataset', lower: '201311110000', - text: 'hello', upper: '201611112359', + text: 'hello', + facets: [ + { + target: 'Dataset', + }, + { + target: 'DatasetParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + }), } ); }); @@ -269,474 +447,557 @@ describe('SearchPageContainer - Tests', () => { '/search/data?searchText=hello&dataset=false&datafile=false&startDate=2013-11-11&endDate=2016-11-11' ); - const wrapper = createWrapper(); + renderComponent(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); - expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + expect(axios.get).toHaveBeenNthCalledWith( + 1, + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Investigation', lower: '201311110000', - text: 'hello', upper: '201611112359', + text: 'hello', + facets: [ + { target: 'Investigation' }, + { + target: 'InvestigationParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'Sample', + dimensions: [{ dimension: 'sample.type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + }), } ); }); it('builds correct parameters for datafile request if only start date is in use', () => { history.replace( - '/search/data?dataset=false&investigation=false&startDate=2013-11-11' + '/search/data?searchText=&dataset=false&investigation=false&startDate=2013-11-11' ); - const wrapper = createWrapper(); + renderComponent(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Datafile', lower: '201311110000', upper: '9000012312359', + facets: [ + { target: 'Datafile' }, + { + target: 'DatafileParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + }), } ); }); it('builds correct parameters for dataset request if only start date is in use', () => { history.replace( - '/search/data?datafile=false&investigation=false&startDate=2013-11-11' + '/search/data?searchText=test&datafile=false&investigation=false&startDate=2013-11-11' ); - const wrapper = createWrapper(); + renderComponent(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Dataset', lower: '201311110000', upper: '9000012312359', + text: 'test', + facets: [ + { + target: 'Dataset', + }, + { + target: 'DatasetParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + }), } ); }); it('builds correct parameters for investigation request if only start date is in use', () => { history.replace( - '/search/data?dataset=false&datafile=false&startDate=2013-11-11' + '/search/data?searchText=test&dataset=false&datafile=false&startDate=2013-11-11' ); - const wrapper = createWrapper(); + renderComponent(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); - expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + expect(axios.get).toHaveBeenNthCalledWith( + 1, + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Investigation', lower: '201311110000', upper: '9000012312359', + text: 'test', + facets: [ + { target: 'Investigation' }, + { + target: 'InvestigationParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'Sample', + dimensions: [{ dimension: 'sample.type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + }), } ); }); - it('builds correct parameters for datafile request if only end date is in use', () => { + it('builds correct parameters for datafile request if only end date is in use', async () => { + const user = userEvent.setup(); + history.replace( - '/search/data?dataset=false&investigation=false&endDate=2016-11-11' + '/search/data?searchText=&dataset=false&investigation=false&endDate=2016-11-11' ); - const wrapper = createWrapper(); + renderComponent(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); - expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + await user.click( + await screen.findByRole('button', { + name: 'searchBox.search_button_arialabel', + }) + ); + + expect(axios.get).toHaveBeenNthCalledWith( + 2, + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Datafile', lower: '0000001010000', upper: '201611112359', + facets: [ + { target: 'Datafile' }, + { + target: 'DatafileParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + }), } ); }); it('builds correct parameters for dataset request if only end date is in use', () => { history.replace( - '/search/data?datafile=false&investigation=false&endDate=2016-11-11' + '/search/data?searchText=test&datafile=false&investigation=false&endDate=2016-11-11' ); - const wrapper = createWrapper(); + renderComponent(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Dataset', lower: '0000001010000', upper: '201611112359', + text: 'test', + facets: [ + { + target: 'Dataset', + }, + { + target: 'DatasetParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + }), } ); }); it('builds correct parameters for investigation request if only end date is in use', () => { history.replace( - '/search/data?dataset=false&datafile=false&endDate=2016-11-11' + '/search/data?searchText=test&dataset=false&datafile=false&endDate=2016-11-11' ); - const wrapper = createWrapper(); + renderComponent(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Investigation', lower: '0000001010000', upper: '201611112359', + text: 'test', + facets: [ + { target: 'Investigation' }, + { + target: 'InvestigationParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'Sample', + dimensions: [{ dimension: 'sample.type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + }), } ); }); - it('builds correct parameters for datafile request if date and search text properties are not in use', () => { + it('builds correct parameters for datafile request if date and search text properties are not in use', async () => { + const user = userEvent.setup(); + history.replace('/search/data?dataset=false&investigation=false'); - const wrapper = createWrapper(); + renderComponent(); + + await user.click( + await screen.findByRole('button', { + name: 'searchBox.search_button_arialabel', + }) + ); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Datafile', + facets: [ + { + target: 'Datafile', + }, + { + target: 'DatafileParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + restrict: 'true', + }), } ); }); - it('builds correct parameters for dataset request if date and search text properties are not in use', () => { + it('builds correct parameters for dataset request if date and search text properties are not in use', async () => { + const user = userEvent.setup(); + history.replace('/search/data?datafile=false&investigation=false'); - const wrapper = createWrapper(); + renderComponent(); + + await user.click( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Dataset', + facets: [ + { + target: 'Dataset', + }, + { + target: 'DatasetParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + restrict: 'true', + }), } ); }); - it('builds correct parameters for investigation request if date and search text properties are not in use', () => { + it('builds correct parameters for investigation request if date and search text properties are not in use', async () => { + const user = userEvent.setup(); + history.replace('/search/data?dataset=false&datafile=false'); - const wrapper = createWrapper(); + renderComponent(); + + await user.click( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Investigation', + facets: [ + { target: 'Investigation' }, + { + target: 'InvestigationParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'Sample', + dimensions: [{ dimension: 'sample.type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + restrict: 'true', + }), } ); }); - it('gets the filters stored in the local storage', () => { - localStorageGetItemMock.mockImplementationOnce( - () => '{"investigation.title":{"value":"test","type":"include"}}' - ); - const result = getFilters('dataset'); - expect(result).toEqual({ - 'investigation.title': { - type: 'include', - value: 'test', - }, - }); - }); - - it('gets the sorts stored in the local storage', () => { - localStorageGetItemMock.mockImplementationOnce(() => '{"name":"asc"}'); - const result = getSorts('dataset'); - expect(result).toEqual({ - name: 'asc', - }); - }); - it('display clear filters button and clear for filters onClick', async () => { - const wrapper = createWrapper(); + const user = userEvent.setup(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.click( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ); history.replace( `/search/data?filters=%7B"title"%3A%7B"value"%3A"spend"%2C"type"%3A"include"%7D%7D` ); - wrapper.update(); - - expect(wrapper.find(ClearFiltersButton).prop('disabled')).toEqual(false); - - wrapper - .find('[data-testid="clear-filters-button"]') - .first() - .simulate('click'); + expect( + await screen.findByRole('button', { name: 'app.clear_filters' }) + ).not.toBeDisabled(); - wrapper.update(); + await user.click(screen.getByRole('button', { name: 'app.clear_filters' })); - expect(wrapper.find(ClearFiltersButton).prop('disabled')).toEqual(true); + expect( + await screen.findByRole('button', { name: 'app.clear_filters' }) + ).toBeDisabled(); expect(history.location.search).toEqual('?'); }); it('display disabled clear filters button', async () => { - const wrapper = createWrapper(); - - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); + const user = userEvent.setup(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - - expect(wrapper.find(ClearFiltersButton).prop('disabled')).toEqual(true); - }); + renderComponent(); - it('gets the page stored in the local storage', () => { - localStorageGetItemMock.mockImplementationOnce(() => 2); - const result = getPage('dataset'); - expect(result).toEqual(2); - }); + await user.click( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ); - it('gets the results stored in the local storage', () => { - localStorageGetItemMock.mockImplementationOnce(() => 10); - const result = getResults('dataset'); - expect(result).toEqual(10); + expect( + await screen.findByRole('button', { name: 'app.clear_filters' }) + ).toBeDisabled(); }); - it('stores the previous filters in the local storage', () => { - storeFilters( - { title: { value: 'test', type: 'include' } }, - 'investigation' + it('should hide tabs when the corresponding search type is disabled', async () => { + // need real store so so that the tab values actually update in the store + // after we dispatch the relevant actions + function renderComponentWithRealStore(): RenderResult { + return render( + + + + + + + + ); + } + + const user = userEvent.setup(); + + // test it works with loading from URL params + history.replace( + '/search/data?searchText=test&dataset=false&datafile=false' ); - expect(localStorage.setItem).toBeCalledWith( - 'investigationFilters', - '{"title":{"value":"test","type":"include"}}' - ); - }); + renderComponentWithRealStore(); - it('stores the previous sorts in the local storage', () => { - storeSort({ name: 'asc' }, 'investigation'); + expect( + screen.getByRole('tab', { name: 'tabs.investigation' }) + ).toBeInTheDocument(); + expect(screen.queryByRole('tab', { name: 'tabs.dataset' })).toBeNull(); + expect(screen.queryByRole('tab', { name: 'tabs.datafile' })).toBeNull(); - expect(localStorage.setItem).toBeCalledWith( - 'investigationSort', - '{"name":"asc"}' - ); - }); + // also test it works on initiateSearch + history.replace('/search/data?searchText=test&datafile=false'); - it('stores the previous page in the local storage', () => { - storePage(4, 'investigation'); + await user.click( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ); - expect(localStorage.setItem).toBeCalledWith('investigationPage', '4'); + expect( + screen.getByRole('tab', { name: 'tabs.investigation' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('tab', { name: 'tabs.dataset' }) + ).toBeInTheDocument(); + expect(screen.queryByRole('tab', { name: 'tabs.datafile' })).toBeNull(); }); - it('stores the previous results in the local storage', () => { - storeResults(20, 'investigation'); + it('search is not initiated when no search types are enabled', async () => { + const user = userEvent.setup(); - expect(localStorage.setItem).toBeCalledWith('investigationResults', '20'); - }); - - it('sends actions to update tabs when user clicks search button', async () => { history.replace( - '/search/data?searchText=test&dataset=false&datafile=false' + '/search/data?searchText=test&investigation=false&dataset=false&datafile=false' ); - const mockStore = configureStore([thunk]); - const testStore = mockStore(state); - const wrapper = mount( - - - - - - - - ); - wrapper.update(); + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + expect( + screen.queryByRole('tablist', { + name: 'searchPageTable.tabs_arialabel', + }) + ).toBeNull(); + + await user.click( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ); - expect(testStore.getActions()[0]).toEqual(setDatafileTab(false)); - expect(testStore.getActions()[1]).toEqual(setDatasetTab(false)); - expect(testStore.getActions()[2]).toEqual(setInvestigationTab(true)); + expect( + screen.queryByRole('tablist', { + name: 'searchPageTable.tabs_arialabel', + }) + ).toBeNull(); }); it('search text state is updated when text is changed and pushes when search initiated', async () => { - const wrapper = createWrapper(); - - wrapper - .find('[aria-label="searchBox.search_text_arialabel"] input') - .simulate('change', { target: { value: 'test' } }); + const user = userEvent.setup(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.type( + screen.getByRole('searchbox', { + name: 'searchBox.search_text_arialabel', + }), + 'test' + ); + await user.click( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ); - expect(pushSpy).toHaveBeenCalledWith('?searchText=test'); + expect(history.location.search).toEqual('?searchText=test&restrict=true'); }); it('shows SelectionAlert banner when item selected', async () => { - (useCart as jest.Mock).mockReturnValue({ - data: [ - { - entityId: 1, - entityType: 'dataset', - id: 1, - name: 'Test 1', - parentEntities: [], - }, - ], - }); - const wrapper = createWrapper(); - - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); - - expect(wrapper.exists('[aria-label="selection-alert"]')).toBeTruthy(); - }); - - it('does not show SelectionAlert banner when no items are selected', async () => { - (useCart as jest.Mock).mockReturnValue({ - data: [], - }); - const wrapper = createWrapper(); + cartItems = [ + { + entityId: 1, + entityType: 'dataset', + id: 1, + name: 'Test 1', + parentEntities: [], + }, + ]; + const user = userEvent.setup(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.click( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ); - expect(wrapper.exists('[aria-label="selection-alert"]')).toBeFalsy(); + expect(await screen.findByLabelText('selection-alert')).toBeInTheDocument(); }); it('initiates search when visiting a direct url', async () => { history.replace( - '/search/data?searchText=hello&startDate=2013-11-11&endDate=2016-11-11' + '/search/data?searchText=hello&restrict=true&startDate=2013-11-11&endDate=2016-11-11' ); - const wrapper = createWrapper(); - wrapper.update(); + renderComponent(); expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Datafile', lower: '201311110000', - text: 'hello', upper: '201611112359', + text: 'hello', + facets: [ + { target: 'Datafile' }, + { + target: 'DatafileParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + restrict: 'true', + }), } ); }); @@ -744,135 +1005,176 @@ describe('SearchPageContainer - Tests', () => { it('initiates search when visiting a direct url with empty search text', async () => { history.replace('/search/data?searchText='); - const wrapper = createWrapper(); - wrapper.update(); + renderComponent(); expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Datafile', + facets: [ + { target: 'Datafile' }, + { + target: 'DatafileParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + }), } ); }); it('does not search for non-searchable entities when visiting a direct url', async () => { - state.dgsearch.searchableEntities = ['investigation', 'dataset']; + if (state.dgsearch) + state.dgsearch.searchableEntities = ['investigation', 'dataset']; history.replace('/search/data?searchText=hello&datafiles=true'); - const wrapper = createWrapper(); - wrapper.update(); + renderComponent(); expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Investigation', text: 'hello', + facets: [ + { target: 'Investigation' }, + { + target: 'InvestigationParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'Sample', + dimensions: [{ dimension: 'sample.type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + }), } ); expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Dataset', text: 'hello', + facets: [ + { + target: 'Dataset', + }, + { + target: 'DatasetParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + }), } ); expect(axios.get).not.toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Datafile', text: 'hello', }, - sessionId: null, - }, + }), } ); }); it('initiates search when the URL is changed', async () => { - const wrapper = createWrapper(); - wrapper.update(); + const user = userEvent.setup(); + + renderComponent(); + (axios.get as jest.Mock).mockClear(); - history.push('?searchText=neutron+AND+scattering'); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.type( + screen.getByRole('searchbox', { + name: 'searchBox.search_text_arialabel', + }), + 'neutron AND scattering' + ); - expect(axios.get).toHaveBeenCalledWith( - 'https://example.com/icat/lucene/data', + await user.click( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ); + + expect(axios.get).toHaveBeenNthCalledWith( + 1, + 'https://example.com/icat/search/documents', { - params: { - maxCount: 300, + params: generateURLSearchParams({ query: { target: 'Investigation', text: 'neutron AND scattering', + facets: [ + { target: 'Investigation' }, + { + target: 'InvestigationParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'Sample', + dimensions: [{ dimension: 'sample.type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - sessionId: null, - }, + restrict: 'true', + }), } ); }); it('switches view button display name when clicked', async () => { - const wrapper = createWrapper(); + const user = userEvent.setup(); - wrapper - .find('button[aria-label="searchBox.search_button_arialabel"]') - .simulate('click'); + renderComponent(); - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.click( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ); - expect( - wrapper.find('[aria-label="page view app.view_cards"]').exists() - ).toBeTruthy(); - expect( - wrapper.find('[aria-label="page view app.view_cards"]').first().text() - ).toEqual('app.view_cards'); + const viewCardBtn = await screen.findByRole('button', { + name: 'page view app.view_cards', + }); + expect(viewCardBtn).toBeInTheDocument(); + expect(viewCardBtn).toHaveTextContent('app.view_cards'); // Click view button - wrapper - .find('[aria-label="page view app.view_cards"]') - .first() - .simulate('click'); - wrapper.update(); - - await act(async () => { - await flushPromises(); - wrapper.update(); - }); + await user.click(viewCardBtn); // Check that the text on the button has changed - expect( - wrapper.find('[aria-label="page view app.view_table"]').first().text() - ).toEqual('app.view_table'); + const viewTableBtn = await screen.findByRole('button', { + name: 'page view app.view_table', + }); + expect(viewTableBtn).toBeInTheDocument(); + expect(viewTableBtn).toHaveTextContent('app.view_table'); }); it('defaults to dataset when investigation is false ', async () => { @@ -885,9 +1187,8 @@ describe('SearchPageContainer - Tests', () => { }, }; - const wrapper = createWrapper(); + renderComponent(); - wrapper.update(); expect(history.location.search).toEqual('?currentTab=dataset'); }); @@ -901,9 +1202,8 @@ describe('SearchPageContainer - Tests', () => { }, }; - const wrapper = createWrapper(); + renderComponent(); - wrapper.update(); expect(history.location.search).toEqual('?currentTab=datafile'); }); @@ -917,10 +1217,57 @@ describe('SearchPageContainer - Tests', () => { }, }; - const wrapper = createWrapper(); + renderComponent(); - wrapper.update(); - // '' i.e default value is investigation it set in the searchPageContainer + // i.e default value is investigation it set in the searchPageContainer expect(history.location.search).toEqual(''); }); + + it('handles anonymous users correctly', async () => { + ( + readSciGatewayToken as jest.MockedFn + ).mockReturnValue({ + sessionId: null, + username: 'anon/anon', + }); + + const user = userEvent.setup(); + + renderComponent(); + + await user.click( + screen.getByRole('button', { name: 'searchBox.search_button_arialabel' }) + ); + + expect( + screen.queryByRole('checkbox', { name: 'check_boxes.my_data' }) + ).not.toBeInTheDocument(); + + expect(axios.get).toHaveBeenCalledWith( + 'https://example.com/icat/search/documents', + { + params: generateURLSearchParams({ + query: { + target: 'Investigation', + facets: [ + { target: 'Investigation' }, + { + target: 'InvestigationParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'Sample', + dimensions: [{ dimension: 'sample.type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], + }, + restrict: 'false', + }), + } + ); + }); }); diff --git a/packages/datagateway-search/src/searchPageContainer.component.tsx b/packages/datagateway-search/src/searchPageContainer.component.tsx index 945db111a..513faac1f 100644 --- a/packages/datagateway-search/src/searchPageContainer.component.tsx +++ b/packages/datagateway-search/src/searchPageContainer.component.tsx @@ -1,50 +1,42 @@ import React from 'react'; import ResizeObserver from 'resize-observer-polyfill'; import { StateType } from './state/app.types'; -import { connect } from 'react-redux'; -import { Switch, Route, RouteComponentProps } from 'react-router'; -import { Link, useLocation } from 'react-router-dom'; - +import { useDispatch, useSelector } from 'react-redux'; import { - Grid, - Paper, - LinearProgress, - makeStyles, - createStyles, - Theme, -} from '@material-ui/core'; - -import SearchPageTable from './searchPageTable.component'; -import SearchPageCardView from './searchPageCardView.component'; + Link, + Route, + RouteComponentProps, + Switch, + useHistory, + useLocation, +} from 'react-router-dom'; + +import { Grid, Paper, styled } from '@mui/material'; + import SearchBoxContainer from './searchBoxContainer.component'; import SearchBoxContainerSide from './searchBoxContainerSide.component'; - -import { useHistory } from 'react-router-dom'; +import SearchTabs from './searchTabs/searchTabs.component'; import { - useLuceneSearch, - ViewsType, + ClearFiltersButton, + FiltersType, parseSearchToQuery, - useUpdateView, - usePushSearchText, - useCart, - SelectionAlert, + parseQueryToSearch, readSciGatewayToken, - FiltersType, - SortType, - usePushCurrentTab, + SelectionAlert, + useCart, + usePushQueryParams, useUpdateQueryParam, + useUpdateView, ViewButton, - ClearFiltersButton, + ViewsType, } from 'datagateway-common'; -import { Action, AnyAction } from 'redux'; -import { ThunkDispatch } from 'redux-thunk'; import { setDatafileTab, setDatasetTab, setInvestigationTab, } from './state/actions/actions'; -export const storeFilters = ( +const storeFilters = ( filters: FiltersType, searchableEntities: string ): void => { @@ -54,33 +46,20 @@ export const storeFilters = ( localStorage.setItem(filter, JSON.stringify(filters)); }; -export const storeSort = ( - sorts: SortType, - searchableEntities: string -): void => { - const sort = (searchableEntities as string) + 'Sort'; - - if (Object.keys(sorts).length !== 0) - localStorage.setItem(sort, JSON.stringify(sorts)); -}; - -export const storePage = (page: number, searchableEntities: string): void => { +const storePage = (page: number, searchableEntities: string): void => { const pageNumber = (searchableEntities as string) + 'Page'; if (page !== 1) localStorage.setItem(pageNumber, JSON.stringify(page)); }; -export const storeResults = ( - results: number, - searchableEntities: string -): void => { +const storeResults = (results: number, searchableEntities: string): void => { const resultsNumber = (searchableEntities as string) + 'Results'; if (results !== 10) localStorage.setItem(resultsNumber, JSON.stringify(results)); }; -export const getFilters = (searchableEntities: string): FiltersType | null => { +const getFilters = (searchableEntities: string): FiltersType | null => { const filter = (searchableEntities as string) + 'Filters'; const savedFilters = localStorage.getItem(filter); if (savedFilters) { @@ -90,17 +69,7 @@ export const getFilters = (searchableEntities: string): FiltersType | null => { } }; -export const getSorts = (searchableEntities: string): SortType | null => { - const sort = (searchableEntities as string) + 'Sort'; - const savedSort = localStorage.getItem(sort); - if (savedSort) { - return JSON.parse(savedSort) as SortType; - } else { - return null; - } -}; - -export const getPage = (searchableEntities: string): number | null => { +const getPage = (searchableEntities: string): number | null => { const pageNumber = (searchableEntities as string) + 'Page'; const savedPage = localStorage.getItem(pageNumber); if (savedPage) { @@ -110,7 +79,7 @@ export const getPage = (searchableEntities: string): number | null => { } }; -export const getResults = (searchableEntities: string): number | null => { +const getResults = (searchableEntities: string): number | null => { const resultsNumber = (searchableEntities as string) + 'Results'; const savedResults = localStorage.getItem(resultsNumber); if (savedResults) { @@ -120,6 +89,41 @@ export const getResults = (searchableEntities: string): number | null => { } }; +export const usePushCurrentTab = (): ((newCurrentTab: string) => void) => { + const { push } = useHistory(); + const location = useLocation(); + const { filters, page, results, currentTab } = React.useMemo( + () => parseSearchToQuery(location.search), + [location.search] + ); + + return React.useCallback( + (newCurrentTab: string) => { + storeFilters(filters, currentTab); + if (page) { + storePage(page, currentTab); + } + if (results) { + storeResults(results, currentTab); + } + + const newFilters = getFilters(newCurrentTab) ?? {}; + const newPage = getPage(newCurrentTab); + const newResults = getResults(newCurrentTab); + + const query = { + ...parseSearchToQuery(window.location.search), + filters: newFilters, + page: newPage, + results: newResults, + currentTab: newCurrentTab, + }; + push(`?${parseQueryToSearch(query).toString()}`); + }, + [currentTab, filters, page, push, results] + ); +}; + const storeDataView = (view: NonNullable): void => { localStorage.setItem('dataView', view); }; @@ -151,91 +155,64 @@ const getToggle = (pathname: string, view: ViewsType): boolean => { return getPathMatch(pathname) ? view ? view === 'card' - ? true - : false : getView() === 'card' - ? true - : false : false; }; -const searchPageStyles = makeStyles< - Theme, - { view: ViewsType; containerHeight: string } ->((theme: Theme) => { - return createStyles({ - root: { - margin: 0, - width: '100%', - }, - topLayout: { - height: '100%', - // make width of box bigger on smaller screens to prevent overflow - // decreasing the space for the search results - width: '100%', - '@media (min-width: 1000px) and (min-height: 700px)': { - width: '98%', - }, - margin: '0 auto', - }, - sideLayout: { - height: '100%', - width: '100%', - }, - dataViewTopBar: { - width: '98%', - backgroundColor: '#00000000', - }, - dataView: { - // Only use height for the paper component if the view is table. - // also ensure we account for the potential horizontal scrollbar - height: ({ view, containerHeight }) => - view !== 'card' ? containerHeight : 'auto', - minHeight: 500, - width: '98%', - backgroundColor: '#00000000', - }, - }); +const TopSearchBoxPaper = styled(Paper)({ + height: '100%', + // make width of box bigger on smaller screens to prevent overflow + // decreasing the space for the search results + width: '100%', + '@media (min-width: 1000px) and (min-height: 700px)': { + width: '98%', + }, + margin: '0 auto', }); -interface SearchPageContainerStoreProps { - sideLayout: boolean; - searchableEntities: string[]; - maxNumResults: number; - datafileTab: boolean; - datasetTab: boolean; - investigationTab: boolean; -} - -interface SearchPageContainerDispatchProps { - setDatasetTab: (toggleOption: boolean) => Action; - setDatafileTab: (toggleOption: boolean) => Action; - setInvestigationTab: (toggleOption: boolean) => Action; -} - -type SearchPageContainerCombinedProps = SearchPageContainerStoreProps & - SearchPageContainerDispatchProps; - -const SearchPageContainer: React.FC = ( - props: SearchPageContainerCombinedProps -) => { - const { - setDatafileTab, - setDatasetTab, - setInvestigationTab, - investigationTab, - datasetTab, - datafileTab, - sideLayout, - searchableEntities, - maxNumResults, - } = props; +const SideSearchBoxPaper = styled(Paper)({ + height: '100%', + width: '100%', +}); + +const DataViewPaper = styled(Paper, { + shouldForwardProp: (prop) => prop !== 'view' && prop !== 'containerHeight', +})<{ view: ViewsType; containerHeight: string }>( + ({ view, containerHeight }) => ({ + // Only use height for the paper component if the view is table. + // also ensure we account for the potential horizontal scrollbar + height: view !== 'card' ? containerHeight : 'auto', + minHeight: 500, + width: '98%', + backgroundColor: '#00000000', + }) +); + +const SearchPageContainer: React.FC = () => { + const investigationTab = useSelector( + (state: StateType) => state.dgsearch.tabs.investigationTab + ); + const datasetTab = useSelector( + (state: StateType) => state.dgsearch.tabs.datasetTab + ); + const datafileTab = useSelector( + (state: StateType) => state.dgsearch.tabs.datafileTab + ); + const sideLayout = useSelector( + (state: StateType) => state.dgsearch.sideLayout + ); + const searchableEntities = useSelector( + (state: StateType) => state.dgsearch.searchableEntities + ); + + const dispatch = useDispatch(); const location = useLocation(); - const queryParams = React.useMemo(() => parseSearchToQuery(location.search), [ - location.search, - ]); - const { view, startDate, endDate } = queryParams; + const queryParams = React.useMemo( + () => parseSearchToQuery(location.search), + [location.search] + ); + const { view } = queryParams; const searchTextURL = queryParams.searchText ? queryParams.searchText : ''; @@ -243,8 +220,26 @@ const SearchPageContainer: React.FC = ( const checkedBoxes = boolSearchableEntities.flatMap((b, i) => b ? searchableEntities[i] : [] ); + + // keep track of first render as checkedBoxes isn't initalised from the URL yet + // and that causes us to lose the currentTab state from the URL without the isFirstRender check + const [isFirstRender, setIsFirstRender] = React.useState(true); + React.useEffect(() => { + setIsFirstRender(false); + + // when page loads, reset all localstorage saved tab items + localStorage.removeItem('investigationFilters'); + localStorage.removeItem('datasetFilters'); + localStorage.removeItem('datafileFilters'); + localStorage.removeItem('investigationPage'); + localStorage.removeItem('datasetPage'); + localStorage.removeItem('investigationResults'); + localStorage.removeItem('datasetResults'); + }, []); + const currentTab = - queryParams.currentTab && checkedBoxes.includes(queryParams.currentTab) + queryParams.currentTab && + (isFirstRender || checkedBoxes.includes(queryParams.currentTab)) ? queryParams.currentTab : checkedBoxes.length !== 0 ? checkedBoxes[0] @@ -264,10 +259,9 @@ const SearchPageContainer: React.FC = ( const pushView = useUpdateView('push'); const replaceView = useUpdateView('replace'); - const pushSearchText = usePushSearchText(); const pushCurrentTab = usePushCurrentTab(); + const pushQueryParams = usePushQueryParams(); const replaceFilters = useUpdateQueryParam('filters', 'replace'); - const replaceSorts = useUpdateQueryParam('sort', 'replace'); const replacePage = useUpdateQueryParam('page', 'replace'); const replaceResults = useUpdateQueryParam('results', 'replace'); @@ -276,7 +270,19 @@ const SearchPageContainer: React.FC = ( }, [checkedBoxes, currentTab, pushCurrentTab, queryParams.currentTab]); const [searchText, setSearchText] = React.useState(searchTextURL); - const [searchOnNextRender, setSearchOnNextRender] = React.useState(false); + const [isSearchInitiated, setIsSearchInitiated] = React.useState( + queryParams.searchText !== null && (investigation || dataset || datafile) + ); + + const username = readSciGatewayToken().username; + const loggedInAnonymously = username === null || username === 'anon/anon'; + + const [shouldRestrictSearch, setShouldRestrictSearch] = React.useState( + // restrict should be false if logged in as anon + // otherwise, default (i.e. !isSearchInitiated) should be checkbox set to true + // otherwise, if search already initiated - respect the restrict param + !loggedInAnonymously && (!isSearchInitiated || queryParams.restrict) + ); const handleSearchTextChange = (searchText: string): void => { setSearchText(searchText); @@ -302,132 +308,60 @@ const SearchPageContainer: React.FC = ( } }, [location.pathname, view, replaceView]); - const { - refetch: searchInvestigations, - isIdle: investigationsIdle, - isFetching: investigationsFetching, - } = useLuceneSearch('Investigation', { - searchText: searchTextURL, - startDate, - endDate, - maxCount: maxNumResults, - }); - const { - refetch: searchDatasets, - isIdle: datasetsIdle, - isFetching: datasetsFetching, - } = useLuceneSearch('Dataset', { - searchText: searchTextURL, - startDate, - endDate, - maxCount: maxNumResults, - }); - const { - refetch: searchDatafiles, - isIdle: datafilesIdle, - isFetching: datafilesFetching, - } = useLuceneSearch('Datafile', { - searchText: searchTextURL, - startDate, - endDate, - maxCount: maxNumResults, - }); - - const requestReceived = - !investigationsIdle || !datasetsIdle || !datafilesIdle; - - const loading = - investigationsFetching || datasetsFetching || datafilesFetching; - const initiateSearch = React.useCallback(() => { - pushSearchText(searchText); - setSearchOnNextRender(true); - - localStorage.removeItem('investigationFilters'); - localStorage.removeItem('datasetFilters'); - localStorage.removeItem('datafileFilters'); - localStorage.removeItem('investigationSort'); - localStorage.removeItem('datasetSort'); - localStorage.removeItem('datafileSort'); - localStorage.removeItem('investigationPage'); - localStorage.removeItem('datasetPage'); - localStorage.removeItem('investigationResults'); - localStorage.removeItem('datasetResults'); - if (Object.keys(queryParams.filters).length !== 0) replaceFilters({}); - if (Object.keys(queryParams.sort).length !== 0) replaceSorts({}); - if (queryParams.page !== null) replacePage(null); - if (queryParams.results !== null) replaceResults(null); + if (investigation || dataset || datafile) { + pushQueryParams({ + searchText, + restrict: shouldRestrictSearch, + }); + + dispatch(setDatafileTab(datafile)); + dispatch(setDatasetTab(dataset)); + dispatch(setInvestigationTab(investigation)); + + localStorage.removeItem('investigationFilters'); + localStorage.removeItem('datasetFilters'); + localStorage.removeItem('datafileFilters'); + localStorage.removeItem('investigationPage'); + localStorage.removeItem('datasetPage'); + localStorage.removeItem('investigationResults'); + localStorage.removeItem('datasetResults'); + + if (Object.keys(queryParams.filters).length !== 0) replaceFilters({}); + if (queryParams.page !== null) replacePage(null); + if (queryParams.results !== null) replaceResults(null); + + setIsSearchInitiated(true); + } }, [ - pushSearchText, + investigation, + dataset, + datafile, + pushQueryParams, searchText, + shouldRestrictSearch, + dispatch, queryParams.filters, - queryParams.sort, queryParams.page, queryParams.results, replaceFilters, - replaceSorts, replacePage, replaceResults, ]); + // set initial tabs based off of page load query params React.useEffect(() => { - if (searchOnNextRender) { - if (dataset) { - // Fetch lucene datasets - searchDatasets(); - } + // Set the appropriate tabs. + dispatch(setDatafileTab(datafile)); + dispatch(setDatasetTab(dataset)); + dispatch(setInvestigationTab(investigation)); - if (datafile) { - // Fetch lucene datafiles - searchDatafiles(); - } - if (investigation) { - // Fetch lucene investigations - searchInvestigations(); - } - - if (dataset || datafile || investigation) { - // Set the appropriate tabs. - setDatafileTab(datafile); - setDatasetTab(dataset); - setInvestigationTab(investigation); - } - - setSearchOnNextRender(false); - } - }, [ - searchOnNextRender, - dataset, - datafile, - investigation, - searchDatasets, - searchDatafiles, - searchInvestigations, - setDatafileTab, - setDatasetTab, - setInvestigationTab, - ]); - - React.useEffect(() => { - //Start search automatically if URL has been supplied with parameters (other than just the checkbox states) - if ( - queryParams.searchText !== null || - queryParams.startDate || - queryParams.endDate - ) - setSearchOnNextRender(true); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); React.useEffect(() => { - if (searchTextURL !== searchText) { - //Ensure search text is assigned from the URL - setSearchText(searchTextURL); - setSearchOnNextRender(true); - } - - //Want to search whenever the search text in the URL changes so that clicking a react-router link also initiates the search - // eslint-disable-next-line react-hooks/exhaustive-deps + // Sync search text in URL with local search text state + setSearchText(searchTextURL); }, [searchTextURL]); const [searchBoxHeight, setSearchBoxHeight] = React.useState(0); @@ -453,21 +387,15 @@ const SearchPageContainer: React.FC = ( }, []); // Table should take up page but leave room for: SG appbar, SG footer, - // search box, search box padding, display as cards button, loading bar - const containerHeight = `calc(100vh - 64px - 36px - ${searchBoxHeight}px - 8px - 47px${ - loading ? '' : ' - 4px' - })`; + // search box, search box padding, display as cards button, loading bar, paper outline + const containerHeight = `calc(100vh - 64px - 36px - ${searchBoxHeight}px - 8px - 49px - 2px)`; const { data: cartItems } = useCart(); const { push } = useHistory(); const navigateToDownload = React.useCallback(() => push('/download'), [push]); - const username = readSciGatewayToken().username; - const loggedInAnonymously = username === null || username === 'anon/anon'; - const classes = searchPageStyles({ view, containerHeight }); - - const disabled = Object.keys(queryParams.filters).length !== 0 ? false : true; + const disabled = Object.keys(queryParams.filters).length === 0; const pushFilters = useUpdateQueryParam('filters', 'push'); @@ -488,40 +416,53 @@ const SearchPageContainer: React.FC = ( {sideLayout ? ( - + + setShouldRestrictSearch(restrict) + } /> - + ) : ( - + + setShouldRestrictSearch(restrict) + } /> - + )} - {requestReceived && ( + {isSearchInitiated && (
- - + + = ( - - - {/* Show loading progress if data is still being loaded */} - {loading && ( - - - - )} - {view === 'card' ? ( - - ) : ( - - )} - + + + +
)} @@ -580,27 +514,4 @@ const SearchPageContainer: React.FC = ( ); }; -const mapDispatchToProps = ( - dispatch: ThunkDispatch -): SearchPageContainerDispatchProps => ({ - setDatasetTab: (toggleOption: boolean) => - dispatch(setDatasetTab(toggleOption)), - setDatafileTab: (toggleOption: boolean) => - dispatch(setDatafileTab(toggleOption)), - setInvestigationTab: (toggleOption: boolean) => - dispatch(setInvestigationTab(toggleOption)), -}); - -const mapStateToProps = (state: StateType): SearchPageContainerStoreProps => ({ - sideLayout: state.dgsearch.sideLayout, - searchableEntities: state.dgsearch.searchableEntities, - maxNumResults: state.dgsearch.maxNumResults, - datafileTab: state.dgsearch.tabs.datafileTab, - datasetTab: state.dgsearch.tabs.datasetTab, - investigationTab: state.dgsearch.tabs.investigationTab, -}); - -export default connect( - mapStateToProps, - mapDispatchToProps -)(SearchPageContainer); +export default SearchPageContainer; diff --git a/packages/datagateway-search/src/searchPageTable.component.test.tsx b/packages/datagateway-search/src/searchPageTable.component.test.tsx deleted file mode 100644 index d311f3c0e..000000000 --- a/packages/datagateway-search/src/searchPageTable.component.test.tsx +++ /dev/null @@ -1,184 +0,0 @@ -import React from 'react'; -import { StateType } from './state/app.types'; -import { Provider } from 'react-redux'; -import { MemoryRouter, Router } from 'react-router'; - -import SearchPageTable, { SearchTableProps } from './searchPageTable.component'; - -import { mount as enzymeMount, ReactWrapper } from 'enzyme'; -import { createMount } from '@material-ui/core/test-utils'; -import configureStore from 'redux-mock-store'; -import thunk from 'redux-thunk'; -import { initialState } from './state/reducers/dgsearch.reducer'; -import { dGCommonInitialState, CartProps } from 'datagateway-common'; -import axios from 'axios'; -import { QueryClientProvider, QueryClient } from 'react-query'; -import { Store } from 'redux'; -import InvestigationSearchTable from './table/investigationSearchTable.component'; -import DatasetSearchTable from './table/datasetSearchTable.component'; -import DatafileSearchTable from './table/datafileSearchTable.component'; -import { createMemoryHistory, History } from 'history'; - -jest.mock('datagateway-common', () => ({ - ...jest.requireActual('datagateway-common'), - __esModule: true, - // mock table to opt out of rendering them in these tests as there's no need - Table: jest.fn(() => 'MockedTable'), -})); - -describe('SearchPageTable', () => { - let mount: typeof enzymeMount; - let state: StateType; - let history: History; - let props: SearchTableProps & CartProps; - const mockStore = configureStore([thunk]); - - const onTabChange = jest.fn(); - const navigateToDownload = jest.fn(); - - const createWrapper = ( - store: Store = mockStore(state), - props: SearchTableProps & CartProps - ): ReactWrapper => { - return mount( - - - - - - - - ); - }; - - beforeEach(() => { - mount = createMount(); - history = createMemoryHistory({ - initialEntries: ['/search/data'], - }); - - state = JSON.parse( - JSON.stringify({ dgsearch: initialState, dgcommon: dGCommonInitialState }) - ); - - props = { - onTabChange: onTabChange, - currentTab: 'investigation', - cartItems: [], - navigateToDownload: navigateToDownload, - }; - - (axios.get as jest.Mock).mockImplementation((url) => { - if (url.includes('count')) { - return Promise.resolve({ data: 0 }); - } else { - return Promise.resolve({ data: [] }); - } - }); - }); - - afterEach(() => { - onTabChange.mockClear(); - navigateToDownload.mockClear(); - }); - - it('renders correctly when request received', () => { - state.dgsearch = { - ...state.dgsearch, - tabs: { - datasetTab: true, - datafileTab: true, - investigationTab: true, - }, - }; - (axios.get as jest.Mock).mockImplementation((url) => { - if (url.includes('count')) { - return Promise.resolve({ data: 1 }); - } else { - return Promise.resolve({ data: Array(1) }); - } - }); - - const createWrapper = (store: Store = mockStore(state)): ReactWrapper => { - return mount( - - - - - - - - ); - }; - - const testStore = mockStore(state); - const wrapper = createWrapper(testStore); - expect(wrapper).toMatchSnapshot(); - }); - - it('changes selected tab value on click of a new tab', () => { - state.dgsearch = { - ...state.dgsearch, - tabs: { - datasetTab: true, - datafileTab: true, - investigationTab: true, - }, - }; - - const testStore = mockStore(state); - const wrapper = createWrapper(testStore, props); - - expect(wrapper.exists(InvestigationSearchTable)).toBeTruthy(); - - wrapper - .find('[aria-controls="simple-tabpanel-dataset"]') - .first() - .simulate('click'); - - expect(onTabChange).toHaveBeenNthCalledWith(1, 'dataset'); - }); - - it('has the investigation search table component when on the investigation tab', () => { - const updatedProps = { - ...props, - currentTab: 'investigation', - }; - - const testStore = mockStore(state); - const wrapper = createWrapper(testStore, updatedProps); - expect(wrapper.exists(InvestigationSearchTable)).toBeTruthy(); - }); - - it('has the dataset search table component when on the dataset tab', () => { - const updatedProps = { - ...props, - currentTab: 'dataset', - }; - - // Mock to prevent error logging - const spy = jest.spyOn(console, 'error').mockImplementation(); - const testStore = mockStore(state); - const wrapper = createWrapper(testStore, updatedProps); - - expect(wrapper.exists(DatasetSearchTable)).toBeTruthy(); - spy.mockRestore(); - }); - - it('has the datafile search table component when on the datafile tab', () => { - const updatedProps = { - ...props, - currentTab: 'datafile', - }; - - // Mock to prevent error logging - const spy = jest.spyOn(console, 'error').mockImplementation(); - const testStore = mockStore(state); - const wrapper = createWrapper(testStore, updatedProps); - - expect(wrapper.exists(DatafileSearchTable)).toBeTruthy(); - spy.mockRestore(); - }); -}); diff --git a/packages/datagateway-search/src/searchPageTable.component.tsx b/packages/datagateway-search/src/searchPageTable.component.tsx deleted file mode 100644 index bc3e16a1f..000000000 --- a/packages/datagateway-search/src/searchPageTable.component.tsx +++ /dev/null @@ -1,445 +0,0 @@ -import React from 'react'; -import AppBar from '@material-ui/core/AppBar'; -import Tabs from '@material-ui/core/Tabs'; -import Tab from '@material-ui/core/Tab'; -import Box from '@material-ui/core/Box'; -import { - Badge, - Paper, - Theme, - createStyles, - withStyles, - LinearProgress, -} from '@material-ui/core'; - -import { StyleRules } from '@material-ui/core/styles'; -import { StateType } from './state/app.types'; -import { connect } from 'react-redux'; -import InvestigationSearchTable from './table/investigationSearchTable.component'; -import DatasetSearchTable from './table/datasetSearchTable.component'; -import DatafileSearchTable from './table/datafileSearchTable.component'; -import { useTranslation } from 'react-i18next'; -import { - ViewCartButton, - CartProps, - parseSearchToQuery, - useDatafileCount, - useDatasetCount, - useInvestigationCount, - useLuceneSearch, - useUpdateQueryParam, -} from 'datagateway-common'; -import { useLocation } from 'react-router-dom'; -import { useIsFetching } from 'react-query'; -import { - getFilters, - getSorts, - storeFilters, - storeSort, -} from './searchPageContainer.component'; - -const badgeStyles = (theme: Theme): StyleRules => - createStyles({ - badge: { - backgroundColor: '#CCCCCC', - //Increase contrast on high contrast modes by using black text - color: - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (theme as any).colours?.type === 'contrast' ? '#000000' : '#333333', - fontSize: '14px', - fontWeight: 'bold', - lineHeight: 'inherit', - top: '1em', - }, - }); - -const tabStyles = (theme: Theme): StyleRules => - createStyles({ - root: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - backgroundColor: (theme as any).colours?.tabsGrey, - //Fixes contrast issue for unselected tabs in darkmode - color: - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (theme as any).palette.type === 'dark' - ? '#FFFFFF' - : // eslint-disable-next-line @typescript-eslint/no-explicit-any - (theme as any).colours?.blue, - boxShadow: 'none', - }, - indicator: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - backgroundColor: (theme as any).colours?.blue, - }, - }); - -const boxStyles = (theme: Theme): StyleRules => - createStyles({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - root: { backgroundColor: (theme as any).colours?.tabsGrey }, - }); - -export interface SearchTableProps { - containerHeight: string; - hierarchy: string; - onTabChange: (currentTab: string) => void; - currentTab: string; -} - -interface SearchTableStoreProps { - maxNumResults: number; - datasetTab: boolean; - datafileTab: boolean; - investigationTab: boolean; -} - -interface TabPanelProps { - children?: React.ReactNode; - index: string; - value: string; -} - -function TabPanel(props: TabPanelProps): React.ReactElement { - const { children, value, index, ...other } = props; - - return ( - - ); -} - -function a11yProps(index: string): React.ReactFragment { - return { - id: `simple-tab-${index}`, - 'aria-controls': `simple-tabpanel-${index}`, - }; -} - -const StyledBadge = withStyles(badgeStyles)(Badge); -const StyledTabs = withStyles(tabStyles)(Tabs); -const StyledBox = withStyles(boxStyles)(Box); - -const SearchPageTable = ( - props: SearchTableProps & SearchTableStoreProps & CartProps -): React.ReactElement => { - const { - maxNumResults, - investigationTab, - datasetTab, - datafileTab, - containerHeight, - hierarchy, - onTabChange, - currentTab, - cartItems, - navigateToDownload, - } = props; - const [t] = useTranslation(); - - const location = useLocation(); - const queryParams = React.useMemo(() => parseSearchToQuery(location.search), [ - location.search, - ]); - const { startDate, endDate } = queryParams; - const searchText = queryParams.searchText ? queryParams.searchText : ''; - - const { data: investigation } = useLuceneSearch('Investigation', { - searchText, - startDate, - endDate, - maxCount: maxNumResults, - }); - const { data: dataset } = useLuceneSearch('Dataset', { - searchText, - startDate, - endDate, - maxCount: maxNumResults, - }); - const { data: datafile } = useLuceneSearch('Datafile', { - searchText, - startDate, - endDate, - maxCount: maxNumResults, - }); - - const isFetchingNum = useIsFetching({ - predicate: (query) => - !query.queryHash.includes('InvestigationCount') && - !query.queryHash.includes('DatasetCount') && - !query.queryHash.includes('DatafileCount'), - }); - const loading = isFetchingNum > 0; - - const { filters, sort } = React.useMemo( - () => parseSearchToQuery(location.search), - [location.search] - ); - - const replaceFilters = useUpdateQueryParam('filters', 'replace'); - const replaceSorts = useUpdateQueryParam('sort', 'replace'); - - const handleChange = ( - event: React.ChangeEvent, - newValue: string - ): void => { - storeFilters(filters, currentTab); - storeSort(sort, currentTab); - - onTabChange(newValue); - - replaceFilters({}); - replaceSorts({}); - }; - - React.useEffect(() => { - const filters = getFilters(currentTab); - const sorts = getSorts(currentTab); - if (filters) replaceFilters(filters); - if (sorts) replaceSorts(sorts); - }, [currentTab, replaceFilters, replaceSorts]); - - const { data: investigationDataCount } = useInvestigationCount( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: investigation || [] }, - }), - }, - ], - getFilters('investigation') ?? {}, - currentTab - ); - - const { data: datasetDataCount } = useDatasetCount( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: dataset || [] }, - }), - }, - ], - getFilters('dataset') ?? {}, - currentTab - ); - - const { data: datafileDataCount } = useDatafileCount( - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: datafile || [] }, - }), - }, - ], - getFilters('datafile') ?? {}, - currentTab - ); - - const badgeDigits = (length?: number): 3 | 2 | 1 => { - return length ? (length >= 100 ? 3 : length >= 10 ? 2 : 1) : 1; - }; - - return ( -
- {/* Show loading progress if data is still being loaded */} - - {loading && } - - - - {investigationTab ? ( - - {investigationDataCount ?? 0} - - } - showZero - max={999} - > - - {t('tabs.investigation')} - - - } - value="investigation" - {...a11yProps('investigation')} - /> - ) : ( - - )} - {datasetTab ? ( - - - {t('tabs.dataset')} - - - } - value="dataset" - {...a11yProps('dataset')} - /> - ) : ( - - )} - {datafileTab ? ( - - - {t('tabs.datafile')} - - - } - value="datafile" - {...a11yProps('datafile')} - /> - ) : ( - - )} - - - - - - - {currentTab === 'investigation' && ( - - - - - - )} - {currentTab === 'dataset' && ( - - - - - - )} - {currentTab === 'datafile' && ( - - - - - - )} -
- ); -}; - -const mapStateToProps = (state: StateType): SearchTableStoreProps => { - return { - maxNumResults: state.dgsearch.maxNumResults, - datasetTab: state.dgsearch.tabs.datasetTab, - datafileTab: state.dgsearch.tabs.datafileTab, - investigationTab: state.dgsearch.tabs.investigationTab, - }; -}; - -export default connect(mapStateToProps)(SearchPageTable); diff --git a/packages/datagateway-search/src/searchTabs/searchTabLabel.component.tsx b/packages/datagateway-search/src/searchTabs/searchTabLabel.component.tsx new file mode 100644 index 000000000..24814d35f --- /dev/null +++ b/packages/datagateway-search/src/searchTabs/searchTabLabel.component.tsx @@ -0,0 +1,64 @@ +import React from 'react'; +import { Badge, badgeClasses, styled } from '@mui/material'; + +const StyledBadge = styled(Badge)(({ theme }) => ({ + [`& .${badgeClasses.badge}`]: { + backgroundColor: '#CCCCCC', + //Increase contrast on high contrast modes by using black text + color: + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (theme as any).colours?.type === 'contrast' ? '#000000' : '#333333', + fontSize: '14px', + fontWeight: 'bold', + lineHeight: 'inherit', + transform: 'none', + position: 'static', + }, +})); + +interface SearchTabLabelProps { + id: string; + label: string; + count: string; +} + +/** + * Label for tabs in {@link SearchTabs}. + * @constructor + */ +function SearchTabLabel({ + id, + label, + count, +}: SearchTabLabelProps): JSX.Element { + return ( + + {count} + + } + showZero + max={999} + > + + {label} + + + ); +} + +export default SearchTabLabel; diff --git a/packages/datagateway-search/src/searchTabs/searchTabs.component.test.tsx b/packages/datagateway-search/src/searchTabs/searchTabs.component.test.tsx new file mode 100644 index 000000000..8202fca48 --- /dev/null +++ b/packages/datagateway-search/src/searchTabs/searchTabs.component.test.tsx @@ -0,0 +1,621 @@ +import * as React from 'react'; +import type { StateType } from '../state/app.types'; +import { Provider } from 'react-redux'; +import configureStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { Router } from 'react-router-dom'; +import { + type DatasearchType, + dGCommonInitialState, + type SearchResponse, +} from 'datagateway-common'; +import axios, { type AxiosRequestConfig, type AxiosResponse } from 'axios'; +import { createMemoryHistory, type History } from 'history'; +import { render, screen, within } from '@testing-library/react'; +import { QueryClient, QueryClientProvider } from 'react-query'; + +import SearchTabs from './searchTabs.component'; +import { initialState } from '../state/reducers/dgsearch.reducer'; +import userEvent from '@testing-library/user-event'; +import { queryAllRows } from '../setupTests'; + +describe('SearchTabs', () => { + let state: StateType; + let history: History; + let user: ReturnType; + const mockStore = configureStore([thunk]); + let searchParams: URLSearchParams; + + const mockAxiosGet = ( + url: string, + config: AxiosRequestConfig + ): Promise> => { + if (/\/search\/documents$/.test(url)) { + const query = JSON.parse( + (config.params as URLSearchParams).get('query') ?? '{}' + ); + const searchType: DatasearchType = query?.target; + let searchResponse: SearchResponse; + switch (searchType) { + case 'Investigation': + searchResponse = { + dimensions: { + 'Investigation.type.name': { + experiment: 10, + }, + }, + results: [ + { + score: 1, + id: 1, + source: { + id: 1, + title: 'Test title 1', + name: 'Test name 1', + summary: 'foo bar', + visitId: '1', + doi: 'doi 1', + fileSize: 10, + fileCount: 9, + investigationinstrument: [ + { + 'instrument.id': 3, + 'instrument.name': 'LARMOR', + }, + ], + startDate: 1560121200000, + endDate: 1560207600000, + 'facility.name': 'facility name', + 'facility.id': 2, + }, + }, + ], + }; + break; + + case 'Dataset': + searchResponse = { + results: [ + { + score: 1, + id: 1, + source: { + id: 1, + name: 'Dataset test name', + startDate: 1563922800000, + endDate: 1564009200000, + fileSize: 10, + fileCount: 9, + investigationinstrument: [ + { + 'instrument.id': 4, + 'instrument.name': 'LARMOR', + }, + ], + 'investigation.id': 2, + 'investigation.title': 'Investigation test title', + 'investigation.name': 'Investigation test name', + 'investigation.startDate': 1560121200000, + }, + }, + ], + }; + break; + + case 'Datafile': + searchResponse = { + results: [ + { + score: 1, + id: 1, + source: { + id: 1, + name: 'Datafile test name', + location: '/datafiletest', + fileSize: 1, + fileCount: 1, + date: 1563836400000, + 'dataset.id': 2, + 'dataset.name': 'Dataset test name', + 'investigation.id': 3, + 'investigation.title': 'Investigation test title', + 'investigation.name': 'Investigation test name', + 'investigation.startDate': 1560121200000, + investigationinstrument: [ + { + 'instrument.id': 5, + 'instrument.name': 'LARMOR', + }, + ], + }, + }, + ], + }; + break; + } + + return Promise.resolve({ + data: searchResponse, + }); + } + + return Promise.reject(`Endpoint not mocked: ${url}`); + }; + + const Wrapper = ({ + children, + }: { + children: React.ReactNode; + }): JSX.Element => ( + + + + {children} + + + + ); + + beforeEach(() => { + searchParams = new URLSearchParams(); + searchParams.append('searchText', 'test'); + history = createMemoryHistory({ + initialEntries: [ + { + pathname: '/search/data', + search: searchParams.toString(), + }, + ], + }); + user = userEvent.setup(); + + state = JSON.parse( + JSON.stringify({ dgsearch: initialState, dgcommon: dGCommonInitialState }) + ); + + axios.get = jest.fn().mockImplementation(mockAxiosGet); + }); + + afterEach(() => { + jest.clearAllMocks(); + jest.resetAllMocks(); + }); + + it('renders tabs and empty tables when loading search query', async () => { + axios.get = jest.fn().mockImplementation( + () => + new Promise((_) => { + // never resolve the promise to pretend the search query is loading + }) + ); + + state.dgsearch = { + ...state.dgsearch, + tabs: { + datasetTab: true, + datafileTab: true, + investigationTab: true, + }, + }; + + render( + , + { wrapper: Wrapper } + ); + + const investigationTab = await screen.findByRole('tab', { + name: 'tabs.investigation', + }); + const datasetTab = screen.getByRole('tab', { name: 'tabs.dataset' }); + const datafileTab = screen.getByRole('tab', { name: 'tabs.datafile' }); + + expect(investigationTab).toBeInTheDocument(); + expect(investigationTab).toHaveAttribute('aria-selected', 'true'); + expect(within(investigationTab).getByText('?')).toBeInTheDocument(); + + expect(datasetTab).toBeInTheDocument(); + expect(datasetTab).toHaveAttribute('aria-selected', 'false'); + expect(within(datasetTab).getByText('?')).toBeInTheDocument(); + + expect(datafileTab).toBeInTheDocument(); + expect(datafileTab).toHaveAttribute('aria-selected', 'false'); + expect(within(datafileTab).getByText('?')).toBeInTheDocument(); + + expect(screen.getByTestId('investigation-search-table')).toBeVisible(); + expect( + screen.queryByTestId('dataset-search-table') + ).not.toBeInTheDocument(); + expect( + screen.queryByTestId('datafile-search-table') + ).not.toBeInTheDocument(); + + expect(queryAllRows()).toHaveLength(0); + }); + + it('renders search tables under their corresponding tabs', async () => { + state.dgsearch = { + ...state.dgsearch, + tabs: { + datasetTab: true, + datafileTab: true, + investigationTab: true, + }, + }; + + const { rerender } = render( + , + { wrapper: Wrapper } + ); + + const investigationTab = await screen.findByRole('tab', { + name: 'tabs.investigation', + }); + const datasetTab = screen.getByRole('tab', { name: 'tabs.dataset' }); + const datafileTab = screen.getByRole('tab', { name: 'tabs.datafile' }); + + expect(investigationTab).toBeInTheDocument(); + expect(investigationTab).toHaveAttribute('aria-selected', 'true'); + expect(await within(investigationTab).findByText('1')).toBeInTheDocument(); + + expect(datasetTab).toBeInTheDocument(); + expect(datasetTab).toHaveAttribute('aria-selected', 'false'); + expect(await within(datasetTab).findByText('1')).toBeInTheDocument(); + + expect(datafileTab).toBeInTheDocument(); + expect(datafileTab).toHaveAttribute('aria-selected', 'false'); + expect(await within(datafileTab).findByText('1')).toBeInTheDocument(); + + expect(screen.getByTestId('investigation-search-table')).toBeVisible(); + expect( + screen.queryByTestId('dataset-search-table') + ).not.toBeInTheDocument(); + expect( + screen.queryByTestId('datafile-search-table') + ).not.toBeInTheDocument(); + + rerender( + + ); + searchParams.set('currentTab', 'dataset'); + history.replace({ search: searchParams.toString() }); + + expect( + screen.queryByTestId('investigation-search-table') + ).not.toBeInTheDocument(); + expect(screen.getByTestId('dataset-search-table')).toBeVisible(); + expect( + screen.queryByTestId('datafile-search-table') + ).not.toBeInTheDocument(); + + rerender( + + ); + searchParams.set('currentTab', 'datafile'); + history.replace({ search: searchParams.toString() }); + + expect( + screen.queryByTestId('investigation-search-table') + ).not.toBeInTheDocument(); + expect( + screen.queryByTestId('dataset-search-table') + ).not.toBeInTheDocument(); + expect(screen.getByTestId('datafile-search-table')).toBeVisible(); + }); + + it('renders search card views under investigation & dataset tab but not datafile tab', async () => { + state.dgsearch = { + ...state.dgsearch, + tabs: { + datasetTab: true, + datafileTab: true, + investigationTab: true, + }, + }; + + const { rerender } = render( + , + { wrapper: Wrapper } + ); + + const investigationTab = await screen.findByRole('tab', { + name: 'tabs.investigation', + }); + const datasetTab = screen.getByRole('tab', { name: 'tabs.dataset' }); + const datafileTab = screen.getByRole('tab', { name: 'tabs.datafile' }); + + expect(investigationTab).toBeInTheDocument(); + expect(investigationTab).toHaveAttribute('aria-selected', 'true'); + // check that search result count is displayed correctly + expect(await within(investigationTab).findByText('1')).toBeInTheDocument(); + + expect(datasetTab).toBeInTheDocument(); + expect(datasetTab).toHaveAttribute('aria-selected', 'false'); + // check that search result count is displayed correctly + expect(await within(datasetTab).findByText('1')).toBeInTheDocument(); + + expect(datafileTab).toBeInTheDocument(); + expect(datafileTab).toHaveAttribute('aria-selected', 'false'); + // check that search result count is displayed correctly + expect(await within(datafileTab).findByText('1')).toBeInTheDocument(); + + expect(screen.getByTestId('investigation-search-card-view')).toBeVisible(); + expect( + screen.queryByTestId('dataset-search-card-view') + ).not.toBeInTheDocument(); + expect( + screen.queryByTestId('datafile-search-table') + ).not.toBeInTheDocument(); + + rerender( + + ); + searchParams.set('currentTab', 'dataset'); + history.replace({ search: searchParams.toString() }); + + expect( + screen.queryByTestId('investigation-search-card-view') + ).not.toBeInTheDocument(); + expect(screen.getByTestId('dataset-search-card-view')).toBeVisible(); + expect( + screen.queryByTestId('datafile-search-table') + ).not.toBeInTheDocument(); + + rerender( + + ); + searchParams.set('currentTab', 'datafile'); + history.replace({ search: searchParams.toString() }); + + expect( + screen.queryByTestId('investigation-search-card-view') + ).not.toBeInTheDocument(); + expect( + screen.queryByTestId('dataset-search-card-view') + ).not.toBeInTheDocument(); + expect(screen.getByTestId('datafile-search-table')).toBeVisible(); + }); + + it('changes selected tab value on click of a new tab', async () => { + state.dgsearch = { + ...state.dgsearch, + tabs: { + datasetTab: true, + datafileTab: true, + investigationTab: true, + }, + }; + + const onTabChange = jest.fn((newTab) => { + searchParams.set('currentTab', newTab); + history.replace({ search: searchParams.toString() }); + }); + + const { rerender } = render( + , + { wrapper: Wrapper } + ); + + const investigationTab = await screen.findByRole('tab', { + name: 'tabs.investigation', + }); + const datasetTab = screen.getByRole('tab', { name: 'tabs.dataset' }); + const datafileTab = screen.getByRole('tab', { name: 'tabs.datafile' }); + + expect(investigationTab).toBeInTheDocument(); + expect(investigationTab).toHaveAttribute('aria-selected', 'true'); + expect(await within(investigationTab).findByText('1')).toBeInTheDocument(); + + expect(datasetTab).toBeInTheDocument(); + expect(datasetTab).toHaveAttribute('aria-selected', 'false'); + expect(await within(datasetTab).findByText('1')).toBeInTheDocument(); + + expect(datafileTab).toBeInTheDocument(); + expect(datafileTab).toHaveAttribute('aria-selected', 'false'); + expect(await within(datafileTab).findByText('1')).toBeInTheDocument(); + + await user.click(datasetTab); + expect(onTabChange).toHaveBeenCalledWith('dataset'); + + rerender( + + ); + + expect( + screen.queryByTestId('investigation-search-table') + ).not.toBeInTheDocument(); + expect(screen.getByTestId('dataset-search-table')).toBeVisible(); + expect( + screen.queryByTestId('datafile-search-table') + ).not.toBeInTheDocument(); + }); + + it('resets search result count when filters are applied', async () => { + let isFilterApplied = false; + + axios.get = jest.fn().mockImplementation((url, config) => { + if (isFilterApplied) { + return new Promise((_) => { + // never resolve the promise to pretend it is loading + }); + } + return mockAxiosGet(url, config); + }); + + state.dgsearch = { + ...state.dgsearch, + tabs: { + datasetTab: true, + datafileTab: true, + investigationTab: true, + }, + }; + + render( + , + { wrapper: Wrapper } + ); + + const investigationTab = await screen.findByRole('tab', { + name: 'tabs.investigation', + }); + const datasetTab = screen.getByRole('tab', { name: 'tabs.dataset' }); + const datafileTab = screen.getByRole('tab', { name: 'tabs.datafile' }); + + // initial search count should be visible + expect(within(investigationTab).getByText('1')).toBeInTheDocument(); + expect(within(datasetTab).getByText('1')).toBeInTheDocument(); + expect(within(datafileTab).getByText('1')).toBeInTheDocument(); + + // apply some filters + await user.click( + screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.Investigation.type.name filter panel', + }) + ); + await user.click( + screen.getByRole('button', { name: 'Add experiment filter' }) + ); + + isFilterApplied = true; + await user.click(screen.getByRole('button', { name: 'facetPanel.apply' })); + + expect(await within(investigationTab).findByText('?')).toBeInTheDocument(); + }); + + it('redirects to download cart page when view card button is clicked', async () => { + const navigateToDownload = jest.fn(); + + render( + , + { wrapper: Wrapper } + ); + + expect(navigateToDownload).not.toBeCalled(); + + await user.click( + screen.getByRole('button', { name: 'app.cart_arialabel' }) + ); + + expect(navigateToDownload).toHaveBeenCalledTimes(1); + }); + + it('does not render disabled tabs', async () => { + state.dgsearch = { + ...state.dgsearch, + tabs: { + datasetTab: false, + datafileTab: true, + investigationTab: true, + }, + }; + + render( + , + { wrapper: Wrapper } + ); + + expect( + await screen.findByRole('tab', { name: 'tabs.investigation' }) + ).toBeInTheDocument(); + expect(screen.queryByRole('tab', { name: 'tabs.dataset' })).toBeNull(); + expect( + screen.getByRole('tab', { name: 'tabs.datafile' }) + ).toBeInTheDocument(); + }); +}); diff --git a/packages/datagateway-search/src/searchTabs/searchTabs.component.tsx b/packages/datagateway-search/src/searchTabs/searchTabs.component.tsx new file mode 100644 index 000000000..d74d90ae6 --- /dev/null +++ b/packages/datagateway-search/src/searchTabs/searchTabs.component.tsx @@ -0,0 +1,275 @@ +import React from 'react'; +import { + Box, + LinearProgress, + Paper, + styled, + Tab, + Tabs, + tabsClasses, +} from '@mui/material'; +import { CartProps, ViewCartButton, ViewsType } from 'datagateway-common'; +import { useTranslation } from 'react-i18next'; +import { useIsFetching } from 'react-query'; +import { useSelector } from 'react-redux'; +import type { StateType } from '../state/app.types'; +import InvestigationSearchTable from '../table/investigationSearchTable.component'; +import InvestigationCardView from '../card/investigationSearchCardView.component'; +import DatafileSearchTable from '../table/datafileSearchTable.component'; +import DatasetCardView from '../card/datasetSearchCardView.component'; +import DatasetSearchTable from '../table/datasetSearchTable.component'; +import SearchTabLabel from './searchTabLabel.component'; +import { + SearchResultCount, + SearchResultCountDispatch, + useSearchResultCounts, +} from './useSearchResultCounter'; + +interface TabPanelProps { + children?: React.ReactNode; + index: string; + value: string; +} + +function TabPanel(props: TabPanelProps): React.ReactElement { + const { children, value, index, ...other } = props; + + return ( + + ); +} + +function a11yProps(index: string): React.ReactFragment { + return { + id: `simple-tab-${index}`, + 'aria-controls': `simple-tabpanel-${index}`, + }; +} + +const StyledTabs = styled(Tabs)(({ theme }) => ({ + [`& .${tabsClasses.root}`]: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + backgroundColor: (theme as any).colours?.tabsGrey, + //Fixes contrast issue for unselected tabs in darkmode + color: + theme.palette.mode === 'dark' + ? '#FFFFFF' + : // eslint-disable-next-line @typescript-eslint/no-explicit-any + (theme as any).colours?.blue, + boxShadow: 'none', + }, +})); + +const StyledBox = styled(Box)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + // eslint-disable-next-line @typescript-eslint/no-explicit-any + backgroundColor: (theme as any).colours?.tabsGrey, +})); + +export interface SearchTabsProps { + view: ViewsType; + containerHeight: string; + hierarchy: string; + onTabChange: (currentTab: string) => void; + currentTab: string; +} + +const SearchTabs = ({ + view, + containerHeight, + hierarchy, + onTabChange, + currentTab, + cartItems, + navigateToDownload, +}: SearchTabsProps & CartProps): React.ReactElement => { + const isDatasetTabEnabled = useSelector( + (state: StateType) => state.dgsearch.tabs.datasetTab + ); + const isDatafileTabEnabled = useSelector( + (state: StateType) => state.dgsearch.tabs.datafileTab + ); + const isInvestigationTabEnabled = useSelector( + (state: StateType) => state.dgsearch.tabs.investigationTab + ); + const [t] = useTranslation(); + + const [searchResultCounts, dispatch] = useSearchResultCounts(); + + const isFetchingNum = useIsFetching({ + predicate: (query) => + !query.queryHash.includes('InvestigationCount') && + !query.queryHash.includes('DatasetCount') && + !query.queryHash.includes('DatafileCount'), + }); + const loading = isFetchingNum > 0; + + function handleChange( + event: React.ChangeEvent, + newValue: string + ): void { + onTabChange(newValue); + } + + /** + * Formats the given {@link SearchResultCount} as a user-facing label. + * If count is unknown, a question mark is shown. + * If count is concrete, the count is displayed literally. + * If there are more search results available, + * the count only counts the number of rows fetched, + * so a '+' is appended at the end of the count to indicate more rows are available. + * + * @param count The count to be formatted + */ + function formatSearchResultCount( + count: SearchResultCount | undefined + ): string { + if (count) { + return `${count.count}${count.hasMore ? '+' : ''}`; + } + return '?'; + } + + return ( +
+ {/* Show loading progress if data is still being loaded */} + {loading && } + + + {isInvestigationTabEnabled ? ( + + } + value="investigation" + {...a11yProps('investigation')} + /> + ) : ( + + )} + {isDatasetTabEnabled ? ( + + } + value="dataset" + {...a11yProps('dataset')} + /> + ) : ( + + )} + {isDatafileTabEnabled ? ( + + } + value="datafile" + {...a11yProps('datafile')} + /> + ) : ( + + )} + + + + + + + + {view === 'card' ? ( + + ) : ( + + + + )} + + + {view === 'card' ? ( + + ) : ( + + + + )} + + + + + + + +
+ ); +}; + +export default SearchTabs; diff --git a/packages/datagateway-search/src/searchTabs/useSearchResultCounter.test.tsx b/packages/datagateway-search/src/searchTabs/useSearchResultCounter.test.tsx new file mode 100644 index 000000000..5324fde47 --- /dev/null +++ b/packages/datagateway-search/src/searchTabs/useSearchResultCounter.test.tsx @@ -0,0 +1,213 @@ +import * as React from 'react'; +import { + type SearchResultCountAction, + SearchResultCountDispatch, + useSearchResultCounter, +} from './useSearchResultCounter'; +import { renderHook } from '@testing-library/react-hooks'; +import { mockSearchResponses } from '../testData'; + +describe('useSearchResultCounter', () => { + const mockDispatch: jest.MockedFn> = + jest.fn(); + + function Wrapper({ + children, + }: { + children: React.ReactNode; + }): React.ReactElement { + return ( + + {children} + + ); + } + + afterEach(() => { + jest.resetAllMocks(); + }); + + it('dispatches search result count for the given search responses', () => { + const { waitFor } = renderHook( + () => + useSearchResultCounter({ + dataSearchType: 'Investigation', + searchResponses: mockSearchResponses, + isFetching: false, + hasMore: false, + }), + { + wrapper: Wrapper, + } + ); + + waitFor(() => { + expect(mockDispatch).toHaveBeenLastCalledWith({ + type: 'UPDATE_SEARCH_RESULT_COUNT', + payload: { + type: 'Investigation', + count: 3, + hasMore: false, + }, + }); + }); + }); + + it('does not dispatch anything if search responses are undefined', () => { + renderHook( + () => + useSearchResultCounter({ + dataSearchType: 'Investigation', + isFetching: false, + hasMore: false, + }), + { + wrapper: Wrapper, + } + ); + + expect(mockDispatch).not.toBeCalled(); + }); + + it('resets search result count when isFetching is set to true', async () => { + const { waitFor, rerender } = renderHook< + Partial[0]>, + void + >( + (props) => + useSearchResultCounter({ + dataSearchType: 'Investigation', + searchResponses: mockSearchResponses, + isFetching: false, + hasMore: false, + ...props, + }), + { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + wrapper: Wrapper, + } + ); + + await waitFor(() => { + expect(mockDispatch).toHaveBeenLastCalledWith({ + type: 'UPDATE_SEARCH_RESULT_COUNT', + payload: { + type: 'Investigation', + count: 3, + hasMore: false, + }, + }); + }); + + rerender({ + isFetching: true, + }); + + await waitFor(() => { + expect(mockDispatch).toHaveBeenLastCalledWith({ + type: 'RESET_SEARCH_RESULT_COUNT', + payload: 'Investigation', + }); + }); + }); + + it('dispatches hasMore if set to true', () => { + const { waitFor } = renderHook( + () => + useSearchResultCounter({ + dataSearchType: 'Investigation', + searchResponses: mockSearchResponses, + isFetching: false, + hasMore: true, + }), + { wrapper: Wrapper } + ); + + waitFor(() => { + expect(mockDispatch).toHaveBeenCalledWith({ + type: 'UPDATE_SEARCH_RESULT_COUNT', + payload: { + type: 'Investigation', + count: 3, + hasMore: true, + }, + }); + }); + }); + + it('dispatches hasMore as false if hasMore not given', () => { + const { waitFor } = renderHook( + () => + useSearchResultCounter({ + dataSearchType: 'Investigation', + searchResponses: mockSearchResponses, + isFetching: false, + }), + { wrapper: Wrapper } + ); + + waitFor(() => { + expect(mockDispatch).toHaveBeenCalledWith({ + type: 'UPDATE_SEARCH_RESULT_COUNT', + payload: { + type: 'Investigation', + count: 3, + hasMore: false, + }, + }); + }); + }); + + it('dispatches the same search result count after fetching and the same search responses are given', async () => { + const { waitFor, rerender } = renderHook( + (props: Partial[0]>) => + useSearchResultCounter({ + dataSearchType: 'Investigation', + searchResponses: mockSearchResponses, + isFetching: false, + hasMore: false, + ...props, + }), + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + { wrapper: Wrapper } + ); + + await waitFor(() => { + expect(mockDispatch).toHaveBeenLastCalledWith({ + type: 'UPDATE_SEARCH_RESULT_COUNT', + payload: { + type: 'Investigation', + count: 3, + hasMore: false, + }, + }); + }); + + rerender({ isFetching: true }); + + await waitFor(() => { + expect(mockDispatch).toHaveBeenLastCalledWith({ + type: 'RESET_SEARCH_RESULT_COUNT', + payload: 'Investigation', + }); + }); + + rerender({ + isFetching: false, + searchResponses: mockSearchResponses, + }); + + await waitFor(() => { + expect(mockDispatch).toHaveBeenLastCalledWith({ + type: 'UPDATE_SEARCH_RESULT_COUNT', + payload: { + type: 'Investigation', + count: 3, + hasMore: false, + }, + }); + }); + }); +}); diff --git a/packages/datagateway-search/src/searchTabs/useSearchResultCounter.ts b/packages/datagateway-search/src/searchTabs/useSearchResultCounter.ts new file mode 100644 index 000000000..252af7277 --- /dev/null +++ b/packages/datagateway-search/src/searchTabs/useSearchResultCounter.ts @@ -0,0 +1,153 @@ +import { DatasearchType, SearchResponse } from 'datagateway-common'; +import React from 'react'; + +/** + * Stores number of search results for each entity type. + */ +type SearchResultCounts = { + [TType in DatasearchType]?: SearchResultCount; +}; + +interface SearchResultCount { + type: DatasearchType; + count: number; + hasMore: boolean; +} + +/** + * Dispatch this action to notify {@link SearchTabs} of the current count of + * the search results of the given {@link DatasearchType}. + */ +interface UpdateSearchResultCountAction { + type: 'UPDATE_SEARCH_RESULT_COUNT'; + payload: SearchResultCount; +} + +/** + * Dispatch this action to notify {@link SearchTabs} to reset the search results + * of the given {@link DatasearchType}. + * {@link SearchTabs} will forget the current count and will display its count as unknown. + */ +interface ResetSearchResultCountAction { + type: 'RESET_SEARCH_RESULT_COUNT'; + payload: DatasearchType; +} + +type SearchResultCountAction = + | UpdateSearchResultCountAction + | ResetSearchResultCountAction; + +/** + * Handles actions dispatched by search tables. + */ +function searchResultCountsReducer( + state: SearchResultCounts, + action: SearchResultCountAction +): SearchResultCounts { + switch (action.type) { + case 'RESET_SEARCH_RESULT_COUNT': + // make a copy of the current state + // and remove the search result count of the given data search type. + const next: SearchResultCounts = { ...state }; + delete next[action.payload]; + return next; + + case 'UPDATE_SEARCH_RESULT_COUNT': + return { + ...state, + [action.payload.type]: action.payload, + }; + + default: + return state; + } +} + +/** + * Context for dispatching search result count after they are available. + * Default value is the identity function (I don't want to deal with null values). + */ +const SearchResultCountDispatch = React.createContext< + React.Dispatch +>((_) => _); + +/** + * This hook stores the search result counts of various data search type. + * since only the actual data views (e.g. search tables) are responsible for fetching the actual search result + * for its own data search type (e.g. investigation search table fetches investigation search results) + * only they know the number of search results returned. + * + * since {@link SearchTabs} is responsible for displaying the search result counts next + * to each tab, it needs to obtain the counts from the data views. + * this is done by passing down the dispatch function returned by this hook + * that data views can call to pass the correct search result count when it is available. + * data views can also reset the count through the dispatch function. + * doing so erases the current search result count, and it will be shown as unknown to the users. + * for example, they can reset the count when they are fetching fresh data. + * + * the dispatch function is available through {@link SearchResultCountDispatch}. + */ +function useSearchResultCounts(): [ + SearchResultCounts, + React.Dispatch +] { + return React.useReducer(searchResultCountsReducer, {}); +} + +/** + * This hook counts the number of search results in the given + * array of SearchResponses, and then dispatches it to SearchTabs. + */ +function useSearchResultCounter({ + dataSearchType, + searchResponses, + isFetching, + hasMore, +}: { + dataSearchType: DatasearchType; + searchResponses?: SearchResponse[]; + isFetching?: boolean; + hasMore?: boolean; +}): void { + const dispatchSearchResultCount = React.useContext(SearchResultCountDispatch); + + React.useEffect(() => { + if (isFetching) { + dispatchSearchResultCount({ + type: 'RESET_SEARCH_RESULT_COUNT', + payload: dataSearchType, + }); + } else if (searchResponses) { + const searchResultCount = searchResponses.reduce( + (count, page) => count + (page.results?.length ?? 0), + 0 + ); + dispatchSearchResultCount({ + type: 'UPDATE_SEARCH_RESULT_COUNT', + payload: { + type: dataSearchType, + count: searchResultCount, + hasMore: hasMore ?? false, + }, + }); + } + }, [ + searchResponses, + dispatchSearchResultCount, + hasMore, + dataSearchType, + isFetching, + ]); +} + +export { + useSearchResultCounts, + useSearchResultCounter, + SearchResultCountDispatch, +}; +export type { + SearchResultCount, + SearchResultCountAction, + UpdateSearchResultCountAction, + ResetSearchResultCountAction, +}; diff --git a/packages/datagateway-search/src/settings.ts b/packages/datagateway-search/src/settings.ts index 38493a5c9..f1ddfc14d 100644 --- a/packages/datagateway-search/src/settings.ts +++ b/packages/datagateway-search/src/settings.ts @@ -8,6 +8,7 @@ export interface SearchSettings { icatUrl: string; selectAllSetting?: boolean; searchableEntities?: string[]; + minNumResults?: number; maxNumResults?: number; routes: PluginRoute[]; helpSteps?: { target: string; content: string }[]; diff --git a/packages/datagateway-search/src/setupTests.ts b/packages/datagateway-search/src/setupTests.ts index 68b6e1cf0..65ac5c818 100644 --- a/packages/datagateway-search/src/setupTests.ts +++ b/packages/datagateway-search/src/setupTests.ts @@ -1,17 +1,38 @@ -import Enzyme from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; -import { Action } from 'redux'; +/* eslint-disable @typescript-eslint/no-empty-function */ +import '@testing-library/jest-dom'; +import { Action, AnyAction } from 'redux'; import { StateType } from './state/app.types'; import { dGCommonInitialState } from 'datagateway-common'; import { initialState as dgSearchInitialState } from './state/reducers/dgsearch.reducer'; +import { screen, within } from '@testing-library/react'; +import failOnConsole from 'jest-fail-on-console'; +import { ThunkAction, ThunkDispatch } from 'redux-thunk'; +import { createLocation } from 'history'; -// React 16 Enzyme adapter -Enzyme.configure({ adapter: new Adapter() }); +failOnConsole(); + +jest.setTimeout(20000); function noOp(): void { // required as work-around for enzyme/jest environment not implementing window.URL.createObjectURL method } +// Mock Date.toLocaleDateString so that it always uses en-GB as locale and UTC timezone +// instead of using the system default, which can be different depending on the environment. +// save a reference to the original implementation of Date.toLocaleDateString + +const toLocaleDateString = Date.prototype.toLocaleDateString; + +jest + .spyOn(Date.prototype, 'toLocaleDateString') + .mockImplementation(function (this: Date) { + // when toLocaleDateString is called with no argument + // pass in 'en-GB' as the locale & UTC as timezone + // so that Date.toLocaleDateString() is equivalent to + // Date.toLocaleDateString('en-GB', { timeZone: 'UTC' }) + return toLocaleDateString.call(this, 'en-GB', { timeZone: 'UTC' }); + }); + if (typeof window.URL.createObjectURL === 'undefined') { Object.defineProperty(window.URL, 'createObjectURL', { value: noOp }); } @@ -21,13 +42,16 @@ export let actions: Action[] = []; export const resetActions = (): void => { actions = []; }; -export const getState = (): Partial => ({ +export const getState = (): StateType => ({ dgsearch: dgSearchInitialState, dgcommon: dGCommonInitialState, + router: { location: { ...createLocation('/'), query: {} }, action: 'POP' }, }); -export const dispatch = (action: Action): void | Promise => { +export const dispatch: ThunkDispatch = ( + action: Action | ThunkAction +) => { if (typeof action === 'function') { - action(dispatch, getState); + action(dispatch, getState, null); return Promise.resolve(); } else { actions.push(action); @@ -39,6 +63,103 @@ export const flushPromises = (): Promise => // Mock lodash.debounce to return the function we want to call. jest.mock('lodash.debounce', () => (fn: (args: unknown) => unknown) => fn); +jest.mock('@mui/utils/useId', () => + jest.fn().mockImplementation((id?: string) => id ?? 'mui-test-id') +); // Add in ResizeObserver as it's not in Jest's environment global.ResizeObserver = require('resize-observer-polyfill'); + +// MUI date pickers default to mobile versions during testing and so functions +// like .simulate('change') will not work, this workaround ensures desktop +// datepickers are used in tests instead +// https://github.com/mui/material-ui-pickers/issues/2073 +export const applyDatePickerWorkaround = (): void => { + // add window.matchMedia + // this is necessary for the date picker to be rendered in desktop mode. + // if this is not provided, the mobile mode is rendered, which might lead to unexpected behavior + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: (query: string) => ({ + media: query, + // this is the media query that @material-ui/pickers uses to determine if a device is a desktop device + matches: query === '(pointer: fine)', + onchange: () => {}, + addEventListener: () => {}, + removeEventListener: () => {}, + addListener: () => {}, + removeListener: () => {}, + dispatchEvent: () => false, + }), + }); +}; + +export const cleanupDatePickerWorkaround = (): void => { + // @ts-expect-error this is a workaround + delete window.matchMedia; +}; + +/** + * Finds the index of the column with the given name. + */ +export const findColumnIndexByName = async ( + columnName: string +): Promise => { + const columnHeaders = await screen.findAllByRole('columnheader'); + return columnHeaders.findIndex( + (header) => within(header).queryByText(columnName) !== null + ); +}; + +/** + * Find the header row of the table currently rendered. + * This assumes that the first row is always the header row. + */ +export const findColumnHeaderByName = async ( + name: string +): Promise => { + const columnHeaders = await screen.findAllByRole('columnheader'); + const header = columnHeaders.find( + (header) => within(header).queryByText(name) !== null + ); + if (!header) { + throw new Error(`Cannot find column header by name: ${name}`); + } + return header; +}; + +/** + * Finds all table rows except the header row. + */ +export const findAllRows = async (): Promise => + (await screen.findAllByRole('row')).slice(1); + +export const queryAllRows = (): HTMLElement[] => + screen.queryAllByRole('row').slice(1); + +/** + * Find the table row at the given index. This assumes the first table row is always the header row. + * + * @param index The index of the table row, igoring the header row. For example, if the table has 2 rows and the first row is the header row, + * the actual row that contains the data is considered the first row, and has an index of 0. + */ +export const findRowAt = async (index: number): Promise => { + const rows = await screen.findAllByRole('row'); + const row = rows[index + 1]; + if (!row) { + throw new Error(`Cannot find row at index ${index}`); + } + return row; +}; + +export const findCellInRow = ( + row: HTMLElement, + { columnIndex }: { columnIndex: number } +): HTMLElement => { + const cells = within(row).getAllByRole('gridcell'); + const cell = cells[columnIndex]; + if (!cell) { + throw new Error(`Cannot find cell in row.`); + } + return cell; +}; diff --git a/packages/datagateway-search/src/state/actions/actions.test.tsx b/packages/datagateway-search/src/state/actions/actions.test.tsx index cf9c94bb5..26eb57eca 100644 --- a/packages/datagateway-search/src/state/actions/actions.test.tsx +++ b/packages/datagateway-search/src/state/actions/actions.test.tsx @@ -1,12 +1,14 @@ import { configureApp, loadMaxNumResults, + loadMinNumResults, loadSearchableEntitites, loadSelectAllSetting, settingsLoaded, } from '.'; import { ConfigureMaxNumResultsType, + ConfigureMinNumResultsType, ConfigureSearchableEntitiesType, ConfigureSelectAllSettingType, SettingsLoadedType, @@ -60,7 +62,7 @@ describe('Actions', () => { maxNumResults: 150, }); const asyncAction = configureApp(); - await asyncAction(dispatch, getState); + await asyncAction(dispatch, getState, null); expect(actions.length).toEqual(6); expect(actions).toContainEqual(loadFacilityName('Generic')); @@ -90,7 +92,7 @@ describe('Actions', () => { icatUrl: 'icat', }); const asyncAction = configureApp(); - await asyncAction(dispatch, getState); + await asyncAction(dispatch, getState, null); expect(actions.length).toEqual(3); expect( @@ -109,8 +111,18 @@ describe('Actions', () => { it("doesn't send any actions when settings are undefined", async () => { mockSettingsGetter.mockReturnValue(undefined); const asyncAction = configureApp(); - await asyncAction(dispatch, getState); + await asyncAction(dispatch, getState, null); expect(actions.length).toEqual(0); }); + + describe('loadMinNumResults', () => { + it('returns an action with type ConfigureMinResultsType and a payload with the given min num results', () => { + const action = loadMinNumResults(20); + expect(action.type).toEqual(ConfigureMinNumResultsType); + expect(action.payload).toEqual({ + minNumResults: 20, + }); + }); + }); }); diff --git a/packages/datagateway-search/src/state/actions/actions.types.tsx b/packages/datagateway-search/src/state/actions/actions.types.tsx index 64a3ccc4f..f4aaa700c 100644 --- a/packages/datagateway-search/src/state/actions/actions.types.tsx +++ b/packages/datagateway-search/src/state/actions/actions.types.tsx @@ -8,6 +8,8 @@ export const ConfigureSelectAllSettingType = 'datagateway_search:configure_select_all'; export const ConfigureSearchableEntitiesType = 'datagateway_search:configure_searchable_entities'; +export const ConfigureMinNumResultsType = + 'datagateway_search:configure_min_num_results'; export const ConfigureMaxNumResultsType = 'datagateway_search:configure_max_num_results'; @@ -23,6 +25,10 @@ export interface ConfigureSearchableEntitiesPayload { entities: string[]; } +export interface ConfigureMinNumResultsPayload { + minNumResults: number; +} + export interface ConfigureMaxNumResultsPayload { maxNumResults: number; } diff --git a/packages/datagateway-search/src/state/actions/index.tsx b/packages/datagateway-search/src/state/actions/index.tsx index 272d99bda..a0c5f2d8d 100644 --- a/packages/datagateway-search/src/state/actions/index.tsx +++ b/packages/datagateway-search/src/state/actions/index.tsx @@ -7,6 +7,8 @@ import { SettingsLoadedType, ConfigureMaxNumResultsPayload, ConfigureMaxNumResultsType, + ConfigureMinNumResultsPayload, + ConfigureMinNumResultsType, } from './actions.types'; import { loadUrls, loadFacilityName } from 'datagateway-common'; import { Action } from 'redux'; @@ -43,6 +45,15 @@ export const loadMaxNumResults = ( }, }); +export const loadMinNumResults = ( + minNumResults: number +): ActionType => ({ + type: ConfigureMinNumResultsType, + payload: { + minNumResults: minNumResults, + }, +}); + export const configureApp = (): ThunkResult> => { return async (dispatch) => { const settingsResult = await settings; @@ -66,6 +77,10 @@ export const configureApp = (): ThunkResult> => { dispatch(loadSearchableEntitites(settingsResult['searchableEntities'])); } + if (settingsResult?.['minNumResults'] !== undefined) { + dispatch(loadMinNumResults(settingsResult['minNumResults'])); + } + if (settingsResult?.['maxNumResults'] !== undefined) { dispatch(loadMaxNumResults(settingsResult['maxNumResults'])); } diff --git a/packages/datagateway-search/src/state/app.types.tsx b/packages/datagateway-search/src/state/app.types.tsx index a49b46ead..fd41e48f1 100644 --- a/packages/datagateway-search/src/state/app.types.tsx +++ b/packages/datagateway-search/src/state/app.types.tsx @@ -12,6 +12,7 @@ export interface DGSearchState { settingsLoaded: boolean; sideLayout: boolean; searchableEntities: string[]; + minNumResults: number; maxNumResults: number; } diff --git a/packages/datagateway-search/src/state/reducers/dgsearch.reducer.test.tsx b/packages/datagateway-search/src/state/reducers/dgsearch.reducer.test.tsx index 7d4e22c2b..8c66c123e 100644 --- a/packages/datagateway-search/src/state/reducers/dgsearch.reducer.test.tsx +++ b/packages/datagateway-search/src/state/reducers/dgsearch.reducer.test.tsx @@ -7,6 +7,7 @@ import { } from '../actions/actions'; import { loadMaxNumResults, + loadMinNumResults, loadSearchableEntitites, loadSelectAllSetting, settingsLoaded, @@ -81,10 +82,18 @@ describe('dgsearch reducer', () => { }); it('should set maxNumResults property when configuring action is sent', () => { - expect(state.maxNumResults).toEqual(300); + expect(state.maxNumResults).toEqual(100); const updatedState = DGSearchReducer(state, loadMaxNumResults(200)); expect(updatedState.maxNumResults).toEqual(200); }); + + it('should set minNumResults property when configuring action is sent', () => { + expect(state.minNumResults).toEqual(initialState.minNumResults); + + const updatedState = DGSearchReducer(state, loadMinNumResults(20)); + + expect(updatedState.minNumResults).toEqual(20); + }); }); diff --git a/packages/datagateway-search/src/state/reducers/dgsearch.reducer.tsx b/packages/datagateway-search/src/state/reducers/dgsearch.reducer.tsx index 501bb8474..f3c49d087 100644 --- a/packages/datagateway-search/src/state/reducers/dgsearch.reducer.tsx +++ b/packages/datagateway-search/src/state/reducers/dgsearch.reducer.tsx @@ -12,6 +12,8 @@ import { ConfigureSearchableEntitiesType, ConfigureMaxNumResultsPayload, ConfigureMaxNumResultsType, + ConfigureMinNumResultsType, + ConfigureMinNumResultsPayload, } from '../actions/actions.types'; export const initialState: DGSearchState = { @@ -24,7 +26,8 @@ export const initialState: DGSearchState = { settingsLoaded: false, sideLayout: false, searchableEntities: ['investigation', 'dataset', 'datafile'], - maxNumResults: 300, + minNumResults: 10, + maxNumResults: 100, }; export function handleSettingsLoaded(state: DGSearchState): DGSearchState { @@ -103,6 +106,16 @@ export function handleConfigureMaxNumResults( }; } +export function handleConfigureMinNumResults( + state: DGSearchState, + payload: ConfigureMinNumResultsPayload +): DGSearchState { + return { + ...state, + minNumResults: payload.minNumResults, + }; +} + const DGSearchReducer = createReducer(initialState, { [SetDatasetTabType]: handleSetDatasetTab, [SetDatafileTabType]: handleSetDatafileTab, @@ -111,6 +124,7 @@ const DGSearchReducer = createReducer(initialState, { [ConfigureSelectAllSettingType]: handleConfigureSelectAllSetting, [ConfigureSearchableEntitiesType]: handleConfigureSearchableEntities, [ConfigureMaxNumResultsType]: handleConfigureMaxNumResults, + [ConfigureMinNumResultsType]: handleConfigureMinNumResults, }); export default DGSearchReducer; diff --git a/packages/datagateway-search/src/table/__snapshots__/datafileSearchTable.component.test.tsx.snap b/packages/datagateway-search/src/table/__snapshots__/datafileSearchTable.component.test.tsx.snap deleted file mode 100644 index f1317afb0..000000000 --- a/packages/datagateway-search/src/table/__snapshots__/datafileSearchTable.component.test.tsx.snap +++ /dev/null @@ -1,119 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Datafile search table component renders correctly 1`] = ` -Object { - "allIds": Array [ - 1, - ], - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "name", - "filterComponent": [Function], - "label": "datafiles.name", - }, - Object { - "dataKey": "location", - "filterComponent": [Function], - "label": "datafiles.location", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "fileSize", - "label": "datafiles.size", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "dataset.name", - "filterComponent": [Function], - "label": "datafiles.dataset", - }, - Object { - "dataKey": "modTime", - "filterComponent": [Function], - "label": "datafiles.modified_time", - }, - ], - "data": Array [ - Object { - "createTime": "2019-07-23", - "dataset": Object { - "createTime": "2019-07-23", - "endDate": "2019-07-25", - "id": 2, - "investigation": Object { - "doi": "doi 1", - "endDate": "2019-06-11", - "facility": Object { - "id": 8, - "name": "facility name", - }, - "id": 3, - "investigationInstruments": Array [ - Object { - "id": 4, - "instrument": Object { - "id": 5, - "name": "LARMOR", - }, - }, - ], - "name": "Investigation test name", - "size": 1, - "startDate": "2019-06-10", - "studyInvestigations": Array [ - Object { - "id": 6, - "investigation": Object { - "id": 3, - "name": "Investigation test name", - "title": "Investigation test title", - "visitId": "1", - }, - "study": Object { - "createTime": "2019-06-10", - "id": 7, - "modTime": "2019-06-10", - "name": "study name", - "pid": "study pid", - }, - }, - ], - "summary": "foo bar", - "title": "Investigation test title", - "visitId": "1", - }, - "modTime": "2019-07-23", - "name": "Dataset test name", - "size": 1, - "startDate": "2019-07-24", - }, - "fileSize": 1, - "id": 1, - "location": "/datafiletest", - "modTime": "2019-07-23", - "name": "Datafile test name", - }, - ], - "detailsPanel": [Function], - "disableSelectAll": false, - "loadMoreRows": [Function], - "loading": false, - "onCheck": [MockFunction], - "onSort": [Function], - "onUncheck": [MockFunction], - "selectedRows": Array [], - "sort": Object {}, - "totalRowCount": 0, -} -`; diff --git a/packages/datagateway-search/src/table/__snapshots__/datasetSearchTable.component.test.tsx.snap b/packages/datagateway-search/src/table/__snapshots__/datasetSearchTable.component.test.tsx.snap deleted file mode 100644 index d86cdcafb..000000000 --- a/packages/datagateway-search/src/table/__snapshots__/datasetSearchTable.component.test.tsx.snap +++ /dev/null @@ -1,265 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Dataset table component renders Dataset title as a link 1`] = ` - - - - - - - - Dataset test name - - - - - - - -`; - -exports[`Dataset table component renders correctly 1`] = ` -Object { - "allIds": Array [ - 1, - ], - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "name", - "filterComponent": [Function], - "label": "datasets.name", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "datafileCount", - "disableSort": true, - "label": "datasets.datafile_count", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "investigation.title", - "filterComponent": [Function], - "label": "datasets.investigation", - }, - Object { - "dataKey": "createTime", - "filterComponent": [Function], - "label": "datasets.create_time", - }, - Object { - "dataKey": "modTime", - "filterComponent": [Function], - "label": "datasets.modified_time", - }, - ], - "data": Array [ - Object { - "createTime": "2019-07-23", - "endDate": "2019-07-25", - "id": 1, - "investigation": Object { - "doi": "doi 1", - "endDate": "2019-06-11", - "facility": Object { - "id": 7, - "name": "facility name", - }, - "id": 2, - "investigationInstruments": Array [ - Object { - "id": 3, - "instrument": Object { - "id": 4, - "name": "LARMOR", - }, - }, - ], - "name": "Investigation test name", - "size": 1, - "startDate": "2019-06-10", - "studyInvestigations": Array [ - Object { - "id": 5, - "investigation": Object { - "id": 2, - "name": "Investigation test name", - "title": "Investigation test title", - "visitId": "1", - }, - "study": Object { - "createTime": "2019-06-10", - "id": 6, - "modTime": "2019-06-10", - "name": "study name", - "pid": "study pid", - }, - }, - ], - "summary": "foo bar", - "title": "Investigation test title", - "visitId": "1", - }, - "modTime": "2019-07-23", - "name": "Dataset test name", - "size": 1, - "startDate": "2019-07-24", - }, - ], - "detailsPanel": [Function], - "disableSelectAll": false, - "loadMoreRows": [Function], - "loading": false, - "onCheck": [MockFunction], - "onSort": [Function], - "onUncheck": [MockFunction], - "selectedRows": Array [], - "sort": Object {}, - "totalRowCount": 0, -} -`; diff --git a/packages/datagateway-search/src/table/__snapshots__/investigationSearchTable.component.test.tsx.snap b/packages/datagateway-search/src/table/__snapshots__/investigationSearchTable.component.test.tsx.snap deleted file mode 100644 index 8ff70a85a..000000000 --- a/packages/datagateway-search/src/table/__snapshots__/investigationSearchTable.component.test.tsx.snap +++ /dev/null @@ -1,366 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Investigation Search Table component renders correctly 1`] = ` -Object { - "allIds": Array [ - 1, - ], - "classes": Object { - "flexContainer": "VirtualizedTable-flexContainer-2", - "headerFlexContainer": "VirtualizedTable-headerFlexContainer-3", - "headerTableCell": "VirtualizedTable-headerTableCell-8", - "table": "VirtualizedTable-table-1", - "tableCell": "VirtualizedTable-tableCell-6", - "tableNoPadding": "VirtualizedTable-tableNoPadding-7", - "tableRow": "VirtualizedTable-tableRow-4", - "tableRowHover": "VirtualizedTable-tableRowHover-5", - }, - "columns": Array [ - Object { - "cellContentRenderer": [Function], - "dataKey": "title", - "filterComponent": [Function], - "label": "investigations.title", - }, - Object { - "dataKey": "visitId", - "filterComponent": [Function], - "label": "investigations.visit_id", - }, - Object { - "dataKey": "name", - "filterComponent": [Function], - "label": "investigations.name", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "doi", - "filterComponent": [Function], - "label": "investigations.doi", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "datasetCount", - "disableSort": true, - "label": "investigations.dataset_count", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "investigationInstruments.instrument.fullName", - "filterComponent": [Function], - "label": "investigations.instrument", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "startDate", - "filterComponent": [Function], - "label": "investigations.start_date", - }, - Object { - "cellContentRenderer": [Function], - "dataKey": "endDate", - "filterComponent": [Function], - "label": "investigations.end_date", - }, - ], - "data": Array [ - Object { - "doi": "doi 1", - "endDate": "2019-06-11", - "facility": Object { - "id": 2, - "name": "facility name", - }, - "id": 1, - "investigationInstruments": Array [ - Object { - "id": 1, - "instrument": Object { - "id": 3, - "name": "LARMOR", - }, - }, - ], - "name": "Test 1", - "size": 1, - "startDate": "2019-06-10", - "studyInvestigations": Array [ - Object { - "id": 6, - "investigation": Object { - "id": 1, - "name": "Test 1", - "title": "Test 1", - "visitId": "1", - }, - "study": Object { - "createTime": "2019-06-10", - "id": 7, - "modTime": "2019-06-10", - "name": "study name", - "pid": "study pid", - }, - }, - ], - "summary": "foo bar", - "title": "Test 1", - "visitId": "1", - }, - ], - "detailsPanel": [Function], - "disableSelectAll": false, - "loadMoreRows": [Function], - "loading": false, - "onCheck": [MockFunction], - "onSort": [Function], - "onUncheck": [MockFunction], - "selectedRows": Array [], - "sort": Object {}, - "totalRowCount": 0, -} -`; - -exports[`Investigation Search Table component renders title, visit ID, Name and DOI as links 1`] = ` - - - - - - - - Test 1 - - - - - - - -`; - -exports[`Investigation Search Table component renders title, visit ID, Name and DOI as links 2`] = `"1"`; - -exports[`Investigation Search Table component renders title, visit ID, Name and DOI as links 3`] = `"Test 1"`; - -exports[`Investigation Search Table component renders title, visit ID, Name and DOI as links 4`] = ` - - - - - - doi 1 - - - - - -`; diff --git a/packages/datagateway-search/src/table/datafileSearchTable.component.test.tsx b/packages/datagateway-search/src/table/datafileSearchTable.component.test.tsx index 37d89d69b..53425c30e 100644 --- a/packages/datagateway-search/src/table/datafileSearchTable.component.test.tsx +++ b/packages/datagateway-search/src/table/datafileSearchTable.component.test.tsx @@ -1,74 +1,134 @@ -import React from 'react'; -import { createMount } from '@material-ui/core/test-utils'; +import * as React from 'react'; import DatafileSearchTable from './datafileSearchTable.component'; import { initialState as dgSearchInitialState } from '../state/reducers/dgsearch.reducer'; import configureStore from 'redux-mock-store'; import { StateType } from '../state/app.types'; import { - Datafile, - useAddToCart, - useCart, - useDatafileCount, - useDatafilesInfinite, - useIds, - useLuceneSearch, - useRemoveFromCart, - useAllFacilityCycles, - ISISDatafileDetailsPanel, - DatafileDetailsPanel, - DLSDatafileDetailsPanel, + dGCommonInitialState, + DownloadCartItem, + SearchResponse, + SearchResult, + SearchResultSource, } from 'datagateway-common'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; import { Router } from 'react-router-dom'; -// this is a dependency of react-router so we already have it -// eslint-disable-next-line import/no-extraneous-dependencies import { createMemoryHistory, History } from 'history'; -import { dGCommonInitialState } from 'datagateway-common'; -import { ReactWrapper } from 'enzyme'; -import { QueryClientProvider, QueryClient } from 'react-query'; - -jest.mock('datagateway-common', () => { - const originalModule = jest.requireActual('datagateway-common'); - - return { - __esModule: true, - ...originalModule, - handleICATError: jest.fn(), - useCart: jest.fn(), - useLuceneSearch: jest.fn(), - useDatafileCount: jest.fn(), - useDatafilesInfinite: jest.fn(), - useIds: jest.fn(), - useAddToCart: jest.fn(), - useRemoveFromCart: jest.fn(), - useAllFacilityCycles: jest.fn(), - }; -}); +import { QueryClient, QueryClientProvider } from 'react-query'; +import { + findAllRows, + findCellInRow, + findColumnHeaderByName, + findColumnIndexByName, + findRowAt, + queryAllRows, +} from '../setupTests'; +import { + render, + type RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'; describe('Datafile search table component', () => { - let mount; const mockStore = configureStore([thunk]); let state: StateType; let history: History; - - let rowData: Datafile[] = []; - - const createWrapper = (hierarchy?: string): ReactWrapper => { - return mount( + let queryClient: QueryClient; + let user: ReturnType; + let cartItems: DownloadCartItem[]; + let rowData: SearchResultSource; + let searchResult: SearchResult; + let holder: HTMLElement; + + const renderComponent = (hierarchy?: string): RenderResult => + render( - + ); - }; + + function mockAxiosGet( + url: string, + config: AxiosRequestConfig + ): Promise> { + if (/\/user\/cart\/$/.test(url)) { + // fetch download cart + return Promise.resolve({ + data: { cartItems: [] }, + }); + } + + if (/\/search\/documents$/.test(url)) { + if ((config.params as URLSearchParams).get('query')?.includes('filter')) { + // filter is applied + return Promise.resolve>>>( + { + data: { + dimensions: { + 'Datafile.datafileFormat.name': { + txt: 1, + }, + }, + results: [], + }, + } + ); + } + + // query lucene data + return Promise.resolve>>>({ + data: { + dimensions: { + 'Datafile.datafileFormat.name': { + txt: 1, + }, + }, + results: [searchResult], + }, + }); + } + + if (/\/datafiles$/.test(url)) { + return Promise.resolve({ + data: [ + { + id: 1, + name: 'Datafile test name', + description: 'Test datafile description', + location: '/datafiletest', + fileSize: 1, + }, + ], + }); + } + + return Promise.reject(`endpoint not mocked: ${url}`); + } beforeEach(() => { - mount = createMount(); - history = createMemoryHistory(); + history = createMemoryHistory({ + initialEntries: [ + { search: '?searchText=test search¤tTab=datafile' }, + ], + }); + user = userEvent.setup(); + queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false }, + }, + }); + + holder = document.createElement('div'); + holder.setAttribute('id', 'datagateway-dataview'); + document.body.appendChild(holder); state = JSON.parse( JSON.stringify({ @@ -77,556 +137,787 @@ describe('Datafile search table component', () => { }) ); - rowData = [ - { - id: 1, - name: 'Datafile test name', - location: '/datafiletest', - fileSize: 1, - modTime: '2019-07-23', - createTime: '2019-07-23', - dataset: { - id: 2, - name: 'Dataset test name', - size: 1, - modTime: '2019-07-23', - createTime: '2019-07-23', - startDate: '2019-07-24', - endDate: '2019-07-25', - investigation: { - id: 3, - title: 'Investigation test title', - name: 'Investigation test name', - summary: 'foo bar', - visitId: '1', - doi: 'doi 1', - size: 1, - investigationInstruments: [ - { - id: 4, - instrument: { - id: 5, - name: 'LARMOR', + cartItems = []; + rowData = { + id: 1, + name: 'Datafile test name', + location: '/datafiletest', + fileSize: 1, + date: 1563854400000, + 'dataset.id': 2, + 'dataset.name': 'Dataset test name', + 'investigation.id': 3, + 'investigation.title': 'Investigation test title', + 'investigation.name': 'Investigation test name', + 'investigation.startDate': 1560139200000, + investigationinstrument: [ + { + 'instrument.id': 5, + 'instrument.name': 'LARMOR', + }, + ], + investigationfacilitycycle: [ + { + 'facilityCycle.id': 6, + }, + ], + }; + searchResult = { + score: 1, + id: 1, + source: rowData, + }; + + axios.get = jest.fn().mockImplementation(mockAxiosGet); + + axios.post = jest + .fn() + .mockImplementation( + (url: string, data: unknown): Promise> => { + if (/\/user\/cart\/\/cartItems$/.test(url)) { + const isRemove: boolean = JSON.parse( + (data as URLSearchParams).get('remove') ?? 'false' + ); + + if (isRemove) { + cartItems = []; + + return Promise.resolve({ + data: { + cardItems: [], }, - }, - ], - studyInvestigations: [ + }); + } + + cartItems = [ + ...cartItems, { - id: 6, - study: { - id: 7, - pid: 'study pid', - name: 'study name', - modTime: '2019-06-10', - createTime: '2019-06-10', - }, - investigation: { - id: 3, - title: 'Investigation test title', - name: 'Investigation test name', - visitId: '1', - }, + id: 1, + entityId: 1, + entityType: 'datafile', + name: 'download cart item name', + parentEntities: [], }, - ], - startDate: '2019-06-10', - endDate: '2019-06-11', - facility: { - id: 8, - name: 'facility name', - }, - }, - }, - }, - ]; + ]; - (useCart as jest.Mock).mockReturnValue({ - data: [], - }); - (useLuceneSearch as jest.Mock).mockReturnValue({ - data: [], - }); - (useDatafileCount as jest.Mock).mockReturnValue({ - data: 0, - }); - (useDatafilesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - (useIds as jest.Mock).mockReturnValue({ - data: [1], - }); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [], - }); + return Promise.resolve({ + data: { cartItems }, + }); + } + + return Promise.reject(`Endpoint not mocked: ${url}`); + } + ); }); afterEach(() => { - mount.cleanUp(); + document.body.removeChild(holder); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); + it('disables the search query if datafile search is disabled', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append('datafile', 'false'); + history.replace({ search: `?${searchParams.toString()}` }); + + renderComponent(); + + // check that column headers are shown correctly. + expect(await findColumnHeaderByName('datafiles.name')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.location') + ).toBeInTheDocument(); + expect(await findColumnHeaderByName('datafiles.size')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.dataset') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.modified_time') + ).toBeInTheDocument(); + + // wait for queries to finish fetching + await waitFor(() => !queryClient.isFetching()); + + expect( + queryClient.getQueryState(['search', 'Datafile'], { exact: false }) + ?.status + ).toBe('idle'); + + expect(queryAllRows()).toHaveLength(0); }); - it('calls the correct data fetching hooks on load', () => { - (useLuceneSearch as jest.Mock).mockReturnValue({ - data: [1], + it('renders search results correctly', async () => { + renderComponent(); + + // check that column headers are shown correctly. + expect(await findColumnHeaderByName('datafiles.name')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.location') + ).toBeInTheDocument(); + expect(await findColumnHeaderByName('datafiles.size')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.dataset') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datafiles.modified_time') + ).toBeInTheDocument(); + + const rows = await findAllRows(); + expect(rows).toHaveLength(1); + + // check that facet filter panel is present + expect(screen.getByText('facetPanel.title')).toBeInTheDocument(); + // apply filter button should be invisible initially + expect( + screen.queryByRole('button', { name: 'facetPanel.apply' }) + ).toBeNull(); + + const accordion = screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.Datafile.datafileFormat.name filter panel', }); - createWrapper(); + expect(accordion).toBeInTheDocument(); - expect(useCart).toHaveBeenCalled(); - expect(useLuceneSearch).toHaveBeenCalledWith('Datafile', { - searchText: '', - startDate: null, - endDate: null, - maxCount: 300, - }); + await user.click(accordion); - expect(useDatafileCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: [1] }, - }), - }, - ]); - expect(useDatafilesInfinite).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: [1] }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - dataset: { - investigation: { investigationInstruments: 'instrument' }, - }, - }), - }, - ]); - expect(useIds).toHaveBeenCalledWith( - 'datafile', - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: [1] }, - }), - }, - ], - true + const filterPanel = await screen.findByLabelText( + 'facetDimensionLabel.Datafile.datafileFormat.name filter panel' ); - expect(useAddToCart).toHaveBeenCalledWith('datafile'); - expect(useRemoveFromCart).toHaveBeenCalledWith('datafile'); + expect(filterPanel).toBeInTheDocument(); + expect( + within(filterPanel).getByRole('button', { name: 'Add txt filter' }) + ).toBeInTheDocument(); + + const row = rows[0]; + + // each cell in the row should contain the correct value + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.name'), + }) + ).getByText('Datafile test name') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.location'), + }) + ).getByText('/datafiletest') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.size'), + }) + ).getByText('1 B') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.dataset'), + }) + ).getByText('Dataset test name') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datafiles.modified_time'), + }) + ).getByText('23/07/2019') + ).toBeInTheDocument(); }); - it('calls fetchNextPage function of useDatafilesInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useDatafilesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); + it('applies selected facet filters correctly', async () => { + renderComponent(); + + // check that no filter chip is visible initially + const selectedFilters = await screen.findByLabelText('selectedFilters'); + expect( + within(selectedFilters).queryAllByText(/^facetDimensionLabel.*/) + ).toHaveLength(0); - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Datafile.datafileFormat.name filter panel', + }) + ); + // select the filter + await user.click( + await screen.findByRole('button', { + name: 'Add txt filter', + }) + ); + // apply the filter + await user.click(screen.getByRole('button', { name: 'facetPanel.apply' })); + + // when filter is applied, the fake axios get will return nothing + // so we should expect no rows in the table + await waitFor(() => { + expect(queryAllRows()).toHaveLength(0); }); - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Datafile.datafileFormat.name filter panel', + }) + ); + + const selectedFilterItem = await screen.findByRole('button', { + name: 'Remove txt filter', }); - }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + expect(selectedFilterItem).toBeInTheDocument(); + expect(within(selectedFilterItem).getByRole('checkbox')).toBeChecked(); - const filterInput = wrapper - .find('[aria-label="Filter by datafiles.name"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + // the selected filters should be displayed + expect(selectedFilters).toBeInTheDocument(); + expect( + within(selectedFilters).getByText( + 'facetDimensionLabel.Datafile.datafileFormat.name: txt' + ) + ).toBeInTheDocument(); + }); - expect(history.length).toBe(2); - expect(history.location.search).toBe( - `?filters=${encodeURIComponent( - '{"name":{"value":"test","type":"include"}}' - )}` + it('applies filters already present in the URL on first render', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append( + 'filters', + JSON.stringify({ + 'Datafile.datafileFormat.name': ['txt'], + }) ); + history.replace({ search: `?${searchParams.toString()}` }); - filterInput.instance().value = ''; - filterInput.simulate('change'); - - expect(history.length).toBe(3); - expect(history.location.search).toBe('?'); - }); + renderComponent(); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + // when filters are applied + // the fake axios.get returns no search results + // so we should expect no rows in the table + await waitFor(() => { + expect(queryAllRows()).toHaveLength(0); + }); - const filterInput = wrapper.find( - 'input[id="datafiles.modified_time filter to"]' + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Datafile.datafileFormat.name filter panel', + }) ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); - expect(history.length).toBe(2); - expect(history.location.search).toBe( - `?filters=${encodeURIComponent('{"modTime":{"endDate":"2019-08-06"}}')}` - ); + // filter should be selected + const filterItem = await screen.findByRole('button', { + name: 'Remove txt filter', + }); + expect(filterItem).toBeInTheDocument(); + expect(filterItem).toHaveAttribute('aria-selected', 'true'); + expect(within(filterItem).getByRole('checkbox')).toBeChecked(); + }); - filterInput.instance().value = ''; - filterInput.simulate('change'); + it('allows filters to be removed through the facet filter panel', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append( + 'filters', + JSON.stringify({ + 'Datafile.datafileFormat.name': ['txt'], + }) + ); + history.replace({ search: `?${searchParams.toString()}` }); - expect(history.length).toBe(3); - expect(history.location.search).toBe('?'); - }); + renderComponent(); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + // when filters are applied + // the fake axios.get returns no search results + // so we should expect no rows in the table + await waitFor(() => { + expect(queryAllRows()).toHaveLength(0); + }); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Datafile.datafileFormat.name filter panel', + }) + ); - expect(history.length).toBe(2); - expect(history.location.search).toBe( - `?sort=${encodeURIComponent('{"name":"asc"}')}` + await user.click( + await screen.findByRole('button', { + name: 'Remove txt filter', + }) ); - }); - it('calls addToCart mutate function on unchecked checkbox click', () => { - const addToCart = jest.fn(); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: addToCart, - loading: false, - }); - const wrapper = createWrapper(); + // apply the changes + await user.click(screen.getByRole('button', { name: 'facetPanel.apply' })); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + expect(await findAllRows()).toHaveLength(1); - expect(addToCart).toHaveBeenCalledWith([1]); - }); + const selectedFilterChips = screen.getByLabelText('selectedFilters'); + // check that the filter chip is removed + expect( + within(selectedFilterChips).queryByRole('button', { + name: 'facetDimensionLabel.Datafile.datafileFormat.name: txt', + }) + ).toBeNull(); - it('calls removeFromCart mutate function on checked checkbox click', () => { - (useCart as jest.Mock).mockReturnValue({ - data: [ - { - entityId: 1, - entityType: 'datafile', - id: 1, - name: 'test', - parentEntities: [], - }, - ], - }); + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Datafile.datafileFormat.name filter panel', + }) + ); - const removeFromCart = jest.fn(); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: removeFromCart, - loading: false, + // filter item should not be selected anymore + const filterItem = await screen.findByRole('button', { + name: 'Add txt filter', }); - const wrapper = createWrapper(); + expect(filterItem).toBeInTheDocument(); + expect(filterItem).toHaveAttribute('aria-selected', 'false'); + expect(within(filterItem).getByRole('checkbox')).not.toBeChecked(); + }); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + it('allows filters to be removed by removing filter chips', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append( + 'filters', + JSON.stringify({ + 'Datafile.datafileFormat.name': ['txt'], + }) + ); + history.replace({ search: `?${searchParams.toString()}` }); - expect(removeFromCart).toHaveBeenCalledWith([1]); - }); + renderComponent(); - it('selected rows only considers relevant cart items', () => { - (useCart as jest.Mock).mockReturnValue({ - data: [ - { - entityId: 1, - entityType: 'dataset', - id: 1, - name: 'test', - parentEntities: [], - }, - { - entityId: 2, - entityType: 'datafile', - id: 2, - name: 'test', - parentEntities: [], - }, - ], + // when filters are applied + // the fake axios.get returns no search results + // so we should expect no rows in the table + await waitFor(() => { + expect(queryAllRows()).toHaveLength(0); }); - const wrapper = createWrapper(); + const selectedFilterChips = screen.getByLabelText('selectedFilters'); + const chip = within(selectedFilterChips).getByRole('button', { + name: 'facetDimensionLabel.Datafile.datafileFormat.name: txt', + }); - const selectAllCheckbox = wrapper - .find('[aria-label="select all rows"]') - .first(); + await user.click(within(chip).getByTestId('CancelIcon')); - expect(selectAllCheckbox.prop('checked')).toEqual(false); - expect(selectAllCheckbox.prop('data-indeterminate')).toEqual(false); - }); + expect(await findAllRows()).toHaveLength(1); - it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', () => { - state.dgsearch.selectAllSetting = false; - - const wrapper = createWrapper(); + // check that the filter chip is removed + expect( + within(selectedFilterChips).queryByRole('button', { + name: 'facetDimensionLabel.Datafile.datafileFormat.name: txt', + }) + ).toBeNull(); - expect(useIds).toHaveBeenCalledWith('datafile', expect.anything(), false); - expect(useIds).not.toHaveBeenCalledWith( - 'datafile', - expect.anything(), - true + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Datafile.datafileFormat.name filter panel', + }) ); - expect(wrapper.find('[aria-label="select all rows"]')).toHaveLength(0); - }); - it('displays generic details panel when expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(DatafileDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); + // filter item should not be selected anymore + const filterItem = await screen.findByRole('button', { + name: 'Add txt filter', + }); - expect(wrapper.find(DatafileDetailsPanel).exists()).toBeTruthy(); + expect(filterItem).toBeInTheDocument(); + expect(filterItem).toHaveAttribute('aria-selected', 'false'); + expect(within(filterItem).getByRole('checkbox')).not.toBeChecked(); }); - it('displays correct details panel for ISIS when expanded', () => { - const wrapper = createWrapper('isis'); - expect(wrapper.find(ISISDatafileDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); - expect(wrapper.find(ISISDatafileDetailsPanel).exists()).toBeTruthy(); - }); + it('adds/removes rows to/from download cart', async () => { + renderComponent(); - it('displays correct details panel for DLS when expanded', () => { - const wrapper = createWrapper('dls'); - expect(wrapper.find(DLSDatafileDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); + const checkbox = await screen.findByRole('checkbox', { + name: 'select row 0', + }); - expect(wrapper.find(DLSDatafileDetailsPanel).exists()).toBeTruthy(); - }); + expect(checkbox).not.toBeChecked(); + expect(cartItems).toHaveLength(0); - // Not necessary as this should be a test of the formatBytes function - // it('renders file size as bytes', () => { - // const wrapper = mount( - // - // - // - // - // - // ); + await user.click(checkbox); - // expect(wrapper.find('[aria-colindex=5]').find('p').text()).toEqual('1 B'); - // }); + await waitFor(() => { + expect(checkbox).toBeChecked(); + expect(cartItems).toHaveLength(1); + }); - // new tests + await user.click(checkbox); - it('renders fine with incomplete data', () => { - // this can happen when navigating between tables and the previous table's state still exists - rowData = [ + await waitFor(() => { + expect(checkbox).not.toBeChecked(); + expect(cartItems).toHaveLength(0); + }); + }); + + it('selected rows only considers relevant cart items', async () => { + cartItems = [ { + entityId: 1, + entityType: 'dataset', id: 1, - name: 'Datafile test name', - location: '/datafiletest', - fileSize: 1, - modTime: '2019-07-23', - dataset: {}, + name: 'test', + parentEntities: [], + }, + { + entityId: 2, + entityType: 'datafile', + id: 2, + name: 'test', + parentEntities: [], }, ]; - (useDatafilesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), + + renderComponent(); + + const selectAllCheckbox = await screen.findByRole('checkbox', { + name: 'select all rows', }); - expect(() => createWrapper()).not.toThrowError(); + expect(selectAllCheckbox).not.toBeChecked(); }); - it('renders generic link correctly', () => { - const wrapper = createWrapper('data'); + it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', async () => { + state.dgsearch.selectAllSetting = false; + renderComponent(); + await waitFor(() => { + expect( + screen.queryByRole('checkbox', { name: 'select all rows' }) + ).toBeNull(); + }); + }); - expect(wrapper.find('[aria-colindex=3]').find('a').prop('href')).toEqual( - `/browse/investigation/3/dataset/2/datafile` - ); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Datafile test name' - ); + it('displays generic details panel when expanded', async () => { + renderComponent(); + + let rows: HTMLElement[] = []; + await waitFor(async () => { + rows = await findAllRows(); + expect(rows).toHaveLength(1); + }); + + const row = rows[0]; + await user.click(within(row).getByRole('button', { name: 'Show details' })); + + const detailsPanel = await screen.findByTestId('datafile-details-panel'); + + expect(detailsPanel).toBeInTheDocument(); + expect( + within(detailsPanel).getByText('Datafile test name') + ).toBeInTheDocument(); + expect(within(detailsPanel).getByText('1 B')).toBeInTheDocument(); + expect(within(detailsPanel).getByText('/datafiletest')).toBeInTheDocument(); }); - it('renders DLS link correctly', () => { - const wrapper = createWrapper('dls'); + it('displays correct details panel for ISIS when expanded', async () => { + renderComponent('isis'); - expect(wrapper.find('[aria-colindex=3]').find('a').prop('href')).toEqual( - '/browse/proposal/Dataset test name/investigation/3/dataset/2/datafile' - ); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Datafile test name' + let rows: HTMLElement[] = []; + await waitFor(async () => { + rows = await findAllRows(); + expect(rows).toHaveLength(1); + }); + + const row = rows[0]; + await user.click(within(row).getByRole('button', { name: 'Show details' })); + + const detailsPanel = await screen.findByTestId( + 'isis-datafile-details-panel' ); + + expect(detailsPanel).toBeInTheDocument(); + expect( + within(detailsPanel).getByText('Datafile test name') + ).toBeInTheDocument(); + expect( + within(detailsPanel).getByText('Test datafile description') + ).toBeInTheDocument(); + expect(within(detailsPanel).getByText('/datafiletest')).toBeInTheDocument(); + expect( + within(detailsPanel).getByRole('tab', { name: 'datafiles.details.label' }) + ).toBeInTheDocument(); + expect( + within(detailsPanel).queryByRole('tab', { + name: 'datafiles.details.parameters.label', + }) + ).toBeNull(); }); - it('renders ISIS link correctly', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], + it('displays correct details panel for DLS when expanded', async () => { + renderComponent('dls'); + + let rows: HTMLElement[] = []; + await waitFor(async () => { + rows = await findAllRows(); + expect(rows).toHaveLength(1); }); - const wrapper = createWrapper('isis'); + const row = rows[0]; + await user.click(within(row).getByRole('button', { name: 'Show details' })); - expect(wrapper.find('[aria-colindex=3]').find('a').prop('href')).toEqual( - `/browse/instrument/5/facilityCycle/4/investigation/3/dataset/2/datafile` - ); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Datafile test name' + const detailsPanel = await screen.findByTestId( + 'dls-datafile-details-panel' ); + + expect(detailsPanel).toBeInTheDocument(); + expect( + within(detailsPanel).getByText('Datafile test name') + ).toBeInTheDocument(); + expect(within(detailsPanel).getByText('1 B')).toBeInTheDocument(); + expect(within(detailsPanel).getByText('/datafiletest')).toBeInTheDocument(); }); - it('does not render ISIS link when instrumentId cannot be found', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], + it('renders generic link correctly', async () => { + renderComponent('data'); + + const datasetColIndex = await findColumnIndexByName('datafiles.dataset'); + + const row = await findRowAt(0); + const datasetLinkCell = await findCellInRow(row, { + columnIndex: datasetColIndex, }); - delete rowData[0].dataset?.investigation?.investigationInstruments; - (useDatafilesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), + + expect( + within(datasetLinkCell).getByRole('link', { name: 'Dataset test name' }) + ).toHaveAttribute('href', '/browse/investigation/3/dataset/2/datafile'); + }); + + it('renders DLS link correctly', async () => { + renderComponent('dls'); + + expect( + await screen.findByRole('link', { name: 'Datafile test name' }) + ).toHaveAttribute( + 'href', + '/browse/proposal/Investigation test name/investigation/3/dataset/2/datafile' + ); + const datasetColIndex = await findColumnIndexByName('datafiles.name'); + + const row = await findRowAt(0); + const datasetLinkCell = await findCellInRow(row, { + columnIndex: datasetColIndex, }); - const wrapper = createWrapper('isis'); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Datafile test name' + expect( + within(datasetLinkCell).getByRole('link', { name: 'Datafile test name' }) + ).toHaveAttribute( + 'href', + '/browse/proposal/Investigation test name/investigation/3/dataset/2/datafile' ); }); - it('does not render ISIS link when facilityCycleId cannot be found', () => { - const wrapper = createWrapper('isis'); + it('renders ISIS link correctly', async () => { + renderComponent('isis'); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Datafile test name' + const datasetColIndex = await findColumnIndexByName('datafiles.name'); + + const row = await findRowAt(0); + const datasetLinkCell = await findCellInRow(row, { + columnIndex: datasetColIndex, + }); + + expect( + within(datasetLinkCell).getByRole('link', { name: 'Datafile test name' }) + ).toHaveAttribute( + 'href', + '/browse/instrument/5/facilityCycle/6/investigation/3/dataset/2/datafile' ); }); - it('does not render ISIS link when facilityCycleId has incompatible dates', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 2, - name: 'facility cycle name', - startDate: '2020-06-11', - endDate: '2000-06-10', - }, - ], + it('does not render ISIS link when instrumentId cannot be found', async () => { + delete rowData.investigationinstrument; + + renderComponent('isis'); + + const datasetColIndex = await findColumnIndexByName('datafiles.name'); + + const row = await findRowAt(0); + const datasetLinkCell = await findCellInRow(row, { + columnIndex: datasetColIndex, }); - const wrapper = createWrapper('isis'); + await waitFor(() => { + expect( + within(datasetLinkCell).queryByRole('link', { + name: 'Datafile test name', + }) + ).toBeNull(); + }); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Datafile test name' - ); + expect( + within(datasetLinkCell).getByText('Datafile test name') + ).toBeInTheDocument(); }); - it('displays only the datafile name when there is no generic dataset to link to', () => { - rowData = [ - { - id: 1, - name: 'Datafile test name', - location: '/datafiletest', - fileSize: 1, - modTime: '2019-07-23', - dataset: {}, - }, - ]; - (useDatafilesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), + it('does not render ISIS link when facilityCycleId cannot be found', async () => { + delete rowData.investigationfacilitycycle; + + renderComponent('isis'); + + const datasetColIndex = await findColumnIndexByName('datafiles.name'); + + const row = await findRowAt(0); + const datasetLinkCell = await findCellInRow(row, { + columnIndex: datasetColIndex, }); - const wrapper = createWrapper('data'); + await waitFor(() => { + expect( + within(datasetLinkCell).queryByRole('link', { + name: 'Datafile test name', + }) + ).toBeNull(); + }); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Datafile test name' - ); + expect( + within(datasetLinkCell).getByText('Datafile test name') + ).toBeInTheDocument(); }); - it('displays only the datafile name when there is no DLS dataset to link to', () => { - rowData = [ - { - id: 1, - name: 'Datafile test name', - location: '/datafiletest', - fileSize: 1, - modTime: '2019-07-23', - dataset: {}, - }, - ]; - (useDatafilesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), + it('displays only the datafile name when there is no generic dataset to link to', async () => { + rowData = { + id: 1, + name: 'Datafile test name', + location: '/datafiletest', + fileSize: 1, + date: 1563836400000, + 'investigation.title': 'Investigation test title', + 'investigation.name': 'Investigation test name', + 'investigation.startDate': 1560121200000, + investigationinstrument: [ + { + 'instrument.id': 5, + 'instrument.name': 'LARMOR', + }, + ], + investigationfacilitycycle: [ + { + 'facilityCycle.id': 6, + }, + ], + }; + searchResult = { + score: 1, + id: 1, + source: rowData, + }; + + renderComponent('data'); + + const datasetColIndex = await findColumnIndexByName('datafiles.name'); + + const row = await findRowAt(0); + const datasetLinkCell = await findCellInRow(row, { + columnIndex: datasetColIndex, }); - const wrapper = createWrapper('dls'); + await waitFor(() => { + expect( + within(datasetLinkCell).queryByRole('link', { + name: 'Datafile test name', + }) + ).toBeNull(); + }); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Datafile test name' - ); + expect( + within(datasetLinkCell).getByText('Datafile test name') + ).toBeInTheDocument(); }); - it('displays only the datafile name when there is no ISIS investigation to link to', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ + it('displays only the datafile name when there is no DLS dataset to link to', async () => { + rowData = { + id: 1, + name: 'Datafile test name', + location: '/datafiletest', + fileSize: 1, + date: 1563836400000, + 'investigation.title': 'Investigation test title', + 'investigation.startDate': 1560121200000, + investigationinstrument: [ + { + 'instrument.id': 5, + 'instrument.name': 'LARMOR', + }, + ], + investigationfacilitycycle: [ { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', + 'facilityCycle.id': 6, }, ], + }; + searchResult = { + score: 1, + id: 1, + source: rowData, + }; + + renderComponent('dls'); + + const datasetColIndex = await findColumnIndexByName('datafiles.name'); + + const row = await findRowAt(0); + const datasetLinkCell = await findCellInRow(row, { + columnIndex: datasetColIndex, }); - rowData = [ - { - id: 1, - name: 'Datafile test name', - location: '/datafiletest', - fileSize: 1, - modTime: '2019-07-23', - dataset: {}, - }, - ]; - (useDatafilesInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), + + await waitFor(() => { + expect( + within(datasetLinkCell).queryByRole('link', { + name: 'Datafile test name', + }) + ).toBeNull(); }); - const wrapper = createWrapper('isis'); + expect( + within(datasetLinkCell).getByText('Datafile test name') + ).toBeInTheDocument(); + }); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Datafile test name' - ); + it('displays only the datafile name when there is no ISIS investigation to link to', async () => { + rowData = { + id: 1, + name: 'Datafile test name', + location: '/datafiletest', + fileSize: 1, + date: 1563836400000, + 'dataset.id': 2, + 'dataset.name': 'Dataset test name', + 'investigation.id': 3, + 'investigation.title': 'Investigation test title', + 'investigation.name': 'Investigation test name', + 'investigation.startDate': 1560121200000, + }; + searchResult = { + score: 1, + id: 1, + source: rowData, + }; + + renderComponent('isis'); + + const datasetColIndex = await findColumnIndexByName('datafiles.name'); + + const row = await findRowAt(0); + const datasetLinkCell = await findCellInRow(row, { + columnIndex: datasetColIndex, + }); + + await waitFor(() => { + expect( + within(datasetLinkCell).queryByRole('link', { + name: 'Datafile test name', + }) + ).toBeNull(); + }); + + expect( + within(datasetLinkCell).getByText('Datafile test name') + ).toBeInTheDocument(); }); }); diff --git a/packages/datagateway-search/src/table/datafileSearchTable.component.tsx b/packages/datagateway-search/src/table/datafileSearchTable.component.tsx index c2042cbd1..e5447afe9 100644 --- a/packages/datagateway-search/src/table/datafileSearchTable.component.tsx +++ b/packages/datagateway-search/src/table/datafileSearchTable.component.tsx @@ -1,231 +1,189 @@ -import React from 'react'; import { - Table, - formatBytes, - Datafile, - tableLink, - FacilityCycle, ColumnType, - Dataset, + DatafileDetailsPanel, + DLSDatafileDetailsPanel, + formatBytes, + ISISDatafileDetailsPanel, parseSearchToQuery, + SearchFilter, + SearchResponse, + SearchResultSource, + buildDatafileTableUrlForDataset, + buildDatasetLandingUrl, + buildUrlToDatafileTableContainingDatafile, + FACILITY_NAME, + isLandingPageSupportedForHierarchy, + Table, + tableLink, useAddToCart, - useAllFacilityCycles, useCart, - useDatafileCount, - useDatafilesInfinite, - useDateFilter, - useIds, - useLuceneSearch, - useSort, + useLuceneSearchInfinite, useRemoveFromCart, - useTextFilter, - DatafileDetailsPanel, - ISISDatafileDetailsPanel, - DLSDatafileDetailsPanel, + useSort, } from 'datagateway-common'; -import { TableCellProps, IndexRange } from 'react-virtualized'; +import type { TableCellProps } from 'react-virtualized'; +import React from 'react'; import { useTranslation } from 'react-i18next'; -import { useLocation } from 'react-router'; import { useSelector } from 'react-redux'; +import { useLocation } from 'react-router-dom'; import { StateType } from '../state/app.types'; +import { Grid, Paper, Typography } from '@mui/material'; +import FacetPanel from '../facet/components/facetPanel/facetPanel.component'; +import { facetClassificationFromSearchResponses } from '../facet/facet'; +import useFacetFilters from '../facet/useFacetFilters'; +import SelectedFilterChips from '../facet/components/selectedFilterChips.component'; +import { useSearchResultCounter } from '../searchTabs/useSearchResultCounter'; interface DatafileSearchTableProps { hierarchy: string; } -const DatafileSearchTable = ( - props: DatafileSearchTableProps -): React.ReactElement => { +const DatafileSearchTable: React.FC = (props) => { const { hierarchy } = props; - const { data: facilityCycles } = useAllFacilityCycles(hierarchy === 'isis'); - const location = useLocation(); - const queryParams = React.useMemo(() => parseSearchToQuery(location.search), [ - location.search, - ]); - const { startDate, endDate } = queryParams; + const queryParams = React.useMemo( + () => parseSearchToQuery(location.search), + [location.search] + ); + const { startDate, endDate, sort, filters, restrict, datafile, currentTab } = + queryParams; const searchText = queryParams.searchText ? queryParams.searchText : ''; const selectAllSetting = useSelector( (state: StateType) => state.dgsearch.selectAllSetting ); - const maxNumResults = useSelector( - (state: StateType) => state.dgsearch.maxNumResults + const minNumResults = useSelector( + (state: StateType) => state.dgsearch.minNumResults ); - const { data: luceneData } = useLuceneSearch('Datafile', { - searchText, - startDate, - endDate, - maxCount: maxNumResults, - }); - const [t] = useTranslation(); - - const { filters, sort } = React.useMemo( - () => parseSearchToQuery(location.search), - [location.search] + const maxNumResults = useSelector( + (state: StateType) => state.dgsearch.maxNumResults ); - const { data: totalDataCount } = useDatafileCount([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: luceneData || [] }, - }), - }, - ]); - const { fetchNextPage, data } = useDatafilesInfinite([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: luceneData || [] }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - dataset: { investigation: { investigationInstruments: 'instrument' } }, - }), - }, - ]); - const { data: allIds } = useIds( - 'datafile', - [ + const { fetchNextPage, data, hasNextPage, isFetching } = + useLuceneSearchInfinite( + 'Datafile', { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: luceneData || [] }, - }), + searchText, + startDate, + endDate, + sort, + minCount: minNumResults, + maxCount: maxNumResults, + restrict, + facets: [ + { target: 'Datafile' }, + { + target: 'DatafileParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - ], - selectAllSetting - ); - const { data: cartItems } = useCart(); - const { mutate: addToCart, isLoading: addToCartLoading } = useAddToCart( - 'datafile' - ); - const { - mutate: removeFromCart, - isLoading: removeFromCartLoading, - } = useRemoveFromCart('datafile'); + currentTab === 'datafile' ? filters : {}, + { + enabled: datafile, + // this select removes the facet count for the InvestigationInstrument.instrument.name + // facet since the number is confusing for datafiles + select: (data) => ({ + ...data, + pages: data.pages.map((searchResponse) => ({ + ...searchResponse, + dimensions: { + ...searchResponse.dimensions, + ...(searchResponse.dimensions?.[ + 'InvestigationInstrument.instrument.name' + ] + ? { + 'InvestigationInstrument.instrument.name': Object.keys( + searchResponse.dimensions?.[ + 'InvestigationInstrument.instrument.name' + ] + ).reduce( + ( + accumulator: { [key: string]: undefined }, + current: string + ) => { + accumulator[current] = undefined; + return accumulator; + }, + {} + ), + } + : {}), + }, + })), + }), + } + ); + const [t] = useTranslation(); - const aggregatedData: Dataset[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); + const { data: cartItems, isLoading: cartLoading } = useCart(); + const { mutate: addToCart, isLoading: addToCartLoading } = + useAddToCart('datafile'); + const { mutate: removeFromCart, isLoading: removeFromCartLoading } = + useRemoveFromCart('datafile'); - const textFilter = useTextFilter(filters); - const dateFilter = useDateFilter(filters); - const handleSort = useSort(); + useSearchResultCounter({ + isFetching, + dataSearchType: 'Datafile', + searchResponses: data?.pages, + hasMore: hasNextPage, + }); - const loadMoreRows = React.useCallback( - (offsetParams: IndexRange) => fetchNextPage({ pageParam: offsetParams }), - [fetchNextPage] - ); + function mapSource(response: SearchResponse): SearchResultSource[] { + return response.results?.map((result) => result.source) ?? []; + } - const dlsLink = ( - datafileData: Datafile, - linkType = 'datafile' - ): React.ReactElement | string => { - if (datafileData.dataset?.investigation) { - return linkType === 'dataset' - ? tableLink( - `/browse/proposal/${datafileData.dataset.investigation.name}/investigation/${datafileData.dataset.investigation?.id}/dataset/${datafileData.dataset.id}/datafile`, - datafileData.dataset.name - ) - : tableLink( - `/browse/proposal/${datafileData.dataset.name}/investigation/${datafileData.dataset.investigation.id}/dataset/${datafileData.dataset.id}/datafile`, - datafileData.name - ); + function mapIds(response: SearchResponse): number[] { + return response.results?.map((result) => result.id) ?? []; + } + + const { aggregatedSource, aggregatedIds, aborted } = React.useMemo(() => { + if (data) { + return { + aggregatedSource: data.pages + .map((response) => mapSource(response)) + .flat(), + aggregatedIds: data.pages.map((response) => mapIds(response)).flat(), + aborted: data.pages[data.pages.length - 1].aborted, + }; } - if (linkType === 'dataset') - return datafileData.dataset ? datafileData.dataset.name : ''; - return datafileData.name; - }; - const isisLink = React.useCallback( - (datafileData: Datafile, linkType = 'datafile') => { - let instrumentId; - let facilityCycleId; - if ( - datafileData.dataset?.investigation?.investigationInstruments?.length - ) { - instrumentId = - datafileData.dataset?.investigation?.investigationInstruments[0] - .instrument?.id; - } else { - if (linkType === 'dataset') - return datafileData.dataset ? datafileData.dataset.name : ''; - return datafileData.name; - } + return { + aggregatedSource: [], + aggregatedIds: [], + aborted: false, + }; + }, [data]); - if ( - facilityCycles?.length && - datafileData.dataset?.investigation?.startDate - ) { - const filteredFacilityCycles: FacilityCycle[] = facilityCycles?.filter( - (facilityCycle: FacilityCycle) => - datafileData.dataset?.investigation?.startDate && - facilityCycle.startDate && - facilityCycle.endDate && - datafileData.dataset.investigation.startDate >= - facilityCycle.startDate && - datafileData.dataset.investigation.startDate <= - facilityCycle.endDate - ); - if (filteredFacilityCycles.length) { - facilityCycleId = filteredFacilityCycles[0].id; - } - } + const { + selectedFacetFilters, + addFacetFilter, + removeFacetFilter, + applyFacetFilters, + haveUnappliedFilters, + } = useFacetFilters(); - if (facilityCycleId) { - return linkType === 'dataset' - ? tableLink( - `/browse/instrument/${instrumentId}/facilityCycle/${facilityCycleId}/investigation/${datafileData.dataset.investigation.id}/dataset/${datafileData.dataset.id}`, - datafileData.dataset.name - ) - : tableLink( - `/browse/instrument/${instrumentId}/facilityCycle/${facilityCycleId}/investigation/${datafileData.dataset.investigation.id}/dataset/${datafileData.dataset.id}/datafile`, - datafileData.name - ); - } - return linkType === 'dataset' ? '' : datafileData.name; - }, - [facilityCycles] + const handleSort = useSort(); + + const loadMoreRows = React.useCallback( + (_) => fetchNextPage(), + [fetchNextPage] ); - const genericLink = ( - datafileData: Datafile, - linkType = 'datafile' - ): React.ReactElement | string => { - if (datafileData.dataset?.investigation) { - return linkType === 'dataset' - ? tableLink( - `/browse/investigation/${datafileData.dataset.investigation.id}/dataset/${datafileData.dataset.id}/datafile`, - datafileData.dataset.name - ) - : tableLink( - `/browse/investigation/${datafileData.dataset.investigation.id}/dataset/${datafileData.dataset.id}/datafile`, - datafileData.name - ); - } - if (linkType === 'dataset') - return datafileData.dataset ? datafileData.dataset.name : ''; - return datafileData.name; + const removeFilterChip = ( + dimension: string, + filterValue: SearchFilter + ): void => { + removeFacetFilter({ dimension, filterValue, applyImmediately: true }); }; - const hierarchyLink = React.useMemo(() => { - if (hierarchy === 'dls') { - return dlsLink; - } else if (hierarchy === 'isis') { - return isisLink; - } else { - return genericLink; - } - }, [hierarchy, isisLink]); - const selectedRows = React.useMemo( () => cartItems @@ -234,10 +192,10 @@ const DatafileSearchTable = ( cartItem.entityType === 'datafile' && // if select all is disabled, it's safe to just pass the whole cart as selectedRows (!selectAllSetting || - (allIds && allIds.includes(cartItem.entityId))) + (aggregatedIds && aggregatedIds.includes(cartItem.entityId))) ) .map((cartItem) => cartItem.entityId), - [cartItems, selectAllSetting, allIds] + [cartItems, selectAllSetting, aggregatedIds] ); const columns: ColumnType[] = React.useMemo( @@ -246,15 +204,46 @@ const DatafileSearchTable = ( label: t('datafiles.name'), dataKey: 'name', cellContentRenderer: (cellProps: TableCellProps) => { - const datafileData = cellProps.rowData as Datafile; - return hierarchyLink(datafileData); + const datafileData = cellProps.rowData as SearchResultSource; + + if ( + !datafileData['dataset.id'] || + !datafileData['dataset.name'] || + !datafileData['investigation.id'] || + !datafileData['investigation.name'] + ) + return datafileData.name; + + const datafile = { + id: datafileData.id, + name: datafileData.name, + dataset: { + id: datafileData['dataset.id'], + name: datafileData['dataset.name'], + investigation: { + id: datafileData['investigation.id'], + name: datafileData['investigation.name'], + instrumentId: + datafileData.investigationinstrument?.[0]?.['instrument.id'], + facilityCycleId: + datafileData.investigationfacilitycycle?.[0]?.[ + 'facilityCycle.id' + ], + }, + }, + }; + const link = buildUrlToDatafileTableContainingDatafile({ + datafile, + facilityName: hierarchy, + }); + return link ? tableLink(link, datafile.name) : datafile.name; }, - filterComponent: textFilter, + disableSort: true, }, { label: t('datafiles.location'), dataKey: 'location', - filterComponent: textFilter, + disableSort: true, }, { label: t('datafiles.size'), @@ -262,45 +251,151 @@ const DatafileSearchTable = ( cellContentRenderer: (cellProps) => { return formatBytes(cellProps.cellData); }, + disableSort: true, }, { label: t('datafiles.dataset'), dataKey: 'dataset.name', cellContentRenderer: (cellProps: TableCellProps) => { - const datafileData = cellProps.rowData as Datafile; - return hierarchyLink(datafileData, 'dataset'); + const datafileData = cellProps.rowData as SearchResultSource; + + if ( + !datafileData['dataset.id'] || + !datafileData['dataset.name'] || + !datafileData['investigation.id'] || + !datafileData['investigation.name'] + ) + return datafileData['dataset.name'] ?? ''; + + const dataset = { + id: datafileData['dataset.id'], + name: datafileData['dataset.name'], + investigation: { + id: datafileData['investigation.id'], + name: datafileData['investigation.name'], + instrumentId: + datafileData.investigationinstrument?.[0]?.['instrument.id'], + facilityCycleId: + datafileData.investigationfacilitycycle?.[0]?.[ + 'facilityCycle.id' + ], + }, + }; + + const link = isLandingPageSupportedForHierarchy(hierarchy) + ? buildDatasetLandingUrl(dataset) + : buildDatafileTableUrlForDataset({ + dataset, + facilityName: hierarchy, + }); + return link ? tableLink(link, dataset.name) : dataset.name; }, - filterComponent: textFilter, + disableSort: true, }, { label: t('datafiles.modified_time'), - dataKey: 'modTime', - filterComponent: dateFilter, + dataKey: 'date', + disableSort: true, + cellContentRenderer: (cellProps: TableCellProps) => { + if (cellProps.cellData) { + return new Date(cellProps.cellData).toLocaleDateString(); + } + }, }, ], - [t, textFilter, dateFilter, hierarchyLink] + [t, hierarchy] ); let detailsPanel = DatafileDetailsPanel; - if (hierarchy === 'isis') detailsPanel = ISISDatafileDetailsPanel; - else if (hierarchy === 'dls') detailsPanel = DLSDatafileDetailsPanel; + if (hierarchy === FACILITY_NAME.isis) detailsPanel = ISISDatafileDetailsPanel; + else if (hierarchy === FACILITY_NAME.dls) + detailsPanel = DLSDatafileDetailsPanel; + + if (currentTab !== 'datafile') return null; return ( - + + + {data?.pages && ( + + addFacetFilter({ + dimension, + filterValue, + applyImmediately: false, + }) + } + onRemoveFilter={(dimension, filterValue) => + removeFacetFilter({ + dimension, + filterValue, + applyImmediately: false, + }) + } + onApplyFacetFilters={applyFacetFilters} + /> + )} + + + + + +
+ {aborted ? ( + + + {t('loading.abort_message')} + + + ) : ( +
+ )} + + + + + ); }; diff --git a/packages/datagateway-search/src/table/datasetSearchTable.component.test.tsx b/packages/datagateway-search/src/table/datasetSearchTable.component.test.tsx index 5e43331f2..69507407e 100644 --- a/packages/datagateway-search/src/table/datasetSearchTable.component.test.tsx +++ b/packages/datagateway-search/src/table/datasetSearchTable.component.test.tsx @@ -1,650 +1,927 @@ -import React from 'react'; -import { createMount } from '@material-ui/core/test-utils'; +import * as React from 'react'; import DatasetSearchTable from './datasetSearchTable.component'; import { initialState } from '../state/reducers/dgsearch.reducer'; import configureStore from 'redux-mock-store'; -import { StateType } from '../state/app.types'; +import type { StateType } from '../state/app.types'; import { - Dataset, dGCommonInitialState, - DatasetDetailsPanel, - ISISDatasetDetailsPanel, - DLSDatasetDetailsPanel, - useAddToCart, - useAllFacilityCycles, - useCart, - useDatasetCount, - useDatasetsDatafileCount, - useDatasetsInfinite, - useDatasetSizes, - useIds, - useLuceneSearch, - useRemoveFromCart, + type DownloadCartItem, + type LuceneSearchParams, + type SearchResponse, + type SearchResult, + FACILITY_NAME, } from 'datagateway-common'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; -import { ReactWrapper } from 'enzyme'; -import { QueryClientProvider, QueryClient } from 'react-query'; -// this is a dependency of react-router so we already have it -// eslint-disable-next-line import/no-extraneous-dependencies -import { createMemoryHistory, History } from 'history'; +import { QueryClient, QueryClientProvider } from 'react-query'; +import { createMemoryHistory, type History } from 'history'; import { Router } from 'react-router-dom'; - -jest.mock('datagateway-common', () => { - const originalModule = jest.requireActual('datagateway-common'); - - return { - __esModule: true, - ...originalModule, - useCart: jest.fn(), - useLuceneSearch: jest.fn(), - useDatasetCount: jest.fn(), - useDatasetsInfinite: jest.fn(), - useIds: jest.fn(), - useAddToCart: jest.fn(), - useRemoveFromCart: jest.fn(), - useAllFacilityCycles: jest.fn(), - useDatasetsDatafileCount: jest.fn(), - useDatasetSizes: jest.fn(), - }; -}); +import { + render, + type RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; +import axios, { AxiosRequestConfig, type AxiosResponse } from 'axios'; +import { mockDataset } from '../testData'; +import userEvent from '@testing-library/user-event'; +import { + findAllRows, + findCellInRow, + findColumnHeaderByName, + findColumnIndexByName, + queryAllRows, +} from '../setupTests'; + +// ====================== FIXTURES ====================== + +const mockSearchResults: SearchResult[] = [ + { + score: 1, + id: 1, + source: { + id: 1, + name: 'Dataset test name', + startDate: 1563940800000, + endDate: 1564027200000, + fileCount: 9, + fileSize: 10, + investigationinstrument: [ + { + 'instrument.id': 4, + 'instrument.name': 'LARMOR', + }, + ], + investigationfacilitycycle: [ + { + 'facilityCycle.id': 6, + }, + ], + 'investigation.id': 2, + 'investigation.title': 'Investigation test title', + 'investigation.name': 'Investigation test name', + 'investigation.startDate': 1560139200000, + }, + }, +]; + +const mockLuceneSearchParams: LuceneSearchParams = { + searchText: '', + startDate: null, + endDate: null, + sort: {}, + minCount: 10, + maxCount: 100, + restrict: true, + facets: [{ target: 'Dataset' }], + filters: {}, +}; + +// ====================== END FIXTURE ====================== describe('Dataset table component', () => { - let mount; const mockStore = configureStore([thunk]); + let container: HTMLDivElement; let state: StateType; let history: History; + let queryClient: QueryClient; + let user: ReturnType; + let cartItems: DownloadCartItem[]; - let rowData: Dataset[] = []; + let searchResponse: SearchResponse; - const createWrapper = (hierarchy?: string): ReactWrapper => { - return mount( + const renderComponent = (hierarchy?: string): RenderResult => { + return render( - + - + , + { container: document.body.appendChild(container) } ); }; + /** + * Mock implementation of axios.get + */ + const mockAxiosGet = ( + url: string, + config: AxiosRequestConfig + ): Promise> => { + if (/.*\/user\/cart\/.*$/.test(url)) { + // fetchDownloadCart + return Promise.resolve({ data: { cartItems } }); + } + if (/.*\/search\/documents$/.test(url)) { + // fetchLuceneData + + if ((config.params as URLSearchParams).get('query')?.includes('filter')) { + // filter is applied + return Promise.resolve>>>( + { + data: { + dimensions: { + 'Dataset.name': { + asd: 1, + }, + }, + results: [], + }, + } + ); + } + + return Promise.resolve>>({ + data: searchResponse, + }); + } + if (/.*\/datasets$/.test(url)) { + return Promise.resolve({ + data: [mockDataset], + }); + } + return Promise.reject(); + }; + beforeEach(() => { - mount = createMount(); - history = createMemoryHistory(); + user = userEvent.setup(); + + history = createMemoryHistory({ + initialEntries: [{ search: 'searchText=test search¤tTab=dataset' }], + }); + queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false }, + }, + }); + container = document.createElement('div'); + container.id = 'datagateway-search'; state = JSON.parse( JSON.stringify({ dgcommon: dGCommonInitialState, dgsearch: initialState }) ); - rowData = [ - { - id: 1, - name: 'Dataset test name', - size: 1, - modTime: '2019-07-23', - createTime: '2019-07-23', - startDate: '2019-07-24', - endDate: '2019-07-25', - investigation: { - id: 2, - title: 'Investigation test title', - name: 'Investigation test name', - summary: 'foo bar', - visitId: '1', - doi: 'doi 1', - size: 1, - investigationInstruments: [ - { - id: 3, - instrument: { - id: 4, - name: 'LARMOR', - }, - }, - ], - studyInvestigations: [ - { - id: 5, - study: { - id: 6, - pid: 'study pid', - name: 'study name', - modTime: '2019-06-10', - createTime: '2019-06-10', - }, - investigation: { - id: 2, - title: 'Investigation test title', - name: 'Investigation test name', - visitId: '1', - }, - }, - ], - startDate: '2019-06-10', - endDate: '2019-06-11', - facility: { - id: 7, - name: 'facility name', - }, + cartItems = []; + searchResponse = { + dimensions: { + 'Dataset.name': { + asd: 1, }, }, - ]; - (useCart as jest.Mock).mockReturnValue({ - data: [], - }); - (useLuceneSearch as jest.Mock).mockReturnValue({ - data: [], - }); - (useDatasetCount as jest.Mock).mockReturnValue({ - data: 0, - }); - (useDatasetsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - (useIds as jest.Mock).mockReturnValue({ - data: [1], - }); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, + results: mockSearchResults, + }; + + axios.get = jest.fn().mockImplementation(mockAxiosGet); + axios.post = jest.fn().mockImplementation((url: string) => { + if (/.*\/user\/cart\/.*\/cartItems$/.test(url)) { + return Promise.resolve({ data: { cartItems } }); + } + return Promise.reject(); }); - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [], - }); - (useDatasetsDatafileCount as jest.Mock).mockImplementation((datasets) => - (datasets - ? 'pages' in datasets - ? datasets.pages.flat() - : datasets - : [] - ).map(() => ({ - data: 1, - isFetching: false, - isSuccess: true, - })) - ); - (useDatasetSizes as jest.Mock).mockImplementation((datasets) => - (datasets - ? 'pages' in datasets - ? datasets.pages.flat() - : datasets - : [] - ).map(() => ({ - data: 1, - isFetching: false, - isSuccess: true, - })) - ); }); afterEach(() => { - mount.cleanUp(); jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); - }); + it('disables the search query if dataset search is disabled', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append('dataset', 'false'); + history.replace({ search: `?${searchParams.toString()}` }); - it('calls the correct data fetching hooks on load', () => { - (useLuceneSearch as jest.Mock).mockReturnValue({ - data: [1], - }); + renderComponent(); - createWrapper(); + // check that column headers are shown correctly. + expect(await findColumnHeaderByName('datasets.name')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.datafile_count') + ).toBeInTheDocument(); + expect(await findColumnHeaderByName('datasets.size')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.investigation') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.create_time') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.modified_time') + ).toBeInTheDocument(); - expect(useCart).toHaveBeenCalled(); - expect(useLuceneSearch).toHaveBeenCalledWith('Dataset', { - searchText: '', - startDate: null, - endDate: null, - maxCount: 300, - }); + // wait for queries to finish fetching + await waitFor(() => !queryClient.isFetching()); - expect(useDatasetCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: [1] }, - }), - }, - ]); - expect(useDatasetsInfinite).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: [1] }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - investigation: { investigationInstruments: 'instrument' }, - }), - }, - ]); - expect(useIds).toHaveBeenCalledWith( - 'dataset', - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: [1] }, - }), - }, - ], - true - ); + expect( + queryClient.getQueryState(['search', 'Dataset'], { exact: false })?.status + ).toBe('idle'); - expect(useAddToCart).toHaveBeenCalledWith('dataset'); - expect(useRemoveFromCart).toHaveBeenCalledWith('dataset'); - expect(useDatasetsDatafileCount).toHaveBeenCalledWith({ pages: [rowData] }); - expect(useDatasetSizes).toHaveBeenCalledWith(undefined); + expect(queryAllRows()).toHaveLength(0); }); - it('calls fetchNextPage function of useDatafilesInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useDatasetsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, - }); - const wrapper = createWrapper(); + it('renders search results correctly', async () => { + renderComponent(); - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, - }); + // check that column headers are shown correctly. + expect(await findColumnHeaderByName('datasets.name')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.datafile_count') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.investigation') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.create_time') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.modified_time') + ).toBeInTheDocument(); - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, + const rows = await findAllRows(); + expect(rows).toHaveLength(1); + + // check that facet filter panel is present + expect(screen.getByText('facetPanel.title')).toBeInTheDocument(); + // apply filter button should be invisible initially + expect( + screen.queryByRole('button', { name: 'facetPanel.apply' }) + ).toBeNull(); + + const accordion = screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.Dataset.name filter panel', }); - }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + expect(accordion).toBeInTheDocument(); - const filterInput = wrapper - .find('[aria-label="Filter by datasets.name"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + await user.click(accordion); - expect(history.length).toBe(2); - expect(history.location.search).toBe( - `?filters=${encodeURIComponent( - '{"name":{"value":"test","type":"include"}}' - )}` + const filterPanel = await screen.getByLabelText( + 'facetDimensionLabel.Dataset.name filter panel' ); - filterInput.instance().value = ''; - filterInput.simulate('change'); + expect(filterPanel).toBeInTheDocument(); + + const asdFilter = within(filterPanel).getByRole('button', { + name: 'Add asd filter', + }); + + expect(asdFilter).toBeInTheDocument(); + expect(within(asdFilter).getByText('asd')).toBeInTheDocument(); + expect(within(asdFilter).getByText('1')).toBeInTheDocument(); - expect(history.length).toBe(3); - expect(history.location.search).toBe('?'); + const row = rows[0]; + + // each cell in the row should contain the correct value + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.name'), + }) + ).getByText('Dataset test name') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.datafile_count'), + }) + ).getByText('9') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.size'), + }) + ).getByText('10 B') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.investigation'), + }) + ).getByText('Investigation test title') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.create_time'), + }) + ).getByText('24/07/2019') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.modified_time'), + }) + ).getByText('25/07/2019') + ).toBeInTheDocument(); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('renders search results in isis correctly', async () => { + renderComponent('isis'); - const filterInput = wrapper.find( - 'input[id="datasets.modified_time filter to"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + let rows: HTMLElement[] = []; + await waitFor(async () => { + rows = await findAllRows(); + expect(rows).toHaveLength(1); + }); - expect(history.length).toBe(2); - expect(history.location.search).toBe( - `?filters=${encodeURIComponent('{"modTime":{"endDate":"2019-08-06"}}')}` - ); + // check that column headers are shown correctly. + expect(await findColumnHeaderByName('datasets.name')).toBeInTheDocument(); + expect(await findColumnHeaderByName('datasets.size')).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.investigation') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.create_time') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('datasets.modified_time') + ).toBeInTheDocument(); - filterInput.instance().value = ''; - filterInput.simulate('change'); + const row = rows[0]; - expect(history.length).toBe(3); - expect(history.location.search).toBe('?'); + // each cell in the row should contain the correct value + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.name'), + }) + ).getByText('Dataset test name') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.size'), + }) + ).getByText('10 B') + ).toBeInTheDocument(); + expect( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.investigation'), + }) + ).toHaveTextContent('Investigation test title'); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.create_time'), + }) + ).getByText('24/07/2019') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('datasets.modified_time'), + }) + ).getByText('25/07/2019') + ).toBeInTheDocument(); }); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + it('applies selected filters correctly', async () => { + renderComponent(); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + // check that no filter chip is visible initially + const selectedFilters = await screen.findByLabelText('selectedFilters'); + expect( + within(selectedFilters).queryAllByText(/^facetDimensionLabel.*/) + ).toHaveLength(0); + + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Dataset.name filter panel', + }) + ); + // select the filter + await user.click( + await screen.findByRole('button', { + name: 'Add asd filter', + }) + ); + // apply the filter + await user.click(screen.getByRole('button', { name: 'facetPanel.apply' })); + + // when filter is applied, the fake axios get will return nothing + // so we should expect no rows in the table + await waitFor(() => { + expect(queryAllRows()).toHaveLength(0); + }); - expect(history.length).toBe(2); - expect(history.location.search).toBe( - `?sort=${encodeURIComponent('{"name":"asc"}')}` + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Dataset.name filter panel', + }) ); - }); - it('calls addToCart mutate function on unchecked checkbox click', () => { - const addToCart = jest.fn(); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: addToCart, - loading: false, + const selectedFilterItem = await screen.findByRole('button', { + name: 'Remove asd filter', }); - const wrapper = createWrapper(); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + expect(selectedFilterItem).toBeInTheDocument(); + expect(selectedFilterItem).toHaveAttribute('aria-selected', 'true'); + expect(within(selectedFilterItem).getByRole('checkbox')).toBeChecked(); - expect(addToCart).toHaveBeenCalledWith([1]); + // the selected filters should be displayed + expect(selectedFilters).toBeInTheDocument(); + expect( + within(selectedFilters).getByText('facetDimensionLabel.Dataset.name: asd') + ).toBeInTheDocument(); }); - it('calls removeFromCart mutate function on checked checkbox click', () => { - (useCart as jest.Mock).mockReturnValue({ - data: [ - { - entityId: 1, - entityType: 'dataset', - id: 1, - name: 'test', - parentEntities: [], - }, - ], + it('applies filters already present in the URL on first render', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append( + 'filters', + JSON.stringify({ + 'Dataset.name': ['asd'], + }) + ); + history.replace({ search: `?${searchParams.toString()}` }); + + renderComponent(); + + // when filters are applied + // the fake axios.get returns no search results + // so we should expect no rows in the table + await waitFor(() => { + expect(queryAllRows()).toHaveLength(0); }); - const removeFromCart = jest.fn(); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: removeFromCart, - loading: false, + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Dataset.name filter panel', + }) + ); + + // filter should be selected + const filterItem = await screen.findByRole('button', { + name: 'Remove asd filter', }); + expect(filterItem).toBeInTheDocument(); + expect(filterItem).toHaveAttribute('aria-selected', 'true'); + expect(within(filterItem).getByRole('checkbox')).toBeChecked(); + }); - const wrapper = createWrapper(); + it('allows filters to be removed through the facet filter panel', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append( + 'filters', + JSON.stringify({ + 'Dataset.name': ['asd'], + }) + ); + history.replace({ search: `?${searchParams.toString()}` }); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + renderComponent(); - expect(removeFromCart).toHaveBeenCalledWith([1]); - }); + const selectedFilterChips = await screen.findByLabelText('selectedFilters'); - it('selected rows only considers relevant cart items', () => { - (useCart as jest.Mock).mockReturnValue({ - data: [ - { - entityId: 1, - entityType: 'investigation', - id: 1, - name: 'test', - parentEntities: [], - }, - { - entityId: 2, - entityType: 'dataset', - id: 2, - name: 'test', - parentEntities: [], - }, - ], + expect( + within(selectedFilterChips).getByRole('button', { + name: 'facetDimensionLabel.Dataset.name: asd', + }) + ).toBeInTheDocument(); + + // when filters are applied + // the fake axios.get returns no search results + // so we should expect no rows in the table + await waitFor(() => { + expect(queryAllRows()).toHaveLength(0); }); - const wrapper = createWrapper(); + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Dataset.name filter panel', + }) + ); - const selectAllCheckbox = wrapper - .find('[aria-label="select all rows"]') - .first(); + await user.click( + await screen.findByRole('button', { + name: 'Remove asd filter', + }) + ); - expect(selectAllCheckbox.prop('checked')).toEqual(false); - expect(selectAllCheckbox.prop('data-indeterminate')).toEqual(false); - }); + // apply the changes + await user.click(screen.getByRole('button', { name: 'facetPanel.apply' })); - it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', () => { - state.dgsearch.selectAllSetting = false; + expect(await findAllRows()).toHaveLength(1); - const wrapper = createWrapper(); + // check that the filter chip is removed + expect( + within(selectedFilterChips).queryByRole('button', { + name: 'facetDimensionLabel.Dataset.name: paper', + }) + ).toBeNull(); + + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Dataset.name filter panel', + }) + ); - expect(useIds).toHaveBeenCalledWith('dataset', expect.anything(), false); - expect(useIds).not.toHaveBeenCalledWith('dataset', expect.anything(), true); - expect(wrapper.find('[aria-label="select all rows"]')).toHaveLength(0); + // filter item should not be selected anymore + const filterItem = await screen.findByRole('button', { + name: 'Add asd filter', + }); + expect(filterItem).toBeInTheDocument(); + expect(filterItem).toHaveAttribute('aria-selected', 'false'); + expect(within(filterItem).getByRole('checkbox')).not.toBeChecked(); }); - it('displays generic details panel when expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(DatasetDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); + it('allows filters to be removed by removing filter chips', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append( + 'filters', + JSON.stringify({ + 'Dataset.name': ['asd'], + }) + ); + history.replace({ search: `?${searchParams.toString()}` }); - expect(wrapper.find(DatasetDetailsPanel).exists()).toBeTruthy(); - }); + renderComponent(); - it('displays correct details panel for ISIS when expanded', () => { - const wrapper = createWrapper('isis'); - expect(wrapper.find(ISISDatasetDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); - expect(wrapper.find(ISISDatasetDetailsPanel).exists()).toBeTruthy(); - }); + // when filters are applied + // the fake axios.get returns no search results + // so we should expect no rows in the table + await waitFor(() => { + expect(queryAllRows()).toHaveLength(0); + }); - it('can navigate using the details panel for ISIS when there are facility cycles', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], + const selectedFilterChips = screen.getByLabelText('selectedFilters'); + const chip = within(selectedFilterChips).getByRole('button', { + name: 'facetDimensionLabel.Dataset.name: asd', }); - const wrapper = createWrapper('isis'); - expect(wrapper.find(ISISDatasetDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); + await user.click(within(chip).getByTestId('CancelIcon')); - expect(wrapper.find(ISISDatasetDetailsPanel).exists()).toBeTruthy(); + expect(await findAllRows()).toHaveLength(1); - wrapper.find('#dataset-datafiles-tab').first().simulate('click'); - expect(history.location.pathname).toBe( - '/browse/instrument/4/facilityCycle/4/investigation/2/dataset/1' + // check that the filter chip is removed + expect( + within(selectedFilterChips).queryByRole('button', { + name: 'facetDimensionLabel.Dataset.name: asd', + }) + ).toBeNull(); + + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Dataset.name filter panel', + }) ); + + // filter item should not be selected anymore + const filterItem = await screen.findByRole('button', { + name: 'Add asd filter', + }); + expect(filterItem).toBeInTheDocument(); + expect(filterItem).toHaveAttribute('aria-selected', 'false'); + expect(within(filterItem).getByRole('checkbox')).not.toBeChecked(); }); - it('displays correct details panel for DLS when expanded', () => { - const wrapper = createWrapper('dls'); - expect(wrapper.find(DLSDatasetDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); + it('should add the selected row to cart', async () => { + const addedCartItem: DownloadCartItem = { + entityId: 1, + entityType: 'dataset', + id: 1, + name: 'Test 1', + parentEntities: [], + }; - expect(wrapper.find(DLSDatasetDetailsPanel).exists()).toBeTruthy(); - }); + renderComponent(); + + // wait for data to finish loading + expect(await screen.findByText('Dataset test name')).toBeInTheDocument(); + + // pretend the server has added the row to the cart + // create a new array to trigger useMemo update + cartItems = [...cartItems, addedCartItem]; - it('renders Dataset title as a link', () => { - const wrapper = createWrapper(); + // clicks on the row checkbox + await user.click(screen.getByRole('checkbox', { name: 'select row 0' })); + // the checkbox should be checked expect( - wrapper.find('[aria-colindex=3]').find('p').children() - ).toMatchSnapshot(); + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).toBeChecked(); }); - // new tests + it('should remove the selected row from cart if it is in the cart', async () => { + const addedCartItem: DownloadCartItem = { + entityId: 1, + entityType: 'dataset', + id: 1, + name: 'Test 1', + parentEntities: [], + }; - it('renders fine with incomplete data', () => { - // this can happen when navigating between tables and the previous table's state still exists - rowData = [ + cartItems.push(addedCartItem); + + renderComponent(); + + // wait for data to finish loading + expect(await screen.findByText('Dataset test name')).toBeInTheDocument(); + + // pretend the server has removed the item from the cart + // create a new array to trigger useMemo update + cartItems = []; + + // clicks on the row checkbox + await user.click(screen.getByRole('checkbox', { name: 'select row 0' })); + + // the checkbox should not be checked + expect( + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).not.toBeChecked(); + }); + + it('selected rows only considers relevant cart items', async () => { + cartItems = [ { + entityId: 1, + entityType: 'investigation', id: 1, name: 'test', - size: 1, - modTime: '2019-07-23', - createTime: '2019-07-23', - investigation: {}, + parentEntities: [], + }, + { + entityId: 2, + entityType: 'dataset', + id: 2, + name: 'test', + parentEntities: [], }, ]; - (useDatasetsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), + + renderComponent(); + + const selectAllCheckbox = await screen.findByRole('checkbox', { + name: 'select all rows', }); - const consoleSpy = jest.spyOn(console, 'error').mockImplementation(); + expect(selectAllCheckbox).not.toBeChecked(); + expect(selectAllCheckbox).toHaveAttribute('data-indeterminate', 'false'); + }); + + it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', async () => { + state.dgsearch.selectAllSetting = false; - expect(() => createWrapper()).not.toThrowError(); + renderComponent(); - expect(consoleSpy).toHaveBeenCalled(); - consoleSpy.mockRestore(); + await waitFor(() => { + expect( + screen.queryByRole('checkbox', { name: 'select all rows' }) + ).toBeNull(); + }); }); - it('renders generic link & pending count correctly', () => { - (useDatasetsDatafileCount as jest.Mock).mockImplementation(() => [ - { - isFetching: true, - }, - ]); - const wrapper = createWrapper('data'); + it('displays generic details panel when expanded', async () => { + renderComponent(); - expect(wrapper.find('[aria-colindex=3]').find('a').prop('href')).toEqual( - `/browse/investigation/2/dataset/1/datafile` - ); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Dataset test name' + await user.click( + await screen.findByRole('button', { name: 'Show details' }) ); - expect(wrapper.find('[aria-colindex=4]').text()).toEqual('Calculating...'); + + expect( + await screen.findByTestId('dataset-details-panel') + ).toBeInTheDocument(); }); - it('renders DLS link correctly', () => { - const wrapper = createWrapper('dls'); + it('displays correct details panel for ISIS when expanded', async () => { + renderComponent(FACILITY_NAME.isis); - expect(wrapper.find('[aria-colindex=3]').find('a').prop('href')).toEqual( - '/browse/proposal/Investigation test name/investigation/2/dataset/1/datafile' - ); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Dataset test name' + await user.click( + await screen.findByRole('button', { name: 'Show details' }) ); + + expect( + await screen.findByTestId('isis-dataset-details-panel') + ).toBeInTheDocument(); }); - it('renders ISIS link & file sizes correctly', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 6, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], - }); + it('can navigate using the details panel for ISIS when there are facility cycles', async () => { + renderComponent(FACILITY_NAME.isis); - const wrapper = createWrapper('isis'); + await user.click( + await screen.findByRole('button', { name: 'Show details' }) + ); - expect(useDatasetSizes).toHaveBeenCalledWith({ pages: [rowData] }); - expect(useDatasetsDatafileCount).toHaveBeenCalledWith(undefined); + await user.click( + await screen.findByRole('tab', { + name: 'datasets.details.datafiles', + }) + ); - expect(wrapper.find('[aria-colindex=3]').find('a').prop('href')).toEqual( - `/browse/instrument/4/facilityCycle/6/investigation/2/dataset/1` + expect(history.location.pathname).toBe( + '/browse/instrument/4/facilityCycle/6/investigation/2/dataset/1/datafile' ); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Dataset test name' + }); + + it('displays correct details panel for DLS when expanded', async () => { + renderComponent(FACILITY_NAME.dls); + + await user.click( + await screen.findByRole('button', { name: 'Show details' }) ); - expect(wrapper.find('[aria-colindex=4]').text()).toEqual('1 B'); + + expect( + await screen.findByTestId('dls-dataset-details-panel') + ).toBeInTheDocument(); }); - it('does not render ISIS link when instrumentId cannot be found', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ + it('renders Dataset title as a link', async () => { + renderComponent(); + + expect( + await screen.findByRole('link', { name: 'Dataset test name' }) + ).toBeInTheDocument(); + }); + + it('renders fine with incomplete data', () => { + // this can happen when navigating between tables and the previous table's state still exists + searchResponse = { + results: [ { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', + ...mockSearchResults[0], + source: { + id: 1, + name: 'test', + }, }, ], - }); - delete rowData[0].investigation?.investigationInstruments; + }; - (useDatasetsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - const wrapper = createWrapper('isis'); + expect(() => renderComponent()).not.toThrowError(); + }); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Dataset test name' - ); + it('renders generic link correctly', async () => { + renderComponent('data'); + + expect( + await screen.findByRole('link', { name: 'Dataset test name' }) + ).toHaveAttribute('href', '/browse/investigation/2/dataset/1/datafile'); }); - it('does not render ISIS link when facilityCycleId cannot be found', () => { - const wrapper = createWrapper('isis'); + it('renders DLS link correctly', async () => { + renderComponent(FACILITY_NAME.dls); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Dataset test name' + expect( + await screen.findByRole('link', { name: 'Dataset test name' }) + ).toHaveAttribute( + 'href', + '/browse/proposal/Investigation test name/investigation/2/dataset/1/datafile' ); + expect(await screen.findByText('10 B')).toBeInTheDocument(); + expect(await screen.findByText('9')).toBeInTheDocument(); }); - it('does not render ISIS link when facilityCycleId has incompatible dates', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ + it('renders ISIS link & file sizes correctly', async () => { + renderComponent(FACILITY_NAME.isis); + + expect( + await screen.findByRole('link', { name: 'Dataset test name' }) + ).toBeInTheDocument(); + expect(await screen.findByText('10 B')).toBeInTheDocument(); + }); + + it('does not render ISIS link when instrumentId cannot be found', async () => { + const { investigationinstrument, ...data } = mockSearchResults[0].source; + searchResponse = { + results: [ { - id: 2, - name: 'facility cycle name', - startDate: '2020-06-11', - endDate: '2000-06-10', + ...mockSearchResults[0], + source: data, }, ], - }); + }; - const wrapper = createWrapper('isis'); + renderComponent(FACILITY_NAME.isis); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Dataset test name' - ); + await waitFor(async () => { + // the title should not be rendered as a link... + expect( + screen.queryByRole('link', { name: 'Dataset test name' }) + ).toBeNull(); + // ...but it should still be rendered as a normal text + expect(screen.getByText('Dataset test name')).toBeInTheDocument(); + }); + expect(await screen.findByText('10 B')).toBeInTheDocument(); }); - it('displays only the dataset name when there is no generic investigation to link to', () => { - delete rowData[0].investigation; - (useDatasetsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); + it('does not render ISIS link when facilityCycleId cannot be found', async () => { + const { investigationfacilitycycle, ...data } = mockSearchResults[0].source; + searchResponse = { + results: [ + { + ...mockSearchResults[0], + source: data, + }, + ], + }; - const wrapper = createWrapper('data'); + renderComponent(FACILITY_NAME.isis); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Dataset test name' - ); + await waitFor(async () => { + // the title should not be rendered as a link... + expect( + screen.queryByRole('link', { name: 'Dataset test name' }) + ).toBeNull(); + // ...but it should still be rendered as a normal text + expect(screen.getByText('Dataset test name')).toBeInTheDocument(); + }); }); - it('displays only the dataset name when there is no DLS investigation to link to', () => { - delete rowData[0].investigation; - (useDatasetsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); + it('displays only the dataset name when there is no generic investigation to link to', async () => { + const data = { ...mockSearchResults[0].source }; + delete data['investigation.id']; + delete data['investigation.name']; + delete data['investigation.title']; + delete data['investigation.startDate']; + searchResponse = { + results: [ + { + ...mockSearchResults[0], + source: data, + }, + ], + }; - const wrapper = createWrapper('dls'); + renderComponent('data'); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Dataset test name' - ); + await waitFor(async () => { + // the title should not be rendered as a link... + expect( + screen.queryByRole('link', { name: 'Dataset test name' }) + ).toBeNull(); + // ...but it should still be rendered as a normal text + expect(screen.getByText('Dataset test name')).toBeInTheDocument(); + }); }); - it('displays only the dataset name when there is no ISIS investigation to link to', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ + it('displays only the dataset name when there is no DLS investigation to link to', async () => { + const data = { ...mockSearchResults[0].source }; + delete data['investigation.id']; + delete data['investigation.name']; + delete data['investigation.title']; + delete data['investigation.startDate']; + searchResponse = { + results: [ { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', + ...mockSearchResults[0], + source: data, }, ], + }; + queryClient.setQueryData( + ['search', 'Dataset', mockLuceneSearchParams], + () => ({ + pages: [searchResponse], + }) + ); + renderComponent(FACILITY_NAME.dls); + + await waitFor(async () => { + // the title should not be rendered as a link... + expect( + screen.queryByRole('link', { name: 'Dataset test name' }) + ).toBeNull(); + // ...but it should still be rendered as a normal text + expect(screen.getByText('Dataset test name')).toBeInTheDocument(); }); - delete rowData[0].investigation; - (useDatasetsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - - const wrapper = createWrapper('isis'); + }); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual( - 'Dataset test name' + it('displays only the dataset name when there is no ISIS investigation to link to', async () => { + const data = { ...mockSearchResults[0].source }; + delete data['investigation.id']; + delete data['investigation.name']; + delete data['investigation.title']; + delete data['investigation.startDate']; + searchResponse = { + results: [ + { + ...mockSearchResults[0], + source: data, + }, + ], + }; + queryClient.setQueryData( + ['search', 'Dataset', mockLuceneSearchParams], + () => ({ + pages: [searchResponse], + }) ); + renderComponent(FACILITY_NAME.isis); + + await waitFor(async () => { + // the title should not be rendered as a link... + expect( + screen.queryByRole('link', { name: 'Dataset test name' }) + ).toBeNull(); + // ...but it should still be rendered as a normal text + expect(screen.getByText('Dataset test name')).toBeInTheDocument(); + }); }); }); diff --git a/packages/datagateway-search/src/table/datasetSearchTable.component.tsx b/packages/datagateway-search/src/table/datasetSearchTable.component.tsx index ba9e6157a..9b46e8c53 100644 --- a/packages/datagateway-search/src/table/datasetSearchTable.component.tsx +++ b/packages/datagateway-search/src/table/datasetSearchTable.component.tsx @@ -1,254 +1,196 @@ -import React from 'react'; import { + type ColumnType, + DatasetDetailsPanel, + DLSDatasetDetailsPanel, + ISISDatasetDetailsPanel, + parseSearchToQuery, + SearchFilter, + type SearchResponse, + type SearchResultSource, + buildDatafileTableUrlForDataset, + buildDatasetLandingUrl, + buildDatasetTableUrlForInvestigation, + buildInvestigationLandingUrl, + FACILITY_NAME, + isLandingPageSupportedForHierarchy, Table, - Dataset, tableLink, - FacilityCycle, - ColumnType, - formatCountOrSize, - parseSearchToQuery, useAddToCart, - useAllFacilityCycles, useCart, - useDatasetCount, - useDatasetsDatafileCount, - useDatasetsInfinite, - useDatasetSizes, - useDateFilter, - useIds, - useLuceneSearch, - useSort, + useLuceneSearchInfinite, useRemoveFromCart, - useTextFilter, - DatasetDetailsPanel, - ISISDatasetDetailsPanel, - DLSDatasetDetailsPanel, + useSort, + formatBytes, } from 'datagateway-common'; -import { TableCellProps, IndexRange } from 'react-virtualized'; +import React from 'react'; import { useTranslation } from 'react-i18next'; -import { useHistory, useLocation } from 'react-router'; import { useSelector } from 'react-redux'; -import { StateType } from '../state/app.types'; +import type { StateType } from '../state/app.types'; +import { Grid, Paper, Typography } from '@mui/material'; +import FacetPanel from '../facet/components/facetPanel/facetPanel.component'; +import { facetClassificationFromSearchResponses } from '../facet/facet'; +import useFacetFilters from '../facet/useFacetFilters'; +import SelectedFilterChips from '../facet/components/selectedFilterChips.component'; +import { useSearchResultCounter } from '../searchTabs/useSearchResultCounter'; +import { useHistory, useLocation } from 'react-router-dom'; +import type { IndexRange, TableCellProps } from 'react-virtualized'; interface DatasetTableProps { hierarchy: string; } -const DatasetSearchTable = (props: DatasetTableProps): React.ReactElement => { - const { hierarchy } = props; - - const { data: facilityCycles } = useAllFacilityCycles(hierarchy === 'isis'); - +const DatasetSearchTable: React.FC = ({ hierarchy }) => { const location = useLocation(); const { push } = useHistory(); - const queryParams = React.useMemo(() => parseSearchToQuery(location.search), [ - location.search, - ]); - const { startDate, endDate } = queryParams; - const searchText = queryParams.searchText ? queryParams.searchText : ''; - - const selectAllSetting = useSelector( - (state: StateType) => state.dgsearch.selectAllSetting - ); - - const maxNumResults = useSelector( - (state: StateType) => state.dgsearch.maxNumResults - ); - - const { data: luceneData } = useLuceneSearch('Dataset', { - searchText, - startDate, - endDate, - maxCount: maxNumResults, - }); - const [t] = useTranslation(); - - const { filters, sort } = React.useMemo( + const queryParams = React.useMemo( () => parseSearchToQuery(location.search), [location.search] ); - - const { data: totalDataCount } = useDatasetCount([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: luceneData || [] }, - }), - }, - ]); - const { fetchNextPage, data } = useDatasetsInfinite([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: luceneData || [] }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - investigation: { investigationInstruments: 'instrument' }, - }), - }, - ]); - const { data: allIds } = useIds( - 'dataset', - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: luceneData || [] }, - }), - }, - ], - selectAllSetting - ); - const { data: cartItems } = useCart(); - const { mutate: addToCart, isLoading: addToCartLoading } = useAddToCart( - 'dataset' - ); const { - mutate: removeFromCart, - isLoading: removeFromCartLoading, - } = useRemoveFromCart('dataset'); + startDate, + endDate, + sort, + filters, + restrict, + searchText, + dataset, + currentTab, + } = queryParams; - const aggregatedData: Dataset[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] + const selectAllSetting = useSelector( + (state: StateType) => state.dgsearch.selectAllSetting ); - const textFilter = useTextFilter(filters); - const dateFilter = useDateFilter(filters); - const handleSort = useSort(); - - const loadMoreRows = React.useCallback( - (offsetParams: IndexRange) => fetchNextPage({ pageParam: offsetParams }), - [fetchNextPage] + const minNumResults = useSelector( + (state: StateType) => state.dgsearch.minNumResults ); - const dlsLinkURL = ( - datasetData: Dataset, - linkType = 'dataset' - ): string | null => { - if (datasetData.investigation) { - return linkType === 'investigation' - ? `/browse/proposal/${datasetData.investigation.name}/investigation/${datasetData.investigation.id}/dataset` - : `/browse/proposal/${datasetData.investigation.name}/investigation/${datasetData.investigation.id}/dataset/${datasetData.id}/datafile`; - } - return null; - }; - - const dlsLink = React.useCallback( - ( - datasetData: Dataset, - linkType = 'dataset' - ): React.ReactElement | string => { - const linkURL = dlsLinkURL(datasetData, linkType); - - if (datasetData.investigation && linkURL) { - return linkType === 'investigation' - ? tableLink(linkURL, datasetData.investigation.title) - : tableLink(linkURL, datasetData.name); - } - return linkType === 'investigation' ? '' : datasetData.name; - }, - [] + const maxNumResults = useSelector( + (state: StateType) => state.dgsearch.maxNumResults ); - const isisLinkURL = React.useCallback( - (datasetData: Dataset, linkType = 'dataset') => { - let instrumentId; - let facilityCycleId; - if (datasetData.investigation?.investigationInstruments?.length) { - instrumentId = - datasetData.investigation?.investigationInstruments[0].instrument?.id; - } else { - return null; + const { fetchNextPage, data, hasNextPage, isFetching } = + useLuceneSearchInfinite( + 'Dataset', + { + searchText: searchText ?? '', + startDate, + endDate, + sort, + minCount: minNumResults, + maxCount: maxNumResults, + restrict, + facets: [ + { target: 'Dataset' }, + { + target: 'DatasetParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], + }, + currentTab === 'dataset' ? filters : {}, + { + enabled: dataset, + // this select removes the facet count for the InvestigationInstrument.instrument.name + // facet since the number is confusing for datafiles + select: (data) => ({ + ...data, + pages: data.pages.map((searchResponse) => ({ + ...searchResponse, + dimensions: { + ...searchResponse.dimensions, + ...(searchResponse.dimensions?.[ + 'InvestigationInstrument.instrument.name' + ] + ? { + 'InvestigationInstrument.instrument.name': Object.keys( + searchResponse.dimensions?.[ + 'InvestigationInstrument.instrument.name' + ] + ).reduce( + ( + accumulator: { [key: string]: undefined }, + current: string + ) => { + accumulator[current] = undefined; + return accumulator; + }, + {} + ), + } + : {}), + }, + })), + }), } + ); - if (facilityCycles?.length && datasetData.investigation?.startDate) { - const filteredFacilityCycles: FacilityCycle[] = facilityCycles?.filter( - (facilityCycle: FacilityCycle) => - datasetData.investigation?.startDate && - facilityCycle.startDate && - facilityCycle.endDate && - datasetData.investigation.startDate >= facilityCycle.startDate && - datasetData.investigation.startDate <= facilityCycle.endDate - ); - if (filteredFacilityCycles.length) { - facilityCycleId = filteredFacilityCycles[0].id; - } - } + const [t] = useTranslation(); - if (facilityCycleId) { - return linkType === 'investigation' - ? `/browse/instrument/${instrumentId}/facilityCycle/${facilityCycleId}/investigation/${datasetData.investigation.id}` - : `/browse/instrument/${instrumentId}/facilityCycle/${facilityCycleId}/investigation/${datasetData.investigation.id}/dataset/${datasetData.id}`; - } - return null; - }, - [facilityCycles] - ); + const { data: cartItems, isLoading: cartLoading } = useCart(); + const { mutate: addToCart, isLoading: addToCartLoading } = + useAddToCart('dataset'); + const { mutate: removeFromCart, isLoading: removeFromCartLoading } = + useRemoveFromCart('dataset'); - const isisLink = React.useCallback( - (datasetData: Dataset, linkType = 'dataset') => { - const linkURL = isisLinkURL(datasetData, linkType); + const { + selectedFacetFilters, + addFacetFilter, + removeFacetFilter, + applyFacetFilters, + haveUnappliedFilters, + } = useFacetFilters(); - if (datasetData.investigation && linkURL) { - return linkType === 'investigation' - ? tableLink(linkURL, datasetData.investigation.title) - : tableLink(linkURL, datasetData.name); - } else return linkType === 'investigation' ? '' : datasetData.name; - }, - [isisLinkURL] - ); + useSearchResultCounter({ + isFetching, + dataSearchType: 'Dataset', + searchResponses: data?.pages, + hasMore: hasNextPage, + }); - const genericLinkURL = React.useCallback( - (datasetData: Dataset, linkType = 'dataset'): string | null => { - if (datasetData.investigation) { - return linkType === 'investigation' - ? `/browse/investigation/${datasetData.investigation.id}/dataset` - : `/browse/investigation/${datasetData.investigation.id}/dataset/${datasetData.id}/datafile`; - } - return null; - }, - [] - ); + function mapSource(response: SearchResponse): SearchResultSource[] { + return response.results?.map((result) => result.source) ?? []; + } - const genericLink = React.useCallback( - ( - datasetData: Dataset, - linkType = 'dataset' - ): React.ReactElement | string => { - const linkURL = genericLinkURL(datasetData, linkType); - if (datasetData.investigation && linkURL) { - return linkType === 'investigation' - ? tableLink(linkURL, datasetData.investigation.title) - : tableLink(linkURL, datasetData.name); - } - return linkType === 'investigation' ? '' : datasetData.name; - }, - [genericLinkURL] - ); + function mapIds(response: SearchResponse): number[] { + return response.results?.map((result) => result.id) ?? []; + } - const hierarchyLinkURL = React.useMemo(() => { - if (hierarchy === 'dls') { - return dlsLinkURL; - } else if (hierarchy === 'isis') { - return isisLinkURL; + const { aggregatedSource, aggregatedIds, aborted } = React.useMemo(() => { + if (data) { + return { + aggregatedSource: data.pages + .map((response) => mapSource(response)) + .flat(), + aggregatedIds: data.pages.map((response) => mapIds(response)).flat(), + aborted: data.pages[data.pages.length - 1].aborted, + }; } else { - return genericLinkURL; + return { + aggregatedSource: [], + aggregatedIds: [], + aborted: false, + }; } - }, [genericLinkURL, hierarchy, isisLinkURL]); + }, [data]); - const hierarchyLink = React.useMemo(() => { - if (hierarchy === 'dls') { - return dlsLink; - } else if (hierarchy === 'isis') { - return isisLink; - } else { - return genericLink; - } - }, [dlsLink, genericLink, hierarchy, isisLink]); + const handleSort = useSort(); + + const loadMoreRows = React.useCallback( + (offsetParams: IndexRange) => fetchNextPage(), + [fetchNextPage] + ); + + const removeFilterChip = ( + dimension: string, + filterValue: SearchFilter + ): void => { + removeFacetFilter({ dimension, filterValue, applyImmediately: true }); + }; const selectedRows = React.useMemo( () => @@ -258,18 +200,11 @@ const DatasetSearchTable = (props: DatasetTableProps): React.ReactElement => { cartItem.entityType === 'dataset' && // if select all is disabled, it's safe to just pass the whole cart as selectedRows (!selectAllSetting || - (allIds && allIds.includes(cartItem.entityId))) + (aggregatedIds && aggregatedIds.includes(cartItem.entityId))) ) .map((cartItem) => cartItem.entityId), - [cartItems, selectAllSetting, allIds] - ); - - // hierarchy === 'isis' ? data : undefined is a 'hack' to only perform - // the correct calculation queries for each facility - const datasetCountQueries = useDatasetsDatafileCount( - hierarchy !== 'isis' ? data : undefined + [cartItems, selectAllSetting, aggregatedIds] ); - const sizeQueries = useDatasetSizes(hierarchy === 'isis' ? data : undefined); const columns: ColumnType[] = React.useMemo( () => [ @@ -277,109 +212,250 @@ const DatasetSearchTable = (props: DatasetTableProps): React.ReactElement => { label: t('datasets.name'), dataKey: 'name', cellContentRenderer: (cellProps: TableCellProps) => { - const datasetData = cellProps.rowData as Dataset; - return hierarchyLink(datasetData); + const datasetData = cellProps.rowData as SearchResultSource; + if ( + !datasetData['investigation.id'] || + !datasetData['investigation.name'] + ) + return datasetData.name; + const dataset = { + id: datasetData.id, + name: datasetData.name, + investigation: { + id: datasetData['investigation.id'], + name: datasetData['investigation.name'], + instrumentId: + datasetData.investigationinstrument?.[0]?.['instrument.id'], + facilityCycleId: + datasetData.investigationfacilitycycle?.[0]?.[ + 'facilityCycle.id' + ], + }, + }; + const url = isLandingPageSupportedForHierarchy(hierarchy) + ? buildDatasetLandingUrl(dataset) + : buildDatafileTableUrlForDataset({ + dataset, + facilityName: hierarchy, + }); + return url ? tableLink(url, dataset.name) : dataset.name; }, - filterComponent: textFilter, + disableSort: true, }, { - label: - hierarchy === 'isis' - ? t('datasets.size') - : t('datasets.datafile_count'), - dataKey: hierarchy === 'isis' ? 'size' : 'datafileCount', - cellContentRenderer: (cellProps: TableCellProps): number | string => { - const query = - hierarchy === 'isis' - ? sizeQueries[cellProps.rowIndex] - : datasetCountQueries[cellProps.rowIndex]; - return formatCountOrSize(query, hierarchy === 'isis'); + label: t('datasets.size'), + dataKey: 'size', + cellContentRenderer: (cellProps: TableCellProps) => { + return formatBytes(cellProps.rowData.fileSize); }, disableSort: true, }, + ...(hierarchy !== FACILITY_NAME.isis + ? [ + { + label: t('datasets.datafile_count'), + dataKey: 'fileCount', + disableSort: true, + }, + ] + : []), { label: t('datasets.investigation'), dataKey: 'investigation.title', cellContentRenderer: (cellProps: TableCellProps) => { - const datasetData = cellProps.rowData as Dataset; - return hierarchyLink(datasetData, 'investigation'); + const datasetData = cellProps.rowData as SearchResultSource; + if ( + !datasetData['investigation.id'] || + !datasetData['investigation.name'] || + !datasetData['investigation.title'] + ) + return ''; + + const investigation = { + id: datasetData['investigation.id'], + name: datasetData['investigation.name'], + title: datasetData['investigation.title'], + instrumentId: + datasetData.investigationinstrument?.[0]?.['instrument.id'], + facilityCycleId: + datasetData.investigationfacilitycycle?.[0]?.['facilityCycle.id'], + }; + + const link = isLandingPageSupportedForHierarchy(hierarchy) + ? buildInvestigationLandingUrl(investigation) + : buildDatasetTableUrlForInvestigation({ + investigation, + facilityName: hierarchy, + }); + return link + ? tableLink(link, investigation.title) + : investigation.title; }, - filterComponent: textFilter, + disableSort: true, }, { label: t('datasets.create_time'), - dataKey: 'createTime', - filterComponent: dateFilter, + dataKey: 'startDate', + disableSort: true, + cellContentRenderer: (cellProps: TableCellProps) => { + if (cellProps.cellData) { + return new Date(cellProps.cellData).toLocaleDateString(); + } + }, }, { label: t('datasets.modified_time'), - dataKey: 'modTime', - filterComponent: dateFilter, + dataKey: 'endDate', + disableSort: true, + cellContentRenderer: (cellProps: TableCellProps) => { + if (cellProps.cellData) { + return new Date(cellProps.cellData).toLocaleDateString(); + } + }, }, ], - [ - t, - textFilter, - hierarchy, - dateFilter, - hierarchyLink, - sizeQueries, - datasetCountQueries, - ] + [t, hierarchy] ); const detailsPanel = React.useCallback( ({ rowData, detailsPanelResize }) => { - if (hierarchy === 'isis') { - const datafilesURL = hierarchyLinkURL(rowData as Dataset); - return ( - { - push(datafilesURL); - } - : undefined - } - /> - ); - } else if (hierarchy === 'dls') { - return ( - - ); - } else { - return ( - - ); + switch (hierarchy) { + case FACILITY_NAME.isis: + const dataset = rowData as SearchResultSource; + let url: string | null = null; + if (dataset['investigation.id'] && dataset['investigation.name']) { + const formattedDataset = { + id: dataset.id, + name: dataset.name, + investigation: { + id: dataset['investigation.id'], + name: dataset['investigation.name'], + instrumentId: + dataset.investigationinstrument?.[0]?.['instrument.id'], + facilityCycleId: + dataset.investigationfacilitycycle?.[0]?.['facilityCycle.id'], + }, + }; + url = buildDatafileTableUrlForDataset({ + dataset: formattedDataset, + facilityName: hierarchy, + }); + } + return ( + { + if (url) push(url); + }} + /> + ); + + case FACILITY_NAME.dls: + return ( + + ); + + default: + return ( + + ); } }, - [hierarchy, hierarchyLinkURL, push] + [hierarchy, push] ); + if (currentTab !== 'dataset') return null; + return ( -
+ + + {data?.pages && ( + + addFacetFilter({ + dimension, + filterValue, + applyImmediately: false, + }) + } + onRemoveFilter={(dimension, filterValue) => + removeFacetFilter({ + dimension, + filterValue, + applyImmediately: false, + }) + } + onApplyFacetFilters={applyFacetFilters} + /> + )} + + + + + +
+ {aborted ? ( + + + {t('loading.abort_message')} + + + ) : ( +
+ )} + + + + + ); }; diff --git a/packages/datagateway-search/src/table/investigationSearchTable.component.test.tsx b/packages/datagateway-search/src/table/investigationSearchTable.component.test.tsx index 51aac33a6..f51ff6b41 100644 --- a/packages/datagateway-search/src/table/investigationSearchTable.component.test.tsx +++ b/packages/datagateway-search/src/table/investigationSearchTable.component.test.tsx @@ -1,35 +1,37 @@ -import React from 'react'; -import { createMount } from '@material-ui/core/test-utils'; +import * as React from 'react'; import { initialState } from '../state/reducers/dgsearch.reducer'; import configureStore from 'redux-mock-store'; -import { StateType } from '../state/app.types'; +import type { StateType } from '../state/app.types'; import { dGCommonInitialState, - handleICATError, - Investigation, - useAddToCart, - useAllFacilityCycles, - useCart, - useIds, - useInvestigationCount, - useInvestigationsDatasetCount, - useInvestigationsInfinite, - useInvestigationSizes, - useLuceneSearch, - useRemoveFromCart, - ISISInvestigationDetailsPanel, - InvestigationDetailsPanel, - DLSVisitDetailsPanel, + type DownloadCartItem, + type SearchResponse, + type SearchResult, + FACILITY_NAME, } from 'datagateway-common'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; -import { ReactWrapper } from 'enzyme'; -import { QueryClientProvider, QueryClient } from 'react-query'; -// this is a dependency of react-router so we already have it -// eslint-disable-next-line import/no-extraneous-dependencies -import { createMemoryHistory, History } from 'history'; +import { QueryClient, QueryClientProvider } from 'react-query'; +import { createMemoryHistory, type History } from 'history'; import { Router } from 'react-router-dom'; import InvestigationSearchTable from './investigationSearchTable.component'; +import userEvent from '@testing-library/user-event'; +import { + render, + type RenderResult, + screen, + waitFor, + within, +} from '@testing-library/react'; +import axios, { AxiosRequestConfig, type AxiosResponse } from 'axios'; +import { mockInvestigation } from '../testData'; +import { + findAllRows, + findCellInRow, + findColumnHeaderByName, + findColumnIndexByName, + queryAllRows, +} from '../setupTests'; jest.mock('datagateway-common', () => { const originalModule = jest.requireActual('datagateway-common'); @@ -38,42 +40,96 @@ jest.mock('datagateway-common', () => { __esModule: true, ...originalModule, handleICATError: jest.fn(), - useCart: jest.fn(), - useLuceneSearch: jest.fn(), - useInvestigationCount: jest.fn(), - useInvestigationsInfinite: jest.fn(), - useIds: jest.fn(), - useAddToCart: jest.fn(), - useRemoveFromCart: jest.fn(), - useAllFacilityCycles: jest.fn(), - useInvestigationsDatasetCount: jest.fn(), - useInvestigationSizes: jest.fn(), }; }); describe('Investigation Search Table component', () => { - let mount; const mockStore = configureStore([thunk]); + let container: HTMLDivElement; let state: StateType; let history: History; + let user: ReturnType; + let queryClient: QueryClient; - let rowData: Investigation[] = []; + let cartItems: DownloadCartItem[]; + let searchResponse: SearchResponse; + let searchResult: SearchResult; - const createWrapper = (hierarchy?: string): ReactWrapper => { - return mount( + const renderComponent = (hierarchy?: string): RenderResult => { + return render( - + - + , + { + container: document.body.appendChild(container), + } ); }; + /** + * Mock implementation of axios.get + */ + const mockAxiosGet = ( + url: string, + config: AxiosRequestConfig + ): Promise> => { + if (/.*\/user\/cart\/.*$/.test(url)) { + // fetchDownloadCart + return Promise.resolve({ data: { cartItems } }); + } + + if (/.*\/search\/documents$/.test(url)) { + // fetchLuceneData + + if ((config.params as URLSearchParams).get('query')?.includes('filter')) { + // filter is applied + return Promise.resolve>>>( + { + data: { + dimensions: { + 'Investigation.type.name': { + experiment: 10, + calibration: 20, + }, + }, + results: [], + }, + } + ); + } + return Promise.resolve>>({ + data: searchResponse, + }); + } + + if (/.*\/investigations$/.test(url)) { + return Promise.resolve({ + data: [mockInvestigation], + }); + } + + return Promise.reject(); + }; + beforeEach(() => { - mount = createMount(); - history = createMemoryHistory(); + user = userEvent.setup(); + + history = createMemoryHistory({ + initialEntries: [ + { search: 'searchText=test search¤tTab=investigation' }, + ], + }); + queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false }, + }, + }); + container = document.createElement('div'); + container.id = 'datagateway-search'; state = JSON.parse( JSON.stringify({ @@ -81,543 +137,796 @@ describe('Investigation Search Table component', () => { dgcommon: dGCommonInitialState, }) ); - rowData = [ - { + cartItems = []; + searchResult = { + score: 1, + id: 1, + source: { id: 1, - title: 'Test 1', - name: 'Test 1', + title: 'Test title 1', + name: 'Test name 1', + fileSize: 1, + fileCount: 1, summary: 'foo bar', visitId: '1', doi: 'doi 1', - size: 1, - investigationInstruments: [ + investigationinstrument: [ { - id: 1, - instrument: { - id: 3, - name: 'LARMOR', - }, + 'instrument.id': 3, + 'instrument.name': 'LARMOR', }, ], - studyInvestigations: [ + investigationfacilitycycle: [ { - id: 6, - study: { - id: 7, - pid: 'study pid', - name: 'study name', - modTime: '2019-06-10', - createTime: '2019-06-10', - }, - investigation: { - id: 1, - title: 'Test 1', - name: 'Test 1', - visitId: '1', - }, + 'facilityCycle.id': 5, }, ], - startDate: '2019-06-10', - endDate: '2019-06-11', - facility: { - id: 2, - name: 'facility name', + startDate: 1560139200000, + endDate: 1560225600000, + 'facility.name': 'facility name', + 'facility.id': 2, + }, + }; + + searchResponse = { + dimensions: { + 'Investigation.type.name': { + experiment: 10, + calibration: 20, }, }, - ]; - (useCart as jest.Mock).mockReturnValue({ - data: [], - }); - (useLuceneSearch as jest.Mock).mockReturnValue({ - data: [], - }); - (useInvestigationCount as jest.Mock).mockReturnValue({ - data: 0, - }); - (useInvestigationsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - (useIds as jest.Mock).mockReturnValue({ - data: [1], - }); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: jest.fn(), - isLoading: false, - }); - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [], + results: [searchResult], + }; + + axios.get = jest.fn().mockImplementation(mockAxiosGet); + + axios.post = jest.fn().mockImplementation((url: string) => { + if (/.*\/user\/cart\/.*\/cartItems$/.test(url)) { + return Promise.resolve({ data: { cartItems } }); + } + return Promise.reject(); }); - (useInvestigationsDatasetCount as jest.Mock).mockImplementation( - (investigations) => - (investigations - ? 'pages' in investigations - ? investigations.pages.flat() - : investigations - : [] - ).map(() => ({ - data: 1, - isFetching: false, - isSuccess: true, - })) - ); - (useInvestigationSizes as jest.Mock).mockImplementation((investigations) => - (investigations - ? 'pages' in investigations - ? investigations.pages.flat() - : investigations - : [] - ).map(() => ({ - data: 1, - isFetching: false, - isSuccess: true, - })) - ); }); afterEach(() => { - mount.cleanUp(); - (handleICATError as jest.Mock).mockClear(); - (useCart as jest.Mock).mockClear(); - (useLuceneSearch as jest.Mock).mockClear(); - (useInvestigationCount as jest.Mock).mockClear(); - (useInvestigationsInfinite as jest.Mock).mockClear(); - (useIds as jest.Mock).mockClear(); - (useAddToCart as jest.Mock).mockClear(); - (useRemoveFromCart as jest.Mock).mockClear(); - (useAllFacilityCycles as jest.Mock).mockClear(); - (useInvestigationsDatasetCount as jest.Mock).mockClear(); - (useInvestigationSizes as jest.Mock).mockClear(); + jest.clearAllMocks(); }); - it('renders correctly', () => { - const wrapper = createWrapper(); - expect(wrapper.find('VirtualizedTable').props()).toMatchSnapshot(); + it('disables the search query if investigation search is disabled', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append('investigation', 'false'); + history.replace({ search: `?${searchParams.toString()}` }); + + renderComponent(); + + // check that column headers are shown correctly. + expect( + await findColumnHeaderByName('investigations.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.visit_id') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.doi') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.instrument') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.end_date') + ).toBeInTheDocument(); + + // wait for queries to finish fetching + await waitFor(() => !queryClient.isFetching()); + + expect( + queryClient.getQueryState(['search', 'Investigation'], { exact: false }) + ?.status + ).toBe('idle'); + + expect(queryAllRows()).toHaveLength(0); }); - it('calls the correct data fetching hooks on load', () => { - (useLuceneSearch as jest.Mock).mockReturnValue({ - data: [1], - }); + it('renders search results correctly', async () => { + renderComponent(); - createWrapper(); + // check that column headers are shown correctly. + expect( + await findColumnHeaderByName('investigations.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.visit_id') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.doi') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.instrument') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.end_date') + ).toBeInTheDocument(); + + const rows = await findAllRows(); + expect(rows).toHaveLength(1); + + // check that facet filter panel is present + expect(screen.getByText('facetPanel.title')).toBeInTheDocument(); + // apply filter button should be invisible initially + expect( + screen.queryByRole('button', { name: 'facetPanel.apply' }) + ).toBeNull(); - expect(useCart).toHaveBeenCalled(); - expect(useLuceneSearch).toHaveBeenCalledWith('Investigation', { - searchText: '', - startDate: null, - endDate: null, - maxCount: 300, + const accordion = screen.getByRole('button', { + name: 'Toggle facetDimensionLabel.Investigation.type.name filter panel', }); - expect(useInvestigationCount).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: [1] }, - }), - }, - ]); - expect(useInvestigationsInfinite).toHaveBeenCalledWith([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: [1] }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - investigationInstruments: 'instrument', - }), - }, - ]); - expect(useIds).toHaveBeenCalledWith( - 'investigation', - [ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: [1] }, - }), - }, - ], - true + expect(accordion).toBeInTheDocument(); + + await user.click(accordion); + + const filterPanel = await screen.getByLabelText( + 'facetDimensionLabel.Investigation.type.name filter panel' ); - expect(useAddToCart).toHaveBeenCalledWith('investigation'); - expect(useRemoveFromCart).toHaveBeenCalledWith('investigation'); - expect(useInvestigationsDatasetCount).toHaveBeenCalledWith({ - pages: [rowData], - }); - expect(useInvestigationSizes).toHaveBeenCalledWith(undefined); - }); + expect(filterPanel).toBeInTheDocument(); - it('calls fetchNextPage function of useDatafilesInfinite when loadMoreRows is called', () => { - const fetchNextPage = jest.fn(); - (useInvestigationsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage, + const experimentFilter = within(filterPanel).getByRole('button', { + name: 'Add experiment filter', }); - const wrapper = createWrapper(); - - wrapper.find('VirtualizedTable').prop('loadMoreRows')({ - startIndex: 50, - stopIndex: 74, + const calibrationFilter = within(filterPanel).getByRole('button', { + name: 'Add calibration filter', }); - expect(fetchNextPage).toHaveBeenCalledWith({ - pageParam: { startIndex: 50, stopIndex: 74 }, - }); - }); + // check that filter items are present and that they show the correct value and count + expect(experimentFilter).toBeInTheDocument(); + expect(calibrationFilter).toBeInTheDocument(); + expect( + within(experimentFilter).getByText('experiment') + ).toBeInTheDocument(); + expect(within(experimentFilter).getByText('10')).toBeInTheDocument(); + expect( + within(calibrationFilter).getByText('calibration') + ).toBeInTheDocument(); + expect(within(calibrationFilter).getByText('20')).toBeInTheDocument(); - it('displays DOI and renders the expected Link ', () => { - const wrapper = createWrapper(); + const row = rows[0]; + + // each cell in the row should contain the correct value + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.title'), + }) + ).getByText('Test title 1') + ).toBeInTheDocument(); expect( - wrapper - .find('[data-testid="investigation-search-table-doi-link"]') - .first() - .text() - ).toEqual('doi 1'); + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.visit_id'), + }) + ).getByText('1') + ).toBeInTheDocument(); expect( - wrapper - .find('[data-testid="investigation-search-table-doi-link"]') - .first() - .prop('href') - ).toEqual('https://doi.org/doi 1'); + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.name'), + }) + ).getByText('Test name 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.doi'), + }) + ).getByRole('link', { name: 'doi 1' }) + ).toHaveAttribute('href', 'https://doi.org/doi 1'); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.size'), + }) + ).getByText('1 B') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.instrument'), + }) + ).getByText('LARMOR') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.start_date'), + }) + ).getByText('10/06/2019') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.end_date'), + }) + ).getByText('11/06/2019') + ).toBeInTheDocument(); }); - it('updates filter query params on text filter', () => { - const wrapper = createWrapper(); + it('displays investigation size for isis', async () => { + renderComponent('isis'); - const filterInput = wrapper - .find('[aria-label="Filter by investigations.title"]') - .first(); - filterInput.instance().value = 'test'; - filterInput.simulate('change'); + // check that column headers are shown correctly. + expect( + await findColumnHeaderByName('investigations.title') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.visit_id') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.name') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.doi') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.size') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.instrument') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.start_date') + ).toBeInTheDocument(); + expect( + await findColumnHeaderByName('investigations.end_date') + ).toBeInTheDocument(); - expect(history.length).toBe(2); - expect(history.location.search).toBe( - `?filters=${encodeURIComponent( - '{"title":{"value":"test","type":"include"}}' - )}` - ); + const rows = await findAllRows(); + expect(rows).toHaveLength(1); + + const row = rows[0]; - filterInput.instance().value = ''; - filterInput.simulate('change'); + // each cell in the row should contain the correct value + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.title'), + }) + ).getByText('Test title 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.visit_id'), + }) + ).getByText('1') + ).toBeInTheDocument(); - expect(history.length).toBe(3); - expect(history.location.search).toBe('?'); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.name'), + }) + ).getByText('Test name 1') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.doi'), + }) + ).getByRole('link', { name: 'doi 1' }) + ).toHaveAttribute('href', 'https://doi.org/doi 1'); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.size'), + }) + ).getByText('1 B') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.instrument'), + }) + ).getByText('LARMOR') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.start_date'), + }) + ).getByText('10/06/2019') + ).toBeInTheDocument(); + expect( + within( + findCellInRow(row, { + columnIndex: await findColumnIndexByName('investigations.end_date'), + }) + ).getByText('11/06/2019') + ).toBeInTheDocument(); }); - it('updates filter query params on date filter', () => { - const wrapper = createWrapper(); + it('applies selected filters correctly', async () => { + renderComponent(); - const filterInput = wrapper.find( - 'input[id="investigations.end_date filter to"]' - ); - filterInput.instance().value = '2019-08-06'; - filterInput.simulate('change'); + // check that no filter chip is visible initially + const selectedFilters = await screen.findByLabelText('selectedFilters'); + expect( + within(selectedFilters).queryAllByText(/^facetDimensionLabel.*/) + ).toHaveLength(0); - expect(history.length).toBe(2); - expect(history.location.search).toBe( - `?filters=${encodeURIComponent('{"endDate":{"endDate":"2019-08-06"}}')}` + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Investigation.type.name filter panel', + }) + ); + // select the filter + await user.click( + await screen.findByRole('button', { + name: 'Add calibration filter', + }) ); + // apply the filter + await user.click(screen.getByRole('button', { name: 'facetPanel.apply' })); - filterInput.instance().value = ''; - filterInput.simulate('change'); + // when filter is applied, the fake axios get will return nothing + // so we should expect no rows in the table + await waitFor(() => { + expect(queryAllRows()).toHaveLength(0); + }); - expect(history.length).toBe(3); - expect(history.location.search).toBe('?'); - }); + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Investigation.type.name filter panel', + }) + ); - it('updates sort query params on sort', () => { - const wrapper = createWrapper(); + const selectedFilterItem = await screen.findByRole('button', { + name: 'Remove calibration filter', + }); - wrapper - .find('[role="columnheader"] span[role="button"]') - .first() - .simulate('click'); + expect(selectedFilterItem).toBeInTheDocument(); + expect(selectedFilterItem).toHaveAttribute('aria-selected', 'true'); + expect(within(selectedFilterItem).getByRole('checkbox')).toBeChecked(); - expect(history.length).toBe(2); - expect(history.location.search).toBe( - `?sort=${encodeURIComponent('{"title":"asc"}')}` - ); + // the selected filters should be displayed + expect(selectedFilters).toBeInTheDocument(); + expect( + within(selectedFilters).getByText( + 'facetDimensionLabel.Investigation.type.name: calibration' + ) + ).toBeInTheDocument(); + + // the rest of the filters should also be displayed but they should not be selected + const experimentFilter = screen.getByRole('button', { + name: 'Add experiment filter', + }); + expect(experimentFilter).toBeInTheDocument(); + expect(experimentFilter).toHaveAttribute('aria-selected', 'false'); + expect(within(experimentFilter).getByRole('checkbox')).not.toBeChecked(); }); - it('calls addToCart mutate function on unchecked checkbox click', () => { - const addToCart = jest.fn(); - (useAddToCart as jest.Mock).mockReturnValue({ - mutate: addToCart, - loading: false, - }); - const wrapper = createWrapper(); + it('applies filters already present in the URL on first render', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append( + 'filters', + JSON.stringify({ + 'Investigation.type.name': ['experiment'], + }) + ); + history.replace({ search: `?${searchParams.toString()}` }); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + renderComponent(); - expect(addToCart).toHaveBeenCalledWith([1]); - }); + // when filters are applied + // the fake axios.get returns no search results + // so we should expect no rows in the table + await waitFor(() => { + expect(queryAllRows()).toHaveLength(0); + }); - it('calls removeFromCart mutate function on checked checkbox click', () => { - (useCart as jest.Mock).mockReturnValue({ - data: [ - { - entityId: 1, - entityType: 'investigation', - id: 1, - name: 'test', - parentEntities: [], - }, - ], + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Investigation.type.name filter panel', + }) + ); + + // filter should be selected + const filterItem = await screen.findByRole('button', { + name: 'Remove experiment filter', }); + expect(filterItem).toBeInTheDocument(); + expect(filterItem).toHaveAttribute('aria-selected', 'true'); + expect(within(filterItem).getByRole('checkbox')).toBeChecked(); - const removeFromCart = jest.fn(); - (useRemoveFromCart as jest.Mock).mockReturnValue({ - mutate: removeFromCart, - loading: false, + // the rest of the filters should also be displayed but they should not be selected + const calibrationFilter = screen.getByRole('button', { + name: 'Add calibration filter', }); + expect(calibrationFilter).toBeInTheDocument(); + expect(calibrationFilter).toHaveAttribute('aria-selected', 'false'); + expect(within(calibrationFilter).getByRole('checkbox')).not.toBeChecked(); + }); - const wrapper = createWrapper(); + it('allows filters to be removed through the facet filter panel', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append( + 'filters', + JSON.stringify({ + 'Investigation.type.name': ['experiment'], + }) + ); + history.replace({ search: `?${searchParams.toString()}` }); - wrapper.find('[aria-label="select row 0"]').first().simulate('click'); + renderComponent(); - expect(removeFromCart).toHaveBeenCalledWith([1]); - }); + const selectedFilterChips = await screen.findByLabelText('selectedFilters'); - it('selected rows only considers relevant cart items', () => { - (useCart as jest.Mock).mockReturnValue({ - data: [ - { - entityId: 2, - entityType: 'investigation', - id: 1, - name: 'test', - parentEntities: [], - }, - { - entityId: 1, - entityType: 'dataset', - id: 2, - name: 'test', - parentEntities: [], - }, - ], + expect( + within(selectedFilterChips).getByRole('button', { + name: 'facetDimensionLabel.Investigation.type.name: experiment', + }) + ).toBeInTheDocument(); + + // when filters are applied + // the fake axios.get returns no search results + // so we should expect no rows in the table + await waitFor(() => { + expect(queryAllRows()).toHaveLength(0); }); - const wrapper = createWrapper(); + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Investigation.type.name filter panel', + }) + ); - const selectAllCheckbox = wrapper - .find('[aria-label="select all rows"]') - .first(); + await user.click( + await screen.findByRole('button', { + name: 'Remove experiment filter', + }) + ); - expect(selectAllCheckbox.prop('checked')).toEqual(false); - expect(selectAllCheckbox.prop('data-indeterminate')).toEqual(false); - }); + // apply the changes + await user.click(screen.getByRole('button', { name: 'facetPanel.apply' })); - it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', () => { - state.dgsearch.selectAllSetting = false; + expect(await findAllRows()).toHaveLength(1); - const wrapper = createWrapper(); + // check that the filter chip is removed + expect( + within(selectedFilterChips).queryByRole('button', { + name: 'facetDimensionLabel.Investigation.type.name: experiment', + }) + ).toBeNull(); - expect(useIds).toHaveBeenCalledWith( - 'investigation', - expect.anything(), - false - ); - expect(useIds).not.toHaveBeenCalledWith( - 'investigation', - expect.anything(), - true + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Investigation.type.name filter panel', + }) ); - expect(wrapper.find('[aria-label="select all rows"]')).toHaveLength(0); + + // filter item should not be selected anymore + const filterItem = await screen.findByRole('button', { + name: 'Add experiment filter', + }); + expect(filterItem).toBeInTheDocument(); + expect(filterItem).toHaveAttribute('aria-selected', 'false'); + expect(within(filterItem).getByRole('checkbox')).not.toBeChecked(); }); - it('displays generic details panel when expanded', () => { - const wrapper = createWrapper(); - expect(wrapper.find(InvestigationDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); + it('allows filters to be removed by removing filter chips', async () => { + const searchParams = new URLSearchParams(history.location.search); + searchParams.append( + 'filters', + JSON.stringify({ + 'Investigation.type.name': ['calibration'], + }) + ); + history.replace({ search: `?${searchParams.toString()}` }); - expect(wrapper.find(InvestigationDetailsPanel).exists()).toBeTruthy(); - }); + renderComponent(); - it('displays correct details panel for ISIS when expanded', () => { - const wrapper = createWrapper('isis'); - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeTruthy(); - }); + // when filters are applied + // the fake axios.get returns no search results + // so we should expect no rows in the table + await waitFor(() => { + expect(queryAllRows()).toHaveLength(0); + }); - it('can navigate using the details panel for ISIS when there are facility cycles', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], + const selectedFilterChips = screen.getByLabelText('selectedFilters'); + const chip = within(selectedFilterChips).getByRole('button', { + name: 'facetDimensionLabel.Investigation.type.name: calibration', }); - const wrapper = createWrapper('isis'); - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); - expect(wrapper.find(ISISInvestigationDetailsPanel).exists()).toBeTruthy(); + await user.click(within(chip).getByTestId('CancelIcon')); - wrapper.find('#investigation-datasets-tab').first().simulate('click'); - expect(history.location.pathname).toBe( - '/browse/instrument/3/facilityCycle/4/investigation/1/dataset' + expect(await findAllRows()).toHaveLength(1); + + // check that the filter chip is removed + expect( + within(selectedFilterChips).queryByRole('button', { + name: 'facetDimensionLabel.Investigation.type.name: calibration', + }) + ).toBeNull(); + + // expand accordion + await user.click( + await screen.findByRole('button', { + name: 'Toggle facetDimensionLabel.Investigation.type.name filter panel', + }) ); - }); - it('displays correct details panel for DLS when expanded', () => { - const wrapper = createWrapper('dls'); - expect(wrapper.find(DLSVisitDetailsPanel).exists()).toBeFalsy(); - wrapper.find('[aria-label="Show details"]').first().simulate('click'); - expect(wrapper.find(DLSVisitDetailsPanel).exists()).toBeTruthy(); + // filter item should not be selected anymore + const filterItem = await screen.findByRole('button', { + name: 'Add calibration filter', + }); + expect(filterItem).toBeInTheDocument(); + expect(filterItem).toHaveAttribute('aria-selected', 'false'); + expect(within(filterItem).getByRole('checkbox')).not.toBeChecked(); }); - it('renders title, visit ID, Name and DOI as links', () => { - const wrapper = createWrapper(); + it('should add the selected row to cart', async () => { + const addedCartItem: DownloadCartItem = { + entityId: 1, + entityType: 'investigation', + id: 1, + name: 'Test 1', + parentEntities: [], + }; - expect( - wrapper.find('[aria-colindex=3]').find('p').children() - ).toMatchSnapshot(); + renderComponent(); - expect( - wrapper.find('[aria-colindex=4]').find('p').children() - ).toMatchSnapshot(); + // wait for data to finish loading + expect(await screen.findByText('Test title 1')).toBeInTheDocument(); + expect(screen.getByText('Test name 1')).toBeInTheDocument(); + + // pretend the server has added the row to the cart + // create a new array to trigger useMemo update + cartItems = [...cartItems, addedCartItem]; + // clicks on the row checkbox + await user.click(screen.getByRole('checkbox', { name: 'select row 0' })); + + // the checkbox should be checked expect( - wrapper.find('[aria-colindex=5]').find('p').children() - ).toMatchSnapshot(); + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).toBeChecked(); + }); + it('should remove the selected row from cart if it is in the cart', async () => { + const addedCartItem: DownloadCartItem = { + entityId: 1, + entityType: 'investigation', + id: 1, + name: 'Test 1', + parentEntities: [], + }; + + cartItems.push(addedCartItem); + + renderComponent(); + + // wait for data to finish loading + expect(await screen.findByText('Test title 1')).toBeInTheDocument(); + expect(screen.getByText('Test name 1')).toBeInTheDocument(); + + // pretend the server has removed the item from the cart + // create a new array to trigger useMemo update + cartItems = []; + + // clicks on the row checkbox + await user.click(screen.getByRole('checkbox', { name: 'select row 0' })); + + // the checkbox should not be checked expect( - wrapper.find('[aria-colindex=6]').find('p').children() - ).toMatchSnapshot(); + await screen.findByRole('checkbox', { name: 'select row 0' }) + ).not.toBeChecked(); }); - it('renders fine with incomplete data', () => { - // this can happen when navigating between tables and the previous table's state still exists - // also tests that empty arrays are fine for investigationInstruments - rowData = [ + it('selected rows only considers relevant cart items', async () => { + cartItems = [ { + entityId: 2, + entityType: 'investigation', id: 1, name: 'test', - title: 'test', - visitId: '1', - doi: 'Test 1', - investigationInstruments: [], + parentEntities: [], + }, + { + entityId: 1, + entityType: 'dataset', + id: 2, + name: 'test', + parentEntities: [], }, ]; - (useInvestigationsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), + renderComponent(); + + const selectAllCheckbox = await screen.findByRole('checkbox', { + name: 'select all rows', }); - expect(() => createWrapper()).not.toThrowError(); + expect(selectAllCheckbox).not.toBeChecked(); + expect(selectAllCheckbox).toHaveAttribute('data-indeterminate', 'false'); }); - it('renders generic link correctly & pending count correctly', () => { - (useInvestigationsDatasetCount as jest.Mock).mockImplementation(() => [ - { - isFetching: true, - }, - ]); - const wrapper = createWrapper('data'); + it('no select all checkbox appears and no fetchAllIds sent if selectAllSetting is false', async () => { + state.dgsearch.selectAllSetting = false; - expect(wrapper.find('[aria-colindex=3]').find('a').prop('href')).toEqual( - '/browse/investigation/1/dataset' + renderComponent(); + + await waitFor(() => { + expect( + screen.queryByRole('checkbox', { name: 'select all rows' }) + ).toBeNull(); + }); + }); + + it('displays generic details panel when expanded', async () => { + renderComponent(); + + await user.click( + await screen.findByRole('button', { name: 'Show details' }) ); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual('Test 1'); - expect(wrapper.find('[aria-colindex=7]').text()).toEqual('Calculating...'); + + expect( + await screen.findByTestId('investigation-details-panel') + ).toBeInTheDocument(); }); - it("renders DLS link correctly and doesn't allow for cart selection", () => { - const wrapper = createWrapper('dls'); + it('displays correct details panel for ISIS when expanded', async () => { + renderComponent(FACILITY_NAME.isis); - expect(wrapper.find('[aria-colindex=2]').find('a').prop('href')).toEqual( - '/browse/proposal/Test 1/investigation/1/dataset' + await user.click( + await screen.findByRole('button', { name: 'Show details' }) ); - expect(wrapper.find('[aria-colindex=2]').text()).toEqual('Test 1'); - expect(wrapper.find('[aria-label="select row 0"]')).toHaveLength(0); + + expect( + await screen.findByTestId('isis-investigation-details-panel') + ).toBeInTheDocument(); }); - it('renders ISIS link & file sizes correctly', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 2, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', - }, - ], - }); + it('can navigate using the details panel for ISIS when there are facility cycles', async () => { + renderComponent(FACILITY_NAME.isis); - const wrapper = createWrapper('isis'); + await user.click( + await screen.findByRole('button', { name: 'Show details' }) + ); - expect(useInvestigationSizes).toHaveBeenCalledWith({ pages: [rowData] }); - expect(useInvestigationsDatasetCount).toHaveBeenCalledWith(undefined); + await user.click( + await screen.findByRole('tab', { + name: 'investigations.details.datasets', + }) + ); - expect(wrapper.find('[aria-colindex=3]').find('a').prop('href')).toEqual( - '/browse/instrument/3/facilityCycle/2/investigation/1/dataset' + expect(history.location.pathname).toBe( + '/browse/instrument/3/facilityCycle/5/investigation/1/dataset' ); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual('Test 1'); - expect(wrapper.find('[aria-colindex=7]').text()).toEqual('1 B'); }); - it('does not render ISIS link when instrumentId cannot be found', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ + it('displays correct details panel for DLS when expanded', async () => { + renderComponent(FACILITY_NAME.dls); + + await user.click( + await screen.findByRole('button', { name: 'Show details' }) + ); + + expect( + await screen.findByTestId('dls-visit-details-panel') + ).toBeInTheDocument(); + }); + + it('renders fine with incomplete data', async () => { + // this can happen when navigating between tables and the previous table's state still exists + // also tests that empty arrays are fine for investigationInstruments & investigationFacilityCycles + searchResponse = { + results: [ { - id: 4, - name: 'facility cycle name', - startDate: '2000-06-10', - endDate: '2020-06-11', + ...searchResult, + source: { + id: 1, + name: 'test', + title: 'test', + visitId: '1', + doi: 'Test 1', + investigationinstrument: [], + investigationfacilitycycle: [], + }, }, ], - }); - delete rowData[0].investigationInstruments; + }; - (useInvestigationsInfinite as jest.Mock).mockReturnValue({ - data: { pages: [rowData] }, - fetchNextPage: jest.fn(), - }); - const wrapper = createWrapper('isis'); + renderComponent(FACILITY_NAME.isis); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual('Test 1'); + await user.click( + await screen.findByRole('button', { name: 'Show details' }) + ); + + expect( + await screen.findByTestId('isis-investigation-details-panel') + ).toBeInTheDocument(); }); - it('does not render ISIS link when facilityCycleId cannot be found', () => { - const wrapper = createWrapper('isis'); + it('renders generic link correctly correctly', async () => { + renderComponent('data'); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual('Test 1'); + expect(await screen.findByText('Test title 1')).toHaveAttribute( + 'href', + '/browse/investigation/1/dataset' + ); }); - it('does not render ISIS link when facilityCycleId has incompatible dates', () => { - (useAllFacilityCycles as jest.Mock).mockReturnValue({ - data: [ - { - id: 2, - name: 'facility cycle name', - startDate: '2020-06-11', - endDate: '2000-06-10', - }, - ], + it("renders DLS link correctly and doesn't allow for cart selection", async () => { + renderComponent(FACILITY_NAME.dls); + + expect(await screen.findByText('Test title 1')).toHaveAttribute( + 'href', + '/browse/proposal/Test name 1/investigation/1/dataset' + ); + expect(screen.queryByRole('checkbox', { name: 'select row 0' })).toBeNull(); + }); + + it('renders ISIS link & file sizes correctly', async () => { + renderComponent(FACILITY_NAME.isis); + + expect( + await screen.findByRole('link', { name: 'Test title 1' }) + ).toHaveAttribute( + 'href', + '/browse/instrument/3/facilityCycle/5/investigation/1/dataset' + ); + expect(await screen.findByText('1 B')).toBeInTheDocument(); + }); + + it('does not render ISIS link when instrumentId cannot be found', async () => { + delete searchResult.source.investigationinstrument; + + renderComponent('isis'); + + await waitFor(async () => { + // the title should not be rendered as a link... + expect(screen.queryByRole('link', { name: 'Test title 1' })).toBeNull(); + // ...but it should still be rendered as a normal text + expect(screen.getByText('Test title 1')).toBeInTheDocument(); + expect(await screen.findByText('1 B')).toBeInTheDocument(); }); + }); + + it('does not render ISIS link when facilityCycleId cannot be found', async () => { + delete searchResult.source.investigationfacilitycycle; - const wrapper = createWrapper('isis'); + renderComponent('isis'); - expect(wrapper.find('[aria-colindex=3]').find('a')).toHaveLength(0); - expect(wrapper.find('[aria-colindex=3]').text()).toEqual('Test 1'); + await waitFor(async () => { + // the title should not be rendered as a link... + expect(screen.queryByRole('link', { name: 'Test title 1' })).toBeNull(); + // ...but it should still be rendered as a normal text + expect(screen.getByText('Test title 1')).toBeInTheDocument(); + expect(await screen.findByText('1 B')).toBeInTheDocument(); + }); }); }); diff --git a/packages/datagateway-search/src/table/investigationSearchTable.component.tsx b/packages/datagateway-search/src/table/investigationSearchTable.component.tsx index ae9056138..f99c67ca4 100644 --- a/packages/datagateway-search/src/table/investigationSearchTable.component.tsx +++ b/packages/datagateway-search/src/table/investigationSearchTable.component.tsx @@ -1,209 +1,171 @@ -import React from 'react'; import { - Table, - Investigation, - tableLink, - externalSiteLink, - FacilityCycle, ColumnType, + DLSVisitDetailsPanel, + externalSiteLink, + formatBytes, + buildDatasetTableUrlForInvestigation, + FACILITY_NAME, + InvestigationDetailsPanel, + ISISInvestigationDetailsPanel, parseSearchToQuery, + SearchFilter, + SearchResponse, + SearchResultSource, + Table, + tableLink, useAddToCart, - useAllFacilityCycles, useCart, - useDateFilter, - useIds, - useInvestigationCount, - useInvestigationsInfinite, - useSort, + useLuceneSearchInfinite, useRemoveFromCart, - useTextFilter, - useInvestigationsDatasetCount, - useInvestigationSizes, - formatCountOrSize, - useLuceneSearch, - InvestigationDetailsPanel, - ISISInvestigationDetailsPanel, - DLSVisitDetailsPanel, + useSort, } from 'datagateway-common'; -import { TableCellProps, IndexRange } from 'react-virtualized'; +import { TableCellProps } from 'react-virtualized'; import { useTranslation } from 'react-i18next'; import { useHistory, useLocation } from 'react-router-dom'; -import { StateType } from '../state/app.types'; import { useSelector } from 'react-redux'; +import { Grid, Paper, Typography } from '@mui/material'; +import { StateType } from '../state/app.types'; +import FacetPanel from '../facet/components/facetPanel/facetPanel.component'; +import { facetClassificationFromSearchResponses } from '../facet/facet'; +import SelectedFilterChips from '../facet/components/selectedFilterChips.component'; +import useFacetFilters from '../facet/useFacetFilters'; +import { useSearchResultCounter } from '../searchTabs/useSearchResultCounter'; +import React from 'react'; interface InvestigationTableProps { hierarchy: string; } -const InvestigationSearchTable = ( - props: InvestigationTableProps -): React.ReactElement => { +const InvestigationSearchTable: React.FC = (props) => { const { hierarchy } = props; - const { data: facilityCycles } = useAllFacilityCycles(hierarchy === 'isis'); - const location = useLocation(); const { push } = useHistory(); - const queryParams = React.useMemo(() => parseSearchToQuery(location.search), [ - location.search, - ]); - const { startDate, endDate } = queryParams; + const queryParams = React.useMemo( + () => parseSearchToQuery(location.search), + [location.search] + ); + const { + startDate, + endDate, + sort, + filters, + restrict, + investigation, + currentTab, + } = queryParams; const searchText = queryParams.searchText ? queryParams.searchText : ''; const selectAllSetting = useSelector( (state: StateType) => state.dgsearch.selectAllSetting ); + const minNumResults = useSelector( + (state: StateType) => state.dgsearch.minNumResults + ); + const maxNumResults = useSelector( (state: StateType) => state.dgsearch.maxNumResults ); - const { data: luceneData } = useLuceneSearch('Investigation', { - searchText, - startDate, - endDate, - maxCount: maxNumResults, - }); - const [t] = useTranslation(); - const { filters, sort } = React.useMemo( - () => parseSearchToQuery(location.search), - [location.search] - ); - - const { data: totalDataCount } = useInvestigationCount([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: luceneData || [] }, - }), - }, - ]); - const { fetchNextPage, data } = useInvestigationsInfinite([ - { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: luceneData || [] }, - }), - }, - { - filterType: 'include', - filterValue: JSON.stringify({ - investigationInstruments: 'instrument', - }), - }, - ]); - const { data: allIds } = useIds( - 'investigation', - [ + const { fetchNextPage, data, hasNextPage, isFetching } = + useLuceneSearchInfinite( + 'Investigation', { - filterType: 'where', - filterValue: JSON.stringify({ - id: { in: luceneData || [] }, - }), + searchText, + startDate, + endDate, + sort, + minCount: minNumResults, + maxCount: maxNumResults, + restrict, + facets: [ + { target: 'Investigation' }, + { + target: 'InvestigationParameter', + dimensions: [{ dimension: 'type.name' }], + }, + { + target: 'Sample', + dimensions: [{ dimension: 'sample.type.name' }], + }, + { + target: 'InvestigationInstrument', + dimensions: [{ dimension: 'instrument.name' }], + }, + ], }, - ], - selectAllSetting - ); - const { data: cartItems } = useCart(); - const { mutate: addToCart, isLoading: addToCartLoading } = useAddToCart( - 'investigation' - ); - const { - mutate: removeFromCart, - isLoading: removeFromCartLoading, - } = useRemoveFromCart('investigation'); + currentTab === 'investigation' ? filters : {}, - const aggregatedData: Investigation[] = React.useMemo( - () => (data ? ('pages' in data ? data.pages.flat() : data) : []), - [data] - ); - - const textFilter = useTextFilter(filters); - const dateFilter = useDateFilter(filters); - const handleSort = useSort(); + { enabled: investigation } + ); + const { data: cartItems, isLoading: cartLoading } = useCart(); + const { mutate: addToCart, isLoading: addToCartLoading } = + useAddToCart('investigation'); + const { mutate: removeFromCart, isLoading: removeFromCartLoading } = + useRemoveFromCart('investigation'); - const loadMoreRows = React.useCallback( - (offsetParams: IndexRange) => fetchNextPage({ pageParam: offsetParams }), - [fetchNextPage] - ); - - const dlsLinkURL = (investigationData: Investigation): string => - `/browse/proposal/${investigationData.name}/investigation/${investigationData.id}/dataset`; - - const isisLinkURL = React.useCallback( - (investigationData: Investigation) => { - let instrumentId; - let facilityCycleId; - if (investigationData.investigationInstruments?.length) { - instrumentId = - investigationData.investigationInstruments[0].instrument?.id; - } else { - return null; - } - - if (investigationData.startDate && facilityCycles?.length) { - const filteredFacilityCycles: FacilityCycle[] = facilityCycles?.filter( - (facilityCycle: FacilityCycle) => - investigationData.startDate && - facilityCycle.startDate && - facilityCycle.endDate && - investigationData.startDate >= facilityCycle.startDate && - investigationData.startDate <= facilityCycle.endDate - ); - if (filteredFacilityCycles.length) { - facilityCycleId = filteredFacilityCycles[0].id; - } - } - - if (facilityCycleId) - return `/browse/instrument/${instrumentId}/facilityCycle/${facilityCycleId}/investigation/${investigationData.id}/dataset`; - else return null; - }, - [facilityCycles] - ); + const { + selectedFacetFilters, + addFacetFilter, + removeFacetFilter, + applyFacetFilters, + haveUnappliedFilters, + } = useFacetFilters(); - const isisLink = React.useCallback( - (investigationData: Investigation) => { - const linkURL = isisLinkURL(investigationData); + useSearchResultCounter({ + isFetching, + dataSearchType: 'Investigation', + searchResponses: data?.pages, + hasMore: hasNextPage, + }); - if (linkURL) return tableLink(linkURL, investigationData.title); - else return investigationData.title; - }, - [isisLinkURL] - ); + function mapSource(response: SearchResponse): SearchResultSource[] { + return response.results?.map((result) => result.source) ?? []; + } - const genericLinkURL = (investigationData: Investigation): string => - `/browse/investigation/${investigationData.id}/dataset`; + function mapIds(response: SearchResponse): number[] { + return response.results?.map((result) => result.id) ?? []; + } - const hierarchyLinkURL = React.useMemo(() => { - if (hierarchy === 'dls') { - return dlsLinkURL; - } else if (hierarchy === 'isis') { - return isisLinkURL; + const { aggregatedSource, aggregatedIds, aborted } = React.useMemo(() => { + const definedData = data ?? { + results: [], + }; + if ('pages' in definedData) { + return { + aggregatedSource: definedData.pages + .map((response) => mapSource(response)) + .flat(), + aggregatedIds: definedData.pages + .map((response) => mapIds(response)) + .flat(), + aborted: definedData.pages[definedData.pages.length - 1].aborted, + }; } else { - return genericLinkURL; + return { + aggregatedSource: mapSource(definedData), + aggregatedIds: mapIds(definedData), + aborted: false, + }; } - }, [hierarchy, isisLinkURL]); + }, [data]); - const hierarchyLink = React.useMemo(() => { - if (hierarchy === 'dls') { - const dlsLink = (investigationData: Investigation): React.ReactElement => - tableLink(dlsLinkURL(investigationData), investigationData.title); + const handleSort = useSort(); - return dlsLink; - } else if (hierarchy === 'isis') { - return isisLink; - } else { - const genericLink = ( - investigationData: Investigation - ): React.ReactElement => - tableLink(genericLinkURL(investigationData), investigationData.title); + const loadMoreRows = React.useCallback( + (_) => fetchNextPage(), + [fetchNextPage] + ); - return genericLink; - } - }, [hierarchy, isisLink]); + const removeFilterChip = ( + dimension: string, + filterValue: SearchFilter + ): void => { + removeFacetFilter({ dimension, filterValue, applyImmediately: true }); + }; const selectedRows = React.useMemo( () => @@ -213,19 +175,10 @@ const InvestigationSearchTable = ( cartItem.entityType === 'investigation' && // if select all is disabled, it's safe to just pass the whole cart as selectedRows (!selectAllSetting || - (allIds && allIds.includes(cartItem.entityId))) + (aggregatedIds && aggregatedIds.includes(cartItem.entityId))) ) .map((cartItem) => cartItem.entityId), - [cartItems, selectAllSetting, allIds] - ); - - // hierarchy === 'isis' ? data : undefined is a 'hack' to only perform - // the correct calculation queries for each facility - const datasetCountQueries = useInvestigationsDatasetCount( - hierarchy !== 'isis' ? data : undefined - ); - const sizeQueries = useInvestigationSizes( - hierarchy === 'isis' ? data : undefined + [cartItems, selectAllSetting, aggregatedIds] ); const columns: ColumnType[] = React.useMemo( @@ -234,149 +187,231 @@ const InvestigationSearchTable = ( label: t('investigations.title'), dataKey: 'title', cellContentRenderer: (cellProps: TableCellProps) => { - const investigationData = cellProps.rowData as Investigation; - return hierarchyLink(investigationData); + const investigationData = cellProps.rowData as SearchResultSource; + const link = buildDatasetTableUrlForInvestigation({ + investigation: { + id: investigationData.id, + name: investigationData.name, + instrumentId: + investigationData.investigationinstrument?.[0]?.[ + 'instrument.id' + ], + facilityCycleId: + investigationData.investigationfacilitycycle?.[0]?.[ + 'facilityCycle.id' + ], + }, + facilityName: hierarchy, + }); + if (!investigationData.title) return ''; + return link + ? tableLink(link, investigationData.title) + : investigationData.title; }, - filterComponent: textFilter, + disableSort: true, }, { label: t('investigations.visit_id'), dataKey: 'visitId', - filterComponent: textFilter, + disableSort: true, }, { label: t('investigations.name'), dataKey: 'name', - filterComponent: textFilter, + disableSort: true, }, { label: t('investigations.doi'), dataKey: 'doi', cellContentRenderer: (cellProps: TableCellProps) => { - const investigationData = cellProps.rowData as Investigation; + const investigation = cellProps.rowData as SearchResultSource; return externalSiteLink( - `https://doi.org/${investigationData.doi}`, - investigationData.doi, + `https://doi.org/${investigation.doi}`, + investigation.doi, 'investigation-search-table-doi-link' ); }, - filterComponent: textFilter, + disableSort: true, }, { - label: - hierarchy === 'isis' - ? t('investigations.size') - : t('investigations.dataset_count'), - dataKey: hierarchy === 'isis' ? 'size' : 'datasetCount', - cellContentRenderer: (cellProps: TableCellProps): number | string => { - const query = - hierarchy === 'isis' - ? sizeQueries[cellProps.rowIndex] - : datasetCountQueries[cellProps.rowIndex]; - return formatCountOrSize(query, hierarchy === 'isis'); - }, + label: t('investigations.size'), + dataKey: 'size', + cellContentRenderer: (cellProps: TableCellProps): number | string => + formatBytes(cellProps.rowData.fileSize), disableSort: true, }, { label: t('investigations.instrument'), dataKey: 'investigationInstruments.instrument.fullName', cellContentRenderer: (cellProps: TableCellProps) => { - const investigationData = cellProps.rowData as Investigation; - if (investigationData?.investigationInstruments?.[0]?.instrument) { - return investigationData.investigationInstruments[0].instrument - .fullName; - } else { - return ''; - } + const investigationData = cellProps.rowData as SearchResultSource; + const investigationInstrument = + investigationData.investigationinstrument?.[0]; + return ( + investigationInstrument?.['instrument.fullName'] ?? + investigationInstrument?.['instrument.name'] ?? + '' + ); }, - filterComponent: textFilter, + disableSort: true, }, { label: t('investigations.start_date'), dataKey: 'startDate', - filterComponent: dateFilter, cellContentRenderer: (cellProps: TableCellProps) => { if (cellProps.cellData) { - return cellProps.cellData.toString().split(' ')[0]; + return new Date(cellProps.cellData).toLocaleDateString(); } }, + disableSort: true, }, { label: t('investigations.end_date'), dataKey: 'endDate', - filterComponent: dateFilter, cellContentRenderer: (cellProps: TableCellProps) => { if (cellProps.cellData) { - return cellProps.cellData.toString().split(' ')[0]; + return new Date(cellProps.cellData).toLocaleDateString(); } }, + disableSort: true, }, ], - [ - t, - textFilter, - hierarchy, - dateFilter, - hierarchyLink, - sizeQueries, - datasetCountQueries, - ] + [t, hierarchy] ); const detailsPanel = React.useCallback( ({ rowData, detailsPanelResize }) => { - if (hierarchy === 'isis') { - const datasetsURL = hierarchyLinkURL(rowData as Investigation); - return ( - { - push(datasetsURL); - } - : undefined - } - /> - ); - } else if (hierarchy === 'dls') { - return ( - - ); - } else { - return ( - - ); + switch (hierarchy) { + case FACILITY_NAME.isis: + const investigation = rowData as SearchResultSource; + const url = buildDatasetTableUrlForInvestigation({ + facilityName: hierarchy, + investigation: { + id: investigation.id, + name: investigation.name, + instrumentId: + investigation.investigationinstrument?.[0]?.['instrument.id'], + facilityCycleId: + investigation.investigationfacilitycycle?.[0]?.[ + 'facilityCycle.id' + ], + }, + }); + return ( + { + if (url) push(url); + }} + /> + ); + + case FACILITY_NAME.dls: + return ( + + ); + + default: + return ( + + ); } }, - [hierarchy, hierarchyLinkURL, push] + [hierarchy, push] ); + if (currentTab !== 'investigation') return null; + return ( -
+ + + {data?.pages && ( + + addFacetFilter({ + dimension, + filterValue, + applyImmediately: false, + }) + } + onRemoveFilter={(dimension, filterValue) => + removeFacetFilter({ + dimension, + filterValue, + applyImmediately: false, + }) + } + onApplyFacetFilters={applyFacetFilters} + /> + )} + + + + + +
+ {aborted ? ( + + {t('loading.abort_message')} + + ) : ( +
+ )} + + + + + ); }; diff --git a/packages/datagateway-search/src/testData.ts b/packages/datagateway-search/src/testData.ts new file mode 100644 index 000000000..e46fa2f31 --- /dev/null +++ b/packages/datagateway-search/src/testData.ts @@ -0,0 +1,71 @@ +// Defines test data used for testing + +import type { Dataset, Investigation } from 'datagateway-common'; +import { SearchResponse } from 'datagateway-common'; + +const mockInvestigation: Investigation = { + id: 1, + name: 'Test investigation name', + title: 'Test investigation title', + visitId: '1', +}; + +const mockDataset: Dataset = { + createTime: '', + id: 1, + modTime: '', + name: 'Test dataset name', +}; + +const mockSearchResponses: SearchResponse[] = [ + { + results: [ + { + score: 1, + id: 1, + source: { + id: 1, + name: 'Datafile test name', + location: '/datafiletest', + fileSize: 1, + date: 1563836400000, + 'dataset.id': 2, + 'dataset.name': 'Dataset test name', + 'investigation.id': 3, + 'investigation.title': 'Investigation test title', + 'investigation.name': 'Investigation test name', + 'investigation.startDate': 1560121200000, // 2019-06-09T23:00:00.000Z + investigationinstrument: [ + { + 'instrument.id': 5, + 'instrument.name': 'LARMOR', + }, + ], + }, + }, + { + id: 596, + score: 269, + source: { + id: 749, + name: 'source 1', + }, + }, + ], + }, + { + results: [ + { + id: 916, + score: 160, + source: { + id: 143, + name: 'source 3', + }, + }, + ], + }, + {}, +]; + +export { mockDataset, mockInvestigation, mockSearchResponses }; diff --git a/packages/datagateway-search/tsconfig.json b/packages/datagateway-search/tsconfig.json index 4aea8e9b3..9aca4f804 100644 --- a/packages/datagateway-search/tsconfig.json +++ b/packages/datagateway-search/tsconfig.json @@ -17,13 +17,10 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "react", - "noFallthroughCasesInSwitch": true + "jsx": "react-jsx", + "noFallthroughCasesInSwitch": true, }, "include": [ - "src" + "src", ], - "exclude": [ - "**/?*test.*", - ] } diff --git a/renovate.json b/renovate.json new file mode 100644 index 000000000..fd00ad30d --- /dev/null +++ b/renovate.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base", + "schedule:nonOfficeHours", + ":maintainLockFilesWeekly", + "npm:unpublishSafe", + "helpers:pinGitHubActionDigests" + ], + "postUpdateOptions": ["yarnDedupeHighest"], + "labels": ["dependencies"], + "separateMinorPatch": true, + "patch": { + "enabled": false + } +} diff --git a/yarn.lock b/yarn.lock index 2107ee5ac..154a1212a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,15745 +1,16741 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.0.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.0.tgz#72becdf17ee44b2d1ac5651fb12f1952c336fe23" - integrity sha512-d5RysTlJ7hmw5Tw4UxgxcY3lkMe92n8sXCcuLPAyIAHK6j8DefDwtGnVVDgOnv+RnEosulDJ9NPKQL27bDId0g== - dependencies: - "@jridgewell/trace-mapping" "^0.3.0" - -"@apideck/better-ajv-errors@^0.3.1": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.2.tgz#cd6d3814eda8aee38ee2e3fa6457be43af4f8361" - integrity sha512-JdEazx7qiVqTBzzBl5rolRwl5cmhihjfIcpqRzIZjtT6b18liVmDn/VlWpqW4C/qP2hrFFMLRV1wlex8ZVBPTg== - dependencies: - json-schema "^0.4.0" - jsonpointer "^5.0.0" - leven "^3.1.0" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== - dependencies: - "@babel/highlight" "^7.0.0" - -"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" - integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== - dependencies: - "@babel/highlight" "^7.12.13" - -"@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.8.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/compat-data@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.13.tgz#27e19e0ed3726ccf54067ced4109501765e7e2e8" - integrity sha512-U/hshG5R+SIoW7HVWIdmy1cB7s3ki+r3FpyEZiCgpi4tFgPnX/vynY80ZGSASOIrUM6O7VxOgCZgdt7h97bUGg== - -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" - integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== - -"@babel/core@^7.1.0", "@babel/core@^7.12.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.13.tgz#b73a87a3a3e7d142a66248bf6ad88b9ceb093425" - integrity sha512-BQKE9kXkPlXHPeqissfxo0lySWJcYdEP0hdtJOH/iJfDdhOCcgtNCjftCJg3qqauB4h+lz2N6ixM++b9DN1Tcw== - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.12.13" - "@babel/helper-module-transforms" "^7.12.13" - "@babel/helpers" "^7.12.13" - "@babel/parser" "^7.12.13" - "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" - 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" - -"@babel/core@^7.11.1", "@babel/core@^7.16.0", "@babel/core@^7.7.2", "@babel/core@^7.8.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.0.tgz#16b8772b0a567f215839f689c5ded6bb20e864d5" - integrity sha512-x/5Ea+RO5MvF9ize5DeVICJoVrNv0Mi2RnIABrZEKYvPEpldXwauPkgvYA17cKa6WpU3LoYvYbuEMFtSNFsarA== - dependencies: - "@ampproject/remapping" "^2.0.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.0" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helpers" "^7.17.0" - "@babel/parser" "^7.17.0" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.0" - "@babel/types" "^7.17.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - -"@babel/eslint-parser@^7.16.3": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.17.0.tgz#eabb24ad9f0afa80e5849f8240d0e5facc2d90d6" - integrity sha512-PUEJ7ZBXbRkbq3qqM/jZ2nIuakUBqCYc7Qf52Lj7dlZ6zERnqisdHioL0l4wwQZnmskMeasqUNzLBFKs3nylXA== - dependencies: - eslint-scope "^5.1.1" - eslint-visitor-keys "^2.1.0" - semver "^6.3.0" - -"@babel/generator@^7.12.13": - version "7.12.15" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.15.tgz#4617b5d0b25cc572474cc1aafee1edeaf9b5368f" - integrity sha512-6F2xHxBiFXWNSGb7vyCUTBF8RCLY66rS0zEPcP8t/nQyXjha5EuK4z7H5o7fWG8B4M7y6mqVWq1J+1PuwRhecQ== - dependencies: - "@babel/types" "^7.12.13" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.0.tgz#7bd890ba706cd86d3e2f727322346ffdbf98f65e" - integrity sha512-I3Omiv6FGOC29dtlZhkfXO6pgkmukJSlT26QjVvS1DGZe/NzSVCPG41X0tS21oZkJYlovfj9qDWgKP+Cn4bXxw== - dependencies: - "@babel/types" "^7.17.0" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.7.2": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.2.tgz#2f4852d04131a5e17ea4f6645488b5da66ebf3af" - integrity sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ== - dependencies: - "@babel/types" "^7.7.2" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - -"@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz#0f58e86dfc4bb3b1fcd7db806570e177d439b6ab" - integrity sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-annotate-as-pure@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" - integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.12.13.tgz#6bc20361c88b0a74d05137a65cac8d3cbf6f61fc" - integrity sha512-CZOv9tGphhDRlVjVkAgm8Nhklm9RzSmWpX2my+t7Ua/KT616pEzXsQCjinzvkRvHWJ9itO4f296efroX23XCMA== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b" - integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-compilation-targets@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.13.tgz#d689cdef88810aa74e15a7a94186f26a3d773c98" - integrity sha512-dXof20y/6wB5HnLOGyLh/gobsMvDNoekcC+8MCV2iaTd5JemhFkPD73QB+tK3iFC9P0xJC73B6MvKkyUfS9cCw== - dependencies: - "@babel/compat-data" "^7.12.13" - "@babel/helper-validator-option" "^7.12.11" - browserslist "^4.14.5" - semver "^5.5.0" - -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" - integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== - dependencies: - "@babel/compat-data" "^7.16.4" - "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.17.5" - semver "^6.3.0" - -"@babel/helper-create-class-features-plugin@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.13.tgz#0f1707c2eec1a4604f2a22a6fb209854ef2a399a" - integrity sha512-Vs/e9wv7rakKYeywsmEBSRC9KtmE7Px+YBlESekLeJOF0zbGUicGfXSNi3o+tfXSNS48U/7K9mIOOCR79Cl3+Q== - dependencies: - "@babel/helper-function-name" "^7.12.13" - "@babel/helper-member-expression-to-functions" "^7.12.13" - "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/helper-replace-supers" "^7.12.13" - "@babel/helper-split-export-declaration" "^7.12.13" - -"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7", "@babel/helper-create-class-features-plugin@^7.17.0": - version "7.17.1" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz#9699f14a88833a7e055ce57dcd3ffdcd25186b21" - integrity sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-member-expression-to-functions" "^7.16.7" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - -"@babel/helper-create-regexp-features-plugin@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.13.tgz#0996d370a92896c612ae41a4215544bd152579c0" - integrity sha512-XC+kiA0J3at6E85dL5UnCYfVOcIZ834QcAY0TIpgUVnz0zDzg+0TtvZTnJ4g9L1dPRGe30Qi03XCIS4tYCLtqw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.12.13" - regexpu-core "^4.7.1" - -"@babel/helper-create-regexp-features-plugin@^7.16.7": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz#1dcc7d40ba0c6b6b25618997c5dbfd310f186fe1" - integrity sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - regexpu-core "^5.0.1" - -"@babel/helper-create-regexp-features-plugin@^7.7.0": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.2.tgz#6f20443778c8fce2af2ff4206284afc0ced65db6" - integrity sha512-pAil/ZixjTlrzNpjx+l/C/wJk002Wo7XbbZ8oujH/AoJ3Juv0iN/UTcPUHXKMFLqsfS0Hy6Aow8M31brUYBlQQ== - dependencies: - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.6.0" - -"@babel/helper-define-polyfill-provider@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665" - integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA== - dependencies: - "@babel/helper-compilation-targets" "^7.13.0" - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/traverse" "^7.13.0" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - semver "^6.1.2" - -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-explode-assignable-expression@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.13.tgz#0e46990da9e271502f77507efa4c9918d3d8634a" - integrity sha512-5loeRNvMo9mx1dA/d6yNi+YiKziJZFylZnCo1nmFF4qPU4yJ14abhWESuSMQSlQxWdxdOFzxXjk/PpfudTtYyw== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-explode-assignable-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a" - integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-function-name@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz#93ad656db3c3c2232559fd7b2c3dbdcbe0eb377a" - integrity sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA== - dependencies: - "@babel/helper-get-function-arity" "^7.12.13" - "@babel/template" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/helper-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" - integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== - dependencies: - "@babel/helper-get-function-arity" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-function-name@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz#44a5ad151cfff8ed2599c91682dda2ec2c8430a3" - integrity sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q== - dependencies: - "@babel/helper-get-function-arity" "^7.7.0" - "@babel/template" "^7.7.0" - "@babel/types" "^7.7.0" - -"@babel/helper-get-function-arity@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583" - integrity sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-get-function-arity@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" - integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-get-function-arity@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz#c604886bc97287a1d1398092bc666bc3d7d7aa2d" - integrity sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw== - dependencies: - "@babel/types" "^7.7.0" - -"@babel/helper-hoist-variables@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.12.13.tgz#13aba58b7480b502362316ea02f52cca0e9796cd" - integrity sha512-KSC5XSj5HreRhYQtZ3cnSnQwDzgnbdUDEFsxkN0m6Q3WrCRt72xrnZ8+h+pX7YxM7hr87zIO3a/v5p/H3TrnVw== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-member-expression-to-functions@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.13.tgz#c5715695b4f8bab32660dbdcdc2341dec7e3df40" - integrity sha512-B+7nN0gIL8FZ8SvMcF+EPyB21KnCcZHQZFczCxbiNGV/O0rsrSBlWGLzmtBJ3GMjSVMIm4lpFhR+VdVBuIsUcQ== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-member-expression-to-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0" - integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-module-imports@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz#ec67e4404f41750463e455cc3203f6a32e93fcb0" - integrity sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-module-transforms@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.13.tgz#01afb052dcad2044289b7b20beb3fa8bd0265bea" - integrity sha512-acKF7EjqOR67ASIlDTupwkKM1eUisNAjaSduo5Cz+793ikfnpe7p4Q7B7EWU2PCoSTPWsQkR7hRUWEIZPiVLGA== - dependencies: - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-replace-supers" "^7.12.13" - "@babel/helper-simple-access" "^7.12.13" - "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/helper-validator-identifier" "^7.12.11" - "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" - lodash "^4.17.19" - -"@babel/helper-module-transforms@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" - integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== - dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-optimise-call-expression@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz#5c02d171b4c8615b1e7163f888c1c81c30a2aaea" - integrity sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-optimise-call-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" - integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-plugin-utils@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" - integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== - -"@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz#174254d0f2424d8aefb4dd48057511247b0a9eeb" - integrity sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA== - -"@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" - integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== - -"@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" - integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== - -"@babel/helper-regex@^7.4.4": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" - integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== - dependencies: - lodash "^4.17.13" - -"@babel/helper-remap-async-to-generator@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.13.tgz#170365f4140e2d20e5c88f8ba23c24468c296878" - integrity sha512-Qa6PU9vNcj1NZacZZI1Mvwt+gXDH6CTfgAkSjeRMLE8HxtDK76+YDId6NQR+z7Rgd5arhD2cIbS74r0SxD6PDA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.12.13" - "@babel/helper-wrap-function" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/helper-remap-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3" - integrity sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-wrap-function" "^7.16.8" - "@babel/types" "^7.16.8" - -"@babel/helper-replace-supers@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.13.tgz#00ec4fb6862546bd3d0aff9aac56074277173121" - integrity sha512-pctAOIAMVStI2TMLhozPKbf5yTEXc0OJa0eENheb4w09SrgOWEs+P4nTOZYJQCqs8JlErGLDPDJTiGIp3ygbLg== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.12.13" - "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/helper-replace-supers@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" - integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== - dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-member-expression-to-functions" "^7.16.7" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-simple-access@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.13.tgz#8478bcc5cacf6aa1672b251c1d2dde5ccd61a6c4" - integrity sha512-0ski5dyYIHEfwpWGx5GPWhH35j342JaflmCeQmsPWcrOQDtCN6C1zKAVRFVbK53lPW2c9TsuLLSUDf0tIGJ5hA== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-simple-access@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" - integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-skip-transparent-expression-wrappers@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" - integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== - dependencies: - "@babel/types" "^7.12.1" - -"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" - integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-split-export-declaration@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05" - integrity sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-split-export-declaration@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz#1365e74ea6c614deeb56ebffabd71006a0eb2300" - integrity sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA== - dependencies: - "@babel/types" "^7.7.0" - -"@babel/helper-validator-identifier@^7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" - integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== - -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - -"@babel/helper-validator-option@^7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" - integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== - -"@babel/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== - -"@babel/helper-wrap-function@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.12.13.tgz#e3ea8cb3ee0a16911f9c1b50d9e99fe8fe30f9ff" - integrity sha512-t0aZFEmBJ1LojdtJnhOaQEVejnzYhyjWHSsNSNo8vOYRbAJNh6r6GQF7pd36SqG7OKGbn+AewVQ/0IfYfIuGdw== - dependencies: - "@babel/helper-function-name" "^7.12.13" - "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/helper-wrap-function@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200" - integrity sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw== - dependencies: - "@babel/helper-function-name" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.8" - "@babel/types" "^7.16.8" - -"@babel/helpers@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.13.tgz#3c75e993632e4dadc0274eae219c73eb7645ba47" - integrity sha512-oohVzLRZ3GQEk4Cjhfs9YkJA4TdIDTObdBEZGrd6F/T0GPSnuV6l22eMcxlvcvzVIPH3VTtxbseudM1zIE+rPQ== - dependencies: - "@babel/template" "^7.12.13" - "@babel/traverse" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/helpers@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.0.tgz#79cdf6c66a579f3a7b5e739371bc63ca0306886b" - integrity sha512-Xe/9NFxjPwELUvW2dsukcMZIp6XwPSbI4ojFBJuX5ramHuVE22SVcZIwqzdWo5uCgeTXW8qV97lMvSOjq+1+nQ== - dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.0" - "@babel/types" "^7.17.0" - -"@babel/highlight@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" - -"@babel/highlight@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.12.13.tgz#8ab538393e00370b26271b01fa08f7f27f2e795c" - integrity sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww== - dependencies: - "@babel/helper-validator-identifier" "^7.12.11" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.16.7": - version "7.16.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" - integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.7.0", "@babel/parser@^7.7.2": - version "7.7.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.3.tgz#5fad457c2529de476a248f75b0f090b3060af043" - integrity sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A== - -"@babel/parser@^7.12.13": - version "7.12.15" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.15.tgz#2b20de7f0b4b332d9b119dd9c33409c538b8aacf" - integrity sha512-AQBOU2Z9kWwSZMd6lNjCX0GUgFonL1wAM1db8L8PMk9UDaGsRCArBkU4Sc+UCM3AE4hjbXx+h58Lb3QT4oRmrA== - -"@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.0.tgz#f0ac33eddbe214e4105363bb17c3341c5ffcc43c" - integrity sha512-VKXSCQx5D8S04ej+Dqsr1CzYvvWgf20jIw2D+YhQCrIlr2UZGaDds23Y0xg75/skOxpLCRpUZvk/1EAVkGoDOw== - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" - integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9" - integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" - "@babel/plugin-proposal-optional-chaining" "^7.16.7" - -"@babel/plugin-proposal-async-generator-functions@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.13.tgz#d1c6d841802ffb88c64a2413e311f7345b9e66b5" - integrity sha512-1KH46Hx4WqP77f978+5Ye/VUbuwQld2hph70yaw2hXS2v7ER2f3nlpNMu909HO2rbvP0NKLlMVDPh9KXklVMhA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-remap-async-to-generator" "^7.12.13" - "@babel/plugin-syntax-async-generators" "^7.8.0" - -"@babel/plugin-proposal-async-generator-functions@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8" - integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-remap-async-to-generator" "^7.16.8" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-proposal-class-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.13.tgz#3d2ce350367058033c93c098e348161d6dc0d8c8" - integrity sha512-8SCJ0Ddrpwv4T7Gwb33EmW1V9PY5lggTO+A8WjyIwxrSHDUyBw4MtF96ifn1n8H806YlxbVCoKXbbmzD6RD+cA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-proposal-class-properties@^7.16.0", "@babel/plugin-proposal-class-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" - integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-proposal-class-static-block@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz#712357570b612106ef5426d13dc433ce0f200c2a" - integrity sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - -"@babel/plugin-proposal-decorators@^7.16.4": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.0.tgz#fc0f689fe2535075056c587bc10c176fa9990443" - integrity sha512-JR8HTf3T1CsdMqfENrZ9pqncwsH4sPcvsyDLpvmv8iIbpDmeyBD7HPfGAIqkQph2j5d3B84hTm+m3qHPAedaPw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.17.0" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - "@babel/plugin-syntax-decorators" "^7.17.0" - charcodes "^0.2.0" - -"@babel/plugin-proposal-dynamic-import@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz#43eb5c2a3487ecd98c5c8ea8b5fdb69a2749b2dc" - integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - -"@babel/plugin-proposal-dynamic-import@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2" - integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - -"@babel/plugin-proposal-export-namespace-from@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.13.tgz#393be47a4acd03fa2af6e3cde9b06e33de1b446d" - integrity sha512-INAgtFo4OnLN3Y/j0VwAgw3HDXcDtX+C/erMvWzuV9v71r7urb6iyMXu7eM9IgLr1ElLlOkaHjJ0SbCmdOQ3Iw== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-proposal-export-namespace-from@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" - integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-proposal-json-strings@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.13.tgz#ced7888a2db92a3d520a2e35eb421fdb7fcc9b5d" - integrity sha512-v9eEi4GiORDg8x+Dmi5r8ibOe0VXoKDeNPYcTTxdGN4eOWikrJfDJCJrr1l5gKGvsNyGJbrfMftC2dTL6oz7pg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-syntax-json-strings" "^7.8.0" - -"@babel/plugin-proposal-json-strings@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8" - integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-json-strings" "^7.8.3" - -"@babel/plugin-proposal-logical-assignment-operators@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.13.tgz#575b5d9a08d8299eeb4db6430da6e16e5cf14350" - integrity sha512-fqmiD3Lz7jVdK6kabeSr1PZlWSUVqSitmHEe3Z00dtGTKieWnX9beafvavc32kjORa5Bai4QNHgFDwWJP+WtSQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-proposal-logical-assignment-operators@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" - integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.13.tgz#24867307285cee4e1031170efd8a7ac807deefde" - integrity sha512-Qoxpy+OxhDBI5kRqliJFAl4uWXk3Bn24WeFstPH0iLymFehSAUR8MHpqU7njyXv/qbo7oN6yTy5bfCmXdKpo1Q== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" - integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - -"@babel/plugin-proposal-numeric-separator@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.13.tgz#bd9da3188e787b5120b4f9d465a8261ce67ed1db" - integrity sha512-O1jFia9R8BUCl3ZGB7eitaAPu62TXJRHn7rh+ojNERCFyqRwJMTmhz+tJ+k0CwI6CLjX/ee4qW74FSqlq9I35w== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-numeric-separator@^7.16.0", "@babel/plugin-proposal-numeric-separator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9" - integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-object-rest-spread@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.13.tgz#f93f3116381ff94bc676fdcb29d71045cd1ec011" - integrity sha512-WvA1okB/0OS/N3Ldb3sziSrXg6sRphsBgqiccfcQq7woEn5wQLNX82Oc4PlaFcdwcWHuQXAtb8ftbS8Fbsg/sg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.12.13" - -"@babel/plugin-proposal-object-rest-spread@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz#94593ef1ddf37021a25bdcb5754c4a8d534b01d8" - integrity sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA== - dependencies: - "@babel/compat-data" "^7.16.4" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.16.7" - -"@babel/plugin-proposal-optional-catch-binding@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.13.tgz#4640520afe57728af14b4d1574ba844f263bcae5" - integrity sha512-9+MIm6msl9sHWg58NvqpNpLtuFbmpFYk37x8kgnGzAHvX35E1FyAwSUt5hIkSoWJFSAH+iwU8bJ4fcD1zKXOzg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - -"@babel/plugin-proposal-optional-catch-binding@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf" - integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-proposal-optional-chaining@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.13.tgz#63a7d805bc8ce626f3234ee5421a2a7fb23f66d9" - integrity sha512-0ZwjGfTcnZqyV3y9DSD1Yk3ebp+sIUpT2YDqP8hovzaNZnQq2Kd7PEqa6iOIUDBXBt7Jl3P7YAcEIL5Pz8u09Q== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - -"@babel/plugin-proposal-optional-chaining@^7.16.0", "@babel/plugin-proposal-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" - integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-proposal-private-methods@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.13.tgz#ea78a12554d784ecf7fc55950b752d469d9c4a71" - integrity sha512-sV0V57uUwpauixvR7s2o75LmwJI6JECwm5oPUY5beZB1nBl2i37hc7CJGqB5G+58fur5Y6ugvl3LRONk5x34rg== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-proposal-private-methods@^7.16.0", "@babel/plugin-proposal-private-methods@^7.16.11": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50" - integrity sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.10" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-proposal-private-property-in-object@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" - integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - -"@babel/plugin-proposal-unicode-property-regex@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.13.tgz#bebde51339be829c17aaaaced18641deb62b39ba" - integrity sha512-XyJmZidNfofEkqFV5VC/bLabGmO5QzenPO/YOfGuEbgU+2sSwMmio3YLb4WtBgcmmdwZHyVyv8on77IUjQ5Gvg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-proposal-unicode-property-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2" - integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.0.tgz#549fe1717a1bd0a2a7e63163841cb37e78179d5d" - integrity sha512-mk34H+hp7kRBWJOOAR0ZMGCydgKMD4iN9TpDRp3IIcbunltxEY89XSimc6WbtSLCDrwcdy/EEw7h5CFCzxTchw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.7.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" - integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-decorators@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.17.0.tgz#a2be3b2c9fe7d78bd4994e790896bc411e2f166d" - integrity sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-export-namespace-from@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" - integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-flow@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.16.7.tgz#202b147e5892b8452bbb0bb269c7ed2539ab8832" - integrity sha512-UDo3YGQO0jH6ytzVwgSLv9i/CzMcUjbKenL67dTrAZPPv6GFAtDhe6jqnvmoKzC/7htNTohhos+onPtDMqJwaQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-syntax-import-meta@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.0", "@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.13.tgz#044fb81ebad6698fe62c478875575bcbb9b70f15" - integrity sha512-d4HM23Q1K7oq/SLNmG6mRt85l2csmQ0cHRaxRXjKW0YFdEXqlZ5kzFQKH5Uc3rDJECgu+yCRgPkG04Mm98R/1g== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-jsx@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz#50b6571d13f764266a113d77c82b4a6508bbe665" - integrity sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" - integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.0", "@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" - integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-top-level-await@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.13.tgz#c5f0fa6e249f5b739727f923540cf7a806130178" - integrity sha512-A81F9pDwyS7yM//KwbCSDqy3Uj4NMIurtplxphWxoYtNPov7cJsDkAFNNyVlIZ3jwGycVsurZ+LtOA8gZ376iQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-top-level-await@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" - integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-typescript@^7.16.7", "@babel/plugin-syntax-typescript@^7.7.2": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz#39c9b55ee153151990fb038651d58d3fd03f98f8" - integrity sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-arrow-functions@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.13.tgz#eda5670b282952100c229f8a3bd49e0f6a72e9fe" - integrity sha512-tBtuN6qtCTd+iHzVZVOMNp+L04iIJBpqkdY42tWbmjIT5wvR2kx7gxMBsyhQtFzHwBbyGi9h8J8r9HgnOpQHxg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-arrow-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" - integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-async-to-generator@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.13.tgz#fed8c69eebf187a535bfa4ee97a614009b24f7ae" - integrity sha512-psM9QHcHaDr+HZpRuJcE1PXESuGWSCcbiGFFhhwfzdbTxaGDVzuVtdNYliAwcRo3GFg0Bc8MmI+AvIGYIJG04A== - dependencies: - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-remap-async-to-generator" "^7.12.13" - -"@babel/plugin-transform-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808" - integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg== - dependencies: - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-remap-async-to-generator" "^7.16.8" - -"@babel/plugin-transform-block-scoped-functions@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.13.tgz#a9bf1836f2a39b4eb6cf09967739de29ea4bf4c4" - integrity sha512-zNyFqbc3kI/fVpqwfqkg6RvBgFpC4J18aKKMmv7KdQ/1GgREapSJAykLMVNwfRGO3BtHj3YQZl8kxCXPcVMVeg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-block-scoped-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620" - integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-block-scoping@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.13.tgz#f36e55076d06f41dfd78557ea039c1b581642e61" - integrity sha512-Pxwe0iqWJX4fOOM2kEZeUuAxHMWb9nK+9oh5d11bsLoB0xMg+mkDpt0eYuDZB7ETrY9bbcVlKUGTOGWy7BHsMQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-block-scoping@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" - integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-classes@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.13.tgz#9728edc1838b5d62fc93ad830bd523b1fcb0e1f6" - integrity sha512-cqZlMlhCC1rVnxE5ZGMtIb896ijL90xppMiuWXcwcOAuFczynpd3KYemb91XFFPi3wJSe/OcrX9lXoowatkkxA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.12.13" - "@babel/helper-function-name" "^7.12.13" - "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-replace-supers" "^7.12.13" - "@babel/helper-split-export-declaration" "^7.12.13" - globals "^11.1.0" - -"@babel/plugin-transform-classes@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" - integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.13.tgz#6a210647a3d67f21f699cfd2a01333803b27339d" - integrity sha512-dDfuROUPGK1mTtLKyDPUavmj2b6kFu82SmgpztBFEO974KMjJT+Ytj3/oWsTUMBmgPcp9J5Pc1SlcAYRpJ2hRA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-computed-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" - integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-destructuring@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.13.tgz#fc56c5176940c5b41735c677124d1d20cecc9aeb" - integrity sha512-Dn83KykIFzjhA3FDPA1z4N+yfF3btDGhjnJwxIj0T43tP0flCujnU8fKgEkf0C1biIpSv9NZegPBQ1J6jYkwvQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-destructuring@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz#ca9588ae2d63978a4c29d3f33282d8603f618e23" - integrity sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-dotall-regex@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.13.tgz#3f1601cc29905bfcb67f53910f197aeafebb25ad" - integrity sha512-foDrozE65ZFdUC2OfgeOCrEPTxdB3yjqxpXh8CH+ipd9CHd4s/iq81kcUpyH8ACGNEPdFqbtzfgzbT/ZGlbDeQ== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-dotall-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241" - integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.0.tgz#c5c9ecacab3a5e0c11db6981610f0c32fd698b3b" - integrity sha512-3QQlF7hSBnSuM1hQ0pS3pmAbWLax/uGNCbPBND9y+oJ4Y776jsyujG2k0Sn2Aj2a0QwVOiOFL5QVPA7spjvzSA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.7.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-duplicate-keys@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.13.tgz#6f06b87a8b803fd928e54b81c258f0a0033904de" - integrity sha512-NfADJiiHdhLBW3pulJlJI2NB0t4cci4WTZ8FtdIuNc2+8pslXdPtRRAEWqUY+m9kNOk2eRYbTAOipAxlrOcwwQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-duplicate-keys@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9" - integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-exponentiation-operator@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.13.tgz#4d52390b9a273e651e4aba6aee49ef40e80cd0a1" - integrity sha512-fbUelkM1apvqez/yYx1/oICVnGo2KM5s63mhGylrmXUxK/IAXSIf87QIxVfZldWf4QsOafY6vV3bX8aMHSvNrA== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-exponentiation-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b" - integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-flow-strip-types@^7.16.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.16.7.tgz#291fb140c78dabbf87f2427e7c7c332b126964b8" - integrity sha512-mzmCq3cNsDpZZu9FADYYyfZJIOrSONmHcop2XEKPdBNMa4PDC4eEvcOvzZaCNcjKu72v0XQlA5y1g58aLRXdYg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-flow" "^7.16.7" - -"@babel/plugin-transform-for-of@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.13.tgz#561ff6d74d9e1c8879cb12dbaf4a14cd29d15cf6" - integrity sha512-xCbdgSzXYmHGyVX3+BsQjcd4hv4vA/FDy7Kc8eOpzKmBBPEOTurt0w5fCRQaGl+GSBORKgJdstQ1rHl4jbNseQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-for-of@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" - integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-function-name@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.13.tgz#bb024452f9aaed861d374c8e7a24252ce3a50051" - integrity sha512-6K7gZycG0cmIwwF7uMK/ZqeCikCGVBdyP2J5SKNCXO5EOHcqi+z7Jwf8AmyDNcBgxET8DrEtCt/mPKPyAzXyqQ== - dependencies: - "@babel/helper-function-name" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf" - integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== - dependencies: - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-literals@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.13.tgz#2ca45bafe4a820197cf315794a4d26560fe4bdb9" - integrity sha512-FW+WPjSR7hiUxMcKqyNjP05tQ2kmBCdpEpZHY1ARm96tGQCCBvXKnpjILtDplUnJ/eHZ0lALLM+d2lMFSpYJrQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" - integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-member-expression-literals@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.13.tgz#5ffa66cd59b9e191314c9f1f803b938e8c081e40" - integrity sha512-kxLkOsg8yir4YeEPHLuO2tXP9R/gTjpuTOjshqSpELUN3ZAg2jfDnKUvzzJxObun38sw3wm4Uu69sX/zA7iRvg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-member-expression-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384" - integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-modules-amd@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.13.tgz#43db16249b274ee2e551e2422090aa1c47692d56" - integrity sha512-JHLOU0o81m5UqG0Ulz/fPC68/v+UTuGTWaZBUwpEk1fYQ1D9LfKV6MPn4ttJKqRo5Lm460fkzjLTL4EHvCprvA== - dependencies: - "@babel/helper-module-transforms" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-amd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186" - integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== - dependencies: - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-commonjs@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.13.tgz#5043b870a784a8421fa1fd9136a24f294da13e50" - integrity sha512-OGQoeVXVi1259HjuoDnsQMlMkT9UkZT9TpXAsqWplS/M0N1g3TJAn/ByOCeQu7mfjc5WpSsRU+jV1Hd89ts0kQ== - dependencies: - "@babel/helper-module-transforms" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-simple-access" "^7.12.13" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-commonjs@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" - integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== - dependencies: - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-simple-access" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-systemjs@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.13.tgz#351937f392c7f07493fc79b2118201d50404a3c5" - integrity sha512-aHfVjhZ8QekaNF/5aNdStCGzwTbU7SI5hUybBKlMzqIMC7w7Ho8hx5a4R/DkTHfRfLwHGGxSpFt9BfxKCoXKoA== - dependencies: - "@babel/helper-hoist-variables" "^7.12.13" - "@babel/helper-module-transforms" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-validator-identifier" "^7.12.11" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-systemjs@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz#887cefaef88e684d29558c2b13ee0563e287c2d7" - integrity sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw== - dependencies: - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-umd@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.13.tgz#26c66f161d3456674e344b4b1255de4d530cfb37" - integrity sha512-BgZndyABRML4z6ibpi7Z98m4EVLFI9tVsZDADC14AElFaNHHBcJIovflJ6wtCqFxwy2YJ1tJhGRsr0yLPKoN+w== - dependencies: - "@babel/helper-module-transforms" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-modules-umd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618" - integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== - dependencies: - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.13.tgz#2213725a5f5bbbe364b50c3ba5998c9599c5c9d9" - integrity sha512-Xsm8P2hr5hAxyYblrfACXpQKdQbx4m2df9/ZZSQ8MAhsadw06+jW7s9zsSw6he+mJZXRlVMyEnVktJo4zjk1WA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.13" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252" - integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - -"@babel/plugin-transform-new-target@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.13.tgz#e22d8c3af24b150dd528cbd6e685e799bf1c351c" - integrity sha512-/KY2hbLxrG5GTQ9zzZSc3xWiOy379pIETEhbtzwZcw9rvuaVV4Fqy7BYGYOWZnaoXIQYbbJ0ziXLa/sKcGCYEQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-new-target@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244" - integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-object-super@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.13.tgz#b4416a2d63b8f7be314f3d349bd55a9c1b5171f7" - integrity sha512-JzYIcj3XtYspZDV8j9ulnoMPZZnF/Cj0LUxPOjR89BdBVx+zYJI9MdMIlUZjbXDX+6YVeS6I3e8op+qQ3BYBoQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-replace-supers" "^7.12.13" - -"@babel/plugin-transform-object-super@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94" - integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - -"@babel/plugin-transform-parameters@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.13.tgz#461e76dfb63c2dfd327b8a008a9e802818ce9853" - integrity sha512-e7QqwZalNiBRHCpJg/P8s/VJeSRYgmtWySs1JwvfwPqhBbiWfOcHDKdeAi6oAyIimoKWBlwc8oTgbZHdhCoVZA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-parameters@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" - integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-property-literals@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.13.tgz#4e6a9e37864d8f1b3bc0e2dce7bf8857db8b1a81" - integrity sha512-nqVigwVan+lR+g8Fj8Exl0UQX2kymtjcWfMOYM1vTYEKujeyv2SkMgazf2qNcK7l4SDiKyTA/nHCPqL4e2zo1A== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-property-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55" - integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-react-constant-elements@^7.12.1": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.12.13.tgz#f8ee56888545d53d80f766b3cc1563ab2c241f92" - integrity sha512-qmzKVTn46Upvtxv8LQoQ8mTCdUC83AOVQIQm57e9oekLT5cmK9GOMOfcWhe8jMNx4UJXn/UDhVZ/7lGofVNeDQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-react-display-name@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.13.tgz#c28effd771b276f4647411c9733dbb2d2da954bd" - integrity sha512-MprESJzI9O5VnJZrL7gg1MpdqmiFcUv41Jc7SahxYsNP2kDkFqClxxTZq+1Qv4AFCamm+GXMRDQINNn+qrxmiA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-react-display-name@^7.16.0", "@babel/plugin-transform-react-display-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz#7b6d40d232f4c0f550ea348593db3b21e2404340" - integrity sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-react-jsx-development@^7.12.12": - version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz#bccca33108fe99d95d7f9e82046bfe762e71f4e7" - integrity sha512-i1AxnKxHeMxUaWVXQOSIco4tvVvvCxMSfeBMnMM06mpaJt3g+MpxYQQrDfojUQldP1xxraPSJYSMEljoWM/dCg== - dependencies: - "@babel/plugin-transform-react-jsx" "^7.12.12" - -"@babel/plugin-transform-react-jsx-development@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz#43a00724a3ed2557ed3f276a01a929e6686ac7b8" - integrity sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A== - dependencies: - "@babel/plugin-transform-react-jsx" "^7.16.7" - -"@babel/plugin-transform-react-jsx@^7.12.12", "@babel/plugin-transform-react-jsx@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.13.tgz#6c9f993b9f6fb6f0e32a4821ed59349748576a3e" - integrity sha512-hhXZMYR8t9RvduN2uW4sjl6MRtUhzNE726JvoJhpjhxKgRUVkZqTsA0xc49ALZxQM7H26pZ/lLvB2Yrea9dllA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.12.13" - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-syntax-jsx" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/plugin-transform-react-jsx@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.7.tgz#86a6a220552afd0e4e1f0388a68a372be7add0d4" - integrity sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-jsx" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/plugin-transform-react-pure-annotations@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz#05d46f0ab4d1339ac59adf20a1462c91b37a1a42" - integrity sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-react-pure-annotations@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz#232bfd2f12eb551d6d7d01d13fe3f86b45eb9c67" - integrity sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-regenerator@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.13.tgz#b628bcc9c85260ac1aeb05b45bde25210194a2f5" - integrity sha512-lxb2ZAvSLyJ2PEe47hoGWPmW22v7CtSl9jW8mingV4H2sEX/JOcrAj2nPuGWi56ERUm2bUpjKzONAuT6HCn2EA== - dependencies: - regenerator-transform "^0.14.2" - -"@babel/plugin-transform-regenerator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb" - integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q== - dependencies: - regenerator-transform "^0.14.2" - -"@babel/plugin-transform-reserved-words@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.13.tgz#7d9988d4f06e0fe697ea1d9803188aa18b472695" - integrity sha512-xhUPzDXxZN1QfiOy/I5tyye+TRz6lA7z6xaT4CLOjPRMVg1ldRf0LHw0TDBpYL4vG78556WuHdyO9oi5UmzZBg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-reserved-words@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586" - integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-runtime@^7.16.4": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz#0a2e08b5e2b2d95c4b1d3b3371a2180617455b70" - integrity sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A== - dependencies: - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - babel-plugin-polyfill-corejs2 "^0.3.0" - babel-plugin-polyfill-corejs3 "^0.5.0" - babel-plugin-polyfill-regenerator "^0.3.0" - semver "^6.3.0" - -"@babel/plugin-transform-shorthand-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.13.tgz#db755732b70c539d504c6390d9ce90fe64aff7ad" - integrity sha512-xpL49pqPnLtf0tVluuqvzWIgLEhuPpZzvs2yabUHSKRNlN7ScYU7aMlmavOeyXJZKgZKQRBlh8rHbKiJDraTSw== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-shorthand-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" - integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-spread@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.13.tgz#ca0d5645abbd560719c354451b849f14df4a7949" - integrity sha512-dUCrqPIowjqk5pXsx1zPftSq4sT0aCeZVAxhdgs3AMgyaDmoUT0G+5h3Dzja27t76aUEIJWlFgPJqJ/d4dbTtg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" - -"@babel/plugin-transform-spread@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" - integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" - -"@babel/plugin-transform-sticky-regex@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.13.tgz#760ffd936face73f860ae646fb86ee82f3d06d1f" - integrity sha512-Jc3JSaaWT8+fr7GRvQP02fKDsYk4K/lYwWq38r/UGfaxo89ajud321NH28KRQ7xy1Ybc0VUE5Pz8psjNNDUglg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-sticky-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660" - integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-template-literals@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.13.tgz#655037b07ebbddaf3b7752f55d15c2fd6f5aa865" - integrity sha512-arIKlWYUgmNsF28EyfmiQHJLJFlAJNYkuQO10jL46ggjBpeb2re1P9K9YGxNJB45BqTbaslVysXDYm/g3sN/Qg== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-template-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" - integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-typeof-symbol@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.13.tgz#785dd67a1f2ea579d9c2be722de8c84cb85f5a7f" - integrity sha512-eKv/LmUJpMnu4npgfvs3LiHhJua5fo/CysENxa45YCQXZwKnGCQKAg87bvoqSW1fFT+HA32l03Qxsm8ouTY3ZQ== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-typeof-symbol@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e" - integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-typescript@^7.16.7": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz#591ce9b6b83504903fa9dd3652c357c2ba7a1ee0" - integrity sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-typescript" "^7.16.7" - -"@babel/plugin-transform-unicode-escapes@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.13.tgz#840ced3b816d3b5127dd1d12dcedc5dead1a5e74" - integrity sha512-0bHEkdwJ/sN/ikBHfSmOXPypN/beiGqjo+o4/5K+vxEFNPRPdImhviPakMKG4x96l85emoa0Z6cDflsdBusZbw== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-unicode-escapes@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3" - integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-unicode-regex@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.13.tgz#b52521685804e155b1202e83fc188d34bb70f5ac" - integrity sha512-mDRzSNY7/zopwisPZ5kM9XKCfhchqIYwAKRERtEnhYscZB79VRekuRSoYbN0+KVe3y8+q1h6A4svXtP7N+UoCA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-transform-unicode-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2" - integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.16.4": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" - integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== - dependencies: - "@babel/compat-data" "^7.16.8" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-validator-option" "^7.16.7" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.7" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.7" - "@babel/plugin-proposal-async-generator-functions" "^7.16.8" - "@babel/plugin-proposal-class-properties" "^7.16.7" - "@babel/plugin-proposal-class-static-block" "^7.16.7" - "@babel/plugin-proposal-dynamic-import" "^7.16.7" - "@babel/plugin-proposal-export-namespace-from" "^7.16.7" - "@babel/plugin-proposal-json-strings" "^7.16.7" - "@babel/plugin-proposal-logical-assignment-operators" "^7.16.7" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.7" - "@babel/plugin-proposal-numeric-separator" "^7.16.7" - "@babel/plugin-proposal-object-rest-spread" "^7.16.7" - "@babel/plugin-proposal-optional-catch-binding" "^7.16.7" - "@babel/plugin-proposal-optional-chaining" "^7.16.7" - "@babel/plugin-proposal-private-methods" "^7.16.11" - "@babel/plugin-proposal-private-property-in-object" "^7.16.7" - "@babel/plugin-proposal-unicode-property-regex" "^7.16.7" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.16.7" - "@babel/plugin-transform-async-to-generator" "^7.16.8" - "@babel/plugin-transform-block-scoped-functions" "^7.16.7" - "@babel/plugin-transform-block-scoping" "^7.16.7" - "@babel/plugin-transform-classes" "^7.16.7" - "@babel/plugin-transform-computed-properties" "^7.16.7" - "@babel/plugin-transform-destructuring" "^7.16.7" - "@babel/plugin-transform-dotall-regex" "^7.16.7" - "@babel/plugin-transform-duplicate-keys" "^7.16.7" - "@babel/plugin-transform-exponentiation-operator" "^7.16.7" - "@babel/plugin-transform-for-of" "^7.16.7" - "@babel/plugin-transform-function-name" "^7.16.7" - "@babel/plugin-transform-literals" "^7.16.7" - "@babel/plugin-transform-member-expression-literals" "^7.16.7" - "@babel/plugin-transform-modules-amd" "^7.16.7" - "@babel/plugin-transform-modules-commonjs" "^7.16.8" - "@babel/plugin-transform-modules-systemjs" "^7.16.7" - "@babel/plugin-transform-modules-umd" "^7.16.7" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.8" - "@babel/plugin-transform-new-target" "^7.16.7" - "@babel/plugin-transform-object-super" "^7.16.7" - "@babel/plugin-transform-parameters" "^7.16.7" - "@babel/plugin-transform-property-literals" "^7.16.7" - "@babel/plugin-transform-regenerator" "^7.16.7" - "@babel/plugin-transform-reserved-words" "^7.16.7" - "@babel/plugin-transform-shorthand-properties" "^7.16.7" - "@babel/plugin-transform-spread" "^7.16.7" - "@babel/plugin-transform-sticky-regex" "^7.16.7" - "@babel/plugin-transform-template-literals" "^7.16.7" - "@babel/plugin-transform-typeof-symbol" "^7.16.7" - "@babel/plugin-transform-unicode-escapes" "^7.16.7" - "@babel/plugin-transform-unicode-regex" "^7.16.7" - "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.16.8" - babel-plugin-polyfill-corejs2 "^0.3.0" - babel-plugin-polyfill-corejs3 "^0.5.0" - babel-plugin-polyfill-regenerator "^0.3.0" - core-js-compat "^3.20.2" - semver "^6.3.0" - -"@babel/preset-env@^7.12.1": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.13.tgz#3aa2d09cf7d255177538dff292ac9af29ad46525" - integrity sha512-JUVlizG8SoFTz4LmVUL8++aVwzwxcvey3N0j1tRbMAXVEy95uQ/cnEkmEKHN00Bwq4voAV3imQGnQvpkLAxsrw== - dependencies: - "@babel/compat-data" "^7.12.13" - "@babel/helper-compilation-targets" "^7.12.13" - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/helper-validator-option" "^7.12.11" - "@babel/plugin-proposal-async-generator-functions" "^7.12.13" - "@babel/plugin-proposal-class-properties" "^7.12.13" - "@babel/plugin-proposal-dynamic-import" "^7.12.1" - "@babel/plugin-proposal-export-namespace-from" "^7.12.13" - "@babel/plugin-proposal-json-strings" "^7.12.13" - "@babel/plugin-proposal-logical-assignment-operators" "^7.12.13" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.13" - "@babel/plugin-proposal-numeric-separator" "^7.12.13" - "@babel/plugin-proposal-object-rest-spread" "^7.12.13" - "@babel/plugin-proposal-optional-catch-binding" "^7.12.13" - "@babel/plugin-proposal-optional-chaining" "^7.12.13" - "@babel/plugin-proposal-private-methods" "^7.12.13" - "@babel/plugin-proposal-unicode-property-regex" "^7.12.13" - "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@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.13" - "@babel/plugin-transform-arrow-functions" "^7.12.13" - "@babel/plugin-transform-async-to-generator" "^7.12.13" - "@babel/plugin-transform-block-scoped-functions" "^7.12.13" - "@babel/plugin-transform-block-scoping" "^7.12.13" - "@babel/plugin-transform-classes" "^7.12.13" - "@babel/plugin-transform-computed-properties" "^7.12.13" - "@babel/plugin-transform-destructuring" "^7.12.13" - "@babel/plugin-transform-dotall-regex" "^7.12.13" - "@babel/plugin-transform-duplicate-keys" "^7.12.13" - "@babel/plugin-transform-exponentiation-operator" "^7.12.13" - "@babel/plugin-transform-for-of" "^7.12.13" - "@babel/plugin-transform-function-name" "^7.12.13" - "@babel/plugin-transform-literals" "^7.12.13" - "@babel/plugin-transform-member-expression-literals" "^7.12.13" - "@babel/plugin-transform-modules-amd" "^7.12.13" - "@babel/plugin-transform-modules-commonjs" "^7.12.13" - "@babel/plugin-transform-modules-systemjs" "^7.12.13" - "@babel/plugin-transform-modules-umd" "^7.12.13" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.13" - "@babel/plugin-transform-new-target" "^7.12.13" - "@babel/plugin-transform-object-super" "^7.12.13" - "@babel/plugin-transform-parameters" "^7.12.13" - "@babel/plugin-transform-property-literals" "^7.12.13" - "@babel/plugin-transform-regenerator" "^7.12.13" - "@babel/plugin-transform-reserved-words" "^7.12.13" - "@babel/plugin-transform-shorthand-properties" "^7.12.13" - "@babel/plugin-transform-spread" "^7.12.13" - "@babel/plugin-transform-sticky-regex" "^7.12.13" - "@babel/plugin-transform-template-literals" "^7.12.13" - "@babel/plugin-transform-typeof-symbol" "^7.12.13" - "@babel/plugin-transform-unicode-escapes" "^7.12.13" - "@babel/plugin-transform-unicode-regex" "^7.12.13" - "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.12.13" - core-js-compat "^3.8.0" - semver "^5.5.0" - -"@babel/preset-modules@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" - integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== - 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" - -"@babel/preset-modules@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" - integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== - 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" - -"@babel/preset-react@^7.12.5": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.13.tgz#5f911b2eb24277fa686820d5bd81cad9a0602a0a" - integrity sha512-TYM0V9z6Abb6dj1K7i5NrEhA13oS5ujUYQYDfqIBXYHOc2c2VkFgc+q9kyssIyUfy4/hEwqrgSlJ/Qgv8zJLsA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-transform-react-display-name" "^7.12.13" - "@babel/plugin-transform-react-jsx" "^7.12.13" - "@babel/plugin-transform-react-jsx-development" "^7.12.12" - "@babel/plugin-transform-react-pure-annotations" "^7.12.1" - -"@babel/preset-react@^7.16.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.7.tgz#4c18150491edc69c183ff818f9f2aecbe5d93852" - integrity sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-validator-option" "^7.16.7" - "@babel/plugin-transform-react-display-name" "^7.16.7" - "@babel/plugin-transform-react-jsx" "^7.16.7" - "@babel/plugin-transform-react-jsx-development" "^7.16.7" - "@babel/plugin-transform-react-pure-annotations" "^7.16.7" - -"@babel/preset-typescript@^7.16.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" - integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-validator-option" "^7.16.7" - "@babel/plugin-transform-typescript" "^7.16.7" - -"@babel/runtime-corejs3@^7.10.2": - version "7.13.7" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.13.7.tgz#f47f882b62961c1ada113dbafc717c69c18a9b09" - integrity sha512-zkDsGGSRU2YyYTXkPfcxuYuCVc6xBOeH1ZMh72ywBvmrDs+kSmoMuCUXZJUPbXZafrPivDHS2Oq7wI37gaTvqw== - dependencies: - core-js-pure "^3.0.0" - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.16.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" - integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.12.13", "@babel/template@^7.3.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" - integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/parser" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/template@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.0.tgz#4fadc1b8e734d97f56de39c77de76f2562e597d0" - integrity sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.0" - "@babel/types" "^7.7.0" - -"@babel/traverse@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.13.tgz#689f0e4b4c08587ad26622832632735fb8c4e0c0" - integrity sha512-3Zb4w7eE/OslI0fTp8c7b286/cQps3+vdLW3UcwC8VSJC6GbKn55aeVVu2QJNuCDoeKyptLOFrPq8WqZZBodyA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.12.13" - "@babel/helper-function-name" "^7.12.13" - "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/parser" "^7.12.13" - "@babel/types" "^7.12.13" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.19" - -"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.7.2": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.0.tgz#3143e5066796408ccc880a33ecd3184f3e75cd30" - integrity sha512-fpFIXvqD6kC7c7PUNnZ0Z8cQXlarCLtCUpt2S1Dx7PjoRtCFffvOkHHSom+m5HIxMZn5bIBVb71lhabcmjEsqg== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.0" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.0" - "@babel/types" "^7.17.0" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.7.0": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.2.tgz#ef0a65e07a2f3c550967366b3d9b62a2dcbeae09" - integrity sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.2" - "@babel/helper-function-name" "^7.7.0" - "@babel/helper-split-export-declaration" "^7.7.0" - "@babel/parser" "^7.7.2" - "@babel/types" "^7.7.2" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.7.2": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.2.tgz#550b82e5571dcd174af576e23f0adba7ffc683f7" - integrity sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.6", "@babel/types@^7.3.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.13.tgz#8be1aa8f2c876da11a9cf650c0ecf656913ad611" - integrity sha512-oKrdZTld2im1z8bDwTOQvUbxKwE+854zc16qWZQlcTqMN00pWxHQ4ZeOq0yDMnisOpRykH2/5Qqcrk/OlbAjiQ== - dependencies: - "@babel/helper-validator-identifier" "^7.12.11" - lodash "^4.17.19" - to-fast-properties "^2.0.0" - -"@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" - integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - -"@craco/craco@^6.4.3": - version "6.4.3" - resolved "https://registry.yarnpkg.com/@craco/craco/-/craco-6.4.3.tgz#784395b6ebab764056550a2860494d24c3abd44e" - integrity sha512-RzkXYmNzRCGUyG7mM+IUMM+nvrpSfA34352sPSGQN76UivAmCAht3sI4v5JKgzO05oUK9Zwi6abCKD7iKXI8hQ== - dependencies: - cosmiconfig "^7.0.1" - cosmiconfig-typescript-loader "^1.0.0" - cross-spawn "^7.0.0" - lodash "^4.17.15" - semver "^7.3.2" - webpack-merge "^4.2.2" - -"@cspotcode/source-map-consumer@0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" - integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== - -"@cspotcode/source-map-support@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" - integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== - dependencies: - "@cspotcode/source-map-consumer" "0.8.0" - -"@csstools/normalize.css@*": - version "12.0.0" - resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-12.0.0.tgz#a9583a75c3f150667771f30b60d9f059473e62c4" - integrity sha512-M0qqxAcwCsIVfpFQSlGN5XjXWu8l5JDZN+fPt1LeW5SZexQTgnaEvgXAY+CeygRw0EeppWHi12JxESWiWrB0Sg== - -"@csstools/postcss-font-format-keywords@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.0.tgz#7e7df948a83a0dfb7eb150a96e2390ac642356a1" - integrity sha512-oO0cZt8do8FdVBX8INftvIA4lUrKUSCcWUf9IwH9IPWOgKT22oAZFXeHLoDK7nhB2SmkNycp5brxfNMRLIhd6Q== - dependencies: - postcss-value-parser "^4.2.0" - -"@csstools/postcss-hwb-function@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.0.tgz#d6785c1c5ba8152d1d392c66f3a6a446c6034f6d" - integrity sha512-VSTd7hGjmde4rTj1rR30sokY3ONJph1reCBTUXqeW1fKwETPy1x4t/XIeaaqbMbC5Xg4SM/lyXZ2S8NELT2TaA== - dependencies: - postcss-value-parser "^4.2.0" - -"@csstools/postcss-is-pseudo-class@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.0.tgz#219a1c1d84de7d9e9b7e662a57fdc194eac38ea7" - integrity sha512-WnfZlyuh/CW4oS530HBbrKq0G8BKl/bsNr5NMFoubBFzJfvFRGJhplCgIJYWUidLuL3WJ/zhMtDIyNFTqhx63Q== - dependencies: - postcss-selector-parser "^6.0.9" - -"@csstools/postcss-normalize-display-values@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.0.tgz#ce698f688c28517447aedf15a9037987e3d2dc97" - integrity sha512-bX+nx5V8XTJEmGtpWTO6kywdS725t71YSLlxWt78XoHUbELWgoCXeOFymRJmL3SU1TLlKSIi7v52EWqe60vJTQ== - dependencies: - postcss-value-parser "^4.2.0" - -"@cypress/request@^2.88.10": - version "2.88.10" - resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.10.tgz#b66d76b07f860d3a4b8d7a0604d020c662752cce" - integrity sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg== - 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" - http-signature "~1.3.6" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - 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 "^8.3.2" - -"@cypress/xvfb@^1.2.4": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a" - integrity sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q== - dependencies: - debug "^3.1.0" - lodash.once "^4.1.1" - -"@date-io/core@1.x", "@date-io/core@^1.3.13": - version "1.3.13" - resolved "https://registry.yarnpkg.com/@date-io/core/-/core-1.3.13.tgz#90c71da493f20204b7a972929cc5c482d078b3fa" - integrity sha512-AlEKV7TxjeK+jxWVKcCFrfYAk8spX9aCyiToFIiLPtfQbsjmRGLIhb5VZgptQcJdHtLXo7+m0DuurwFgUToQuA== - -"@date-io/date-fns@^1.3.13": - version "1.3.13" - resolved "https://registry.yarnpkg.com/@date-io/date-fns/-/date-fns-1.3.13.tgz#7798844041640ab393f7e21a7769a65d672f4735" - integrity sha512-yXxGzcRUPcogiMj58wVgFjc9qUYrCnnU9eLcyNbsQCmae4jPuZCDoIBR21j8ZURsM7GRtU62VOw5yNd4dDHunA== - dependencies: - "@date-io/core" "^1.3.13" - -"@emotion/hash@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" - integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== - -"@eslint/eslintrc@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.1.0.tgz#583d12dbec5d4f22f333f9669f7d0b7c7815b4d3" - integrity sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg== - 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" - -"@gar/promisify@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210" - integrity sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw== - -"@hapi/hoek@^9.0.0": - version "9.0.4" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.0.4.tgz#e80ad4e8e8d2adc6c77d985f698447e8628b6010" - integrity sha512-EwaJS7RjoXUZ2cXXKZZxZqieGtc7RbvQhUy8FwDoMQtxWVi14tFjeFCYPZAM1mBCpOpiBpyaZbb9NeHc7eGKgw== - -"@hapi/topo@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.0.0.tgz#c19af8577fa393a06e9c77b60995af959be721e7" - integrity sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw== - dependencies: - "@hapi/hoek" "^9.0.0" - -"@humanwhocodes/config-array@^0.9.2": - version "0.9.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.3.tgz#f2564c744b387775b436418491f15fce6601f63e" - integrity sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ== - dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" - minimatch "^3.0.4" - -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== - -"@hutson/parse-repository-url@^3.0.0": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340" - integrity sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q== - -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" - integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== - -"@jest/console@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.5.1.tgz#260fe7239602fe5130a94f1aa386eff54b014bba" - integrity sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg== - dependencies: - "@jest/types" "^27.5.1" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^27.5.1" - jest-util "^27.5.1" - slash "^3.0.0" - -"@jest/core@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626" - integrity sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ== - dependencies: - "@jest/console" "^27.5.1" - "@jest/reporters" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.8.1" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^27.5.1" - jest-config "^27.5.1" - jest-haste-map "^27.5.1" - jest-message-util "^27.5.1" - jest-regex-util "^27.5.1" - jest-resolve "^27.5.1" - jest-resolve-dependencies "^27.5.1" - jest-runner "^27.5.1" - jest-runtime "^27.5.1" - jest-snapshot "^27.5.1" - jest-util "^27.5.1" - jest-validate "^27.5.1" - jest-watcher "^27.5.1" - micromatch "^4.0.4" - rimraf "^3.0.0" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/environment@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74" - integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA== - dependencies: - "@jest/fake-timers" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - jest-mock "^27.5.1" - -"@jest/fake-timers@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" - integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ== - dependencies: - "@jest/types" "^27.5.1" - "@sinonjs/fake-timers" "^8.0.1" - "@types/node" "*" - jest-message-util "^27.5.1" - jest-mock "^27.5.1" - jest-util "^27.5.1" - -"@jest/globals@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b" - integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/types" "^27.5.1" - expect "^27.5.1" - -"@jest/reporters@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04" - integrity sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.2" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^5.1.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-haste-map "^27.5.1" - jest-resolve "^27.5.1" - jest-util "^27.5.1" - jest-worker "^27.5.1" - slash "^3.0.0" - source-map "^0.6.0" - string-length "^4.0.1" - terminal-link "^2.0.0" - v8-to-istanbul "^8.1.0" - -"@jest/source-map@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf" - integrity sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg== - dependencies: - callsites "^3.0.0" - graceful-fs "^4.2.9" - source-map "^0.6.0" - -"@jest/test-result@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb" - integrity sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag== - dependencies: - "@jest/console" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-sequencer@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b" - integrity sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ== - dependencies: - "@jest/test-result" "^27.5.1" - graceful-fs "^4.2.9" - jest-haste-map "^27.5.1" - jest-runtime "^27.5.1" - -"@jest/transform@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409" - integrity sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw== - dependencies: - "@babel/core" "^7.1.0" - "@jest/types" "^27.5.1" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^1.4.0" - fast-json-stable-stringify "^2.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^27.5.1" - jest-regex-util "^27.5.1" - jest-util "^27.5.1" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - source-map "^0.6.1" - write-file-atomic "^3.0.0" - -"@jest/types@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" - integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^16.0.0" - chalk "^4.0.0" - -"@jridgewell/resolve-uri@^3.0.3": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.4.tgz#b876e3feefb9c8d3aa84014da28b5e52a0640d72" - integrity sha512-cz8HFjOFfUBtvN+NXYSFMHYRdxZMaEl0XypVrhzxBgadKIXhIkRd8aMeHhmF56Sl7SuS8OnUpQ73/k9LE4VnLg== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.10" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.10.tgz#baf57b4e2a690d4f38560171f91783656b7f8186" - integrity sha512-Ht8wIW5v165atIX1p+JvKR5ONzUyF4Ac8DZIQ5kZs9zrb6M8SJNXpx1zn04rn65VjBMygRoMXcyYwNK0fT7bEg== - -"@jridgewell/trace-mapping@^0.3.0": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.2.tgz#e051581782a770c30ba219634f2019241c5d3cde" - integrity sha512-9KzzH4kMjA2XmBRHfqG2/Vtl7s92l6uNDd0wW7frDE+EUvQFGqNXhWp0UGJjSkt3v2AYjzOZn1QO9XaTNJIt1Q== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@lerna/add@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/add/-/add-4.0.0.tgz#c36f57d132502a57b9e7058d1548b7a565ef183f" - integrity sha512-cpmAH1iS3k8JBxNvnMqrGTTjbY/ZAiKa1ChJzFevMYY3eeqbvhsBKnBcxjRXtdrJ6bd3dCQM+ZtK+0i682Fhng== - dependencies: - "@lerna/bootstrap" "4.0.0" - "@lerna/command" "4.0.0" - "@lerna/filter-options" "4.0.0" - "@lerna/npm-conf" "4.0.0" - "@lerna/validation-error" "4.0.0" - dedent "^0.7.0" - npm-package-arg "^8.1.0" - p-map "^4.0.0" - pacote "^11.2.6" - semver "^7.3.4" - -"@lerna/bootstrap@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-4.0.0.tgz#5f5c5e2c6cfc8fcec50cb2fbe569a8c607101891" - integrity sha512-RkS7UbeM2vu+kJnHzxNRCLvoOP9yGNgkzRdy4UV2hNalD7EP41bLvRVOwRYQ7fhc2QcbhnKNdOBihYRL0LcKtw== - dependencies: - "@lerna/command" "4.0.0" - "@lerna/filter-options" "4.0.0" - "@lerna/has-npm-version" "4.0.0" - "@lerna/npm-install" "4.0.0" - "@lerna/package-graph" "4.0.0" - "@lerna/pulse-till-done" "4.0.0" - "@lerna/rimraf-dir" "4.0.0" - "@lerna/run-lifecycle" "4.0.0" - "@lerna/run-topologically" "4.0.0" - "@lerna/symlink-binary" "4.0.0" - "@lerna/symlink-dependencies" "4.0.0" - "@lerna/validation-error" "4.0.0" - dedent "^0.7.0" - get-port "^5.1.1" - multimatch "^5.0.0" - npm-package-arg "^8.1.0" - npmlog "^4.1.2" - p-map "^4.0.0" - p-map-series "^2.1.0" - p-waterfall "^2.1.1" - read-package-tree "^5.3.1" - semver "^7.3.4" - -"@lerna/changed@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-4.0.0.tgz#b9fc76cea39b9292a6cd263f03eb57af85c9270b" - integrity sha512-cD+KuPRp6qiPOD+BO6S6SN5cARspIaWSOqGBpGnYzLb4uWT8Vk4JzKyYtc8ym1DIwyoFXHosXt8+GDAgR8QrgQ== - dependencies: - "@lerna/collect-updates" "4.0.0" - "@lerna/command" "4.0.0" - "@lerna/listable" "4.0.0" - "@lerna/output" "4.0.0" - -"@lerna/check-working-tree@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/check-working-tree/-/check-working-tree-4.0.0.tgz#257e36a602c00142e76082a19358e3e1ae8dbd58" - integrity sha512-/++bxM43jYJCshBiKP5cRlCTwSJdRSxVmcDAXM+1oUewlZJVSVlnks5eO0uLxokVFvLhHlC5kHMc7gbVFPHv6Q== - dependencies: - "@lerna/collect-uncommitted" "4.0.0" - "@lerna/describe-ref" "4.0.0" - "@lerna/validation-error" "4.0.0" - -"@lerna/child-process@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-4.0.0.tgz#341b96a57dffbd9705646d316e231df6fa4df6e1" - integrity sha512-XtCnmCT9eyVsUUHx6y/CTBYdV9g2Cr/VxyseTWBgfIur92/YKClfEtJTbOh94jRT62hlKLqSvux/UhxXVh613Q== - dependencies: - chalk "^4.1.0" - execa "^5.0.0" - strong-log-transformer "^2.1.0" - -"@lerna/clean@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-4.0.0.tgz#8f778b6f2617aa2a936a6b5e085ae62498e57dc5" - integrity sha512-uugG2iN9k45ITx2jtd8nEOoAtca8hNlDCUM0N3lFgU/b1mEQYAPRkqr1qs4FLRl/Y50ZJ41wUz1eazS+d/0osA== - dependencies: - "@lerna/command" "4.0.0" - "@lerna/filter-options" "4.0.0" - "@lerna/prompt" "4.0.0" - "@lerna/pulse-till-done" "4.0.0" - "@lerna/rimraf-dir" "4.0.0" - p-map "^4.0.0" - p-map-series "^2.1.0" - p-waterfall "^2.1.1" - -"@lerna/cli@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/cli/-/cli-4.0.0.tgz#8eabd334558836c1664df23f19acb95e98b5bbf3" - integrity sha512-Neaw3GzFrwZiRZv2g7g6NwFjs3er1vhraIniEs0jjVLPMNC4eata0na3GfE5yibkM/9d3gZdmihhZdZ3EBdvYA== - dependencies: - "@lerna/global-options" "4.0.0" - dedent "^0.7.0" - npmlog "^4.1.2" - yargs "^16.2.0" - -"@lerna/collect-uncommitted@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/collect-uncommitted/-/collect-uncommitted-4.0.0.tgz#855cd64612969371cfc2453b90593053ff1ba779" - integrity sha512-ufSTfHZzbx69YNj7KXQ3o66V4RC76ffOjwLX0q/ab//61bObJ41n03SiQEhSlmpP+gmFbTJ3/7pTe04AHX9m/g== - dependencies: - "@lerna/child-process" "4.0.0" - chalk "^4.1.0" - npmlog "^4.1.2" - -"@lerna/collect-updates@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-4.0.0.tgz#8e208b1bafd98a372ff1177f7a5e288f6bea8041" - integrity sha512-bnNGpaj4zuxsEkyaCZLka9s7nMs58uZoxrRIPJ+nrmrZYp1V5rrd+7/NYTuunOhY2ug1sTBvTAxj3NZQ+JKnOw== - dependencies: - "@lerna/child-process" "4.0.0" - "@lerna/describe-ref" "4.0.0" - minimatch "^3.0.4" - npmlog "^4.1.2" - slash "^3.0.0" - -"@lerna/command@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/command/-/command-4.0.0.tgz#991c7971df8f5bf6ae6e42c808869a55361c1b98" - integrity sha512-LM9g3rt5FsPNFqIHUeRwWXLNHJ5NKzOwmVKZ8anSp4e1SPrv2HNc1V02/9QyDDZK/w+5POXH5lxZUI1CHaOK/A== - dependencies: - "@lerna/child-process" "4.0.0" - "@lerna/package-graph" "4.0.0" - "@lerna/project" "4.0.0" - "@lerna/validation-error" "4.0.0" - "@lerna/write-log-file" "4.0.0" - clone-deep "^4.0.1" - dedent "^0.7.0" - execa "^5.0.0" - is-ci "^2.0.0" - npmlog "^4.1.2" - -"@lerna/conventional-commits@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/conventional-commits/-/conventional-commits-4.0.0.tgz#660fb2c7b718cb942ead70110df61f18c6f99750" - integrity sha512-CSUQRjJHFrH8eBn7+wegZLV3OrNc0Y1FehYfYGhjLE2SIfpCL4bmfu/ViYuHh9YjwHaA+4SX6d3hR+xkeseKmw== - dependencies: - "@lerna/validation-error" "4.0.0" - conventional-changelog-angular "^5.0.12" - conventional-changelog-core "^4.2.2" - conventional-recommended-bump "^6.1.0" - fs-extra "^9.1.0" - get-stream "^6.0.0" - lodash.template "^4.5.0" - npm-package-arg "^8.1.0" - npmlog "^4.1.2" - pify "^5.0.0" - semver "^7.3.4" - -"@lerna/create-symlink@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/create-symlink/-/create-symlink-4.0.0.tgz#8c5317ce5ae89f67825443bd7651bf4121786228" - integrity sha512-I0phtKJJdafUiDwm7BBlEUOtogmu8+taxq6PtIrxZbllV9hWg59qkpuIsiFp+no7nfRVuaasNYHwNUhDAVQBig== - dependencies: - cmd-shim "^4.1.0" - fs-extra "^9.1.0" - npmlog "^4.1.2" - -"@lerna/create@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/create/-/create-4.0.0.tgz#b6947e9b5dfb6530321952998948c3e63d64d730" - integrity sha512-mVOB1niKByEUfxlbKTM1UNECWAjwUdiioIbRQZEeEabtjCL69r9rscIsjlGyhGWCfsdAG5wfq4t47nlDXdLLag== - dependencies: - "@lerna/child-process" "4.0.0" - "@lerna/command" "4.0.0" - "@lerna/npm-conf" "4.0.0" - "@lerna/validation-error" "4.0.0" - dedent "^0.7.0" - fs-extra "^9.1.0" - globby "^11.0.2" - init-package-json "^2.0.2" - npm-package-arg "^8.1.0" - p-reduce "^2.1.0" - pacote "^11.2.6" - pify "^5.0.0" - semver "^7.3.4" - slash "^3.0.0" - validate-npm-package-license "^3.0.4" - validate-npm-package-name "^3.0.0" - whatwg-url "^8.4.0" - yargs-parser "20.2.4" - -"@lerna/describe-ref@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/describe-ref/-/describe-ref-4.0.0.tgz#53c53b4ea65fdceffa072a62bfebe6772c45d9ec" - integrity sha512-eTU5+xC4C5Gcgz+Ey4Qiw9nV2B4JJbMulsYJMW8QjGcGh8zudib7Sduj6urgZXUYNyhYpRs+teci9M2J8u+UvQ== - dependencies: - "@lerna/child-process" "4.0.0" - npmlog "^4.1.2" - -"@lerna/diff@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-4.0.0.tgz#6d3071817aaa4205a07bf77cfc6e932796d48b92" - integrity sha512-jYPKprQVg41+MUMxx6cwtqsNm0Yxx9GDEwdiPLwcUTFx+/qKCEwifKNJ1oGIPBxyEHX2PFCOjkK39lHoj2qiag== - dependencies: - "@lerna/child-process" "4.0.0" - "@lerna/command" "4.0.0" - "@lerna/validation-error" "4.0.0" - npmlog "^4.1.2" - -"@lerna/exec@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-4.0.0.tgz#eb6cb95cb92d42590e9e2d628fcaf4719d4a8be6" - integrity sha512-VGXtL/b/JfY84NB98VWZpIExfhLOzy0ozm/0XaS4a2SmkAJc5CeUfrhvHxxkxiTBLkU+iVQUyYEoAT0ulQ8PCw== - dependencies: - "@lerna/child-process" "4.0.0" - "@lerna/command" "4.0.0" - "@lerna/filter-options" "4.0.0" - "@lerna/profiler" "4.0.0" - "@lerna/run-topologically" "4.0.0" - "@lerna/validation-error" "4.0.0" - p-map "^4.0.0" - -"@lerna/filter-options@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-4.0.0.tgz#ac94cc515d7fa3b47e2f7d74deddeabb1de5e9e6" - integrity sha512-vV2ANOeZhOqM0rzXnYcFFCJ/kBWy/3OA58irXih9AMTAlQLymWAK0akWybl++sUJ4HB9Hx12TOqaXbYS2NM5uw== - dependencies: - "@lerna/collect-updates" "4.0.0" - "@lerna/filter-packages" "4.0.0" - dedent "^0.7.0" - npmlog "^4.1.2" - -"@lerna/filter-packages@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/filter-packages/-/filter-packages-4.0.0.tgz#b1f70d70e1de9cdd36a4e50caa0ac501f8d012f2" - integrity sha512-+4AJIkK7iIiOaqCiVTYJxh/I9qikk4XjNQLhE3kixaqgMuHl1NQ99qXRR0OZqAWB9mh8Z1HA9bM5K1HZLBTOqA== - dependencies: - "@lerna/validation-error" "4.0.0" - multimatch "^5.0.0" - npmlog "^4.1.2" - -"@lerna/get-npm-exec-opts@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-4.0.0.tgz#dc955be94a4ae75c374ef9bce91320887d34608f" - integrity sha512-yvmkerU31CTWS2c7DvmAWmZVeclPBqI7gPVr5VATUKNWJ/zmVcU4PqbYoLu92I9Qc4gY1TuUplMNdNuZTSL7IQ== - dependencies: - npmlog "^4.1.2" - -"@lerna/get-packed@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/get-packed/-/get-packed-4.0.0.tgz#0989d61624ac1f97e393bdad2137c49cd7a37823" - integrity sha512-rfWONRsEIGyPJTxFzC8ECb3ZbsDXJbfqWYyeeQQDrJRPnEJErlltRLPLgC2QWbxFgFPsoDLeQmFHJnf0iDfd8w== - dependencies: - fs-extra "^9.1.0" - ssri "^8.0.1" - tar "^6.1.0" - -"@lerna/github-client@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/github-client/-/github-client-4.0.0.tgz#2ced67721363ef70f8e12ffafce4410918f4a8a4" - integrity sha512-2jhsldZtTKXYUBnOm23Lb0Fx8G4qfSXF9y7UpyUgWUj+YZYd+cFxSuorwQIgk5P4XXrtVhsUesIsli+BYSThiw== - dependencies: - "@lerna/child-process" "4.0.0" - "@octokit/plugin-enterprise-rest" "^6.0.1" - "@octokit/rest" "^18.1.0" - git-url-parse "^11.4.4" - npmlog "^4.1.2" - -"@lerna/gitlab-client@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/gitlab-client/-/gitlab-client-4.0.0.tgz#00dad73379c7b38951d4b4ded043504c14e2b67d" - integrity sha512-OMUpGSkeDWFf7BxGHlkbb35T7YHqVFCwBPSIR6wRsszY8PAzCYahtH3IaJzEJyUg6vmZsNl0FSr3pdA2skhxqA== - dependencies: - node-fetch "^2.6.1" - npmlog "^4.1.2" - whatwg-url "^8.4.0" - -"@lerna/global-options@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/global-options/-/global-options-4.0.0.tgz#c7d8b0de6a01d8a845e2621ea89e7f60f18c6a5f" - integrity sha512-TRMR8afAHxuYBHK7F++Ogop2a82xQjoGna1dvPOY6ltj/pEx59pdgcJfYcynYqMkFIk8bhLJJN9/ndIfX29FTQ== - -"@lerna/has-npm-version@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/has-npm-version/-/has-npm-version-4.0.0.tgz#d3fc3292c545eb28bd493b36e6237cf0279f631c" - integrity sha512-LQ3U6XFH8ZmLCsvsgq1zNDqka0Xzjq5ibVN+igAI5ccRWNaUsE/OcmsyMr50xAtNQMYMzmpw5GVLAivT2/YzCg== - dependencies: - "@lerna/child-process" "4.0.0" - semver "^7.3.4" - -"@lerna/import@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/import/-/import-4.0.0.tgz#bde656c4a451fa87ae41733ff8a8da60547c5465" - integrity sha512-FaIhd+4aiBousKNqC7TX1Uhe97eNKf5/SC7c5WZANVWtC7aBWdmswwDt3usrzCNpj6/Wwr9EtEbYROzxKH8ffg== - dependencies: - "@lerna/child-process" "4.0.0" - "@lerna/command" "4.0.0" - "@lerna/prompt" "4.0.0" - "@lerna/pulse-till-done" "4.0.0" - "@lerna/validation-error" "4.0.0" - dedent "^0.7.0" - fs-extra "^9.1.0" - p-map-series "^2.1.0" - -"@lerna/info@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/info/-/info-4.0.0.tgz#b9fb0e479d60efe1623603958a831a88b1d7f1fc" - integrity sha512-8Uboa12kaCSZEn4XRfPz5KU9XXoexSPS4oeYGj76s2UQb1O1GdnEyfjyNWoUl1KlJ2i/8nxUskpXIftoFYH0/Q== - dependencies: - "@lerna/command" "4.0.0" - "@lerna/output" "4.0.0" - envinfo "^7.7.4" - -"@lerna/init@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/init/-/init-4.0.0.tgz#dadff67e6dfb981e8ccbe0e6a310e837962f6c7a" - integrity sha512-wY6kygop0BCXupzWj5eLvTUqdR7vIAm0OgyV9WHpMYQGfs1V22jhztt8mtjCloD/O0nEe4tJhdG62XU5aYmPNQ== - dependencies: - "@lerna/child-process" "4.0.0" - "@lerna/command" "4.0.0" - fs-extra "^9.1.0" - p-map "^4.0.0" - write-json-file "^4.3.0" - -"@lerna/link@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/link/-/link-4.0.0.tgz#c3a38aabd44279d714e90f2451e31b63f0fb65ba" - integrity sha512-KlvPi7XTAcVOByfaLlOeYOfkkDcd+bejpHMCd1KcArcFTwijOwXOVi24DYomIeHvy6HsX/IUquJ4PPUJIeB4+w== - dependencies: - "@lerna/command" "4.0.0" - "@lerna/package-graph" "4.0.0" - "@lerna/symlink-dependencies" "4.0.0" - p-map "^4.0.0" - slash "^3.0.0" - -"@lerna/list@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/list/-/list-4.0.0.tgz#24b4e6995bd73f81c556793fe502b847efd9d1d7" - integrity sha512-L2B5m3P+U4Bif5PultR4TI+KtW+SArwq1i75QZ78mRYxPc0U/piau1DbLOmwrdqr99wzM49t0Dlvl6twd7GHFg== - dependencies: - "@lerna/command" "4.0.0" - "@lerna/filter-options" "4.0.0" - "@lerna/listable" "4.0.0" - "@lerna/output" "4.0.0" - -"@lerna/listable@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/listable/-/listable-4.0.0.tgz#d00d6cb4809b403f2b0374fc521a78e318b01214" - integrity sha512-/rPOSDKsOHs5/PBLINZOkRIX1joOXUXEtyUs5DHLM8q6/RP668x/1lFhw6Dx7/U+L0+tbkpGtZ1Yt0LewCLgeQ== - dependencies: - "@lerna/query-graph" "4.0.0" - chalk "^4.1.0" - columnify "^1.5.4" - -"@lerna/log-packed@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/log-packed/-/log-packed-4.0.0.tgz#95168fe2e26ac6a71e42f4be857519b77e57a09f" - integrity sha512-+dpCiWbdzgMAtpajLToy9PO713IHoE6GV/aizXycAyA07QlqnkpaBNZ8DW84gHdM1j79TWockGJo9PybVhrrZQ== - dependencies: - byte-size "^7.0.0" - columnify "^1.5.4" - has-unicode "^2.0.1" - npmlog "^4.1.2" - -"@lerna/npm-conf@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/npm-conf/-/npm-conf-4.0.0.tgz#b259fd1e1cee2bf5402b236e770140ff9ade7fd2" - integrity sha512-uS7H02yQNq3oejgjxAxqq/jhwGEE0W0ntr8vM3EfpCW1F/wZruwQw+7bleJQ9vUBjmdXST//tk8mXzr5+JXCfw== - dependencies: - config-chain "^1.1.12" - pify "^5.0.0" - -"@lerna/npm-dist-tag@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/npm-dist-tag/-/npm-dist-tag-4.0.0.tgz#d1e99b4eccd3414142f0548ad331bf2d53f3257a" - integrity sha512-F20sg28FMYTgXqEQihgoqSfwmq+Id3zT23CnOwD+XQMPSy9IzyLf1fFVH319vXIw6NF6Pgs4JZN2Qty6/CQXGw== - dependencies: - "@lerna/otplease" "4.0.0" - npm-package-arg "^8.1.0" - npm-registry-fetch "^9.0.0" - npmlog "^4.1.2" - -"@lerna/npm-install@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/npm-install/-/npm-install-4.0.0.tgz#31180be3ab3b7d1818a1a0c206aec156b7094c78" - integrity sha512-aKNxq2j3bCH3eXl3Fmu4D54s/YLL9WSwV8W7X2O25r98wzrO38AUN6AB9EtmAx+LV/SP15et7Yueg9vSaanRWg== - dependencies: - "@lerna/child-process" "4.0.0" - "@lerna/get-npm-exec-opts" "4.0.0" - fs-extra "^9.1.0" - npm-package-arg "^8.1.0" - npmlog "^4.1.2" - signal-exit "^3.0.3" - write-pkg "^4.0.0" - -"@lerna/npm-publish@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/npm-publish/-/npm-publish-4.0.0.tgz#84eb62e876fe949ae1fd62c60804423dbc2c4472" - integrity sha512-vQb7yAPRo5G5r77DRjHITc9piR9gvEKWrmfCH7wkfBnGWEqu7n8/4bFQ7lhnkujvc8RXOsYpvbMQkNfkYibD/w== - dependencies: - "@lerna/otplease" "4.0.0" - "@lerna/run-lifecycle" "4.0.0" - fs-extra "^9.1.0" - libnpmpublish "^4.0.0" - npm-package-arg "^8.1.0" - npmlog "^4.1.2" - pify "^5.0.0" - read-package-json "^3.0.0" - -"@lerna/npm-run-script@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/npm-run-script/-/npm-run-script-4.0.0.tgz#dfebf4f4601442e7c0b5214f9fb0d96c9350743b" - integrity sha512-Jmyh9/IwXJjOXqKfIgtxi0bxi1pUeKe5bD3S81tkcy+kyng/GNj9WSqD5ZggoNP2NP//s4CLDAtUYLdP7CU9rA== - dependencies: - "@lerna/child-process" "4.0.0" - "@lerna/get-npm-exec-opts" "4.0.0" - npmlog "^4.1.2" - -"@lerna/otplease@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/otplease/-/otplease-4.0.0.tgz#84972eb43448f8a1077435ba1c5e59233b725850" - integrity sha512-Sgzbqdk1GH4psNiT6hk+BhjOfIr/5KhGBk86CEfHNJTk9BK4aZYyJD4lpDbDdMjIV4g03G7pYoqHzH765T4fxw== - dependencies: - "@lerna/prompt" "4.0.0" - -"@lerna/output@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/output/-/output-4.0.0.tgz#b1d72215c0e35483e4f3e9994debc82c621851f2" - integrity sha512-Un1sHtO1AD7buDQrpnaYTi2EG6sLF+KOPEAMxeUYG5qG3khTs2Zgzq5WE3dt2N/bKh7naESt20JjIW6tBELP0w== - dependencies: - npmlog "^4.1.2" - -"@lerna/pack-directory@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/pack-directory/-/pack-directory-4.0.0.tgz#8b617db95d20792f043aaaa13a9ccc0e04cb4c74" - integrity sha512-NJrmZNmBHS+5aM+T8N6FVbaKFScVqKlQFJNY2k7nsJ/uklNKsLLl6VhTQBPwMTbf6Tf7l6bcKzpy7aePuq9UiQ== - dependencies: - "@lerna/get-packed" "4.0.0" - "@lerna/package" "4.0.0" - "@lerna/run-lifecycle" "4.0.0" - npm-packlist "^2.1.4" - npmlog "^4.1.2" - tar "^6.1.0" - temp-write "^4.0.0" - -"@lerna/package-graph@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/package-graph/-/package-graph-4.0.0.tgz#16a00253a8ac810f72041481cb46bcee8d8123dd" - integrity sha512-QED2ZCTkfXMKFoTGoccwUzjHtZMSf3UKX14A4/kYyBms9xfFsesCZ6SLI5YeySEgcul8iuIWfQFZqRw+Qrjraw== - dependencies: - "@lerna/prerelease-id-from-version" "4.0.0" - "@lerna/validation-error" "4.0.0" - npm-package-arg "^8.1.0" - npmlog "^4.1.2" - semver "^7.3.4" - -"@lerna/package@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/package/-/package-4.0.0.tgz#1b4c259c4bcff45c876ee1d591a043aacbc0d6b7" - integrity sha512-l0M/izok6FlyyitxiQKr+gZLVFnvxRQdNhzmQ6nRnN9dvBJWn+IxxpM+cLqGACatTnyo9LDzNTOj2Db3+s0s8Q== - dependencies: - load-json-file "^6.2.0" - npm-package-arg "^8.1.0" - write-pkg "^4.0.0" - -"@lerna/prerelease-id-from-version@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-4.0.0.tgz#c7e0676fcee1950d85630e108eddecdd5b48c916" - integrity sha512-GQqguzETdsYRxOSmdFZ6zDBXDErIETWOqomLERRY54f4p+tk4aJjoVdd9xKwehC9TBfIFvlRbL1V9uQGHh1opg== - dependencies: - semver "^7.3.4" - -"@lerna/profiler@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/profiler/-/profiler-4.0.0.tgz#8a53ab874522eae15d178402bff90a14071908e9" - integrity sha512-/BaEbqnVh1LgW/+qz8wCuI+obzi5/vRE8nlhjPzdEzdmWmZXuCKyWSEzAyHOJWw1ntwMiww5dZHhFQABuoFz9Q== - dependencies: - fs-extra "^9.1.0" - npmlog "^4.1.2" - upath "^2.0.1" - -"@lerna/project@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/project/-/project-4.0.0.tgz#ff84893935833533a74deff30c0e64ddb7f0ba6b" - integrity sha512-o0MlVbDkD5qRPkFKlBZsXZjoNTWPyuL58564nSfZJ6JYNmgAptnWPB2dQlAc7HWRZkmnC2fCkEdoU+jioPavbg== - dependencies: - "@lerna/package" "4.0.0" - "@lerna/validation-error" "4.0.0" - cosmiconfig "^7.0.0" - dedent "^0.7.0" - dot-prop "^6.0.1" - glob-parent "^5.1.1" - globby "^11.0.2" - load-json-file "^6.2.0" - npmlog "^4.1.2" - p-map "^4.0.0" - resolve-from "^5.0.0" - write-json-file "^4.3.0" - -"@lerna/prompt@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/prompt/-/prompt-4.0.0.tgz#5ec69a803f3f0db0ad9f221dad64664d3daca41b" - integrity sha512-4Ig46oCH1TH5M7YyTt53fT6TuaKMgqUUaqdgxvp6HP6jtdak6+amcsqB8YGz2eQnw/sdxunx84DfI9XpoLj4bQ== - dependencies: - inquirer "^7.3.3" - npmlog "^4.1.2" - -"@lerna/publish@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-4.0.0.tgz#f67011305adeba120066a3b6d984a5bb5fceef65" - integrity sha512-K8jpqjHrChH22qtkytA5GRKIVFEtqBF6JWj1I8dWZtHs4Jywn8yB1jQ3BAMLhqmDJjWJtRck0KXhQQKzDK2UPg== - dependencies: - "@lerna/check-working-tree" "4.0.0" - "@lerna/child-process" "4.0.0" - "@lerna/collect-updates" "4.0.0" - "@lerna/command" "4.0.0" - "@lerna/describe-ref" "4.0.0" - "@lerna/log-packed" "4.0.0" - "@lerna/npm-conf" "4.0.0" - "@lerna/npm-dist-tag" "4.0.0" - "@lerna/npm-publish" "4.0.0" - "@lerna/otplease" "4.0.0" - "@lerna/output" "4.0.0" - "@lerna/pack-directory" "4.0.0" - "@lerna/prerelease-id-from-version" "4.0.0" - "@lerna/prompt" "4.0.0" - "@lerna/pulse-till-done" "4.0.0" - "@lerna/run-lifecycle" "4.0.0" - "@lerna/run-topologically" "4.0.0" - "@lerna/validation-error" "4.0.0" - "@lerna/version" "4.0.0" - fs-extra "^9.1.0" - libnpmaccess "^4.0.1" - npm-package-arg "^8.1.0" - npm-registry-fetch "^9.0.0" - npmlog "^4.1.2" - p-map "^4.0.0" - p-pipe "^3.1.0" - pacote "^11.2.6" - semver "^7.3.4" - -"@lerna/pulse-till-done@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/pulse-till-done/-/pulse-till-done-4.0.0.tgz#04bace7d483a8205c187b806bcd8be23d7bb80a3" - integrity sha512-Frb4F7QGckaybRhbF7aosLsJ5e9WuH7h0KUkjlzSByVycxY91UZgaEIVjS2oN9wQLrheLMHl6SiFY0/Pvo0Cxg== - dependencies: - npmlog "^4.1.2" - -"@lerna/query-graph@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/query-graph/-/query-graph-4.0.0.tgz#09dd1c819ac5ee3f38db23931143701f8a6eef63" - integrity sha512-YlP6yI3tM4WbBmL9GCmNDoeQyzcyg1e4W96y/PKMZa5GbyUvkS2+Jc2kwPD+5KcXou3wQZxSPzR3Te5OenaDdg== - dependencies: - "@lerna/package-graph" "4.0.0" - -"@lerna/resolve-symlink@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/resolve-symlink/-/resolve-symlink-4.0.0.tgz#6d006628a210c9b821964657a9e20a8c9a115e14" - integrity sha512-RtX8VEUzqT+uLSCohx8zgmjc6zjyRlh6i/helxtZTMmc4+6O4FS9q5LJas2uGO2wKvBlhcD6siibGt7dIC3xZA== - dependencies: - fs-extra "^9.1.0" - npmlog "^4.1.2" - read-cmd-shim "^2.0.0" - -"@lerna/rimraf-dir@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/rimraf-dir/-/rimraf-dir-4.0.0.tgz#2edf3b62d4eb0ef4e44e430f5844667d551ec25a" - integrity sha512-QNH9ABWk9mcMJh2/muD9iYWBk1oQd40y6oH+f3wwmVGKYU5YJD//+zMiBI13jxZRtwBx0vmBZzkBkK1dR11cBg== - dependencies: - "@lerna/child-process" "4.0.0" - npmlog "^4.1.2" - path-exists "^4.0.0" - rimraf "^3.0.2" - -"@lerna/run-lifecycle@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/run-lifecycle/-/run-lifecycle-4.0.0.tgz#e648a46f9210a9bcd7c391df6844498cb5079334" - integrity sha512-IwxxsajjCQQEJAeAaxF8QdEixfI7eLKNm4GHhXHrgBu185JcwScFZrj9Bs+PFKxwb+gNLR4iI5rpUdY8Y0UdGQ== - dependencies: - "@lerna/npm-conf" "4.0.0" - npm-lifecycle "^3.1.5" - npmlog "^4.1.2" - -"@lerna/run-topologically@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/run-topologically/-/run-topologically-4.0.0.tgz#af846eeee1a09b0c2be0d1bfb5ef0f7b04bb1827" - integrity sha512-EVZw9hGwo+5yp+VL94+NXRYisqgAlj0jWKWtAIynDCpghRxCE5GMO3xrQLmQgqkpUl9ZxQFpICgYv5DW4DksQA== - dependencies: - "@lerna/query-graph" "4.0.0" - p-queue "^6.6.2" - -"@lerna/run@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/run/-/run-4.0.0.tgz#4bc7fda055a729487897c23579694f6183c91262" - integrity sha512-9giulCOzlMPzcZS/6Eov6pxE9gNTyaXk0Man+iCIdGJNMrCnW7Dme0Z229WWP/UoxDKg71F2tMsVVGDiRd8fFQ== - dependencies: - "@lerna/command" "4.0.0" - "@lerna/filter-options" "4.0.0" - "@lerna/npm-run-script" "4.0.0" - "@lerna/output" "4.0.0" - "@lerna/profiler" "4.0.0" - "@lerna/run-topologically" "4.0.0" - "@lerna/timer" "4.0.0" - "@lerna/validation-error" "4.0.0" - p-map "^4.0.0" - -"@lerna/symlink-binary@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/symlink-binary/-/symlink-binary-4.0.0.tgz#21009f62d53a425f136cb4c1a32c6b2a0cc02d47" - integrity sha512-zualodWC4q1QQc1pkz969hcFeWXOsVYZC5AWVtAPTDfLl+TwM7eG/O6oP+Rr3fFowspxo6b1TQ6sYfDV6HXNWA== - dependencies: - "@lerna/create-symlink" "4.0.0" - "@lerna/package" "4.0.0" - fs-extra "^9.1.0" - p-map "^4.0.0" - -"@lerna/symlink-dependencies@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/symlink-dependencies/-/symlink-dependencies-4.0.0.tgz#8910eca084ae062642d0490d8972cf2d98e9ebbd" - integrity sha512-BABo0MjeUHNAe2FNGty1eantWp8u83BHSeIMPDxNq0MuW2K3CiQRaeWT3EGPAzXpGt0+hVzBrA6+OT0GPn7Yuw== - dependencies: - "@lerna/create-symlink" "4.0.0" - "@lerna/resolve-symlink" "4.0.0" - "@lerna/symlink-binary" "4.0.0" - fs-extra "^9.1.0" - p-map "^4.0.0" - p-map-series "^2.1.0" - -"@lerna/timer@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/timer/-/timer-4.0.0.tgz#a52e51bfcd39bfd768988049ace7b15c1fd7a6da" - integrity sha512-WFsnlaE7SdOvjuyd05oKt8Leg3ENHICnvX3uYKKdByA+S3g+TCz38JsNs7OUZVt+ba63nC2nbXDlUnuT2Xbsfg== - -"@lerna/validation-error@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/validation-error/-/validation-error-4.0.0.tgz#af9d62fe8304eaa2eb9a6ba1394f9aa807026d35" - integrity sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw== - dependencies: - npmlog "^4.1.2" - -"@lerna/version@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/version/-/version-4.0.0.tgz#532659ec6154d8a8789c5ab53878663e244e3228" - integrity sha512-otUgiqs5W9zGWJZSCCMRV/2Zm2A9q9JwSDS7s/tlKq4mWCYriWo7+wsHEA/nPTMDyYyBO5oyZDj+3X50KDUzeA== - dependencies: - "@lerna/check-working-tree" "4.0.0" - "@lerna/child-process" "4.0.0" - "@lerna/collect-updates" "4.0.0" - "@lerna/command" "4.0.0" - "@lerna/conventional-commits" "4.0.0" - "@lerna/github-client" "4.0.0" - "@lerna/gitlab-client" "4.0.0" - "@lerna/output" "4.0.0" - "@lerna/prerelease-id-from-version" "4.0.0" - "@lerna/prompt" "4.0.0" - "@lerna/run-lifecycle" "4.0.0" - "@lerna/run-topologically" "4.0.0" - "@lerna/validation-error" "4.0.0" - chalk "^4.1.0" - dedent "^0.7.0" - load-json-file "^6.2.0" - minimatch "^3.0.4" - npmlog "^4.1.2" - p-map "^4.0.0" - p-pipe "^3.1.0" - p-reduce "^2.1.0" - p-waterfall "^2.1.1" - semver "^7.3.4" - slash "^3.0.0" - temp-write "^4.0.0" - write-json-file "^4.3.0" - -"@lerna/write-log-file@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lerna/write-log-file/-/write-log-file-4.0.0.tgz#18221a38a6a307d6b0a5844dd592ad53fa27091e" - integrity sha512-XRG5BloiArpXRakcnPHmEHJp+4AtnhRtpDIHSghmXD5EichI1uD73J7FgPp30mm2pDRq3FdqB0NbwSEsJ9xFQg== - dependencies: - npmlog "^4.1.2" - write-file-atomic "^3.0.3" - -"@material-ui/core@^4.11.3": - version "4.11.3" - resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.11.3.tgz#f22e41775b0bd075e36a7a093d43951bf7f63850" - integrity sha512-Adt40rGW6Uds+cAyk3pVgcErpzU/qxc7KBR94jFHBYretU4AtWZltYcNsbeMn9tXL86jjVL1kuGcIHsgLgFGRw== - dependencies: - "@babel/runtime" "^7.4.4" - "@material-ui/styles" "^4.11.3" - "@material-ui/system" "^4.11.3" - "@material-ui/types" "^5.1.0" - "@material-ui/utils" "^4.11.2" - "@types/react-transition-group" "^4.2.0" - clsx "^1.0.4" - hoist-non-react-statics "^3.3.2" - popper.js "1.16.1-lts" - prop-types "^15.7.2" - react-is "^16.8.0 || ^17.0.0" - react-transition-group "^4.4.0" - -"@material-ui/icons@^4.11.2": - version "4.11.2" - resolved "https://registry.yarnpkg.com/@material-ui/icons/-/icons-4.11.2.tgz#b3a7353266519cd743b6461ae9fdfcb1b25eb4c5" - integrity sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ== - dependencies: - "@babel/runtime" "^7.4.4" - -"@material-ui/lab@^4.0.0-alpha.58": - version "4.0.0-alpha.58" - resolved "https://registry.yarnpkg.com/@material-ui/lab/-/lab-4.0.0-alpha.58.tgz#c7ebb66f49863c5acbb20817163737caa299fafc" - integrity sha512-GKHlJqLxUeHH3L3dGQ48ZavYrqGOTXkFkiEiuYMAnAvXAZP4rhMIqeHOPXSUQan4Bd8QnafDcpovOSLnadDmKw== - dependencies: - "@babel/runtime" "^7.4.4" - "@material-ui/utils" "^4.11.2" - clsx "^1.0.4" - prop-types "^15.7.2" - react-is "^16.8.0 || ^17.0.0" - -"@material-ui/pickers@^3.3.10": - version "3.3.10" - resolved "https://registry.yarnpkg.com/@material-ui/pickers/-/pickers-3.3.10.tgz#f1b0f963348cc191645ef0bdeff7a67c6aa25485" - integrity sha512-hS4pxwn1ZGXVkmgD4tpFpaumUaAg2ZzbTrxltfC5yPw4BJV+mGkfnQOB4VpWEYZw2jv65Z0wLwDE/piQiPPZ3w== - dependencies: - "@babel/runtime" "^7.6.0" - "@date-io/core" "1.x" - "@types/styled-jsx" "^2.2.8" - clsx "^1.0.2" - react-transition-group "^4.0.0" - rifm "^0.7.0" - -"@material-ui/styles@^4.11.3": - version "4.11.3" - resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.11.3.tgz#1b8d97775a4a643b53478c895e3f2a464e8916f2" - integrity sha512-HzVzCG+PpgUGMUYEJ2rTEmQYeonGh41BYfILNFb/1ueqma+p1meSdu4RX6NjxYBMhf7k+jgfHFTTz+L1SXL/Zg== - dependencies: - "@babel/runtime" "^7.4.4" - "@emotion/hash" "^0.8.0" - "@material-ui/types" "^5.1.0" - "@material-ui/utils" "^4.11.2" - clsx "^1.0.4" - csstype "^2.5.2" - hoist-non-react-statics "^3.3.2" - jss "^10.5.1" - jss-plugin-camel-case "^10.5.1" - jss-plugin-default-unit "^10.5.1" - jss-plugin-global "^10.5.1" - jss-plugin-nested "^10.5.1" - jss-plugin-props-sort "^10.5.1" - jss-plugin-rule-value-function "^10.5.1" - jss-plugin-vendor-prefixer "^10.5.1" - prop-types "^15.7.2" - -"@material-ui/system@^4.11.3": - version "4.11.3" - resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.11.3.tgz#466bc14c9986798fd325665927c963eb47cc4143" - integrity sha512-SY7otguNGol41Mu2Sg6KbBP1ZRFIbFLHGK81y4KYbsV2yIcaEPOmsCK6zwWlp+2yTV3J/VwT6oSBARtGIVdXPw== - dependencies: - "@babel/runtime" "^7.4.4" - "@material-ui/utils" "^4.11.2" - csstype "^2.5.2" - prop-types "^15.7.2" - -"@material-ui/types@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-5.1.0.tgz#efa1c7a0b0eaa4c7c87ac0390445f0f88b0d88f2" - integrity sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A== - -"@material-ui/utils@^4.11.2": - version "4.11.2" - resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-4.11.2.tgz#f1aefa7e7dff2ebcb97d31de51aecab1bb57540a" - integrity sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA== - dependencies: - "@babel/runtime" "^7.4.4" - prop-types "^15.7.2" - react-is "^16.8.0 || ^17.0.0" - -"@nodelib/fs.scandir@2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69" - integrity sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA== - dependencies: - "@nodelib/fs.stat" "2.0.4" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.4", "@nodelib/fs.stat@^2.0.2": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz#a3f2dd61bab43b8db8fa108a121cfffe4c676655" - integrity sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz#cce9396b30aa5afe9e3756608f5831adcb53d063" - integrity sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow== - dependencies: - "@nodelib/fs.scandir" "2.1.4" - fastq "^1.6.0" - -"@npmcli/ci-detect@^1.0.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@npmcli/ci-detect/-/ci-detect-1.4.0.tgz#18478bbaa900c37bfbd8a2006a6262c62e8b0fe1" - integrity sha512-3BGrt6FLjqM6br5AhWRKTr3u5GIVkjRYeAFrMp3HjnfICrg4xOrVRwFavKT6tsp++bq5dluL5t8ME/Nha/6c1Q== - -"@npmcli/fs@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.0.0.tgz#589612cfad3a6ea0feafcb901d29c63fd52db09f" - integrity sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ== - dependencies: - "@gar/promisify" "^1.0.1" - semver "^7.3.5" - -"@npmcli/git@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-2.1.0.tgz#2fbd77e147530247d37f325930d457b3ebe894f6" - integrity sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw== - 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" - -"@npmcli/installed-package-contents@^1.0.6": - version "1.0.7" - resolved "https://registry.yarnpkg.com/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz#ab7408c6147911b970a8abe261ce512232a3f4fa" - integrity sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw== - dependencies: - npm-bundled "^1.1.1" - npm-normalize-package-bin "^1.0.1" - -"@npmcli/move-file@^1.0.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.1.tgz#31a3afae95308ef12f58ac147b3e33aae621241d" - integrity sha512-LtWTicuF2wp7PNTuyCwABx7nNG+DnzSE8gN0iWxkC6mpgm/iOPu0ZMTkXuCxmJxtWFsDxUaixM9COSNJEMUfuQ== - dependencies: - mkdirp "^1.0.4" - rimraf "^3.0.2" - -"@npmcli/node-gyp@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz#a912e637418ffc5f2db375e93b85837691a43a33" - integrity sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA== - -"@npmcli/promise-spawn@^1.2.0", "@npmcli/promise-spawn@^1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz#42d4e56a8e9274fba180dabc0aea6e38f29274f5" - integrity sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg== - dependencies: - infer-owner "^1.0.4" - -"@npmcli/run-script@^1.8.2": - version "1.8.6" - resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-1.8.6.tgz#18314802a6660b0d4baa4c3afe7f1ad39d8c28b7" - integrity sha512-e42bVZnC6VluBZBAFEr3YrdqSspG3bgilyg4nSLBJ7TRGNCzxHa92XAHxQBLYg0BmgwO4b2mf3h/l5EkEWRn3g== - dependencies: - "@npmcli/node-gyp" "^1.0.2" - "@npmcli/promise-spawn" "^1.3.2" - node-gyp "^7.1.0" - read-package-json-fast "^2.0.1" - -"@octokit/auth-token@^2.4.4": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.5.0.tgz#27c37ea26c205f28443402477ffd261311f21e36" - integrity sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g== - dependencies: - "@octokit/types" "^6.0.3" - -"@octokit/core@^3.5.1": - version "3.5.1" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.5.1.tgz#8601ceeb1ec0e1b1b8217b960a413ed8e947809b" - integrity sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw== - dependencies: - "@octokit/auth-token" "^2.4.4" - "@octokit/graphql" "^4.5.8" - "@octokit/request" "^5.6.0" - "@octokit/request-error" "^2.0.5" - "@octokit/types" "^6.0.3" - before-after-hook "^2.2.0" - universal-user-agent "^6.0.0" - -"@octokit/endpoint@^6.0.1": - version "6.0.12" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.12.tgz#3b4d47a4b0e79b1027fb8d75d4221928b2d05658" - integrity sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA== - dependencies: - "@octokit/types" "^6.0.3" - is-plain-object "^5.0.0" - universal-user-agent "^6.0.0" - -"@octokit/graphql@^4.5.8": - version "4.8.0" - resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.8.0.tgz#664d9b11c0e12112cbf78e10f49a05959aa22cc3" - integrity sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg== - dependencies: - "@octokit/request" "^5.6.0" - "@octokit/types" "^6.0.3" - universal-user-agent "^6.0.0" - -"@octokit/openapi-types@^11.2.0": - version "11.2.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-11.2.0.tgz#b38d7fc3736d52a1e96b230c1ccd4a58a2f400a6" - integrity sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA== - -"@octokit/plugin-enterprise-rest@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz#e07896739618dab8da7d4077c658003775f95437" - integrity sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw== - -"@octokit/plugin-paginate-rest@^2.16.8": - version "2.17.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz#32e9c7cab2a374421d3d0de239102287d791bce7" - integrity sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw== - dependencies: - "@octokit/types" "^6.34.0" - -"@octokit/plugin-request-log@^1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85" - integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA== - -"@octokit/plugin-rest-endpoint-methods@^5.12.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz#8c46109021a3412233f6f50d28786f8e552427ba" - integrity sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA== - dependencies: - "@octokit/types" "^6.34.0" - deprecation "^2.3.1" - -"@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677" - integrity sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg== - dependencies: - "@octokit/types" "^6.0.3" - deprecation "^2.0.0" - once "^1.4.0" - -"@octokit/request@^5.6.0": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.2.tgz#1aa74d5da7b9e04ac60ef232edd9a7438dcf32d8" - integrity sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA== - dependencies: - "@octokit/endpoint" "^6.0.1" - "@octokit/request-error" "^2.1.0" - "@octokit/types" "^6.16.1" - is-plain-object "^5.0.0" - node-fetch "^2.6.1" - universal-user-agent "^6.0.0" - -"@octokit/rest@^18.1.0": - version "18.12.0" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.12.0.tgz#f06bc4952fc87130308d810ca9d00e79f6988881" - integrity sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q== - dependencies: - "@octokit/core" "^3.5.1" - "@octokit/plugin-paginate-rest" "^2.16.8" - "@octokit/plugin-request-log" "^1.0.4" - "@octokit/plugin-rest-endpoint-methods" "^5.12.0" - -"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.34.0": - version "6.34.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.34.0.tgz#c6021333334d1ecfb5d370a8798162ddf1ae8218" - integrity sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw== - dependencies: - "@octokit/openapi-types" "^11.2.0" - -"@pmmmwh/react-refresh-webpack-plugin@^0.5.3": - version "0.5.4" - resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.4.tgz#df0d0d855fc527db48aac93c218a0bf4ada41f99" - integrity sha512-zZbZeHQDnoTlt2AF+diQT0wsSXpvWiaIOZwBRdltNFhG1+I3ozyaw7U/nBiUwyJ0D+zwdXp0E3bWOl38Ag2BMw== - dependencies: - ansi-html-community "^0.0.8" - common-path-prefix "^3.0.0" - core-js-pure "^3.8.1" - error-stack-parser "^2.0.6" - find-up "^5.0.0" - html-entities "^2.1.0" - loader-utils "^2.0.0" - schema-utils "^3.0.0" - source-map "^0.7.3" - -"@rollup/plugin-babel@^5.2.0": - version "5.3.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz#9cb1c5146ddd6a4968ad96f209c50c62f92f9879" - integrity sha512-9uIC8HZOnVLrLHxayq/PTzw+uS25E14KPUBh5ktF+18Mjo5yK0ToMMx6epY0uEgkjwJw0aBW4x2horYXh8juWw== - dependencies: - "@babel/helper-module-imports" "^7.10.4" - "@rollup/pluginutils" "^3.1.0" - -"@rollup/plugin-node-resolve@^11.2.1": - version "11.2.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz#82aa59397a29cd4e13248b106e6a4a1880362a60" - integrity sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg== - dependencies: - "@rollup/pluginutils" "^3.1.0" - "@types/resolve" "1.17.1" - builtin-modules "^3.1.0" - deepmerge "^4.2.2" - is-module "^1.0.0" - resolve "^1.19.0" - -"@rollup/plugin-replace@^2.4.1": - version "2.4.2" - resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz#a2d539314fbc77c244858faa523012825068510a" - integrity sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg== - dependencies: - "@rollup/pluginutils" "^3.1.0" - magic-string "^0.25.7" - -"@rollup/pluginutils@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" - integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== - dependencies: - "@types/estree" "0.0.39" - estree-walker "^1.0.1" - picomatch "^2.2.2" - -"@rushstack/eslint-patch@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323" - integrity sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A== - -"@sideway/address@^4.1.3": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.3.tgz#d93cce5d45c5daec92ad76db492cc2ee3c64ab27" - integrity sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ== - dependencies: - "@hapi/hoek" "^9.0.0" - -"@sideway/formula@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" - integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== - -"@sideway/pinpoint@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" - integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== - -"@sinonjs/commons@^1.7.0": - version "1.8.2" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.2.tgz#858f5c4b48d80778fde4b9d541f27edc0d56488b" - integrity sha512-sruwd86RJHdsVf/AtBoijDmUqJp3B6hF/DGC23C+JaegnDHaZyewCjoVGTdg3J0uz3Zs7NnIT05OBOmML72lQw== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^8.0.1": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7" - integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg== - dependencies: - "@sinonjs/commons" "^1.7.0" - -"@surma/rollup-plugin-off-main-thread@^2.2.3": - version "2.2.3" - resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz#ee34985952ca21558ab0d952f00298ad2190c053" - integrity sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ== - dependencies: - ejs "^3.1.6" - json5 "^2.2.0" - magic-string "^0.25.0" - string.prototype.matchall "^4.0.6" - -"@svgr/babel-plugin-add-jsx-attribute@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz#81ef61947bb268eb9d50523446f9c638fb355906" - integrity sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg== - -"@svgr/babel-plugin-remove-jsx-attribute@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz#6b2c770c95c874654fd5e1d5ef475b78a0a962ef" - integrity sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg== - -"@svgr/babel-plugin-remove-jsx-empty-expression@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz#25621a8915ed7ad70da6cea3d0a6dbc2ea933efd" - integrity sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA== - -"@svgr/babel-plugin-replace-jsx-attribute-value@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz#0b221fc57f9fcd10e91fe219e2cd0dd03145a897" - integrity sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ== - -"@svgr/babel-plugin-svg-dynamic-title@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz#139b546dd0c3186b6e5db4fefc26cb0baea729d7" - integrity sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg== - -"@svgr/babel-plugin-svg-em-dimensions@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz#6543f69526632a133ce5cabab965deeaea2234a0" - integrity sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw== - -"@svgr/babel-plugin-transform-react-native-svg@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz#00bf9a7a73f1cad3948cdab1f8dfb774750f8c80" - integrity sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q== - -"@svgr/babel-plugin-transform-svg-component@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz#583a5e2a193e214da2f3afeb0b9e8d3250126b4a" - integrity sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ== - -"@svgr/babel-preset@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-5.5.0.tgz#8af54f3e0a8add7b1e2b0fcd5a882c55393df327" - integrity sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig== - dependencies: - "@svgr/babel-plugin-add-jsx-attribute" "^5.4.0" - "@svgr/babel-plugin-remove-jsx-attribute" "^5.4.0" - "@svgr/babel-plugin-remove-jsx-empty-expression" "^5.0.1" - "@svgr/babel-plugin-replace-jsx-attribute-value" "^5.0.1" - "@svgr/babel-plugin-svg-dynamic-title" "^5.4.0" - "@svgr/babel-plugin-svg-em-dimensions" "^5.4.0" - "@svgr/babel-plugin-transform-react-native-svg" "^5.4.0" - "@svgr/babel-plugin-transform-svg-component" "^5.5.0" - -"@svgr/core@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-5.5.0.tgz#82e826b8715d71083120fe8f2492ec7d7874a579" - integrity sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ== - dependencies: - "@svgr/plugin-jsx" "^5.5.0" - camelcase "^6.2.0" - cosmiconfig "^7.0.0" - -"@svgr/hast-util-to-babel-ast@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz#5ee52a9c2533f73e63f8f22b779f93cd432a5461" - integrity sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ== - dependencies: - "@babel/types" "^7.12.6" - -"@svgr/plugin-jsx@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz#1aa8cd798a1db7173ac043466d7b52236b369000" - integrity sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA== - dependencies: - "@babel/core" "^7.12.3" - "@svgr/babel-preset" "^5.5.0" - "@svgr/hast-util-to-babel-ast" "^5.5.0" - svg-parser "^2.0.2" - -"@svgr/plugin-svgo@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz#02da55d85320549324e201c7b2e53bf431fcc246" - integrity sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ== - dependencies: - cosmiconfig "^7.0.0" - deepmerge "^4.2.2" - svgo "^1.2.2" - -"@svgr/webpack@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-5.5.0.tgz#aae858ee579f5fa8ce6c3166ef56c6a1b381b640" - integrity sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g== - dependencies: - "@babel/core" "^7.12.3" - "@babel/plugin-transform-react-constant-elements" "^7.12.1" - "@babel/preset-env" "^7.12.1" - "@babel/preset-react" "^7.12.5" - "@svgr/core" "^5.5.0" - "@svgr/plugin-jsx" "^5.5.0" - "@svgr/plugin-svgo" "^5.5.0" - loader-utils "^2.0.0" - -"@testing-library/react-hooks@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-7.0.1.tgz#8429d8bf55bfe82e486bd582dd06457c2464900a" - integrity sha512-bpEQ2SHSBSzBmfJ437NmnP+oArQ7aVmmULiAp6Ag2rtyLBLPNFSMmgltUbFGmQOJdPWo4Ub31kpUC5T46zXNwQ== - dependencies: - "@babel/runtime" "^7.12.5" - "@types/react" ">=16.9.0" - "@types/react-dom" ">=16.9.0" - "@types/react-test-renderer" ">=16.9.0" - react-error-boundary "^3.1.0" - -"@tootallnate/once@1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" - integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== - -"@trysound/sax@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" - integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== - -"@tsconfig/node10@^1.0.7": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" - integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== - -"@tsconfig/node12@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" - integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== - -"@tsconfig/node14@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" - integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== - -"@tsconfig/node16@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" - integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== - -"@types/babel__core@^7.0.0": - version "7.1.12" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.12.tgz#4d8e9e51eb265552a7e4f1ff2219ab6133bdfb2d" - integrity sha512-wMTHiiTiBAAPebqaPiPDLFA4LYPKr6Ph0Xq/6rq1Ur3v66HXyG+clfR9CNETkD7MQS8ZHvpQOtA53DLws5WAEQ== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__core@^7.1.14": - version "7.1.18" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.18.tgz#1a29abcc411a9c05e2094c98f9a1b7da6cdf49f8" - integrity sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.0.tgz#f1ec1c104d1bb463556ecb724018ab788d0c172a" - integrity sha512-c1mZUu4up5cp9KROs/QAw0gTeHrw/x7m52LcnvMxxOZ03DmLwPV0MlGmlgzV3cnSdjhJOZsj7E7FHeioai+egw== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307" - integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.0.8" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.8.tgz#479a4ee3e291a403a1096106013ec22cf9b64012" - integrity sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw== - dependencies: - "@babel/types" "^7.3.0" - -"@types/babel__traverse@^7.0.4": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.11.0.tgz#b9a1efa635201ba9bc850323a8793ee2d36c04a0" - integrity sha512-kSjgDMZONiIfSH1Nxcr5JIRMwUetDki63FSQfpTCz8ogF3Ulqm8+mr5f78dUYs6vMiB6gBusQqfQmBvHZj/lwg== - dependencies: - "@babel/types" "^7.3.0" - -"@types/body-parser@*": - version "1.19.2" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" - integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== - dependencies: - "@types/connect" "*" - "@types/node" "*" - -"@types/bonjour@^3.5.9": - version "3.5.10" - resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" - integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== - dependencies: - "@types/node" "*" - -"@types/cheerio@*", "@types/cheerio@^0.22.22": - version "0.22.24" - resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.24.tgz#fcee47074aa221ac0f31ede0c72c0800bf3bf0aa" - integrity sha512-iKXt/cwltGvN06Dd6zwQG1U35edPwId9lmcSeYfcxSNvvNg4vysnFB+iBQNjj06tSVV7MBj0GWMQ7dwb4Z+p8Q== - dependencies: - "@types/node" "*" - -"@types/color-name@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" - integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== - -"@types/connect-history-api-fallback@^1.3.5": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" - integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== - dependencies: - "@types/express-serve-static-core" "*" - "@types/node" "*" - -"@types/connect@*": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== - dependencies: - "@types/node" "*" - -"@types/enzyme@^3.10.10": - version "3.10.10" - resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.10.10.tgz#3a44cc66571432ab9e1773a831af3742beb39275" - integrity sha512-/D4wFhiEjUDfPu+j5FVK0g/jf7rqeEIpNfAI+kyxzLpw5CKO0drnW3W5NC38alIjsWgnyQ8pbuPF5+UD+vhVyg== - dependencies: - "@types/cheerio" "*" - "@types/react" "*" - -"@types/eslint-scope@^3.7.0": - version "3.7.3" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" - integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== - dependencies: - "@types/eslint" "*" - "@types/estree" "*" - -"@types/eslint@*": - version "8.4.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304" - integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/eslint@^7.28.2": - version "7.29.0" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.29.0.tgz#e56ddc8e542815272720bb0b4ccc2aff9c3e1c78" - integrity sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree@*": - version "0.0.46" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe" - integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg== - -"@types/estree@0.0.39": - version "0.0.39" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" - integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== - -"@types/estree@^0.0.50": - version "0.0.50" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" - integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== - -"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": - version "4.17.28" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" - integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - -"@types/express@*", "@types/express@^4.17.13": - version "4.17.13" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" - integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.18" - "@types/qs" "*" - "@types/serve-static" "*" - -"@types/graceful-fs@^4.1.2": - version "4.1.4" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.4.tgz#4ff9f641a7c6d1a3508ff88bc3141b152772e753" - integrity sha512-mWA/4zFQhfvOA8zWkXobwJvBD7vzcxgrOQ0J5CH1votGqdq9m7+FwtGaqyCZqC3NyyBkc9z4m+iry4LlqcMWJg== - dependencies: - "@types/node" "*" - -"@types/history@*", "@types/history@^4.7.11": - version "4.7.11" - resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" - integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== - -"@types/hoist-non-react-statics@^3.3.0": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" - integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== - dependencies: - "@types/react" "*" - hoist-non-react-statics "^3.3.0" - -"@types/html-minifier-terser@^6.0.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" - integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== - -"@types/http-proxy@^1.17.8": - version "1.17.8" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55" - integrity sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA== - dependencies: - "@types/node" "*" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" - integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg== - -"@types/istanbul-lib-coverage@^2.0.1": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" - integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== - -"@types/istanbul-lib-report@*": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c" - integrity sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" - integrity sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/jest@^27.4.0": - version "27.4.0" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.0.tgz#037ab8b872067cae842a320841693080f9cb84ed" - integrity sha512-gHl8XuC1RZ8H2j5sHv/JqsaxXkDDM9iDOgu0Wp8sjs4u/snb2PVehyWXJPr+ORA0RPpgw231mnutWI1+0hgjIQ== - dependencies: - jest-diff "^27.0.0" - pretty-format "^27.0.0" - -"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": - version "7.0.7" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" - integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== - -"@types/json-schema@^7.0.4", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= - -"@types/jsrsasign@^9.0.3": - version "9.0.3" - resolved "https://registry.yarnpkg.com/@types/jsrsasign/-/jsrsasign-9.0.3.tgz#f51120f0e3ef8122d657257438dd19269e777c6e" - integrity sha512-asLFAXUBdp4T8tSfqlGai+ax7nCTtMzyLELfnmb0L3QXXStDo1NzYtgbYlGXTp8EokBjZYmuH3x42ce+XHms4g== - -"@types/lodash.chunk@^4.2.6": - version "4.2.6" - resolved "https://registry.yarnpkg.com/@types/lodash.chunk/-/lodash.chunk-4.2.6.tgz#9d35f05360b0298715d7f3d9efb34dd4f77e5d2a" - integrity sha512-SPlusB7jxXyGcTXYcUdWr7WmhArO/rmTq54VN88iKMxGUhyg79I4Q8n4riGn3kjaTjOJrVlHhxgX/d7woak5BQ== - dependencies: - "@types/lodash" "*" - -"@types/lodash.debounce@^4.0.6": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@types/lodash.debounce/-/lodash.debounce-4.0.6.tgz#c5a2326cd3efc46566c47e4c0aa248dc0ee57d60" - integrity sha512-4WTmnnhCfDvvuLMaF3KV4Qfki93KebocUF45msxhYyjMttZDQYzHkO639ohhk8+oco2cluAFL3t5+Jn4mleylQ== - dependencies: - "@types/lodash" "*" - -"@types/lodash.memoize@^4.1.6": - version "4.1.6" - resolved "https://registry.yarnpkg.com/@types/lodash.memoize/-/lodash.memoize-4.1.6.tgz#3221f981790a415cab1a239f25c17efd8b604c23" - integrity sha512-mYxjKiKzRadRJVClLKxS4wb3Iy9kzwJ1CkbyKiadVxejnswnRByyofmPMscFKscmYpl36BEEhCMPuWhA1R/1ZQ== - dependencies: - "@types/lodash" "*" - -"@types/lodash@*": - version "4.14.149" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.149.tgz#1342d63d948c6062838fbf961012f74d4e638440" - integrity sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ== - -"@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== - -"@types/minimatch@^3.0.3": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" - integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== - -"@types/minimist@^1.2.0": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" - integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== - -"@types/node@*", "@types/node@^17.0.17": - version "17.0.17" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.17.tgz#a8ddf6e0c2341718d74ee3dc413a13a042c45a0c" - integrity sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw== - -"@types/node@^14.14.31": - version "14.18.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.12.tgz#0d4557fd3b94497d793efd4e7d92df2f83b4ef24" - integrity sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A== - -"@types/normalize-package-data@^2.4.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" - integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== - -"@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== - -"@types/prettier@^2.1.5": - version "2.4.3" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.3.tgz#a3c65525b91fca7da00ab1a3ac2b5a2a4afbffbf" - integrity sha512-QzSuZMBuG5u8HqYz01qtMdg/Jfctlnvj1z/lYnIDXs/golxw0fxtRAHd9KrzjR7Yxz1qVeI00o0kiO3PmVdJ9w== - -"@types/prop-types@*": - version "15.7.3" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" - integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== - -"@types/q@^1.5.1": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" - integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== - -"@types/qs@*": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== - -"@types/range-parser@*": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== - -"@types/react-dom@>=16.9.0": - version "17.0.9" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.9.tgz#441a981da9d7be117042e1a6fd3dac4b30f55add" - integrity sha512-wIvGxLfgpVDSAMH5utdL9Ngm5Owu0VsGmldro3ORLXV8CShrL8awVj06NuEXFQ5xyaYfdca7Sgbk/50Ri1GdPg== - dependencies: - "@types/react" "*" - -"@types/react-dom@^17.0.1": - version "17.0.1" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.1.tgz#d92d77d020bfb083e07cc8e0ac9f933599a4d56a" - integrity sha512-yIVyopxQb8IDZ7SOHeTovurFq+fXiPICa+GV3gp0Xedsl+MwQlMLKmvrnEjFbQxjliH5YVAEWFh975eVNmKj7Q== - dependencies: - "@types/react" "*" - -"@types/react-redux@^7.1.16": - version "7.1.16" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.16.tgz#0fbd04c2500c12105494c83d4a3e45c084e3cb21" - integrity sha512-f/FKzIrZwZk7YEO9E1yoxIuDNRiDducxkFlkw/GNMGEnK9n4K8wJzlJBghpSuOVDgEUHoDkDF7Gi9lHNQR4siw== - dependencies: - "@types/hoist-non-react-statics" "^3.3.0" - "@types/react" "*" - hoist-non-react-statics "^3.3.0" - redux "^4.0.0" - -"@types/react-router-dom@^5.3.3": - version "5.3.3" - resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" - integrity sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw== - dependencies: - "@types/history" "^4.7.11" - "@types/react" "*" - "@types/react-router" "*" - -"@types/react-router@*", "@types/react-router@^5.1.17": - version "5.1.17" - resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.17.tgz#087091006213b11042f39570e5cd414863693968" - integrity sha512-RNSXOyb3VyRs/EOGmjBhhGKTbnN6fHWvy5FNLzWfOWOGjgVUKqJZXfpKzLmgoU8h6Hj8mpALj/mbXQASOb92wQ== - dependencies: - "@types/history" "*" - "@types/react" "*" - -"@types/react-test-renderer@>=16.9.0": - version "17.0.1" - resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-17.0.1.tgz#3120f7d1c157fba9df0118dae20cb0297ee0e06b" - integrity sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw== - dependencies: - "@types/react" "*" - -"@types/react-transition-group@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.2.3.tgz#4924133f7268694058e415bf7aea2d4c21131470" - integrity sha512-Hk8jiuT7iLOHrcjKP/ZVSyCNXK73wJAUz60xm0mVhiRujrdiI++j4duLiL282VGxwAgxetHQFfqA29LgEeSkFA== - dependencies: - "@types/react" "*" - -"@types/react-virtualized@^9.21.10": - version "9.21.10" - resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.21.10.tgz#cd072dc9c889291ace2c4c9de8e8c050da8738b7" - integrity sha512-f5Ti3A7gGdLkPPFNHTrvKblpsPNBiQoSorOEOD+JPx72g/Ng2lOt4MYfhvQFQNgyIrAro+Z643jbcKafsMW2ag== - dependencies: - "@types/prop-types" "*" - "@types/react" "*" - -"@types/react@*", "@types/react@>=16.9.0", "@types/react@^17.0.2": - version "17.0.15" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.15.tgz#c7533dc38025677e312606502df7656a6ea626d0" - integrity sha512-uTKHDK9STXFHLaKv6IMnwp52fm0hwU+N89w/p9grdUqcFA6WuqDyPhaWopbNyE1k/VhgzmHl8pu1L4wITtmlLw== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/redux-logger@^3.0.8": - version "3.0.8" - resolved "https://registry.yarnpkg.com/@types/redux-logger/-/redux-logger-3.0.8.tgz#1fb6d26917bb198792bb1cf57feb31cae1532c5d" - integrity sha512-zM+cxiSw6nZtRbxpVp9SE3x/X77Z7e7YAfHD1NkxJyJbAGSXJGF0E9aqajZfPOa/sTYnuwutmlCldveExuCeLw== - dependencies: - redux "^4.0.0" - -"@types/redux-mock-store@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/redux-mock-store/-/redux-mock-store-1.0.3.tgz#895de4a364bc4836661570aec82f2eef5989d1fb" - integrity sha512-Wqe3tJa6x9MxMN4DJnMfZoBRBRak1XTPklqj4qkVm5VBpZnC8PSADf4kLuFQ9NAdHaowfWoEeUMz7NWc2GMtnA== - dependencies: - redux "^4.0.5" - -"@types/resolve@1.17.1": - version "1.17.1" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" - integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== - dependencies: - "@types/node" "*" - -"@types/retry@^0.12.0": - version "0.12.1" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" - integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== - -"@types/scheduler@*": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== - -"@types/serve-index@^1.9.1": - version "1.9.1" - resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" - integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== - dependencies: - "@types/express" "*" - -"@types/serve-static@*": - version "1.13.10" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" - integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== - dependencies: - "@types/mime" "^1" - "@types/node" "*" - -"@types/sinonjs__fake-timers@8.1.1": - version "8.1.1" - resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" - integrity sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g== - -"@types/sizzle@^2.3.2": - version "2.3.2" - resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" - integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg== - -"@types/sockjs@^0.3.33": - version "0.3.33" - resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" - integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== - dependencies: - "@types/node" "*" - -"@types/stack-utils@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" - integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== - -"@types/styled-jsx@^2.2.8": - version "2.2.8" - resolved "https://registry.yarnpkg.com/@types/styled-jsx/-/styled-jsx-2.2.8.tgz#b50d13d8a3c34036282d65194554cf186bab7234" - integrity sha512-Yjye9VwMdYeXfS71ihueWRSxrruuXTwKCbzue4+5b2rjnQ//AtyM7myZ1BEhNhBQ/nL/RE7bdToUoLln2miKvg== - dependencies: - "@types/react" "*" - -"@types/trusted-types@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756" - integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg== - -"@types/ws@^8.2.2": - version "8.2.2" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21" - integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg== - dependencies: - "@types/node" "*" - -"@types/yargs-parser@*": - version "13.1.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-13.1.0.tgz#c563aa192f39350a1d18da36c5a8da382bbd8228" - integrity sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg== - -"@types/yargs@^16.0.0": - version "16.0.4" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977" - integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== - dependencies: - "@types/yargs-parser" "*" - -"@types/yauzl@^2.9.1": - version "2.9.2" - resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.2.tgz#c48e5d56aff1444409e39fa164b0b4d4552a7b7a" - integrity sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA== - dependencies: - "@types/node" "*" - -"@typescript-eslint/eslint-plugin@^5.5.0": - version "5.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.11.0.tgz#3b866371d8d75c70f9b81535e7f7d3aa26527c7a" - integrity sha512-HJh33bgzXe6jGRocOj4FmefD7hRY4itgjzOrSs3JPrTNXsX7j5+nQPciAUj/1nZtwo2kAc3C75jZO+T23gzSGw== - dependencies: - "@typescript-eslint/scope-manager" "5.11.0" - "@typescript-eslint/type-utils" "5.11.0" - "@typescript-eslint/utils" "5.11.0" - debug "^4.3.2" - functional-red-black-tree "^1.0.1" - ignore "^5.1.8" - regexpp "^3.2.0" - semver "^7.3.5" - tsutils "^3.21.0" - -"@typescript-eslint/experimental-utils@^5.0.0": - version "5.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.11.0.tgz#e7b2bfd57ddda47c3f658faad57655ed9e01fea0" - integrity sha512-EPvC/bU2n1LKtzKWP1AjGWkp7r8tJ8giVlZHIODo6q7SAd6J+/9vjtEKHK2G/Qp+D2IGPsQge+oadDR3CZcFtQ== - dependencies: - "@typescript-eslint/utils" "5.11.0" - -"@typescript-eslint/parser@^5.13.0", "@typescript-eslint/parser@^5.5.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.13.0.tgz#0394ed8f2f849273c0bf4b811994d177112ced5c" - integrity sha512-GdrU4GvBE29tm2RqWOM0P5QfCtgCyN4hXICj/X9ibKED16136l9ZpoJvCL5pSKtmJzA+NRDzQ312wWMejCVVfg== - dependencies: - "@typescript-eslint/scope-manager" "5.13.0" - "@typescript-eslint/types" "5.13.0" - "@typescript-eslint/typescript-estree" "5.13.0" - debug "^4.3.2" - -"@typescript-eslint/scope-manager@5.11.0": - version "5.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.11.0.tgz#f5aef83ff253f457ecbee5f46f762298f0101e4b" - integrity sha512-z+K4LlahDFVMww20t/0zcA7gq/NgOawaLuxgqGRVKS0PiZlCTIUtX0EJbC0BK1JtR4CelmkPK67zuCgpdlF4EA== - dependencies: - "@typescript-eslint/types" "5.11.0" - "@typescript-eslint/visitor-keys" "5.11.0" - -"@typescript-eslint/scope-manager@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz#cf6aff61ca497cb19f0397eea8444a58f46156b6" - integrity sha512-T4N8UvKYDSfVYdmJq7g2IPJYCRzwtp74KyDZytkR4OL3NRupvswvmJQJ4CX5tDSurW2cvCc1Ia1qM7d0jpa7IA== - dependencies: - "@typescript-eslint/types" "5.13.0" - "@typescript-eslint/visitor-keys" "5.13.0" - -"@typescript-eslint/type-utils@5.11.0": - version "5.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.11.0.tgz#58be0ba73d1f6ef8983d79f7f0bc2209b253fefe" - integrity sha512-wDqdsYO6ofLaD4DsGZ0jGwxp4HrzD2YKulpEZXmgN3xo4BHJwf7kq49JTRpV0Gx6bxkSUmc9s0EIK1xPbFFpIA== - dependencies: - "@typescript-eslint/utils" "5.11.0" - debug "^4.3.2" - tsutils "^3.21.0" - -"@typescript-eslint/types@5.11.0": - version "5.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.11.0.tgz#ba345818a2540fdf2755c804dc2158517ab61188" - integrity sha512-cxgBFGSRCoBEhvSVLkKw39+kMzUKHlJGVwwMbPcTZX3qEhuXhrjwaZXWMxVfxDgyMm+b5Q5b29Llo2yow8Y7xQ== - -"@typescript-eslint/types@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.13.0.tgz#da1de4ae905b1b9ff682cab0bed6b2e3be9c04e5" - integrity sha512-LmE/KO6DUy0nFY/OoQU0XelnmDt+V8lPQhh8MOVa7Y5k2gGRd6U9Kp3wAjhB4OHg57tUO0nOnwYQhRRyEAyOyg== - -"@typescript-eslint/typescript-estree@5.11.0": - version "5.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.11.0.tgz#53f9e09b88368191e52020af77c312a4777ffa43" - integrity sha512-yVH9hKIv3ZN3lw8m/Jy5I4oXO4ZBMqijcXCdA4mY8ull6TPTAoQnKKrcZ0HDXg7Bsl0Unwwx7jcXMuNZc0m4lg== - dependencies: - "@typescript-eslint/types" "5.11.0" - "@typescript-eslint/visitor-keys" "5.11.0" - debug "^4.3.2" - globby "^11.0.4" - is-glob "^4.0.3" - semver "^7.3.5" - tsutils "^3.21.0" - -"@typescript-eslint/typescript-estree@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz#b37c07b748ff030a3e93d87c842714e020b78141" - integrity sha512-Q9cQow0DeLjnp5DuEDjLZ6JIkwGx3oYZe+BfcNuw/POhtpcxMTy18Icl6BJqTSd+3ftsrfuVb7mNHRZf7xiaNA== - dependencies: - "@typescript-eslint/types" "5.13.0" - "@typescript-eslint/visitor-keys" "5.13.0" - debug "^4.3.2" - globby "^11.0.4" - is-glob "^4.0.3" - semver "^7.3.5" - tsutils "^3.21.0" - -"@typescript-eslint/utils@5.11.0", "@typescript-eslint/utils@^5.10.2": - version "5.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.11.0.tgz#d91548ef180d74c95d417950336d9260fdbe1dc5" - integrity sha512-g2I480tFE1iYRDyMhxPAtLQ9HAn0jjBtipgTCZmd9I9s11OV8CTsG+YfFciuNDcHqm4csbAgC2aVZCHzLxMSUw== - dependencies: - "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.11.0" - "@typescript-eslint/types" "5.11.0" - "@typescript-eslint/typescript-estree" "5.11.0" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - -"@typescript-eslint/visitor-keys@5.11.0": - version "5.11.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.11.0.tgz#888542381f1a2ac745b06d110c83c0b261487ebb" - integrity sha512-E8w/vJReMGuloGxJDkpPlGwhxocxOpSVgSvjiLO5IxZPmxZF30weOeJYyPSEACwM+X4NziYS9q+WkN/2DHYQwA== - dependencies: - "@typescript-eslint/types" "5.11.0" - eslint-visitor-keys "^3.0.0" - -"@typescript-eslint/visitor-keys@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz#f45ff55bcce16403b221ac9240fbeeae4764f0fd" - integrity sha512-HLKEAS/qA1V7d9EzcpLFykTePmOQqOFim8oCvhY3pZgQ8Hi38hYpHd9e5GN6nQBFQNecNhws5wkS9Y5XIO0s/g== - dependencies: - "@typescript-eslint/types" "5.13.0" - eslint-visitor-keys "^3.0.0" - -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== - dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== - -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== - -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== - -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== - dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== - -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== - -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" - -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@xtuc/long" "4.2.2" - -"@welldone-software/why-did-you-render@^6.2.3": - version "6.2.3" - resolved "https://registry.yarnpkg.com/@welldone-software/why-did-you-render/-/why-did-you-render-6.2.3.tgz#cdd5e27cf25b7e767c1c0b0e8808f67d3f6be833" - integrity sha512-FQgi90jvC9uw2aALlonJfqaWOvU5UUBBVvdAnS2iryXwCc4YJkKsPJY5Y/LzaND3OIyk8XGUn1vTRn6hcem28Q== - dependencies: - lodash "^4" - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -"@zeit/schemas@2.6.0": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@zeit/schemas/-/schemas-2.6.0.tgz#004e8e553b4cd53d538bd38eac7bcbf58a867fe3" - integrity sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg== - -JSONStream@^1.0.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" - integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== - dependencies: - jsonparse "^1.2.0" - through ">=2.2.7 <3" - -abab@^2.0.3, abab@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" - integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -acorn-globals@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" - integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== - dependencies: - acorn "^7.1.1" - acorn-walk "^7.1.1" - -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== - -acorn-jsx@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" - integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== - -acorn-node@^1.6.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" - integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A== - dependencies: - acorn "^7.0.0" - acorn-walk "^7.0.0" - xtend "^4.0.2" - -acorn-walk@^7.0.0, acorn-walk@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" - integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== - -acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^7.0.0: - version "7.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" - integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== - -acorn@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe" - integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ== - -acorn@^8.2.4, acorn@^8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== - -acorn@^8.4.1: - version "8.6.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895" - integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw== - -add-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" - integrity sha1-anmQQ3ynNtXhKI25K9MmbV9csqo= - -address@^1.0.1, address@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" - integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== - -adjust-sourcemap-loader@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz#fc4a0fd080f7d10471f30a7320f25560ade28c99" - integrity sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A== - dependencies: - loader-utils "^2.0.0" - regex-parser "^2.2.11" - -agent-base@6, agent-base@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - -agentkeepalive@^4.1.3: - version "4.1.4" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.1.4.tgz#d928028a4862cb11718e55227872e842a44c945b" - integrity sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ== - dependencies: - debug "^4.1.0" - depd "^1.1.2" - humanize-ms "^1.2.1" - -aggregate-error@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" - integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -airbnb-prop-types@^2.16.0: - version "2.16.0" - resolved "https://registry.yarnpkg.com/airbnb-prop-types/-/airbnb-prop-types-2.16.0.tgz#b96274cefa1abb14f623f804173ee97c13971dc2" - integrity sha512-7WHOFolP/6cS96PhKNrslCLMYAI8yB1Pp6u6XmxozQOiZbsI5ycglZr5cHhBFfuRcQQjzCMith5ZPZdYiJCxUg== - dependencies: - array.prototype.find "^2.1.1" - function.prototype.name "^1.1.2" - is-regex "^1.1.0" - object-is "^1.1.2" - object.assign "^4.1.0" - object.entries "^1.1.2" - prop-types "^15.7.2" - prop-types-exact "^1.2.0" - react-is "^16.13.1" - -ajv-formats@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" - -ajv-keywords@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" - integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== - -ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv-keywords@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" - integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== - dependencies: - fast-deep-equal "^3.1.3" - -ajv@6.12.6, ajv@^6.10.0, ajv@^6.12.0, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.5.5: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - 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" - -ajv@^8.0.0, ajv@^8.6.0, ajv@^8.8.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" - 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" - -ansi-align@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" - integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== - dependencies: - string-width "^4.1.0" - -ansi-colors@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - -ansi-escapes@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== - -ansi-escapes@^4.2.1, ansi-escapes@^4.3.0, ansi-escapes@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" - integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== - dependencies: - type-fest "^0.11.0" - -ansi-html-community@^0.0.8: - 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@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" - integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== - dependencies: - "@types/color-name" "^1.1.1" - color-convert "^2.0.1" - -ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -anymatch@^3.0.3: - version "3.1.1" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" - integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -aproba@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" - integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== - -arch@^2.1.1, arch@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" - integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -arg@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arg/-/arg-2.0.0.tgz#c06e7ff69ab05b3a4a03ebe0407fac4cba657545" - integrity sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w== - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -arg@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb" - integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -aria-query@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" - integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== - dependencies: - "@babel/runtime" "^7.10.2" - "@babel/runtime-corejs3" "^7.10.2" - -array-differ@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" - integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg== - -array-filter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" - integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-flatten@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - -array-ify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" - integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= - -array-includes@^3.1.3, array-includes@^3.1.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9" - integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - get-intrinsic "^1.1.1" - is-string "^1.0.7" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array.prototype.find@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.1.1.tgz#3baca26108ca7affb08db06bf0be6cb3115a969c" - integrity sha512-mi+MYNJYLTx2eNYy+Yh6raoQacCsNeeMUaspFPh9Y141lFSsWxxB8V9mM2ye+eqiRs917J6/pJ4M9ZPzenWckA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.4" - -array.prototype.flat@^1.2.3, array.prototype.flat@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13" - integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - -array.prototype.flatmap@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446" - integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - es-abstract "^1.19.0" - -arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - -arrify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" - integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== - -asap@^2.0.0, asap@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -ast-types-flow@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" - integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= - -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - -async@^2.6.2: - version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== - dependencies: - lodash "^4.17.14" - -async@^3.2.0, async@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9" - integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g== - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - -autoprefixer@^10.4.2: - version "10.4.2" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b" - integrity sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ== - dependencies: - browserslist "^4.19.1" - caniuse-lite "^1.0.30001297" - fraction.js "^4.1.2" - normalize-range "^0.1.2" - picocolors "^1.0.0" - postcss-value-parser "^4.2.0" - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== - -axe-core@^4.3.5: - version "4.3.5" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.3.5.tgz#78d6911ba317a8262bfee292aeafcc1e04b49cc5" - integrity sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA== - -axios@^0.21.1: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - -axios@^0.26.0: - version "0.26.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.0.tgz#9a318f1c69ec108f8cd5f3c3d390366635e13928" - integrity sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og== - dependencies: - follow-redirects "^1.14.8" - -axobject-query@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" - integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== - -babel-eslint@10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" - integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" - eslint-visitor-keys "^1.0.0" - resolve "^1.12.0" - -babel-jest@^27.4.2, babel-jest@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444" - integrity sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg== - dependencies: - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^27.5.1" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - -babel-loader@^8.2.3: - version "8.2.3" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" - integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== - dependencies: - find-cache-dir "^3.3.1" - loader-utils "^1.4.0" - make-dir "^3.1.0" - schema-utils "^2.6.5" - -babel-plugin-dynamic-import-node@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" - integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== - dependencies: - object.assign "^4.1.0" - -babel-plugin-istanbul@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^5.0.4" - test-exclude "^6.0.0" - -babel-plugin-jest-hoist@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz#9be98ecf28c331eb9f5df9c72d6f89deb8181c2e" - integrity sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.0.0" - "@types/babel__traverse" "^7.0.6" - -babel-plugin-macros@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" - integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== - dependencies: - "@babel/runtime" "^7.12.5" - cosmiconfig "^7.0.0" - resolve "^1.19.0" - -babel-plugin-named-asset-import@^0.3.8: - version "0.3.8" - resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz#6b7fa43c59229685368683c28bc9734f24524cc2" - integrity sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q== - -babel-plugin-polyfill-corejs2@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" - integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== - dependencies: - "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.3.1" - semver "^6.1.1" - -babel-plugin-polyfill-corejs3@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72" - integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.1" - core-js-compat "^3.21.0" - -babel-plugin-polyfill-regenerator@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990" - integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.1" - -babel-plugin-transform-react-remove-prop-types@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" - integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== - -babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - -babel-preset-jest@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz#91f10f58034cb7989cb4f962b69fa6eef6a6bc81" - integrity sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag== - dependencies: - babel-plugin-jest-hoist "^27.5.1" - babel-preset-current-node-syntax "^1.0.0" - -babel-preset-react-app@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz#ed6005a20a24f2c88521809fa9aea99903751584" - integrity sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg== - dependencies: - "@babel/core" "^7.16.0" - "@babel/plugin-proposal-class-properties" "^7.16.0" - "@babel/plugin-proposal-decorators" "^7.16.4" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.0" - "@babel/plugin-proposal-numeric-separator" "^7.16.0" - "@babel/plugin-proposal-optional-chaining" "^7.16.0" - "@babel/plugin-proposal-private-methods" "^7.16.0" - "@babel/plugin-transform-flow-strip-types" "^7.16.0" - "@babel/plugin-transform-react-display-name" "^7.16.0" - "@babel/plugin-transform-runtime" "^7.16.4" - "@babel/preset-env" "^7.16.4" - "@babel/preset-react" "^7.16.0" - "@babel/preset-typescript" "^7.16.0" - "@babel/runtime" "^7.16.3" - babel-plugin-macros "^3.1.0" - babel-plugin-transform-react-remove-prop-types "^0.4.24" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -before-after-hook@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e" - integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ== - -bfj@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/bfj/-/bfj-7.0.2.tgz#1988ce76f3add9ac2913fd8ba47aad9e651bfbb2" - integrity sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw== - dependencies: - bluebird "^3.5.5" - check-types "^11.1.1" - hoopy "^0.1.4" - tryer "^1.0.1" - -big-integer@^1.6.16: - version "1.6.48" - resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e" - integrity sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w== - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -binary-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" - integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== - -blob-util@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" - integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== - -bluebird@3.7.2, bluebird@^3.5.5, bluebird@^3.7.2: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" - -bonjour@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" - 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" - -boolbase@^1.0.0, boolbase@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= - -boxen@5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" - integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== - dependencies: - ansi-align "^3.0.0" - camelcase "^6.2.0" - chalk "^4.1.0" - cli-boxes "^2.2.1" - string-width "^4.2.2" - type-fest "^0.20.2" - widest-line "^3.1.0" - wrap-ansi "^7.0.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.1, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -broadcast-channel@^3.4.1: - version "3.7.0" - resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-3.7.0.tgz#2dfa5c7b4289547ac3f6705f9c00af8723889937" - integrity sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg== - dependencies: - "@babel/runtime" "^7.7.2" - detect-node "^2.1.0" - js-sha3 "0.8.0" - microseconds "0.2.0" - nano-time "1.0.0" - oblivious-set "1.0.0" - rimraf "3.0.2" - unload "2.2.0" - -browser-process-hrtime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" - integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== - -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.1, browserslist@^4.16.6, browserslist@^4.17.5, browserslist@^4.18.1, browserslist@^4.19.1: - version "4.19.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" - integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== - dependencies: - caniuse-lite "^1.0.30001286" - electron-to-chromium "^1.4.17" - escalade "^3.1.1" - node-releases "^2.0.1" - picocolors "^1.0.0" - -bser@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -buffer-indexof@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" - integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== - -buffer@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -builtin-modules@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" - integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA== - -builtins@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" - integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= - -byline@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" - integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE= - -byte-size@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-7.0.1.tgz#b1daf3386de7ab9d706b941a748dbfc71130dee3" - integrity sha512-crQdqyCwhokxwV1UyDzLZanhkugAgft7vt0qbbdt60C6Zf3CAiGmtUCylbtYwrU6loOUw3euGrNtW1J651ot1A== - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -cacache@^15.0.5: - version "15.0.5" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.5.tgz#69162833da29170d6732334643c60e005f5f17d0" - integrity sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A== - dependencies: - "@npmcli/move-file" "^1.0.1" - chownr "^2.0.0" - fs-minipass "^2.0.0" - glob "^7.1.4" - infer-owner "^1.0.4" - lru-cache "^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" - -cacache@^15.2.0: - version "15.3.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" - integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== - dependencies: - "@npmcli/fs" "^1.0.0" - "@npmcli/move-file" "^1.0.1" - chownr "^2.0.0" - fs-minipass "^2.0.0" - glob "^7.1.4" - infer-owner "^1.0.4" - lru-cache "^6.0.0" - minipass "^3.1.1" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.2" - mkdirp "^1.0.3" - p-map "^4.0.0" - promise-inflight "^1.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.0.2" - unique-filename "^1.1.1" - -cachedir@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" - integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camel-case@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" - integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== - dependencies: - pascal-case "^3.1.2" - tslib "^2.0.3" - -camelcase-css@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" - integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== - -camelcase-keys@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" - integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== - dependencies: - camelcase "^5.3.1" - map-obj "^4.0.0" - quick-lru "^4.0.1" - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" - integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== - -camelcase@^6.2.1: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297: - version "1.0.30001311" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001311.tgz#682ef3f4e617f1a177ad943de59775ed3032e511" - integrity sha512-mleTFtFKfykEeW34EyfhGIFjGCqzhh38Y0LhdQ9aWF+HorZTtdgKV/1hEE0NlFkG2ubvisPV6l400tlbPys98A== - -case-sensitive-paths-webpack-plugin@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz#db64066c6422eed2e08cc14b986ca43796dbc6d4" - integrity sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw== - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chalk@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -char-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-2.0.0.tgz#16f98f3f874edceddd300fda5d58df380a7641a6" - integrity sha512-oGu2QekBMXgyQNWPDRQ001bjvDnZe4/zBTz37TMbiKz1NbNiyiH5hRkobe7npRN6GfbGbxMYFck/vQ1r9c1VMA== - -charcodes@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/charcodes/-/charcodes-0.2.0.tgz#5208d327e6cc05f99eb80ffc814707572d1f14e4" - integrity sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ== - -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - -check-more-types@2.24.0, check-more-types@^2.24.0: - version "2.24.0" - resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" - integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= - -check-types@^11.1.1: - version "11.1.2" - resolved "https://registry.yarnpkg.com/check-types/-/check-types-11.1.2.tgz#86a7c12bf5539f6324eb0e70ca8896c0e38f3e2f" - integrity sha512-tzWzvgePgLORb9/3a0YenggReLKAIb2owL03H2Xdoe5pKcUyWRSEQ8xfCar8t2SIAuEDwtmx2da1YB52YuHQMQ== - -cheerio@^1.0.0-rc.3: - version "1.0.0-rc.3" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.3.tgz#094636d425b2e9c0f4eb91a46c05630c9a1a8bf6" - integrity sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA== - dependencies: - css-select "~1.2.0" - dom-serializer "~0.1.1" - entities "~1.1.1" - htmlparser2 "^3.9.1" - lodash "^4.15.0" - parse5 "^3.0.1" - -chokidar@^3.4.2, chokidar@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - 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" - optionalDependencies: - fsevents "~2.3.2" - -chownr@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - -chownr@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" - integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== - -chrome-trace-event@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" - integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== - dependencies: - tslib "^1.9.0" - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -ci-info@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2" - integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== - -cjs-module-lexer@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" - integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== - -classnames@^2.2.5: - version "2.2.6" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" - integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== - -clean-css@^5.2.2: - version "5.2.4" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.4.tgz#982b058f8581adb2ae062520808fb2429bd487a4" - integrity sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg== - dependencies: - source-map "~0.6.0" - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cli-boxes@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" - integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== - -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= - dependencies: - restore-cursor "^2.0.0" - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-table3@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.1.tgz#36ce9b7af4847f288d3cdd081fbd09bf7bd237b8" - integrity sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA== - dependencies: - string-width "^4.2.0" - optionalDependencies: - colors "1.4.0" - -cli-truncate@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" - integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== - dependencies: - slice-ansi "^3.0.0" - string-width "^4.2.0" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= - -cli-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" - integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== - -clipboardy@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-2.3.0.tgz#3c2903650c68e46a91b388985bc2774287dba290" - integrity sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ== - dependencies: - arch "^2.1.1" - execa "^1.0.0" - is-wsl "^2.1.1" - -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" - -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - -clsx@^1.0.2, clsx@^1.0.4, clsx@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" - integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== - -cmd-shim@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-4.1.0.tgz#b3a904a6743e9fede4148c6f3800bf2a08135bdd" - integrity sha512-lb9L7EM4I/ZRVuljLPEtUJOP+xiQVknZ4ZMpMgEp4JzNldPb27HU03hi6K1/6CoIuit/Zm/LQXySErFeXxDprw== - dependencies: - mkdirp-infer-owner "^2.0.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -coa@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" - integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== - dependencies: - "@types/q" "^1.5.1" - chalk "^2.4.1" - q "^1.1.2" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -collect-v8-coverage@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" - integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@^1.1.4, color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colord@^2.9.1: - version "2.9.2" - resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1" - integrity sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ== - -colorette@^2.0.10, colorette@^2.0.16: - version "2.0.16" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" - integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== - -colors@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== - -columnify@^1.5.4: - version "1.5.4" - resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" - integrity sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs= - dependencies: - strip-ansi "^3.0.0" - wcwidth "^1.0.0" - -combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -commander@^2.19.0, commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== - -commander@^6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" - integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== - -commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -commander@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - -common-path-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" - integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w== - -common-tags@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" - integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -compare-func@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3" - integrity sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA== - dependencies: - array-ify "^1.0.0" - dot-prop "^5.1.0" - -compressible@~2.0.14, compressible@~2.0.16: - version "2.0.17" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1" - integrity sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw== - dependencies: - mime-db ">= 1.40.0 < 2" - -compression@1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.3.tgz#27e0e176aaf260f7f2c2813c3e440adb9f1993db" - integrity sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg== - dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.14" - debug "2.6.9" - on-headers "~1.0.1" - safe-buffer "5.1.2" - vary "~1.1.2" - -compression@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - 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" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -concat-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1" - integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.0.2" - typedarray "^0.0.6" - -config-chain@^1.1.12: - version "1.1.13" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4" - integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ== - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - -confusing-browser-globals@^1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" - integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== - -connect-history-api-fallback@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== - -connected-react-router@^6.9.1: - version "6.9.1" - resolved "https://registry.yarnpkg.com/connected-react-router/-/connected-react-router-6.9.1.tgz#d842eebaa15b9920e2e45fc03d74e41110e94e4c" - integrity sha512-BbtB6t0iqAwGwygDenJl9zmlk7vpKWIRSycULmkAOn2RUaF6+bqETprl0qcIqQmY5CTqSwKanaxkLXYWiffAfQ== - dependencies: - lodash.isequalwith "^4.4.0" - prop-types "^15.7.2" - optionalDependencies: - immutable "^3.8.1 || ^4.0.0-rc.1" - seamless-immutable "^7.1.3" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -content-disposition@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= - -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== - dependencies: - safe-buffer "5.1.2" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -conventional-changelog-angular@^5.0.12: - version "5.0.13" - resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz#896885d63b914a70d4934b59d2fe7bde1832b28c" - integrity sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA== - dependencies: - compare-func "^2.0.0" - q "^1.5.1" - -conventional-changelog-core@^4.2.2: - version "4.2.4" - resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz#e50d047e8ebacf63fac3dc67bf918177001e1e9f" - integrity sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg== - dependencies: - add-stream "^1.0.0" - conventional-changelog-writer "^5.0.0" - conventional-commits-parser "^3.2.0" - dateformat "^3.0.0" - get-pkg-repo "^4.0.0" - git-raw-commits "^2.0.8" - git-remote-origin-url "^2.0.0" - git-semver-tags "^4.1.1" - lodash "^4.17.15" - normalize-package-data "^3.0.0" - q "^1.5.1" - read-pkg "^3.0.0" - read-pkg-up "^3.0.0" - through2 "^4.0.0" - -conventional-changelog-preset-loader@^2.3.4: - version "2.3.4" - resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz#14a855abbffd59027fd602581f1f34d9862ea44c" - integrity sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g== - -conventional-changelog-writer@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz#c4042f3f1542f2f41d7d2e0d6cad23aba8df8eec" - integrity sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g== - dependencies: - conventional-commits-filter "^2.0.7" - dateformat "^3.0.0" - handlebars "^4.7.6" - json-stringify-safe "^5.0.1" - lodash "^4.17.15" - meow "^8.0.0" - semver "^6.0.0" - split "^1.0.0" - through2 "^4.0.0" - -conventional-commits-filter@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz#f8d9b4f182fce00c9af7139da49365b136c8a0b3" - integrity sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA== - dependencies: - lodash.ismatch "^4.4.0" - modify-values "^1.0.0" - -conventional-commits-parser@^3.2.0: - version "3.2.3" - resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.3.tgz#fc43704698239451e3ef35fd1d8ed644f46bd86e" - integrity sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw== - dependencies: - JSONStream "^1.0.4" - is-text-path "^1.0.1" - lodash "^4.17.15" - meow "^8.0.0" - split2 "^3.0.0" - through2 "^4.0.0" - -conventional-recommended-bump@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz#cfa623285d1de554012f2ffde70d9c8a22231f55" - integrity sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw== - dependencies: - concat-stream "^2.0.0" - conventional-changelog-preset-loader "^2.3.4" - conventional-commits-filter "^2.0.7" - conventional-commits-parser "^3.2.0" - git-raw-commits "^2.0.8" - git-semver-tags "^4.1.1" - meow "^8.0.0" - q "^1.5.1" - -convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - -core-js-compat@^3.20.2, core-js-compat@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.0.tgz#bcc86aa5a589cee358e7a7fa0a4979d5a76c3885" - integrity sha512-OSXseNPSK2OPJa6GdtkMz/XxeXx8/CJvfhQWTqd6neuUraujcL4jVsjkLQz1OWnax8xVQJnRPe0V2jqNWORA+A== - dependencies: - browserslist "^4.19.1" - semver "7.0.0" - -core-js-compat@^3.8.0: - version "3.8.3" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.3.tgz#9123fb6b9cad30f0651332dc77deba48ef9b0b3f" - integrity sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog== - dependencies: - browserslist "^4.16.1" - semver "7.0.0" - -core-js-pure@^3.0.0: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" - integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== - -core-js-pure@^3.8.1: - version "3.21.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.0.tgz#819adc8dfb808205ce25b51d50591becd615db7e" - integrity sha512-VaJUunCZLnxuDbo1rNOzwbet9E1K9joiXS5+DQMPtgxd24wfsZbJZMMfQLGYMlCUvSxLfsRUUhoOR2x28mFfeg== - -core-js@^3.19.2: - version "3.21.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.0.tgz#f479dbfc3dffb035a0827602dd056839a774aa71" - integrity sha512-YUdI3fFu4TF/2WykQ2xzSiTQdldLB4KVuL9WeAy5XONZYt5Cun/fpQvctoKbCgvPhmzADeesTk/j2Rdx77AcKQ== - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cosmiconfig-typescript-loader@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-1.0.1.tgz#b24b6d0452c68245b75cefae5164b59520cc1213" - integrity sha512-At4Ms7dDDxhfCLCg5D4HDO+B/7hl8mLZs+cjtbNIAb3sv+g7Piu1ryR5K9MpmWUVZkoCXN4mck9vx8ITcqfdvQ== - dependencies: - cosmiconfig "^7" - ts-node "^10.4.0" - -cosmiconfig@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" - integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.1.0" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.7.2" - -cosmiconfig@^7, cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" - integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== - 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" - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -cross-env@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" - integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== - dependencies: - cross-spawn "^7.0.1" - -cross-fetch@3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" - integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== - dependencies: - node-fetch "2.6.7" - -cross-spawn@^6.0.0: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -crypto-random-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" - integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== - -css-blank-pseudo@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz#36523b01c12a25d812df343a32c322d2a2324561" - integrity sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ== - dependencies: - postcss-selector-parser "^6.0.9" - -css-declaration-sorter@^6.0.3: - version "6.1.4" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz#b9bfb4ed9a41f8dcca9bf7184d849ea94a8294b4" - integrity sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw== - dependencies: - timsort "^0.3.0" - -css-has-pseudo@^3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz#57f6be91ca242d5c9020ee3e51bbb5b89fc7af73" - integrity sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw== - dependencies: - postcss-selector-parser "^6.0.9" - -css-loader@^6.5.1: - version "6.6.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.6.0.tgz#c792ad5510bd1712618b49381bd0310574fafbd3" - integrity sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg== - dependencies: - icss-utils "^5.1.0" - postcss "^8.4.5" - 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.2.0" - semver "^7.3.5" - -css-minimizer-webpack-plugin@^3.2.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz#ab78f781ced9181992fe7b6e4f3422e76429878f" - integrity sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q== - dependencies: - cssnano "^5.0.6" - jest-worker "^27.0.2" - postcss "^8.3.5" - schema-utils "^4.0.0" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - -css-prefers-color-scheme@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz#ca8a22e5992c10a5b9d315155e7caee625903349" - integrity sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA== - -css-select-base-adapter@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" - integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== - -css-select@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" - integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== - dependencies: - boolbase "^1.0.0" - css-what "^3.2.1" - domutils "^1.7.0" - nth-check "^1.0.2" - -css-select@^4.1.3: - version "4.2.1" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" - integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ== - dependencies: - boolbase "^1.0.0" - css-what "^5.1.0" - domhandler "^4.3.0" - domutils "^2.8.0" - nth-check "^2.0.1" - -css-select@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= - dependencies: - boolbase "~1.0.0" - css-what "2.1" - domutils "1.5.1" - nth-check "~1.0.1" - -css-tree@1.0.0-alpha.37: - version "1.0.0-alpha.37" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" - integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== - dependencies: - mdn-data "2.0.4" - source-map "^0.6.1" - -css-tree@^1.1.2, css-tree@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" - integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== - dependencies: - mdn-data "2.0.14" - source-map "^0.6.1" - -css-vendor@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/css-vendor/-/css-vendor-2.0.8.tgz#e47f91d3bd3117d49180a3c935e62e3d9f7f449d" - integrity sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ== - dependencies: - "@babel/runtime" "^7.8.3" - is-in-browser "^1.0.2" - -css-what@2.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" - integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== - -css-what@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" - integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== - -css-what@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" - integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== - -cssdb@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-6.2.0.tgz#dea14422e3084b9e2da54d439e310a46e9e36107" - integrity sha512-OP1owHiK7IkCPSmNvWGMOEbfMcPZ8HA1TkzUXzB2SA708Y4pFGXWtLAVxds2QJI/0FA3mCNwRkEA9B4U4fW2Dw== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -cssnano-preset-default@^5.1.12: - version "5.1.12" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.1.12.tgz#64e2ad8e27a279e1413d2d2383ef89a41c909be9" - integrity sha512-rO/JZYyjW1QNkWBxMGV28DW7d98UDLaF759frhli58QFehZ+D/LSmwQ2z/ylBAe2hUlsIWTq6NYGfQPq65EF9w== - dependencies: - css-declaration-sorter "^6.0.3" - cssnano-utils "^3.0.2" - postcss-calc "^8.2.0" - postcss-colormin "^5.2.5" - postcss-convert-values "^5.0.4" - postcss-discard-comments "^5.0.3" - postcss-discard-duplicates "^5.0.3" - postcss-discard-empty "^5.0.3" - postcss-discard-overridden "^5.0.4" - postcss-merge-longhand "^5.0.6" - postcss-merge-rules "^5.0.6" - postcss-minify-font-values "^5.0.4" - postcss-minify-gradients "^5.0.6" - postcss-minify-params "^5.0.5" - postcss-minify-selectors "^5.1.3" - postcss-normalize-charset "^5.0.3" - postcss-normalize-display-values "^5.0.3" - postcss-normalize-positions "^5.0.4" - postcss-normalize-repeat-style "^5.0.4" - postcss-normalize-string "^5.0.4" - postcss-normalize-timing-functions "^5.0.3" - postcss-normalize-unicode "^5.0.4" - postcss-normalize-url "^5.0.5" - postcss-normalize-whitespace "^5.0.4" - postcss-ordered-values "^5.0.5" - postcss-reduce-initial "^5.0.3" - postcss-reduce-transforms "^5.0.4" - postcss-svgo "^5.0.4" - postcss-unique-selectors "^5.0.4" - -cssnano-utils@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.0.2.tgz#d82b4991a27ba6fec644b39bab35fe027137f516" - integrity sha512-KhprijuQv2sP4kT92sSQwhlK3SJTbDIsxcfIEySB0O+3m9esFOai7dP9bMx5enHAh2MwarVIcnwiWoOm01RIbQ== - -cssnano@^5.0.6: - version "5.0.17" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.17.tgz#ff45713c05cfc780a1aeb3e663b6f224d091cabf" - integrity sha512-fmjLP7k8kL18xSspeXTzRhaFtRI7DL9b8IcXR80JgtnWBpvAzHT7sCR/6qdn0tnxIaINUN6OEQu83wF57Gs3Xw== - dependencies: - cssnano-preset-default "^5.1.12" - lilconfig "^2.0.3" - yaml "^1.10.2" - -csso@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d" - integrity sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg== - dependencies: - css-tree "1.0.0-alpha.37" - -csso@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== - dependencies: - css-tree "^1.1.2" - -cssom@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" - integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== - -cssom@~0.3.6: - version "0.3.8" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" - integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== - -cssstyle@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" - integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== - dependencies: - cssom "~0.3.6" - -csstype@^2.5.2: - version "2.6.7" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5" - integrity sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ== - -csstype@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.2.tgz#ee5ff8f208c8cd613b389f7b222c9801ca62b3f7" - integrity sha512-ofovWglpqoqbfLNOTBNZLSbMuGrblAf1efvvArGKOZMBrIoJeu5UsAipQolkijtyQx5MtAzT/J9IHj/CEY1mJw== - -custom-event-polyfill@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz#9bc993ddda937c1a30ccd335614c6c58c4f87aee" - integrity sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w== - -cypress-failed-log@^2.9.1: - version "2.9.1" - resolved "https://registry.yarnpkg.com/cypress-failed-log/-/cypress-failed-log-2.9.1.tgz#8a5f0779ee58d40dbd93047d47938da14300fd0e" - integrity sha512-mQABpDZNaUeHl7Ex82cfp5PgDVRiBRU+Hy3/nMZOiTlJeNGDd2m+3sGRGOtl8irObhO9mA0n6alOjzhgpNVUbg== - dependencies: - debug "4.3.1" - logdown "3.3.1" - -cypress@9.5.1: - version "9.5.1" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-9.5.1.tgz#51162f3688cedf5ffce311b914ef49a7c1ece076" - integrity sha512-H7lUWB3Svr44gz1rNnj941xmdsCljXoJa2cDneAltjI9leKLMQLm30x6jLlpQ730tiVtIbW5HdUmBzPzwzfUQg== - dependencies: - "@cypress/request" "^2.88.10" - "@cypress/xvfb" "^1.2.4" - "@types/node" "^14.14.31" - "@types/sinonjs__fake-timers" "8.1.1" - "@types/sizzle" "^2.3.2" - arch "^2.2.0" - blob-util "^2.0.2" - bluebird "^3.7.2" - buffer "^5.6.0" - cachedir "^2.3.0" - chalk "^4.1.0" - check-more-types "^2.24.0" - cli-cursor "^3.1.0" - cli-table3 "~0.6.1" - commander "^5.1.0" - common-tags "^1.8.0" - dayjs "^1.10.4" - debug "^4.3.2" - enquirer "^2.3.6" - eventemitter2 "^6.4.3" - execa "4.1.0" - executable "^4.1.1" - extract-zip "2.0.1" - figures "^3.2.0" - fs-extra "^9.1.0" - getos "^3.2.1" - is-ci "^3.0.0" - is-installed-globally "~0.4.0" - lazy-ass "^1.6.0" - listr2 "^3.8.3" - lodash "^4.17.21" - log-symbols "^4.0.0" - minimist "^1.2.5" - ospath "^1.2.2" - pretty-bytes "^5.6.0" - proxy-from-env "1.0.0" - request-progress "^3.0.0" - semver "^7.3.2" - supports-color "^8.1.1" - tmp "~0.2.1" - untildify "^4.0.0" - yauzl "^2.10.0" - -damerau-levenshtein@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d" - integrity sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw== - -dargs@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" - integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg== - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -data-urls@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" - integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== - dependencies: - abab "^2.0.3" - whatwg-mimetype "^2.3.0" - whatwg-url "^8.0.0" - -date-fns-tz@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/date-fns-tz/-/date-fns-tz-1.1.6.tgz#93cbf354e2aeb2cd312ffa32e462c1943cf20a8e" - integrity sha512-nyy+URfFI3KUY7udEJozcoftju+KduaqkVfwyTIE0traBiVye09QnyWKLZK7drRr5h9B7sPJITmQnS3U6YOdQg== - -date-fns@^2.28.0: - version "2.28.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.28.0.tgz#9570d656f5fc13143e50c975a3b6bbeb46cd08b2" - integrity sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw== - -dateformat@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" - integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== - -dayjs@^1.10.4: - version "1.10.8" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.8.tgz#267df4bc6276fcb33c04a6735287e3f429abec41" - integrity sha512-wbNwDfBHHur9UOzNUjeKUOJ0fCb0a52Wx0xInmQ7Y8FstyajiV1NmK1e00cxsr9YrE9r7yAChE0VvpuY5Rnlow== - -debug@2.6.9, debug@^2.6.0, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -debug@4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" - integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== - dependencies: - ms "2.1.2" - -debug@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== - dependencies: - ms "2.1.2" - -debug@^3.1.0, debug@^3.1.1, debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debuglog@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" - integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= - -decamelize-keys@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" - integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= - dependencies: - decamelize "^1.1.0" - map-obj "^1.0.0" - -decamelize@^1.1.0, decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decimal.js@^10.2.1: - version "10.3.1" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" - integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== - -dedent@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" - integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= - -deep-diff@^0.3.5: - version "0.3.8" - resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84" - integrity sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ= - -deep-equal@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deep-is@^0.1.3, deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== - -default-gateway@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" - integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== - dependencies: - execa "^5.0.0" - -defaults@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= - dependencies: - clone "^1.0.2" - -define-lazy-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" - integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== - -define-properties@^1.1.2, define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -defined@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= - -del@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" - 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" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -depd@^1.1.2, depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -deprecation@^2.0.0, deprecation@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" - integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== - -dequal@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.2.tgz#85ca22025e3a87e65ef75a7a437b35284a7e319d" - integrity sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug== - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -detect-indent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" - integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= - -detect-indent@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" - integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== - -detect-newline@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - -detect-node@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" - integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== - -detect-node@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" - integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== - -detect-port-alt@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275" - integrity sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q== - dependencies: - address "^1.0.1" - debug "^2.6.0" - -detective@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" - integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg== - dependencies: - acorn-node "^1.6.1" - defined "^1.0.0" - minimist "^1.1.1" - -dezalgo@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" - integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY= - dependencies: - asap "^2.0.0" - wrappy "1" - -didyoumean@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" - integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== - -diff-sequences@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" - integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -discontinuous-range@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" - integrity sha1-44Mx8IRLukm5qctxx3FYWqsbxlo= - -dlv@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" - integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== - -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= - -dns-packet@^1.3.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" - integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== - dependencies: - ip "^1.1.0" - safe-buffer "^5.0.1" - -dns-txt@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" - integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= - dependencies: - buffer-indexof "^1.0.0" - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dom-converter@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" - integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== - dependencies: - utila "~0.4" - -dom-helpers@^5.0.1, dom-helpers@^5.1.3: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.0.tgz#57fd054c5f8f34c52a3eeffdb7e7e93cd357d95b" - integrity sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ== - dependencies: - "@babel/runtime" "^7.8.7" - csstype "^3.0.2" - -dom-serializer@0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -dom-serializer@^1.0.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" - integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.2.0" - entities "^2.0.0" - -dom-serializer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" - integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== - dependencies: - domelementtype "^1.3.0" - entities "^1.1.1" - -domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - -domelementtype@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" - integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== - -domelementtype@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== - -domexception@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" - integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== - dependencies: - webidl-conversions "^5.0.0" - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" - integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== - dependencies: - domelementtype "^2.2.0" - -domutils@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^1.5.1, domutils@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^2.5.2, domutils@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" - integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== - dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - -dot-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" - integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -dot-prop@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" - integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== - dependencies: - is-obj "^2.0.0" - -dot-prop@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083" - integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA== - dependencies: - is-obj "^2.0.0" - -dotenv-expand@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" - integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== - -dotenv@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" - integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== - -duplexer@^0.1.1, duplexer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= - -duplexer@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" - integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -ejs@^3.1.6: - version "3.1.7" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.7.tgz#c544d9c7f715783dd92f0bddcf73a59e6962d006" - integrity sha512-BIar7R6abbUxDA3bfXrO4DSgwo8I+fB5/1zgujl3HLLjwd6+9iOnrT+t3grn2qbk9vOgBubXOFwX2m9axoFaGw== - dependencies: - jake "^10.8.5" - -electron-to-chromium@^1.4.17: - version "1.4.68" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.68.tgz#d79447b6bd1bec9183f166bb33d4bef0d5e4e568" - integrity sha512-cId+QwWrV8R1UawO6b9BR1hnkJ4EJPCPAr4h315vliHUtVUJDk39Sg1PMNnaWKfj5x+93ssjeJ9LKL6r8LaMiA== - -emittery@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" - integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -encoding@^0.1.12: - version "0.1.13" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" - integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== - dependencies: - iconv-lite "^0.6.2" - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -enhanced-resolve@^5.8.3: - version "5.9.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz#49ac24953ac8452ed8fed2ef1340fc8e043667ee" - integrity sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -enquirer@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== - dependencies: - ansi-colors "^4.1.1" - -entities@^1.1.1, entities@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - -entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" - integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== - -env-paths@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0" - integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA= - -env-paths@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" - integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== - -envinfo@^7.7.4: - version "7.8.1" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" - integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== - -enzyme-adapter-react-16@^1.15.6: - version "1.15.6" - resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.6.tgz#fd677a658d62661ac5afd7f7f541f141f8085901" - integrity sha512-yFlVJCXh8T+mcQo8M6my9sPgeGzj85HSHi6Apgf1Cvq/7EL/J9+1JoJmJsRxZgyTvPMAqOEpRSu/Ii/ZpyOk0g== - dependencies: - enzyme-adapter-utils "^1.14.0" - enzyme-shallow-equal "^1.0.4" - has "^1.0.3" - object.assign "^4.1.2" - object.values "^1.1.2" - prop-types "^15.7.2" - react-is "^16.13.1" - react-test-renderer "^16.0.0-0" - semver "^5.7.0" - -enzyme-adapter-utils@^1.14.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.14.0.tgz#afbb0485e8033aa50c744efb5f5711e64fbf1ad0" - integrity sha512-F/z/7SeLt+reKFcb7597IThpDp0bmzcH1E9Oabqv+o01cID2/YInlqHbFl7HzWBl4h3OdZYedtwNDOmSKkk0bg== - dependencies: - airbnb-prop-types "^2.16.0" - function.prototype.name "^1.1.3" - has "^1.0.3" - object.assign "^4.1.2" - object.fromentries "^2.0.3" - prop-types "^15.7.2" - semver "^5.7.1" - -enzyme-shallow-equal@^1.0.1, enzyme-shallow-equal@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.4.tgz#b9256cb25a5f430f9bfe073a84808c1d74fced2e" - integrity sha512-MttIwB8kKxypwHvRynuC3ahyNc+cFbR8mjVIltnmzQ0uKGqmsfO4bfBuLxb0beLNPhjblUEYvEbsg+VSygvF1Q== - dependencies: - has "^1.0.3" - object-is "^1.1.2" - -enzyme-to-json@^3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.6.1.tgz#d60740950bc7ca6384dfe6fe405494ec5df996bc" - integrity sha512-15tXuONeq5ORoZjV/bUo2gbtZrN2IH+Z6DvL35QmZyKHgbY1ahn6wcnLd9Xv9OjiwbAXiiP8MRZwbZrCv1wYNg== - dependencies: - "@types/cheerio" "^0.22.22" - lodash "^4.17.15" - react-is "^16.12.0" - -enzyme@^3.10.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.11.0.tgz#71d680c580fe9349f6f5ac6c775bc3e6b7a79c28" - integrity sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw== - dependencies: - array.prototype.flat "^1.2.3" - cheerio "^1.0.0-rc.3" - enzyme-shallow-equal "^1.0.1" - function.prototype.name "^1.1.2" - has "^1.0.3" - html-element-map "^1.2.0" - is-boolean-object "^1.0.1" - is-callable "^1.1.5" - is-number-object "^1.0.4" - is-regex "^1.0.5" - is-string "^1.0.5" - is-subset "^0.1.1" - lodash.escape "^4.0.1" - lodash.isequal "^4.5.0" - object-inspect "^1.7.0" - object-is "^1.0.2" - object.assign "^4.1.0" - object.entries "^1.1.1" - object.values "^1.1.1" - raf "^3.4.1" - rst-selector-parser "^2.2.3" - string.prototype.trim "^1.2.1" - -err-code@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" - integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -error-stack-parser@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8" - integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ== - dependencies: - stackframe "^1.1.1" - -es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: - version "1.17.5" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" - integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.1.5" - is-regex "^1.0.5" - object-inspect "^1.7.0" - object-keys "^1.1.1" - object.assign "^4.1.0" - string.prototype.trimleft "^2.1.1" - string.prototype.trimright "^2.1.1" - -es-abstract@^1.17.4: - version "1.17.7" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" - integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.2" - is-regex "^1.1.1" - object-inspect "^1.8.0" - object-keys "^1.1.1" - object.assign "^4.1.1" - string.prototype.trimend "^1.0.1" - string.prototype.trimstart "^1.0.1" - -es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2: - version "1.18.0-next.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.2.tgz#088101a55f0541f595e7e057199e27ddc8f3a5c2" - integrity sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.2" - is-negative-zero "^2.0.1" - is-regex "^1.1.1" - object-inspect "^1.9.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.3" - string.prototype.trimstart "^1.0.3" - -es-abstract@^1.18.2: - version "1.18.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.3.tgz#25c4c3380a27aa203c44b2b685bba94da31b63e0" - integrity sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.2" - is-callable "^1.2.3" - is-negative-zero "^2.0.1" - is-regex "^1.1.3" - is-string "^1.0.6" - object-inspect "^1.10.3" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" - -es-abstract@^1.19.0, es-abstract@^1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" - integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.1" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.1" - is-string "^1.0.7" - is-weakref "^1.0.1" - object-inspect "^1.11.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" - -es-abstract@^1.5.1: - version "1.16.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" - integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== - dependencies: - es-to-primitive "^1.2.0" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.0" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-inspect "^1.6.0" - object-keys "^1.1.1" - string.prototype.trimleft "^2.1.0" - string.prototype.trimright "^2.1.0" - -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== - -es-to-primitive@^1.2.0, es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -escodegen@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" - integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== - dependencies: - esprima "^4.0.1" - estraverse "^5.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -eslint-config-prettier@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" - integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew== - -eslint-config-react-app@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-7.0.0.tgz#0fa96d5ec1dfb99c029b1554362ab3fa1c3757df" - integrity sha512-xyymoxtIt1EOsSaGag+/jmcywRuieQoA2JbPCjnw9HukFj9/97aGPoZVFioaotzk1K5Qt9sHO5EutZbkrAXS0g== - dependencies: - "@babel/core" "^7.16.0" - "@babel/eslint-parser" "^7.16.3" - "@rushstack/eslint-patch" "^1.1.0" - "@typescript-eslint/eslint-plugin" "^5.5.0" - "@typescript-eslint/parser" "^5.5.0" - babel-preset-react-app "^10.0.1" - confusing-browser-globals "^1.0.11" - eslint-plugin-flowtype "^8.0.3" - eslint-plugin-import "^2.25.3" - eslint-plugin-jest "^25.3.0" - eslint-plugin-jsx-a11y "^6.5.1" - eslint-plugin-react "^7.27.1" - eslint-plugin-react-hooks "^4.3.0" - eslint-plugin-testing-library "^5.0.1" - -eslint-import-resolver-node@^0.3.6: - version "0.3.6" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" - integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== - dependencies: - debug "^3.2.7" - resolve "^1.20.0" - -eslint-module-utils@^2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz#b435001c9f8dd4ab7f6d0efcae4b9696d4c24b7c" - integrity sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ== - dependencies: - debug "^3.2.7" - find-up "^2.1.0" - pkg-dir "^2.0.0" - -eslint-plugin-cypress@^2.12.1: - version "2.12.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.12.1.tgz#9aeee700708ca8c058e00cdafe215199918c2632" - integrity sha512-c2W/uPADl5kospNDihgiLc7n87t5XhUbFDoTl6CfVkmG+kDAb5Ux10V9PoLPu9N+r7znpc+iQlcmAqT1A/89HA== - dependencies: - globals "^11.12.0" - -eslint-plugin-flowtype@^8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz#e1557e37118f24734aa3122e7536a038d34a4912" - integrity sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ== - dependencies: - lodash "^4.17.21" - string-natural-compare "^3.0.1" - -eslint-plugin-import@^2.25.3: - version "2.25.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz#a554b5f66e08fb4f6dc99221866e57cfff824766" - integrity sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg== - dependencies: - array-includes "^3.1.4" - array.prototype.flat "^1.2.5" - debug "^2.6.9" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.6" - eslint-module-utils "^2.7.1" - has "^1.0.3" - is-core-module "^2.8.0" - is-glob "^4.0.3" - minimatch "^3.0.4" - object.values "^1.1.5" - resolve "^1.20.0" - tsconfig-paths "^3.11.0" - -eslint-plugin-jest@^25.3.0: - version "25.7.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz#ff4ac97520b53a96187bad9c9814e7d00de09a6a" - integrity sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ== - dependencies: - "@typescript-eslint/experimental-utils" "^5.0.0" - -eslint-plugin-jsx-a11y@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz#cdbf2df901040ca140b6ec14715c988889c2a6d8" - integrity sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g== - dependencies: - "@babel/runtime" "^7.16.3" - aria-query "^4.2.2" - array-includes "^3.1.4" - ast-types-flow "^0.0.7" - axe-core "^4.3.5" - axobject-query "^2.2.0" - damerau-levenshtein "^1.0.7" - emoji-regex "^9.2.2" - has "^1.0.3" - jsx-ast-utils "^3.2.1" - language-tags "^1.0.5" - minimatch "^3.0.4" - -eslint-plugin-prettier@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz#7079cfa2497078905011e6f82e8dd8453d1371b7" - integrity sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ== - dependencies: - prettier-linter-helpers "^1.0.0" - -eslint-plugin-react-hooks@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172" - integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA== - -eslint-plugin-react@^7.27.1: - version "7.28.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.28.0.tgz#8f3ff450677571a659ce76efc6d80b6a525adbdf" - integrity sha512-IOlFIRHzWfEQQKcAD4iyYDndHwTQiCMcJVJjxempf203jnNLUnW34AXLrV33+nEXoifJE2ZEGmcjKPL8957eSw== - dependencies: - array-includes "^3.1.4" - array.prototype.flatmap "^1.2.5" - doctrine "^2.1.0" - estraverse "^5.3.0" - jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.0.4" - object.entries "^1.1.5" - object.fromentries "^2.0.5" - object.hasown "^1.1.0" - object.values "^1.1.5" - prop-types "^15.7.2" - resolve "^2.0.0-next.3" - semver "^6.3.0" - string.prototype.matchall "^4.0.6" - -eslint-plugin-testing-library@^5.0.1: - version "5.0.5" - resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.0.5.tgz#5757961ec20a6ca8b0992d2c5487db1b51612d8d" - integrity sha512-0j355vJpJCE/2g+aayIgJRUB6jBVqpD5ztMLGcadR1PgrgGPnPxN1HJuOAsAAwiMo27GwRnpJB8KOQzyNuNZrw== - dependencies: - "@typescript-eslint/utils" "^5.10.2" - -eslint-scope@5.1.1, eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== - -eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== - -eslint-webpack-plugin@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-3.1.1.tgz#83dad2395e5f572d6f4d919eedaa9cf902890fcb" - integrity sha512-xSucskTN9tOkfW7so4EaiFIkulWLXwCB/15H917lR6pTv0Zot6/fetFucmENRb7J5whVSFKIvwnrnsa78SG2yg== - dependencies: - "@types/eslint" "^7.28.2" - jest-worker "^27.3.1" - micromatch "^4.0.4" - normalize-path "^3.0.0" - schema-utils "^3.1.1" - -eslint@^8.3.0, eslint@^8.9.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.9.0.tgz#a2a8227a99599adc4342fd9b854cb8d8d6412fdb" - integrity sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q== - dependencies: - "@eslint/eslintrc" "^1.1.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" - -espree@^9.3.1: - version "9.3.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd" - integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ== - dependencies: - acorn "^8.7.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^3.3.0" - -esprima@^4.0.0, esprima@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== - -estraverse@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -estree-walker@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" - integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -event-stream@=3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.3" - stream-combiner "~0.0.4" - through "~2.3.1" - -eventemitter2@^6.4.3: - version "6.4.5" - resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.5.tgz#97380f758ae24ac15df8353e0cc27f8b95644655" - integrity sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw== - -eventemitter3@^4.0.0, eventemitter3@^4.0.4: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -execa@4.1.0, execa@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" - integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== - dependencies: - cross-spawn "^7.0.0" - get-stream "^5.0.0" - human-signals "^1.1.1" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.0" - onetime "^5.1.0" - signal-exit "^3.0.2" - strip-final-newline "^2.0.0" - -execa@5.1.1, execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - 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" - -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -executable@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" - integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== - dependencies: - pify "^2.2.0" - -execution-time@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/execution-time/-/execution-time-1.3.0.tgz#39ea4eb7feac903024b166ab0a7065cc87080aee" - integrity sha512-r0cFNI/v6XMK7sipeJ23DwL2EvRro8T8JaVAAn+LbvctYTQ/gBhbTw/6FnC8pBXMgcvJ4Q8o3hNlAzUgE2R0yg== - dependencies: - pretty-hrtime "^1.0.3" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= - -expect@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74" - integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw== - dependencies: - "@jest/types" "^27.5.1" - jest-get-type "^27.5.1" - jest-matcher-utils "^27.5.1" - jest-message-util "^27.5.1" - -express@^4.17.1: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - 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.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -extract-zip@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" - integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== - dependencies: - debug "^4.1.1" - get-stream "^5.1.0" - yauzl "^2.10.0" - optionalDependencies: - "@types/yauzl" "^2.9.1" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - -fast-glob@^3.1.1: - version "3.2.5" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661" - 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" - -fast-glob@^3.2.11: - version "3.2.11" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" - integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= - -fast-json-stable-stringify@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -fast-url-parser@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" - integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= - dependencies: - punycode "^1.3.2" - -fastq@^1.6.0: - version "1.10.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.10.1.tgz#8b8f2ac8bf3632d67afcd65dac248d5fdc45385e" - integrity sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA== - dependencies: - reusify "^1.0.4" - -faye-websocket@^0.11.3: - version "0.11.3" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" - integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== - dependencies: - websocket-driver ">=0.5.1" - -fb-watchman@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" - integrity sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg= - dependencies: - bser "^2.0.0" - -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= - dependencies: - pend "~1.2.0" - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= - dependencies: - escape-string-regexp "^1.0.5" - -figures@^3.0.0, figures@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -file-loader@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" - integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - -filelist@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.3.tgz#448607750376484932f67ef1b9ff07386b036c83" - integrity sha512-LwjCsruLWQULGYKy7TX0OPtrL9kLpojOFKc5VCTxdFTV7w5zbsgqVKfnkKG7Qgjtq50gKfO56hJv88OfcGb70Q== - dependencies: - minimatch "^5.0.1" - -filesize@^8.0.6: - version "8.0.7" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8" - integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ== - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - 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" - -find-cache-dir@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" - integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flatted@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" - integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== - -follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.8: - version "1.14.8" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" - integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA== - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -fork-ts-checker-webpack-plugin@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e" - integrity sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw== - dependencies: - "@babel/code-frame" "^7.8.3" - "@types/json-schema" "^7.0.5" - chalk "^4.1.0" - chokidar "^3.4.2" - cosmiconfig "^6.0.0" - deepmerge "^4.2.2" - fs-extra "^9.0.0" - glob "^7.1.6" - memfs "^3.1.2" - minimatch "^3.0.4" - schema-utils "2.7.0" - semver "^7.3.2" - tapable "^1.0.0" - -form-data@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - -fraction.js@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.3.tgz#be65b0f20762ef27e1e793860bc2dfb716e99e65" - integrity sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -from@~0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= - -fs-extra@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" - integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-extra@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-minipass@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== - dependencies: - minipass "^2.6.0" - -fs-minipass@^2.0.0, fs-minipass@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" - integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== - dependencies: - minipass "^3.0.0" - -fs-monkey@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" - integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^2.3.2, fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -function.prototype.name@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.2.tgz#5cdf79d7c05db401591dfde83e3b70c5123e9a45" - integrity sha512-C8A+LlHBJjB2AdcRPorc5JvJ5VUoWlXdEHLOJdCI7kjHEtGTpHQUiqMvCIKUwIsGwZX2jZJy761AXsn356bJQg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - functions-have-names "^1.2.0" - -function.prototype.name@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.3.tgz#0bb034bb308e7682826f215eb6b2ae64918847fe" - integrity sha512-H51qkbNSp8mtkJt+nyW1gyStBiKZxfRqySNUR99ylq6BPXHKI4SEvIlTKp4odLfjRKJV04DFWMU3G/YRlQOsag== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" - functions-have-names "^1.2.1" - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= - -functions-have-names@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.1.tgz#a981ac397fa0c9964551402cdc5533d7a4d52f91" - integrity sha512-j48B/ZI7VKs3sgeI2cZp7WXWmZXu7Iq5pl5/vptV5N2mq+DGFuS/ulaDjtaoLpYzuD6u8UgrUKHfgo7fDTSiBA== - -functions-have-names@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.2.tgz#98d93991c39da9361f8e50b337c4f6e41f120e21" - integrity sha512-bLgc3asbWdwPbx2mNk2S49kmJCuQeu0nfmaOgbs8WIyzzkw3r4htszdIi9Q9EMezDPTYuJx2wvjZ/EwgAthpnA== - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - 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" - -gensync@^1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" - integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-own-enumerable-property-symbols@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.1.tgz#6f7764f88ea11e0b514bd9bd860a132259992ca4" - integrity sha512-09/VS4iek66Dh2bctjRkowueRJbY1JDGR1L/zRxO1Qk8Uxs6PnqaNSqalpizPT+CDjre3hnEsuzvhgomz9qYrA== - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-pkg-repo@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz#75973e1c8050c73f48190c52047c4cee3acbf385" - integrity sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA== - dependencies: - "@hutson/parse-repository-url" "^3.0.0" - hosted-git-info "^4.0.0" - through2 "^2.0.0" - yargs "^16.2.0" - -get-port@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" - integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== - -get-stream@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" - integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -getos@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5" - integrity sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q== - dependencies: - async "^3.2.0" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -git-raw-commits@^2.0.8: - version "2.0.10" - resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.10.tgz#e2255ed9563b1c9c3ea6bd05806410290297bbc1" - integrity sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ== - dependencies: - dargs "^7.0.0" - lodash "^4.17.15" - meow "^8.0.0" - split2 "^3.0.0" - through2 "^4.0.0" - -git-remote-origin-url@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f" - integrity sha1-UoJlna4hBxRaERJhEq0yFuxfpl8= - dependencies: - gitconfiglocal "^1.0.0" - pify "^2.3.0" - -git-semver-tags@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-4.1.1.tgz#63191bcd809b0ec3e151ba4751c16c444e5b5780" - integrity sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA== - dependencies: - meow "^8.0.0" - semver "^6.0.0" - -git-up@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.1.tgz#cb2ef086653640e721d2042fe3104857d89007c0" - integrity sha512-LFTZZrBlrCrGCG07/dm1aCjjpL1z9L3+5aEeI9SBhAqSc+kiA9Or1bgZhQFNppJX6h/f5McrvJt1mQXTFm6Qrw== - dependencies: - is-ssh "^1.3.0" - parse-url "^5.0.0" - -git-url-parse@^11.4.4: - version "11.6.0" - resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-11.6.0.tgz#c634b8de7faa66498a2b88932df31702c67df605" - integrity sha512-WWUxvJs5HsyHL6L08wOusa/IXYtMuCAhrMmnTjQPpBU0TTHyDhnOATNH3xNQz7YOQUsqIIPTGr4xiVti1Hsk5g== - dependencies: - git-up "^4.0.0" - -gitconfiglocal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b" - integrity sha1-QdBF84UaXqiPA/JMocYXgRRGS5s= - dependencies: - ini "^1.3.2" - -glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.1, glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global-dirs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" - integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== - dependencies: - ini "2.0.0" - -global-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - -global-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" - integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== - dependencies: - ini "^1.3.5" - kind-of "^6.0.2" - which "^1.3.1" - -globals@^11.1.0, globals@^11.12.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.6.0, globals@^13.9.0: - version "13.12.1" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.1.tgz#ec206be932e6c77236677127577aa8e50bf1c5cb" - integrity sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw== - dependencies: - type-fest "^0.20.2" - -globby@^11.0.1, globby@^11.0.2, globby@^11.0.4: - version "11.0.4" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" - 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" - -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" - integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== - -graceful-fs@^4.2.3: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== - -graceful-fs@^4.2.4: - version "4.2.5" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.5.tgz#bc18864a6c9fc7b303f2e2abdb9155ad178fbe29" - integrity sha512-kBBSQbz2K0Nyn+31j/w36fUfxkBW9/gfwRWdUY1ULReH3iokVJgddZAFcD1D0xlgTmFxJCbUkUclAlc6/IDJkw== - -graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== - -gzip-size@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" - integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== - dependencies: - duplexer "^0.1.2" - -handle-thing@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" - integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ== - -handlebars@^4.7.6: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== - dependencies: - minimist "^1.2.5" - neo-async "^2.6.0" - source-map "^0.6.1" - wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.0, har-validator@~5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== - dependencies: - ajv "^6.5.5" - har-schema "^2.0.0" - -hard-rejection@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" - integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== - -harmony-reflect@^1.4.6: - version "1.6.1" - resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.1.tgz#c108d4f2bb451efef7a37861fdbdae72c9bdefa9" - integrity sha512-WJTeyp0JzGtHcuMsi7rw2VwtkvLa+JyfEKJCFyfcS0+CDkjQ5lHPu7zEhFZP+PDSRrEgXa5Ah0l1MbgbE41XjA== - -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbols@^1.0.0, has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== - -has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has-unicode@^2.0.0, has-unicode@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -he@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -hex-to-rgba@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/hex-to-rgba/-/hex-to-rgba-2.0.1.tgz#4176977882a1cb32b83ce5ab1db6828ab84d5a13" - integrity sha512-5XqPJBpsEUMsseJUi2w2Hl7cHFFi3+OO10M2pzAvKB1zL6fc+koGMhmBqoDOCB4GemiRM/zvDMRIhVw6EkB8dQ== - -history@^4.10.1, history@^4.9.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" - integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== - dependencies: - "@babel/runtime" "^7.1.2" - loose-envify "^1.2.0" - resolve-pathname "^3.0.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - value-equal "^1.0.1" - -hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" - integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== - dependencies: - react-is "^16.7.0" - -hoopy@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" - integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== - -hosted-git-info@^2.1.4: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - -hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.2.tgz#5e425507eede4fea846b7262f0838456c4209961" - integrity sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg== - dependencies: - lru-cache "^6.0.0" - -hpack.js@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= - dependencies: - inherits "^2.0.1" - obuf "^1.0.0" - readable-stream "^2.0.1" - wbuf "^1.1.0" - -html-element-map@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/html-element-map/-/html-element-map-1.2.0.tgz#dfbb09efe882806af63d990cf6db37993f099f22" - integrity sha512-0uXq8HsuG1v2TmQ8QkIhzbrqeskE4kn52Q18QJ9iAA/SnHoEKXWiUxHQtclRsCFWEUD2So34X+0+pZZu862nnw== - dependencies: - array-filter "^1.0.0" - -html-encoding-sniffer@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" - integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== - dependencies: - whatwg-encoding "^1.0.5" - -html-entities@^2.1.0, html-entities@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488" - integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ== - -html-escaper@^2.0.0, html-escaper@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -html-minifier-terser@^6.0.2: - version "6.1.0" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" - integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== - dependencies: - camel-case "^4.1.2" - clean-css "^5.2.2" - commander "^8.3.0" - he "^1.2.0" - param-case "^3.0.4" - relateurl "^0.2.7" - terser "^5.10.0" - -html-parse-stringify@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2" - integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg== - dependencies: - void-elements "3.1.0" - -html-webpack-plugin@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" - integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== - dependencies: - "@types/html-minifier-terser" "^6.0.0" - html-minifier-terser "^6.0.2" - lodash "^4.17.21" - pretty-error "^4.0.0" - tapable "^2.0.0" - -htmlparser2@^3.9.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - -htmlparser2@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" - integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.0.0" - domutils "^2.5.2" - entities "^2.0.0" - -http-cache-semantics@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - -http-deceiver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= - -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -"http-parser-js@>=0.4.0 <0.4.11": - version "0.4.10" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" - integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= - -http-parser-js@>=0.5.1: - version "0.5.3" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" - integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== - -http-proxy-agent@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" - integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== - dependencies: - "@tootallnate/once" "1" - agent-base "6" - debug "4" - -http-proxy-middleware@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz#5df04f69a89f530c2284cd71eeaa51ba52243289" - 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" - -http-proxy@^1.18.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -http-signature@~1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9" - integrity sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw== - dependencies: - assert-plus "^1.0.0" - jsprim "^2.0.2" - sshpk "^1.14.1" - -https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== - dependencies: - agent-base "6" - debug "4" - -human-signals@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" - integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -humanize-ms@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" - integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0= - dependencies: - ms "^2.0.0" - -husky@^7.0.4: - version "7.0.4" - resolved "https://registry.yarnpkg.com/husky/-/husky-7.0.4.tgz#242048245dc49c8fb1bf0cc7cfb98dd722531535" - integrity sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ== - -hyphenate-style-name@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48" - integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ== - -i18next-browser-languagedetector@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.2.tgz#68565a28b929cbc98ab6a56826ef2faf0e927ff8" - integrity sha512-YDzIGHhMRvr7M+c8B3EQUKyiMBhfqox4o1qkFvt4QXuu5V2cxf74+NCr+VEkUuU0y+RwcupA238eeolW1Yn80g== - dependencies: - "@babel/runtime" "^7.14.6" - -i18next-http-backend@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/i18next-http-backend/-/i18next-http-backend-1.3.2.tgz#ce6aff7aa60b6170e006d62b8f9cc1b3de55413e" - integrity sha512-SfcoUmsSWnc2LYsDsCq5TCg18cxJXvXymX9N37V+qqMKQY8Gf0rWkjOnRd20sMK633Dq4NF9tvqPbOiFJ49Kbw== - dependencies: - cross-fetch "3.1.5" - -i18next@^21.6.13: - version "21.6.13" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-21.6.13.tgz#e881b05f156ac06997e9b63379d8b2674bb4a4f2" - integrity sha512-MVjNttw+5mIuu2/fwTpSU0EeI7iU/6pnDvGQboCzkILiv0/gD+FLZaF7qSHmUHO4ZkE6xJQ9SlBgGvMHxhC82Q== - dependencies: - "@babel/runtime" "^7.12.0" - -iconv-lite@0.4.24, iconv-lite@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -iconv-lite@^0.6.2, iconv-lite@^0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" - integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== - dependencies: - safer-buffer ">= 2.1.2 < 3.0.0" - -icss-utils@^5.0.0, icss-utils@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" - integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== - -idb@^6.1.4: - version "6.1.5" - resolved "https://registry.yarnpkg.com/idb/-/idb-6.1.5.tgz#dbc53e7adf1ac7c59f9b2bf56e00b4ea4fce8c7b" - integrity sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw== - -identity-obj-proxy@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" - integrity sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ= - dependencies: - harmony-reflect "^1.4.6" - -ieee754@^1.1.13: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore-walk@^3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335" - integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ== - dependencies: - minimatch "^3.0.4" - -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -ignore@^5.1.4, ignore@^5.1.8, ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - -immer@^9.0.7: - version "9.0.12" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" - integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA== - -"immutable@^3.8.1 || ^4.0.0-rc.1": - version "4.0.0-rc.12" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0-rc.12.tgz#ca59a7e4c19ae8d9bf74a97bdf0f6e2f2a5d0217" - integrity sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A== - -import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-local@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" - integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -indefinite-observable@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/indefinite-observable/-/indefinite-observable-2.0.1.tgz#574af29bfbc17eb5947793797bddc94c9d859400" - integrity sha512-G8vgmork+6H9S8lUAg1gtXEj2JxIQTo0g2PbFiYOdjkziSI0F7UYBiVwhZRuixhBCNGczAls34+5HJPyZysvxQ== - dependencies: - symbol-observable "1.2.0" - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= - -infer-owner@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" - integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" - integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== - -ini@^1.3.2, ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -init-package-json@^2.0.2: - version "2.0.5" - resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-2.0.5.tgz#78b85f3c36014db42d8f32117252504f68022646" - integrity sha512-u1uGAtEFu3VA6HNl/yUWw57jmKEMx8SKOxHhxjGnOFUiIlFnohKDFg4ZrPpv9wWqk44nDxGJAtqjdQFm+9XXQA== - dependencies: - npm-package-arg "^8.1.5" - promzard "^0.3.0" - read "~1.0.1" - read-package-json "^4.1.1" - semver "^7.3.5" - validate-npm-package-license "^3.0.4" - validate-npm-package-name "^3.0.0" - -inquirer-autocomplete-prompt@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-1.0.2.tgz#3f2548f73dd12f0a541be055ea9c8c7aedeb42bf" - integrity sha512-vNmAhhrOQwPnUm4B9kz1UB7P98rVF1z8txnjp53r40N0PBCuqoRWqjg3Tl0yz0UkDg7rEUtZ2OZpNc7jnOU9Zw== - dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" - figures "^2.0.0" - run-async "^2.3.0" - -inquirer@^7.0.0: - version "7.0.6" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.6.tgz#ee4ff0ea7ecda5324656fe665878790f66df7d0c" - integrity sha512-7SVO4h+QIdMq6XcqIqrNte3gS5MzCCKZdsq9DO4PJziBFNYzP3PGFbDjgadDb//MCahzgjCxvQ/O2wa7kx9o4w== - dependencies: - ansi-escapes "^4.2.1" - chalk "^3.0.0" - cli-cursor "^3.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.15" - mute-stream "0.0.8" - run-async "^2.4.0" - rxjs "^6.5.3" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - -inquirer@^7.3.3: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" - integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== - dependencies: - ansi-escapes "^4.2.1" - chalk "^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" - -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - -ip@^1.1.0, ip@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= - -ipaddr.js@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" - integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== - -ipaddr.js@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" - integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== - -is-arguments@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" - integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-bigint@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.2.tgz#ffb381442503235ad245ea89e45b3dbff040ee5a" - integrity sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA== - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.1.tgz#10edc0900dd127697a92f6f9807c7617d68ac48e" - integrity sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ== - -is-boolean-object@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.1.tgz#3c0878f035cb821228d350d2e1e36719716a3de8" - integrity sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng== - dependencies: - call-bind "^1.0.2" - -is-callable@^1.1.4, is-callable@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" - integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== - -is-callable@^1.2.2, is-callable@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" - integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ== - -is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-ci@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" - integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ== - dependencies: - ci-info "^3.2.0" - -is-core-module@^2.2.0, is-core-module@^2.5.0, is-core-module@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" - integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== - dependencies: - has "^1.0.3" - -is-core-module@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== - dependencies: - has "^1.0.3" - -is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= - -is-docker@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" - integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ== - -is-docker@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-in-browser@^1.0.2, is-in-browser@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835" - integrity sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU= - -is-installed-globally@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" - integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== - dependencies: - global-dirs "^3.0.0" - is-path-inside "^3.0.2" - -is-lambda@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" - integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU= - -is-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" - integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= - -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== - -is-number-object@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" - integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - -is-path-cwd@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-inside@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-plain-obj@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-plain-obj@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" - integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== - -is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-plain-object@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" - integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== - -is-potential-custom-element-name@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" - integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== - -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - -is-regex@^1.0.4, is-regex@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" - integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== - dependencies: - has "^1.0.3" - -is-regex@^1.1.0, is-regex@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251" - integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg== - dependencies: - call-bind "^1.0.2" - has-symbols "^1.0.1" - -is-regex@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.3.tgz#d029f9aff6448b93ebbe3f33dac71511fdcbef9f" - integrity sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ== - dependencies: - call-bind "^1.0.2" - has-symbols "^1.0.2" - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= - -is-root@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" - integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== - -is-shared-array-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" - integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== - -is-ssh@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.1.tgz#f349a8cadd24e65298037a522cf7520f2e81a0f3" - integrity sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg== - dependencies: - protocols "^1.1.0" - -is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" - integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== - -is-string@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" - integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== - -is-string@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.6.tgz#3fe5d5992fb0d93404f32584d4b0179a71b54a5f" - integrity sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w== - -is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-subset@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" - integrity sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY= - -is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== - dependencies: - has-symbols "^1.0.0" - -is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-text-path@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" - integrity sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4= - dependencies: - text-extensions "^1.0.0" - -is-typedarray@^1.0.0, is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-weakref@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.1.tgz#842dba4ec17fa9ac9850df2d6efbc1737274f2a2" - integrity sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ== - dependencies: - call-bind "^1.0.0" - -is-wsl@^2.1.1, is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -istanbul-lib-coverage@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" - integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== - -istanbul-lib-coverage@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" - integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== - -istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" - integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^6.3.0" - -istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" - integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.1.3: - version "3.1.4" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c" - integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -jake@^10.8.5: - version "10.8.5" - resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.5.tgz#f2183d2c59382cb274226034543b9c03b8164c46" - integrity sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw== - dependencies: - async "^3.2.3" - chalk "^4.0.2" - filelist "^1.0.1" - minimatch "^3.0.4" - -jest-changed-files@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5" - integrity sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw== - dependencies: - "@jest/types" "^27.5.1" - execa "^5.0.0" - throat "^6.0.1" - -jest-circus@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc" - integrity sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^0.7.0" - expect "^27.5.1" - is-generator-fn "^2.0.0" - jest-each "^27.5.1" - jest-matcher-utils "^27.5.1" - jest-message-util "^27.5.1" - jest-runtime "^27.5.1" - jest-snapshot "^27.5.1" - jest-util "^27.5.1" - pretty-format "^27.5.1" - slash "^3.0.0" - stack-utils "^2.0.3" - throat "^6.0.1" - -jest-cli@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145" - integrity sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw== - dependencies: - "@jest/core" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/types" "^27.5.1" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - import-local "^3.0.2" - jest-config "^27.5.1" - jest-util "^27.5.1" - jest-validate "^27.5.1" - prompts "^2.0.1" - yargs "^16.2.0" - -jest-config@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41" - integrity sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA== - dependencies: - "@babel/core" "^7.8.0" - "@jest/test-sequencer" "^27.5.1" - "@jest/types" "^27.5.1" - babel-jest "^27.5.1" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.1" - graceful-fs "^4.2.9" - jest-circus "^27.5.1" - jest-environment-jsdom "^27.5.1" - jest-environment-node "^27.5.1" - jest-get-type "^27.5.1" - jest-jasmine2 "^27.5.1" - jest-regex-util "^27.5.1" - jest-resolve "^27.5.1" - jest-runner "^27.5.1" - jest-util "^27.5.1" - jest-validate "^27.5.1" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^27.5.1" - slash "^3.0.0" - strip-json-comments "^3.1.1" - -jest-diff@^27.0.0, jest-diff@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" - integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== - dependencies: - chalk "^4.0.0" - diff-sequences "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" - -jest-docblock@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0" - integrity sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ== - dependencies: - detect-newline "^3.0.0" - -jest-each@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e" - integrity sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ== - dependencies: - "@jest/types" "^27.5.1" - chalk "^4.0.0" - jest-get-type "^27.5.1" - jest-util "^27.5.1" - pretty-format "^27.5.1" - -jest-environment-jsdom@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546" - integrity sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/fake-timers" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - jest-mock "^27.5.1" - jest-util "^27.5.1" - jsdom "^16.6.0" - -jest-environment-node@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.5.1.tgz#dedc2cfe52fab6b8f5714b4808aefa85357a365e" - integrity sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/fake-timers" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - jest-mock "^27.5.1" - jest-util "^27.5.1" - -jest-get-type@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" - integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== - -jest-haste-map@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f" - integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng== - dependencies: - "@jest/types" "^27.5.1" - "@types/graceful-fs" "^4.1.2" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^27.5.1" - jest-serializer "^27.5.1" - jest-util "^27.5.1" - jest-worker "^27.5.1" - micromatch "^4.0.4" - walker "^1.0.7" - optionalDependencies: - fsevents "^2.3.2" - -jest-jasmine2@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4" - integrity sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/source-map" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - expect "^27.5.1" - is-generator-fn "^2.0.0" - jest-each "^27.5.1" - jest-matcher-utils "^27.5.1" - jest-message-util "^27.5.1" - jest-runtime "^27.5.1" - jest-snapshot "^27.5.1" - jest-util "^27.5.1" - pretty-format "^27.5.1" - throat "^6.0.1" - -jest-leak-detector@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8" - integrity sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ== - dependencies: - jest-get-type "^27.5.1" - pretty-format "^27.5.1" - -jest-matcher-utils@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" - integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== - dependencies: - chalk "^4.0.0" - jest-diff "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" - -jest-message-util@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf" - integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^27.5.1" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^27.5.1" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6" - integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og== - dependencies: - "@jest/types" "^27.5.1" - "@types/node" "*" - -jest-pnp-resolver@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" - integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== - -jest-regex-util@^27.0.0, jest-regex-util@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" - integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== - -jest-resolve-dependencies@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8" - integrity sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg== - dependencies: - "@jest/types" "^27.5.1" - jest-regex-util "^27.5.1" - jest-snapshot "^27.5.1" - -jest-resolve@^27.4.2, jest-resolve@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384" - integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw== - dependencies: - "@jest/types" "^27.5.1" - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^27.5.1" - jest-pnp-resolver "^1.2.2" - jest-util "^27.5.1" - jest-validate "^27.5.1" - resolve "^1.20.0" - resolve.exports "^1.1.0" - slash "^3.0.0" - -jest-runner@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5" - integrity sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ== - dependencies: - "@jest/console" "^27.5.1" - "@jest/environment" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.8.1" - graceful-fs "^4.2.9" - jest-docblock "^27.5.1" - jest-environment-jsdom "^27.5.1" - jest-environment-node "^27.5.1" - jest-haste-map "^27.5.1" - jest-leak-detector "^27.5.1" - jest-message-util "^27.5.1" - jest-resolve "^27.5.1" - jest-runtime "^27.5.1" - jest-util "^27.5.1" - jest-worker "^27.5.1" - source-map-support "^0.5.6" - throat "^6.0.1" - -jest-runtime@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af" - integrity sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/fake-timers" "^27.5.1" - "@jest/globals" "^27.5.1" - "@jest/source-map" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - execa "^5.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^27.5.1" - jest-message-util "^27.5.1" - jest-mock "^27.5.1" - jest-regex-util "^27.5.1" - jest-resolve "^27.5.1" - jest-snapshot "^27.5.1" - jest-util "^27.5.1" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-serializer@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64" - integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w== - dependencies: - "@types/node" "*" - graceful-fs "^4.2.9" - -jest-snapshot@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1" - integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA== - dependencies: - "@babel/core" "^7.7.2" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/traverse" "^7.7.2" - "@babel/types" "^7.0.0" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/babel__traverse" "^7.0.4" - "@types/prettier" "^2.1.5" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^27.5.1" - graceful-fs "^4.2.9" - jest-diff "^27.5.1" - jest-get-type "^27.5.1" - jest-haste-map "^27.5.1" - jest-matcher-utils "^27.5.1" - jest-message-util "^27.5.1" - jest-util "^27.5.1" - natural-compare "^1.4.0" - pretty-format "^27.5.1" - semver "^7.3.2" - -jest-util@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" - integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== - dependencies: - "@jest/types" "^27.5.1" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-validate@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067" - integrity sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ== - dependencies: - "@jest/types" "^27.5.1" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^27.5.1" - leven "^3.1.0" - pretty-format "^27.5.1" - -jest-watch-typeahead@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/jest-watch-typeahead/-/jest-watch-typeahead-1.0.0.tgz#4de2ca1eb596acb1889752afbab84b74fcd99173" - integrity sha512-jxoszalAb394WElmiJTFBMzie/RDCF+W7Q29n5LzOPtcoQoHWfdUtHFkbhgf5NwWe8uMOxvKb/g7ea7CshfkTw== - dependencies: - ansi-escapes "^4.3.1" - chalk "^4.0.0" - jest-regex-util "^27.0.0" - jest-watcher "^27.0.0" - slash "^4.0.0" - string-length "^5.0.1" - strip-ansi "^7.0.1" - -jest-watcher@^27.0.0, jest-watcher@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2" - integrity sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw== - dependencies: - "@jest/test-result" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - jest-util "^27.5.1" - string-length "^4.0.1" - -jest-worker@^26.2.1: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" - integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^7.0.0" - -jest-worker@^27.0.2, jest-worker@^27.3.1, jest-worker@^27.4.5, jest-worker@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest@^27.4.3: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc" - integrity sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ== - dependencies: - "@jest/core" "^27.5.1" - import-local "^3.0.2" - jest-cli "^27.5.1" - -joi@^17.4.0: - version "17.4.3" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.4.3.tgz#462941fd994f11fcb92f59ba9f004706b9a45d17" - integrity sha512-8W3oOogFRuy2aLAdlhMpzS4fNBIMiyIa3xBaBYMFgA272/d5sob1DAth6jjo+5VrOlzbEgmbBGbU4cLrffPKog== - dependencies: - "@hapi/hoek" "^9.0.0" - "@hapi/topo" "^5.0.0" - "@sideway/address" "^4.1.3" - "@sideway/formula" "^3.0.0" - "@sideway/pinpoint" "^2.0.0" - -js-sha3@0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -jsdom@^16.6.0: - version "16.7.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" - integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== - dependencies: - abab "^2.0.5" - acorn "^8.2.4" - acorn-globals "^6.0.0" - cssom "^0.4.4" - cssstyle "^2.3.0" - data-urls "^2.0.0" - decimal.js "^10.2.1" - domexception "^2.0.1" - escodegen "^2.0.0" - form-data "^3.0.0" - html-encoding-sniffer "^2.0.1" - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" - is-potential-custom-element-name "^1.0.1" - nwsapi "^2.2.0" - parse5 "6.0.1" - saxes "^5.0.1" - symbol-tree "^3.2.4" - tough-cookie "^4.0.0" - w3c-hr-time "^1.0.2" - w3c-xmlserializer "^2.0.0" - webidl-conversions "^6.1.0" - whatwg-encoding "^1.0.5" - whatwg-mimetype "^2.3.0" - whatwg-url "^8.5.0" - ws "^7.4.6" - xml-name-validator "^3.0.0" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-schema@0.4.0, json-schema@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" - integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - -json5@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" - integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== - dependencies: - minimist "^1.2.5" - -json5@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= - optionalDependencies: - graceful-fs "^4.1.6" - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -jsonparse@^1.2.0, jsonparse@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= - -jsonpointer@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.0.tgz#f802669a524ec4805fa7389eadbc9921d5dc8072" - integrity sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg== - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -jsprim@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d" - integrity sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ== - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" - -jsrsasign@^10.5.8: - version "10.5.8" - resolved "https://registry.yarnpkg.com/jsrsasign/-/jsrsasign-10.5.8.tgz#df269e5694ebb53245c4dadfca68ee2fc8aa41ec" - integrity sha512-ewFUGPZJujIR9j84Q5LEzPTG4D1qQZ4CjJrgHfMEAAiArkC3xfdgNP0ZAXXxXbb+K8Phw15soOIJ8bX3+usEdQ== - -jss-plugin-camel-case@^10.5.1: - version "10.5.1" - resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.5.1.tgz#427b24a9951b4c2eaa7e3d5267acd2e00b0934f9" - integrity sha512-9+oymA7wPtswm+zxVti1qiowC5q7bRdCJNORtns2JUj/QHp2QPXYwSNRD8+D2Cy3/CEMtdJzlNnt5aXmpS6NAg== - dependencies: - "@babel/runtime" "^7.3.1" - hyphenate-style-name "^1.0.3" - jss "10.5.1" - -jss-plugin-default-unit@^10.5.1: - version "10.5.1" - resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.5.1.tgz#2be385d71d50aee2ee81c2a9ac70e00592ed861b" - integrity sha512-D48hJBc9Tj3PusvlillHW8Fz0y/QqA7MNmTYDQaSB/7mTrCZjt7AVRROExoOHEtd2qIYKOYJW3Jc2agnvsXRlQ== - dependencies: - "@babel/runtime" "^7.3.1" - jss "10.5.1" - -jss-plugin-global@^10.5.1: - version "10.5.1" - resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.5.1.tgz#0e1793dea86c298360a7e2004721351653c7e764" - integrity sha512-jX4XpNgoaB8yPWw/gA1aPXJEoX0LNpvsROPvxlnYe+SE0JOhuvF7mA6dCkgpXBxfTWKJsno7cDSCgzHTocRjCQ== - dependencies: - "@babel/runtime" "^7.3.1" - jss "10.5.1" - -jss-plugin-nested@^10.5.1: - version "10.5.1" - resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.5.1.tgz#8753a80ad31190fb6ac6fdd39f57352dcf1295bb" - integrity sha512-xXkWKOCljuwHNjSYcXrCxBnjd8eJp90KVFW1rlhvKKRXnEKVD6vdKXYezk2a89uKAHckSvBvBoDGsfZrldWqqQ== - dependencies: - "@babel/runtime" "^7.3.1" - jss "10.5.1" - tiny-warning "^1.0.2" - -jss-plugin-props-sort@^10.5.1: - version "10.5.1" - resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.5.1.tgz#ab1c167fd2d4506fb6a1c1d66c5f3ef545ff1cd8" - integrity sha512-t+2vcevNmMg4U/jAuxlfjKt46D/jHzCPEjsjLRj/J56CvP7Iy03scsUP58Iw8mVnaV36xAUZH2CmAmAdo8994g== - dependencies: - "@babel/runtime" "^7.3.1" - jss "10.5.1" - -jss-plugin-rule-value-function@^10.5.1: - version "10.5.1" - resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.5.1.tgz#37f4030523fb3032c8801fab48c36c373004de7e" - integrity sha512-3gjrSxsy4ka/lGQsTDY8oYYtkt2esBvQiceGBB4PykXxHoGRz14tbCK31Zc6DHEnIeqsjMUGbq+wEly5UViStQ== - dependencies: - "@babel/runtime" "^7.3.1" - jss "10.5.1" - tiny-warning "^1.0.2" - -jss-plugin-vendor-prefixer@^10.5.1: - version "10.5.1" - resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.5.1.tgz#45a183a3a0eb097bdfab0986b858d99920c0bbd8" - integrity sha512-cLkH6RaPZWHa1TqSfd2vszNNgxT1W0omlSjAd6hCFHp3KIocSrW21gaHjlMU26JpTHwkc+tJTCQOmE/O1A4FKQ== - dependencies: - "@babel/runtime" "^7.3.1" - css-vendor "^2.0.8" - jss "10.5.1" - -jss@10.5.1, jss@^10.5.1: - version "10.5.1" - resolved "https://registry.yarnpkg.com/jss/-/jss-10.5.1.tgz#93e6b2428c840408372d8b548c3f3c60fa601c40" - integrity sha512-hbbO3+FOTqVdd7ZUoTiwpHzKXIo5vGpMNbuXH1a0wubRSWLWSBvwvaq4CiHH/U42CmjOnp6lVNNs/l+Z7ZdDmg== - dependencies: - "@babel/runtime" "^7.3.1" - csstype "^3.0.2" - indefinite-observable "^2.0.1" - is-in-browser "^1.1.3" - tiny-warning "^1.0.2" - -"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b" - integrity sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA== - dependencies: - array-includes "^3.1.3" - object.assign "^4.1.2" - -kind-of@^6.0.2, kind-of@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -klona@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" - integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== - -klona@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" - integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== - -language-subtag-registry@~0.3.2: - version "0.3.20" - resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.20.tgz#a00a37121894f224f763268e431c55556b0c0755" - integrity sha512-KPMwROklF4tEx283Xw0pNKtfTj1gZ4UByp4EsIFWLgBavJltF4TiYPc39k06zSTsLzxTVXXDSpbwaQXaFB4Qeg== - -language-tags@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" - integrity sha1-0yHbxNowuovzAk4ED6XBRmH5GTo= - dependencies: - language-subtag-registry "~0.3.2" - -lazy-ass@1.6.0, lazy-ass@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" - integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= - -lerna-update-wizard@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/lerna-update-wizard/-/lerna-update-wizard-1.1.0.tgz#dd3c209f692dfc374d8405e5c54bf920935067cf" - integrity sha512-V6VtJFbt4BS1HKsNDsyBMeAU86CYRoQSikZsJyEMVc2x/yqH/hX+Z79fI0J3gSiWFkkIKrLj/vPUf6Zvn/79jw== - dependencies: - chalk "^4.1.2" - cli-cursor "^2.1.0" - execution-time "^1.2.0" - fs-extra "^7.0.0" - globby "^11.0.4" - inquirer "^7.0.0" - inquirer-autocomplete-prompt "^1.0.1" - lodash "^4.17.21" - meow "^9.0.0" - minimist "^1.2.3" - semver-compare "^1.0.0" - -lerna@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/lerna/-/lerna-4.0.0.tgz#b139d685d50ea0ca1be87713a7c2f44a5b678e9e" - integrity sha512-DD/i1znurfOmNJb0OBw66NmNqiM8kF6uIrzrJ0wGE3VNdzeOhz9ziWLYiRaZDGGwgbcjOo6eIfcx9O5Qynz+kg== - dependencies: - "@lerna/add" "4.0.0" - "@lerna/bootstrap" "4.0.0" - "@lerna/changed" "4.0.0" - "@lerna/clean" "4.0.0" - "@lerna/cli" "4.0.0" - "@lerna/create" "4.0.0" - "@lerna/diff" "4.0.0" - "@lerna/exec" "4.0.0" - "@lerna/import" "4.0.0" - "@lerna/info" "4.0.0" - "@lerna/init" "4.0.0" - "@lerna/link" "4.0.0" - "@lerna/list" "4.0.0" - "@lerna/publish" "4.0.0" - "@lerna/run" "4.0.0" - "@lerna/version" "4.0.0" - import-local "^3.0.2" - npmlog "^4.1.2" - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -libnpmaccess@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-4.0.3.tgz#dfb0e5b0a53c315a2610d300e46b4ddeb66e7eec" - integrity sha512-sPeTSNImksm8O2b6/pf3ikv4N567ERYEpeKRPSmqlNt1dTZbvgpJIzg5vAhXHpw2ISBsELFRelk0jEahj1c6nQ== - dependencies: - aproba "^2.0.0" - minipass "^3.1.1" - npm-package-arg "^8.1.2" - npm-registry-fetch "^11.0.0" - -libnpmpublish@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-4.0.2.tgz#be77e8bf5956131bcb45e3caa6b96a842dec0794" - integrity sha512-+AD7A2zbVeGRCFI2aO//oUmapCwy7GHqPXFJh3qpToSRNU+tXKJ2YFUgjt04LPPAf2dlEH95s6EhIHM1J7bmOw== - dependencies: - normalize-package-data "^3.0.2" - npm-package-arg "^8.1.2" - npm-registry-fetch "^11.0.0" - semver "^7.1.3" - ssri "^8.0.1" - -lilconfig@^2.0.3, lilconfig@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082" - integrity sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA== - -lines-and-columns@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" - integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= - -lint-staged@^10.5.4: - version "10.5.4" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.5.4.tgz#cd153b5f0987d2371fc1d2847a409a2fe705b665" - integrity sha512-EechC3DdFic/TdOPgj/RB3FicqE6932LTHCUm0Y2fsD9KGlLB+RwJl2q1IYBIvEsKzDOgn0D4gll+YxG5RsrKg== - dependencies: - chalk "^4.1.0" - cli-truncate "^2.1.0" - commander "^6.2.0" - cosmiconfig "^7.0.0" - debug "^4.2.0" - dedent "^0.7.0" - enquirer "^2.3.6" - execa "^4.1.0" - listr2 "^3.2.2" - log-symbols "^4.0.0" - micromatch "^4.0.2" - normalize-path "^3.0.0" - please-upgrade-node "^3.2.0" - string-argv "0.3.1" - stringify-object "^3.3.0" - -listr2@^3.2.2, listr2@^3.8.3: - version "3.14.0" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e" - integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g== - dependencies: - cli-truncate "^2.1.0" - colorette "^2.0.16" - log-update "^4.0.0" - p-map "^4.0.0" - rfdc "^1.3.0" - rxjs "^7.5.1" - through "^2.3.8" - wrap-ansi "^7.0.0" - -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - -load-json-file@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-6.2.0.tgz#5c7770b42cafa97074ca2848707c61662f4251a1" - integrity sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ== - dependencies: - graceful-fs "^4.1.15" - parse-json "^5.0.0" - strip-bom "^4.0.0" - type-fest "^0.6.0" - -loader-runner@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" - integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== - -loader-utils@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^1.0.1" - -loader-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" - integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" - -loader-utils@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.0.tgz#bcecc51a7898bee7473d4bc6b845b23af8304d4f" - integrity sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ== - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash.chunk@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.chunk/-/lodash.chunk-4.2.0.tgz#66e5ce1f76ed27b4303d8c6512e8d1216e8106bc" - integrity sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw= - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - -lodash.escape@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98" - integrity sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg= - -lodash.flattendeep@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" - integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= - -lodash.isequal@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - -lodash.isequalwith@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.isequalwith/-/lodash.isequalwith-4.4.0.tgz#266726ddd528f854f21f4ea98a065606e0fbc6b0" - integrity sha1-Jmcm3dUo+FTyH06pigZWBuD7xrA= - -lodash.ismatch@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" - integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.once@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= - -lodash.sortby@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" - integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= - -lodash.template@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" - integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.templatesettings "^4.0.0" - -lodash.templatesettings@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" - integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== - dependencies: - lodash._reinterpolate "^3.0.0" - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -lodash@^4, lodash@^4.15.0, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -log-symbols@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" - integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== - dependencies: - chalk "^4.0.0" - -log-update@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" - integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== - dependencies: - ansi-escapes "^4.3.0" - cli-cursor "^3.1.0" - slice-ansi "^4.0.0" - wrap-ansi "^6.2.0" - -logdown@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/logdown/-/logdown-3.3.1.tgz#836d5a195b5949c6db631ccc9fecce0492e01d10" - integrity sha512-pjX0vlIJsYQlgVzFba2amXI1wZZnhrEorL68MdLI7B0/sN1TNUozBNFaHfcPHMM3A+INZ0OXFDxtnoaEgOmGjQ== - dependencies: - chalk "^2.3.0" - -loglevel@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.0.tgz#e7ec73a57e1e7b419cb6c6ac06bf050b67356114" - integrity sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA== - -loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lower-case@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" - integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== - dependencies: - tslib "^2.0.3" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -magic-string@^0.25.0, magic-string@^0.25.7: - version "0.25.7" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" - integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== - dependencies: - sourcemap-codec "^1.4.4" - -make-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -make-fetch-happen@^8.0.9: - version "8.0.14" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz#aaba73ae0ab5586ad8eaa68bd83332669393e222" - integrity sha512-EsS89h6l4vbfJEtBZnENTOFk8mCRpY5ru36Xe5bcX1KYIli2mkSHqoFsp5O1wMDvTJJzxe/4THpCTtygjeeGWQ== - dependencies: - agentkeepalive "^4.1.3" - cacache "^15.0.5" - http-cache-semantics "^4.1.0" - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" - is-lambda "^1.0.1" - lru-cache "^6.0.0" - minipass "^3.1.3" - minipass-collect "^1.0.2" - minipass-fetch "^1.3.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - promise-retry "^2.0.1" - socks-proxy-agent "^5.0.0" - ssri "^8.0.0" - -make-fetch-happen@^9.0.1: - version "9.1.0" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" - integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== - dependencies: - agentkeepalive "^4.1.3" - cacache "^15.2.0" - 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" - negotiator "^0.6.2" - promise-retry "^2.0.1" - socks-proxy-agent "^6.0.0" - ssri "^8.0.0" - -makeerror@1.0.x: - version "1.0.11" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" - integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= - dependencies: - tmpl "1.0.x" - -map-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= - -map-obj@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" - integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== - -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= - -match-sorter@^6.0.2: - version "6.3.0" - resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.0.tgz#454a1b31ed218cddbce6231a0ecb5fdc549fed01" - integrity sha512-efYOf/wUpNb8FgNY+cOD2EIJI1S5I7YPKsw0LBp7wqPh5pmMS6i/wr3ZWwfwrAw1NvqTA2KUReVRWDX84lUcOQ== - dependencies: - "@babel/runtime" "^7.12.5" - remove-accents "0.4.2" - -mdn-data@2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== - -mdn-data@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" - integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -memfs@^3.1.2, memfs@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" - integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== - dependencies: - fs-monkey "1.0.3" - -meow@^8.0.0: - version "8.1.2" - resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897" - integrity sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q== - dependencies: - "@types/minimist" "^1.2.0" - camelcase-keys "^6.2.2" - decamelize-keys "^1.1.0" - hard-rejection "^2.1.0" - minimist-options "4.1.0" - normalize-package-data "^3.0.0" - read-pkg-up "^7.0.1" - redent "^3.0.0" - trim-newlines "^3.0.0" - type-fest "^0.18.0" - yargs-parser "^20.2.3" - -meow@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" - integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== - dependencies: - "@types/minimist" "^1.2.0" - camelcase-keys "^6.2.2" - decamelize "^1.2.0" - decamelize-keys "^1.1.0" - hard-rejection "^2.1.0" - minimist-options "4.1.0" - normalize-package-data "^3.0.0" - read-pkg-up "^7.0.1" - redent "^3.0.0" - trim-newlines "^3.0.0" - type-fest "^0.18.0" - yargs-parser "^20.2.3" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -micromatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" - integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== - dependencies: - braces "^3.0.1" - picomatch "^2.0.5" - -micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - -microseconds@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39" - integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA== - -mime-db@1.42.0, "mime-db@>= 1.40.0 < 2": - version "1.42.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" - integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== - -mime-db@1.45.0: - version "1.45.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" - integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== - -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== - -mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" - integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== - -mime-types@2.1.18: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== - dependencies: - mime-db "~1.33.0" - -mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.25" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437" - integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg== - dependencies: - mime-db "1.42.0" - -mime-types@^2.1.27: - version "2.1.28" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" - integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== - dependencies: - mime-db "1.45.0" - -mime-types@^2.1.31: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== - dependencies: - mime-db "1.51.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -min-indent@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" - integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== - -mini-create-react-context@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz#df60501c83151db69e28eac0ef08b4002efab040" - integrity sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA== - dependencies: - "@babel/runtime" "^7.5.5" - tiny-warning "^1.0.3" - -mini-css-extract-plugin@^2.4.5: - version "2.5.3" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.3.tgz#c5c79f9b22ce9b4f164e9492267358dbe35376d9" - integrity sha512-YseMB8cs8U/KCaAGQoqYmfUuhhGW0a9p9XvWXrxVOkE3/IiISTLw4ALNt7JR5B2eYauFM+PQGSbXMDmVbR7Tfw== - dependencies: - schema-utils "^4.0.0" - -minimalistic-assert@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimatch@3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^3.0.4: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== - dependencies: - brace-expansion "^2.0.1" - -minimist-options@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" - integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== - dependencies: - arrify "^1.0.1" - is-plain-obj "^1.1.0" - kind-of "^6.0.3" - -minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== - -minipass-collect@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" - integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== - dependencies: - minipass "^3.0.0" - -minipass-fetch@^1.3.0, minipass-fetch@^1.3.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6" - integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw== - dependencies: - minipass "^3.1.0" - minipass-sized "^1.0.3" - minizlib "^2.0.0" - optionalDependencies: - encoding "^0.1.12" - -minipass-flush@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" - integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== - dependencies: - minipass "^3.0.0" - -minipass-json-stream@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz#7edbb92588fbfc2ff1db2fc10397acb7b6b44aa7" - integrity sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg== - dependencies: - jsonparse "^1.3.1" - minipass "^3.0.0" - -minipass-pipeline@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.3.tgz#55f7839307d74859d6e8ada9c3ebe72cec216a34" - integrity sha512-cFOknTvng5vqnwOpDsZTWhNll6Jf8o2x+/diplafmxpuIymAjzoOolZG0VvQf3V2HgqzJNhnuKHYp2BqDgz8IQ== - dependencies: - minipass "^3.0.0" - -minipass-pipeline@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" - integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== - dependencies: - minipass "^3.0.0" - -minipass-sized@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" - integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== - dependencies: - minipass "^3.0.0" - -minipass@^2.6.0, minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minipass@^3.0.0, minipass@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" - integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== - dependencies: - yallist "^4.0.0" - -minipass@^3.1.0, minipass@^3.1.3: - version "3.1.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.5.tgz#71f6251b0a33a49c01b3cf97ff77eda030dff732" - integrity sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw== - dependencies: - yallist "^4.0.0" - -minizlib@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== - dependencies: - minipass "^2.9.0" - -minizlib@^2.0.0, minizlib@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" - integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== - dependencies: - minipass "^3.0.0" - yallist "^4.0.0" - -mkdirp-infer-owner@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz#55d3b368e7d89065c38f32fd38e638f0ab61d316" - integrity sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw== - dependencies: - chownr "^2.0.0" - infer-owner "^1.0.4" - mkdirp "^1.0.3" - -mkdirp@^0.5.0, mkdirp@^0.5.5, mkdirp@~0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -mkdirp@^1.0.3, mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -modify-values@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" - integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== - -moo@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/moo/-/moo-0.4.3.tgz#3f847a26f31cf625a956a87f2b10fbc013bfd10e" - integrity sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -ms@2.1.2, ms@^2.0.0, ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -multicast-dns-service-types@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" - integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= - -multicast-dns@^6.0.1: - version "6.2.3" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" - integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== - dependencies: - dns-packet "^1.3.1" - thunky "^1.0.2" - -multimatch@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-5.0.0.tgz#932b800963cea7a31a033328fa1e0c3a1874dbe6" - integrity sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA== - dependencies: - "@types/minimatch" "^3.0.3" - array-differ "^3.0.0" - array-union "^2.1.0" - arrify "^2.0.1" - minimatch "^3.0.4" - -mute-stream@0.0.8, mute-stream@~0.0.4: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - -nano-time@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef" - integrity sha1-sFVPaa2J4i0JB/ehKwmTpdlhN+8= - dependencies: - big-integer "^1.6.16" - -nanoid@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" - integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -nearley@^2.7.10: - version "2.19.0" - resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.19.0.tgz#37717781d0fd0f2bfc95e233ebd75678ca4bda46" - integrity sha512-2v52FTw7RPqieZr3Gth1luAXZR7Je6q3KaDHY5bjl/paDUdMu35fZ8ICNgiYJRr3tf3NMvIQQR1r27AvEr9CRA== - dependencies: - commander "^2.19.0" - moo "^0.4.3" - railroad-diagrams "^1.0.0" - randexp "0.4.6" - semver "^5.4.1" - -negotiator@0.6.2, negotiator@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -neo-async@^2.6.0, neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -no-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" - integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== - dependencies: - lower-case "^2.0.2" - tslib "^2.0.3" - -node-fetch@2.6.7, node-fetch@^2.6.1: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - -node-forge@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.0.tgz#37a874ea723855f37db091e6c186e5b67a01d4b2" - integrity sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA== - -node-gyp@^5.0.2: - version "5.0.5" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.0.5.tgz#f6cf1da246eb8c42b097d7cd4d6c3ce23a4163af" - integrity sha512-WABl9s4/mqQdZneZHVWVG4TVr6QQJZUC6PAx47ITSk9lreZ1n+7Z9mMAIbA3vnO4J9W20P7LhCxtzfWsAD/KDw== - dependencies: - env-paths "^1.0.0" - glob "^7.0.3" - graceful-fs "^4.1.2" - mkdirp "^0.5.0" - nopt "2 || 3" - npmlog "0 || 1 || 2 || 3 || 4" - request "^2.87.0" - rimraf "2" - semver "~5.3.0" - tar "^4.4.12" - which "1" - -node-gyp@^7.1.0: - version "7.1.2" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.2.tgz#21a810aebb187120251c3bcec979af1587b188ae" - integrity sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ== - dependencies: - env-paths "^2.2.0" - glob "^7.1.4" - graceful-fs "^4.2.3" - nopt "^5.0.0" - npmlog "^4.1.2" - request "^2.88.2" - rimraf "^3.0.2" - semver "^7.3.2" - tar "^6.0.2" - which "^2.0.2" - -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= - -node-releases@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" - integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== - -"nopt@2 || 3": - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= - dependencies: - abbrev "1" - -nopt@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" - integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== - dependencies: - abbrev "1" - -normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-package-data@^3.0.0, normalize-package-data@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" - integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== - dependencies: - hosted-git-info "^4.0.1" - is-core-module "^2.5.0" - semver "^7.3.4" - validate-npm-package-license "^3.0.1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= - -normalize-url@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" - integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== - -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - -npm-bundled@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" - integrity sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ== - dependencies: - npm-normalize-package-bin "^1.0.1" - -npm-install-checks@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-4.0.0.tgz#a37facc763a2fde0497ef2c6d0ac7c3fbe00d7b4" - integrity sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w== - dependencies: - semver "^7.1.1" - -npm-lifecycle@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-3.1.5.tgz#9882d3642b8c82c815782a12e6a1bfeed0026309" - integrity sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g== - dependencies: - byline "^5.0.0" - graceful-fs "^4.1.15" - node-gyp "^5.0.2" - resolve-from "^4.0.0" - slide "^1.1.6" - uid-number "0.0.6" - umask "^1.1.0" - which "^1.3.1" - -npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" - integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== - -npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-package-arg@^8.1.0, npm-package-arg@^8.1.2, npm-package-arg@^8.1.5: - version "8.1.5" - resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-8.1.5.tgz#3369b2d5fe8fdc674baa7f1786514ddc15466e44" - integrity sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q== - dependencies: - hosted-git-info "^4.0.1" - semver "^7.3.4" - validate-npm-package-name "^3.0.0" - -npm-packlist@^2.1.4: - version "2.2.2" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-2.2.2.tgz#076b97293fa620f632833186a7a8f65aaa6148c8" - integrity sha512-Jt01acDvJRhJGthnUJVF/w6gumWOZxO7IkpY/lsX9//zqQgnF7OJaxgQXcerd4uQOLu7W5bkb4mChL9mdfm+Zg== - dependencies: - glob "^7.1.6" - ignore-walk "^3.0.3" - npm-bundled "^1.1.1" - npm-normalize-package-bin "^1.0.1" - -npm-pick-manifest@^6.0.0, npm-pick-manifest@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz#7b5484ca2c908565f43b7f27644f36bb816f5148" - integrity sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA== - dependencies: - npm-install-checks "^4.0.0" - npm-normalize-package-bin "^1.0.1" - npm-package-arg "^8.1.2" - semver "^7.3.4" - -npm-registry-fetch@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz#68c1bb810c46542760d62a6a965f85a702d43a76" - integrity sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA== - dependencies: - make-fetch-happen "^9.0.1" - 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" - -npm-registry-fetch@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-9.0.0.tgz#86f3feb4ce00313bc0b8f1f8f69daae6face1661" - integrity sha512-PuFYYtnQ8IyVl6ib9d3PepeehcUeHN9IO5N/iCRhyg9tStQcqGQBRVHmfmMWPDERU3KwZoHFvbJ4FPXPspvzbA== - dependencies: - "@npmcli/ci-detect" "^1.0.0" - lru-cache "^6.0.0" - make-fetch-happen "^8.0.9" - minipass "^3.1.3" - minipass-fetch "^1.3.0" - minipass-json-stream "^1.0.1" - minizlib "^2.0.0" - npm-package-arg "^8.0.0" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - -npm-run-path@^4.0.0, npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -nth-check@^1.0.2, nth-check@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" - -nth-check@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" - integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== - dependencies: - boolbase "^1.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -nwsapi@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" - integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-hash@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" - integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== - -object-inspect@^1.10.3: - version "1.10.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369" - integrity sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw== - -object-inspect@^1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" - integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== - -object-inspect@^1.6.0, object-inspect@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" - integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== - -object-inspect@^1.8.0, object-inspect@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" - integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== - -object-is@^1.0.1, object-is@^1.0.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" - integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - -object-is@^1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.0, object.assign@^4.1.1, object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -object.entries@^1.1.1, object.entries@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.4.tgz#43ccf9a50bc5fd5b649d45ab1a579f24e088cafd" - integrity sha512-h4LWKWE+wKQGhtMjZEBud7uLGhqyLwj8fpHOarZhD2uY3C9cRtk57VQ89ke3moByLXMedqs3XCHzyb4AmA2DjA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.18.2" - -object.entries@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861" - integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - -object.fromentries@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.4.tgz#26e1ba5c4571c5c6f0890cef4473066456a120b8" - integrity sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" - has "^1.0.3" - -object.fromentries@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251" - integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - -object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" - -object.hasown@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.0.tgz#7232ed266f34d197d15cac5880232f7a4790afe5" - integrity sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.19.1" - -object.values@^1.1.0, object.values@^1.1.1, object.values@^1.1.2, object.values@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" - integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - -oblivious-set@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/oblivious-set/-/oblivious-set-1.0.0.tgz#c8316f2c2fb6ff7b11b6158db3234c49f733c566" - integrity sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw== - -obuf@^1.0.0, obuf@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.1, on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= - dependencies: - mimic-fn "^1.0.0" - -onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== - dependencies: - mimic-fn "^2.1.0" - -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -open@^8.0.9, open@^8.4.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" - integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== - dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" - -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - 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" - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -ospath@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" - integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs= - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -p-limit@3.1.0, p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== - dependencies: - p-try "^2.0.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-map-series@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-2.1.0.tgz#7560d4c452d9da0c07e692fdbfe6e2c81a2a91f2" - integrity sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q== - -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - -p-pipe@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.1.0.tgz#48b57c922aa2e1af6a6404cb7c6bf0eb9cc8e60e" - integrity sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw== - -p-queue@^6.6.2: - version "6.6.2" - resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426" - integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ== - dependencies: - eventemitter3 "^4.0.4" - p-timeout "^3.2.0" - -p-reduce@^2.0.0, p-reduce@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-2.1.0.tgz#09408da49507c6c274faa31f28df334bc712b64a" - integrity sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw== - -p-retry@^4.5.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" - integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== - dependencies: - "@types/retry" "^0.12.0" - retry "^0.13.1" - -p-timeout@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" - integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== - dependencies: - p-finally "^1.0.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -p-waterfall@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/p-waterfall/-/p-waterfall-2.1.1.tgz#63153a774f472ccdc4eb281cdb2967fcf158b2ee" - integrity sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw== - dependencies: - p-reduce "^2.0.0" - -pacote@^11.2.6: - version "11.3.5" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-11.3.5.tgz#73cf1fc3772b533f575e39efa96c50be8c3dc9d2" - integrity sha512-fT375Yczn4zi+6Hkk2TBe1x1sP8FgFsEIZ2/iWaXY2r/NkhDJfxbcn5paz1+RTFCyNf+dPnaoBDJoAxXSU8Bkg== - dependencies: - "@npmcli/git" "^2.1.0" - "@npmcli/installed-package-contents" "^1.0.6" - "@npmcli/promise-spawn" "^1.2.0" - "@npmcli/run-script" "^1.8.2" - cacache "^15.0.5" - chownr "^2.0.0" - fs-minipass "^2.1.0" - infer-owner "^1.0.4" - minipass "^3.1.3" - mkdirp "^1.0.3" - npm-package-arg "^8.0.1" - npm-packlist "^2.1.4" - npm-pick-manifest "^6.0.0" - npm-registry-fetch "^11.0.0" - promise-retry "^2.0.1" - read-package-json-fast "^2.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.1.0" - -param-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" - integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parse-json@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" - integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - lines-and-columns "^1.1.6" - -parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parse-path@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.1.tgz#0ec769704949778cb3b8eda5e994c32073a1adff" - integrity sha512-d7yhga0Oc+PwNXDvQ0Jv1BuWkLVPXcAoQ/WREgd6vNNoKYaW52KI+RdOFjI63wjkmps9yUE8VS4veP+AgpQ/hA== - dependencies: - is-ssh "^1.3.0" - protocols "^1.4.0" - -parse-url@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-5.0.1.tgz#99c4084fc11be14141efa41b3d117a96fcb9527f" - integrity sha512-flNUPP27r3vJpROi0/R3/2efgKkyXqnXwyP1KQ2U0SfFRgdizOdWfvrrvJg1LuOoxs7GQhmxJlq23IpQ/BkByg== - dependencies: - is-ssh "^1.3.0" - normalize-url "^3.3.0" - parse-path "^4.0.0" - protocols "^1.4.0" - -parse5@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" - integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== - -parse5@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" - integrity sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA== - dependencies: - "@types/node" "*" - -parseurl@~1.3.2, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascal-case@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" - integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-is-inside@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.0.tgz#99a10d870a803bdd5ee6f0470e58dfcd2f9a54d3" - integrity sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg== - -path-parse@^1.0.6, path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -path-to-regexp@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" - integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== - -path-to-regexp@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== - dependencies: - isarray "0.0.1" - -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -pause-stream@0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= - dependencies: - through "~2.3" - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -picocolors@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" - integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" - integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== - -picomatch@^2.0.5: - version "2.1.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5" - integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA== - -picomatch@^2.2.3: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pify@^2.2.0, pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" - integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA== - -pirates@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" - integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== - -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= - dependencies: - find-up "^2.1.0" - -pkg-dir@^4.1.0, pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -pkg-up@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" - integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== - dependencies: - find-up "^3.0.0" - -please-upgrade-node@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" - integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== - dependencies: - semver-compare "^1.0.0" - -popper.js@1.16.1-lts: - version "1.16.1-lts" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05" - integrity sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA== - -portfinder@^1.0.28: - version "1.0.28" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" - integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== - dependencies: - async "^2.6.2" - debug "^3.1.1" - mkdirp "^0.5.5" - -postcss-attribute-case-insensitive@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.0.tgz#39cbf6babf3ded1e4abf37d09d6eda21c644105c" - integrity sha512-b4g9eagFGq9T5SWX4+USfVyjIb3liPnjhHHRMP7FMB2kFVpYyfEscV0wP3eaXhKlcHKUut8lt5BGoeylWA/dBQ== - dependencies: - postcss-selector-parser "^6.0.2" - -postcss-browser-comments@^4: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz#bcfc86134df5807f5d3c0eefa191d42136b5e72a" - integrity sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg== - -postcss-calc@^8.2.0: - version "8.2.4" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" - integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== - dependencies: - postcss-selector-parser "^6.0.9" - postcss-value-parser "^4.2.0" - -postcss-clamp@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-clamp/-/postcss-clamp-3.0.0.tgz#09cb1ad64243b46c9159ded5e8d3e8349150a09e" - integrity sha512-QENQMIF/Grw0qX0RzSPJjw+mAiGPIwG2AnsQDIoR/WJ5Q19zLB0NrZX8cH7CzzdDWEerTPGCdep7ItFaAdtItg== - dependencies: - postcss-value-parser "^4.1.0" - -postcss-color-functional-notation@^4.2.1: - version "4.2.2" - resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.2.tgz#f59ccaeb4ee78f1b32987d43df146109cc743073" - integrity sha512-DXVtwUhIk4f49KK5EGuEdgx4Gnyj6+t2jBSEmxvpIK9QI40tWrpS2Pua8Q7iIZWBrki2QOaeUdEaLPPa91K0RQ== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-color-hex-alpha@^8.0.2: - version "8.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.3.tgz#61a0fd151d28b128aa6a8a21a2dad24eebb34d52" - integrity sha512-fESawWJCrBV035DcbKRPAVmy21LpoyiXdPTuHUfWJ14ZRjY7Y7PA6P4g8z6LQGYhU1WAxkTxjIjurXzoe68Glw== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-color-rebeccapurple@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.0.2.tgz#5d397039424a58a9ca628762eb0b88a61a66e079" - integrity sha512-SFc3MaocHaQ6k3oZaFwH8io6MdypkUtEy/eXzXEB1vEQlO3S3oDc/FSZA8AsS04Z25RirQhlDlHLh3dn7XewWw== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-colormin@^5.2.5: - version "5.2.5" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.2.5.tgz#d1fc269ac2ad03fe641d462b5d1dada35c69968a" - integrity sha512-+X30aDaGYq81mFqwyPpnYInsZQnNpdxMX0ajlY7AExCexEFkPVV+KrO7kXwayqEWL2xwEbNQ4nUO0ZsRWGnevg== - dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" - colord "^2.9.1" - postcss-value-parser "^4.2.0" - -postcss-convert-values@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.0.4.tgz#3e74dd97c581f475ae7b4500bc0a7c4fb3a6b1b6" - integrity sha512-bugzSAyjIexdObovsPZu/sBCTHccImJxLyFgeV0MmNBm/Lw5h5XnjfML6gzEmJ3A6nyfCW7hb1JXzcsA4Zfbdw== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-custom-media@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz#1be6aff8be7dc9bf1fe014bde3b71b92bb4552f1" - integrity sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g== - -postcss-custom-properties@^12.1.4: - version "12.1.4" - resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-12.1.4.tgz#e3d8a8000f28094453b836dff5132385f2862285" - integrity sha512-i6AytuTCoDLJkWN/MtAIGriJz3j7UX6bV7Z5t+KgFz+dwZS15/mlTJY1S0kRizlk6ba0V8u8hN50Fz5Nm7tdZw== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-custom-selectors@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-6.0.0.tgz#022839e41fbf71c47ae6e316cb0e6213012df5ef" - integrity sha512-/1iyBhz/W8jUepjGyu7V1OPcGbc636snN1yXEQCinb6Bwt7KxsiU7/bLQlp8GwAXzCh7cobBU5odNn/2zQWR8Q== - dependencies: - postcss-selector-parser "^6.0.4" - -postcss-dir-pseudo-class@^6.0.3: - version "6.0.4" - resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.4.tgz#9afe49ea631f0cb36fa0076e7c2feb4e7e3f049c" - integrity sha512-I8epwGy5ftdzNWEYok9VjW9whC4xnelAtbajGv4adql4FIF09rnrxnA9Y8xSHN47y7gqFIv10C5+ImsLeJpKBw== - dependencies: - postcss-selector-parser "^6.0.9" - -postcss-discard-comments@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.0.3.tgz#011acb63418d600fdbe18804e1bbecb543ad2f87" - integrity sha512-6W5BemziRoqIdAKT+1QjM4bNcJAQ7z7zk073730NHg4cUXh3/rQHHj7pmYxUB9aGhuRhBiUf0pXvIHkRwhQP0Q== - -postcss-discard-duplicates@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.3.tgz#10f202a4cfe9d407b73dfea7a477054d21ea0c1f" - integrity sha512-vPtm1Mf+kp7iAENTG7jI1MN1lk+fBqL5y+qxyi4v3H+lzsXEdfS3dwUZD45KVhgzDEgduur8ycB4hMegyMTeRw== - -postcss-discard-empty@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.0.3.tgz#ec185af4a3710b88933b0ff751aa157b6041dd6a" - integrity sha512-xGJugpaXKakwKI7sSdZjUuN4V3zSzb2Y0LOlmTajFbNinEjTfVs9PFW2lmKBaC/E64WwYppfqLD03P8l9BuueA== - -postcss-discard-overridden@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.0.4.tgz#cc999d6caf18ea16eff8b2b58f48ec3ddee35c9c" - integrity sha512-3j9QH0Qh1KkdxwiZOW82cId7zdwXVQv/gRXYDnwx5pBtR1sTkU4cXRK9lp5dSdiM0r0OICO/L8J6sV1/7m0kHg== - -postcss-double-position-gradients@^3.0.4: - version "3.0.5" - resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-3.0.5.tgz#f6b755e9850bb9816dfbf8fa346d9ce2e8a03848" - integrity sha512-XiZzvdxLOWZwtt/1GgHJYGoD9scog/DD/yI5dcvPrXNdNDEv7T53/6tL7ikl+EM3jcerII5/XIQzd1UHOdTi2w== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-env-function@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-4.0.5.tgz#b9614d50abd91e4c88a114644a9766880dabe393" - integrity sha512-gPUJc71ji9XKyl0WSzAalBeEA/89kU+XpffpPxSaaaZ1c48OL36r1Ep5R6+9XAPkIiDlSvVAwP4io12q/vTcvA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-flexbugs-fixes@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz#2028e145313074fc9abe276cb7ca14e5401eb49d" - integrity sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ== - -postcss-focus-visible@^6.0.3: - version "6.0.4" - resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz#50c9ea9afa0ee657fb75635fabad25e18d76bf9e" - integrity sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw== - dependencies: - postcss-selector-parser "^6.0.9" - -postcss-focus-within@^5.0.3: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz#5b1d2ec603195f3344b716c0b75f61e44e8d2e20" - integrity sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ== - dependencies: - postcss-selector-parser "^6.0.9" - -postcss-font-variant@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz#efd59b4b7ea8bb06127f2d031bfbb7f24d32fa66" - integrity sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA== - -postcss-gap-properties@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-3.0.3.tgz#6401bb2f67d9cf255d677042928a70a915e6ba60" - integrity sha512-rPPZRLPmEKgLk/KlXMqRaNkYTUpE7YC+bOIQFN5xcu1Vp11Y4faIXv6/Jpft6FMnl6YRxZqDZG0qQOW80stzxQ== - -postcss-image-set-function@^4.0.5: - version "4.0.6" - resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-4.0.6.tgz#bcff2794efae778c09441498f40e0c77374870a9" - integrity sha512-KfdC6vg53GC+vPd2+HYzsZ6obmPqOk6HY09kttU19+Gj1nC3S3XBVEXDHxkhxTohgZqzbUb94bKXvKDnYWBm/A== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-initial@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-4.0.1.tgz#529f735f72c5724a0fb30527df6fb7ac54d7de42" - integrity sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ== - -postcss-js@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.0.tgz#31db79889531b80dc7bc9b0ad283e418dce0ac00" - integrity sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ== - dependencies: - camelcase-css "^2.0.1" - -postcss-lab-function@^4.0.3: - version "4.0.4" - resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-4.0.4.tgz#504747ab2754e046fb01e72779bbb434a05357df" - integrity sha512-TAEW8X/ahMYV33mvLFQARtBPAy1VVJsiR9VVx3Pcbu+zlqQj0EIyJ/Ie1/EwxwIt530CWtEDzzTXBDzfdb+qIQ== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-load-config@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.1.tgz#2f53a17f2f543d9e63864460af42efdac0d41f87" - integrity sha512-c/9XYboIbSEUZpiD1UQD0IKiUe8n9WHYV7YFe7X7J+ZwCsEKkUJSFWjS9hBU1RR9THR7jMXst8sxiqP0jjo2mg== - dependencies: - lilconfig "^2.0.4" - yaml "^1.10.2" - -postcss-loader@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.1.tgz#0895f7346b1702103d30fdc66e4d494a93c008ef" - integrity sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q== - dependencies: - cosmiconfig "^7.0.0" - klona "^2.0.5" - semver "^7.3.5" - -postcss-logical@^5.0.3: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-5.0.4.tgz#ec75b1ee54421acc04d5921576b7d8db6b0e6f73" - integrity sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g== - -postcss-media-minmax@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz#7140bddec173e2d6d657edbd8554a55794e2a5b5" - integrity sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ== - -postcss-merge-longhand@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.0.6.tgz#090e60d5d3b3caad899f8774f8dccb33217d2166" - integrity sha512-rkmoPwQO6ymJSmWsX6l2hHeEBQa7C4kJb9jyi5fZB1sE8nSCv7sqchoYPixRwX/yvLoZP2y6FA5kcjiByeJqDg== - dependencies: - postcss-value-parser "^4.2.0" - stylehacks "^5.0.3" - -postcss-merge-rules@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.6.tgz#26b37411fe1e80202fcef61cab027265b8925f2b" - integrity sha512-nzJWJ9yXWp8AOEpn/HFAW72WKVGD2bsLiAmgw4hDchSij27bt6TF+sIK0cJUBAYT3SGcjtGGsOR89bwkkMuMgQ== - dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" - cssnano-utils "^3.0.2" - postcss-selector-parser "^6.0.5" - -postcss-minify-font-values@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.0.4.tgz#627d824406b0712243221891f40a44fffe1467fd" - integrity sha512-RN6q3tyuEesvyCYYFCRGJ41J1XFvgV+dvYGHr0CeHv8F00yILlN8Slf4t8XW4IghlfZYCeyRrANO6HpJ948ieA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-minify-gradients@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.0.6.tgz#b07cef51a93f075e94053fd972ff1cba2eaf6503" - integrity sha512-E/dT6oVxB9nLGUTiY/rG5dX9taugv9cbLNTFad3dKxOO+BQg25Q/xo2z2ddG+ZB1CbkZYaVwx5blY8VC7R/43A== - dependencies: - colord "^2.9.1" - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" - -postcss-minify-params@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.0.5.tgz#86cb624358cd45c21946f8c317893f0449396646" - integrity sha512-YBNuq3Rz5LfLFNHb9wrvm6t859b8qIqfXsWeK7wROm3jSKNpO1Y5e8cOyBv6Acji15TgSrAwb3JkVNCqNyLvBg== - dependencies: - browserslist "^4.16.6" - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" - -postcss-minify-selectors@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.1.3.tgz#6ac12d52aa661fd509469d87ab2cebb0a1e3a1b5" - integrity sha512-9RJfTiQEKA/kZhMaEXND893nBqmYQ8qYa/G+uPdVnXF6D/FzpfI6kwBtWEcHx5FqDbA79O9n6fQJfrIj6M8jvQ== - dependencies: - postcss-selector-parser "^6.0.5" - -postcss-modules-extract-imports@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" - integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== - -postcss-modules-local-by-default@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" - integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== - dependencies: - icss-utils "^5.0.0" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.1.0" - -postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== - dependencies: - postcss-selector-parser "^6.0.4" - -postcss-modules-values@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" - integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== - dependencies: - icss-utils "^5.0.0" - -postcss-nested@5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-5.0.6.tgz#466343f7fc8d3d46af3e7dba3fcd47d052a945bc" - integrity sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA== - dependencies: - postcss-selector-parser "^6.0.6" - -postcss-nesting@^10.1.2: - version "10.1.2" - resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-10.1.2.tgz#2e5f811b3d75602ea18a95dd445bde5297145141" - integrity sha512-dJGmgmsvpzKoVMtDMQQG/T6FSqs6kDtUDirIfl4KnjMCiY9/ETX8jdKyCd20swSRAbUYkaBKV20pxkzxoOXLqQ== - dependencies: - postcss-selector-parser "^6.0.8" - -postcss-normalize-charset@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.0.3.tgz#719fb9f9ca9835fcbd4fed8d6e0d72a79e7b5472" - integrity sha512-iKEplDBco9EfH7sx4ut7R2r/dwTnUqyfACf62Unc9UiyFuI7uUqZZtY+u+qp7g8Qszl/U28HIfcsI3pEABWFfA== - -postcss-normalize-display-values@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.3.tgz#94cc82e20c51cc4ffba6b36e9618adc1e50db8c1" - integrity sha512-FIV5FY/qs4Ja32jiDb5mVj5iWBlS3N8tFcw2yg98+8MkRgyhtnBgSC0lxU+16AMHbjX5fbSJgw5AXLMolonuRQ== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-positions@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.0.4.tgz#4001f38c99675437b83277836fb4291887fcc6cc" - integrity sha512-qynirjBX0Lc73ROomZE3lzzmXXTu48/QiEzKgMeqh28+MfuHLsuqC9po4kj84igZqqFGovz8F8hf44hA3dPYmQ== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-repeat-style@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.4.tgz#d005adf9ee45fae78b673031a376c0c871315145" - integrity sha512-Innt+wctD7YpfeDR7r5Ik6krdyppyAg2HBRpX88fo5AYzC1Ut/l3xaxACG0KsbX49cO2n5EB13clPwuYVt8cMA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-string@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.0.4.tgz#b5e00a07597e7aa8a871817bfeac2bfaa59c3333" - integrity sha512-Dfk42l0+A1CDnVpgE606ENvdmksttLynEqTQf5FL3XGQOyqxjbo25+pglCUvziicTxjtI2NLUR6KkxyUWEVubQ== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-timing-functions@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.3.tgz#47210227bfcba5e52650d7a18654337090de7072" - integrity sha512-QRfjvFh11moN4PYnJ7hia4uJXeFotyK3t2jjg8lM9mswleGsNw2Lm3I5wO+l4k1FzK96EFwEVn8X8Ojrp2gP4g== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize-unicode@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.4.tgz#02866096937005cdb2c17116c690f29505a1623d" - integrity sha512-W79Regn+a+eXTzB+oV/8XJ33s3pDyFTND2yDuUCo0Xa3QSy1HtNIfRVPXNubHxjhlqmMFADr3FSCHT84ITW3ig== - dependencies: - browserslist "^4.16.6" - postcss-value-parser "^4.2.0" - -postcss-normalize-url@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.0.5.tgz#c39efc12ff119f6f45f0b4f516902b12c8080e3a" - integrity sha512-Ws3tX+PcekYlXh+ycAt0wyzqGthkvVtZ9SZLutMVvHARxcpu4o7vvXcNoiNKyjKuWecnjS6HDI3fjBuDr5MQxQ== - dependencies: - normalize-url "^6.0.1" - postcss-value-parser "^4.2.0" - -postcss-normalize-whitespace@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.4.tgz#1d477e7da23fecef91fc4e37d462272c7b55c5ca" - integrity sha512-wsnuHolYZjMwWZJoTC9jeI2AcjA67v4UuidDrPN9RnX8KIZfE+r2Nd6XZRwHVwUiHmRvKQtxiqo64K+h8/imaw== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-normalize@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize/-/postcss-normalize-10.0.1.tgz#464692676b52792a06b06880a176279216540dd7" - integrity sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA== - dependencies: - "@csstools/normalize.css" "*" - postcss-browser-comments "^4" - sanitize.css "*" - -postcss-opacity-percentage@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.2.tgz#bd698bb3670a0a27f6d657cc16744b3ebf3b1145" - integrity sha512-lyUfF7miG+yewZ8EAk9XUBIlrHyUE6fijnesuz+Mj5zrIHIEw6KcIZSOk/elVMqzLvREmXB83Zi/5QpNRYd47w== - -postcss-ordered-values@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.0.5.tgz#e878af822a130c3f3709737e24cb815ca7c6d040" - integrity sha512-mfY7lXpq+8bDEHfP+muqibDPhZ5eP9zgBEF9XRvoQgXcQe2Db3G1wcvjbnfjXG6wYsl+0UIjikqq4ym1V2jGMQ== - dependencies: - cssnano-utils "^3.0.2" - postcss-value-parser "^4.2.0" - -postcss-overflow-shorthand@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.3.tgz#ebcfc0483a15bbf1b27fdd9b3c10125372f4cbc2" - integrity sha512-CxZwoWup9KXzQeeIxtgOciQ00tDtnylYIlJBBODqkgS/PU2jISuWOL/mYLHmZb9ZhZiCaNKsCRiLp22dZUtNsg== - -postcss-page-break@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-3.0.4.tgz#7fbf741c233621622b68d435babfb70dd8c1ee5f" - integrity sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ== - -postcss-place@^7.0.3: - version "7.0.4" - resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-7.0.4.tgz#eb026650b7f769ae57ca4f938c1addd6be2f62c9" - integrity sha512-MrgKeiiu5OC/TETQO45kV3npRjOFxEHthsqGtkh3I1rPbZSbXGD/lZVi9j13cYh+NA8PIAPyk6sGjT9QbRyvSg== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-preset-env@^7.0.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-7.3.1.tgz#f17c609cfab3432620b92888464f92b4dba5eca0" - integrity sha512-x7fNsJxfkY60P4FUNwhJUOfXBFfnObd2EcUYY97sXZ0XRLgmAE65es9EFIYHq1rAk7X3LMfbG+L9wYgkrNsq5Q== - dependencies: - "@csstools/postcss-font-format-keywords" "^1.0.0" - "@csstools/postcss-hwb-function" "^1.0.0" - "@csstools/postcss-is-pseudo-class" "^2.0.0" - "@csstools/postcss-normalize-display-values" "^1.0.0" - autoprefixer "^10.4.2" - browserslist "^4.19.1" - css-blank-pseudo "^3.0.2" - css-has-pseudo "^3.0.3" - css-prefers-color-scheme "^6.0.3" - cssdb "^6.1.0" - postcss-attribute-case-insensitive "^5.0.0" - postcss-clamp "^3.0.0" - postcss-color-functional-notation "^4.2.1" - postcss-color-hex-alpha "^8.0.2" - postcss-color-rebeccapurple "^7.0.2" - postcss-custom-media "^8.0.0" - postcss-custom-properties "^12.1.4" - postcss-custom-selectors "^6.0.0" - postcss-dir-pseudo-class "^6.0.3" - postcss-double-position-gradients "^3.0.4" - postcss-env-function "^4.0.4" - postcss-focus-visible "^6.0.3" - postcss-focus-within "^5.0.3" - postcss-font-variant "^5.0.0" - postcss-gap-properties "^3.0.2" - postcss-image-set-function "^4.0.5" - postcss-initial "^4.0.1" - postcss-lab-function "^4.0.3" - postcss-logical "^5.0.3" - postcss-media-minmax "^5.0.0" - postcss-nesting "^10.1.2" - postcss-opacity-percentage "^1.1.2" - postcss-overflow-shorthand "^3.0.2" - postcss-page-break "^3.0.4" - postcss-place "^7.0.3" - postcss-pseudo-class-any-link "^7.1.0" - postcss-replace-overflow-wrap "^4.0.0" - postcss-selector-not "^5.0.0" - -postcss-pseudo-class-any-link@^7.1.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.1.tgz#534eb1dadd9945eb07830dbcc06fb4d5d865b8e0" - integrity sha512-JRoLFvPEX/1YTPxRxp1JO4WxBVXJYrSY7NHeak5LImwJ+VobFMwYDQHvfTXEpcn+7fYIeGkC29zYFhFWIZD8fg== - dependencies: - postcss-selector-parser "^6.0.9" - -postcss-reduce-initial@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.0.3.tgz#68891594defd648253703bbd8f1093162f19568d" - integrity sha512-c88TkSnQ/Dnwgb4OZbKPOBbCaauwEjbECP5uAuFPOzQ+XdjNjRH7SG0dteXrpp1LlIFEKK76iUGgmw2V0xeieA== - dependencies: - browserslist "^4.16.6" - caniuse-api "^3.0.0" - -postcss-reduce-transforms@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.4.tgz#717e72d30befe857f7d2784dba10eb1157863712" - integrity sha512-VIJB9SFSaL8B/B7AXb7KHL6/GNNbbCHslgdzS9UDfBZYIA2nx8NLY7iD/BXFSO/1sRUILzBTfHCoW5inP37C5g== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-replace-overflow-wrap@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz#d2df6bed10b477bf9c52fab28c568b4b29ca4319" - integrity sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw== - -postcss-selector-not@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-5.0.0.tgz#ac5fc506f7565dd872f82f5314c0f81a05630dc7" - integrity sha512-/2K3A4TCP9orP4TNS7u3tGdRFVKqz/E6pX3aGnriPG0jU78of8wsUcqE4QAhWEU0d+WnMSF93Ah3F//vUtK+iQ== - dependencies: - balanced-match "^1.0.0" - -postcss-selector-parser@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" - integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== - dependencies: - cssesc "^3.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.8, postcss-selector-parser@^6.0.9: - version "6.0.9" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" - integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - -postcss-svgo@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.4.tgz#cfa8682f47b88f7cd75108ec499e133b43102abf" - integrity sha512-yDKHvULbnZtIrRqhZoA+rxreWpee28JSRH/gy9727u0UCgtpv1M/9WEWY3xySlFa0zQJcqf6oCBJPR5NwkmYpg== - dependencies: - postcss-value-parser "^4.2.0" - svgo "^2.7.0" - -postcss-unique-selectors@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.0.4.tgz#08e188126b634ddfa615fb1d6c262bafdd64826e" - integrity sha512-5ampwoSDJCxDPoANBIlMgoBcYUHnhaiuLYJR5pj1DLnYQvMRVyFuTA5C3Bvt+aHtiqWpJkD/lXT50Vo1D0ZsAQ== - dependencies: - postcss-selector-parser "^6.0.5" - -postcss-value-parser@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" - integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== - -postcss-value-parser@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" - integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== - -postcss@^7.0.35: - version "7.0.39" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" - integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== - dependencies: - picocolors "^0.2.1" - source-map "^0.6.1" - -postcss@^8.3.5, postcss@^8.4.4, postcss@^8.4.5: - version "8.4.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1" - integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA== - dependencies: - nanoid "^3.2.0" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - -prettier@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" - integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== - -pretty-bytes@^5.3.0, pretty-bytes@^5.4.1, pretty-bytes@^5.6.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" - integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== - -pretty-error@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" - integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== - dependencies: - lodash "^4.17.20" - renderkid "^3.0.0" - -pretty-format@^27.0.0, pretty-format@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" - integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== - dependencies: - ansi-regex "^5.0.1" - ansi-styles "^5.0.0" - react-is "^17.0.1" - -pretty-hrtime@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" - integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= - -private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -promise-inflight@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= - -promise-retry@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" - integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== - dependencies: - err-code "^2.0.2" - retry "^0.12.0" - -promise@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/promise/-/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e" - integrity sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q== - dependencies: - asap "~2.0.6" - -prompts@^2.0.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.0.tgz#4aa5de0723a231d1ee9121c40fdf663df73f61d7" - integrity sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -prompts@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -promzard@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee" - integrity sha1-JqXW7ox97kyxIggwWs+5O6OCqe4= - dependencies: - read "1" - -prop-types-exact@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/prop-types-exact/-/prop-types-exact-1.2.0.tgz#825d6be46094663848237e3925a98c6e944e9869" - integrity sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA== - dependencies: - has "^1.0.3" - object.assign "^4.1.0" - reflect.ownkeys "^0.2.0" - -prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2: - version "15.7.2" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" - integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.8.1" - -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= - -protocols@^1.1.0, protocols@^1.4.0: - version "1.4.7" - resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.7.tgz#95f788a4f0e979b291ffefcf5636ad113d037d32" - integrity sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg== - -proxy-addr@~2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" - integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ== - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.9.0" - -proxy-from-env@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" - integrity sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4= - -ps-tree@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd" - integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA== - dependencies: - event-stream "=3.3.4" - -psl@^1.1.24, psl@^1.1.28: - version "1.4.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" - integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== - -psl@^1.1.33: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@^1.3.2, punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -q@^1.1.2, q@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= - -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -quick-lru@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" - integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== - -quick-lru@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" - integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== - -raf@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" - integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== - dependencies: - performance-now "^2.1.0" - -railroad-diagrams@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e" - integrity sha1-635iZ1SN3t+4mcG5Dlc3RVnN234= - -randexp@0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3" - integrity sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ== - dependencies: - discontinuous-range "1.0.0" - ret "~0.1.10" - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -range-parser@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= - -range-parser@^1.2.1, range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - -rc@^1.0.1, rc@^1.1.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -react-app-polyfill@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz#95221e0a9bd259e5ca6b177c7bb1cb6768f68fd7" - integrity sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w== - dependencies: - core-js "^3.19.2" - object-assign "^4.1.1" - promise "^8.1.0" - raf "^3.4.1" - regenerator-runtime "^0.13.9" - whatwg-fetch "^3.6.2" - -react-dev-utils@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.0.tgz#4eab12cdb95692a077616770b5988f0adf806526" - integrity sha512-xBQkitdxozPxt1YZ9O1097EJiVpwHr9FoAuEVURCKV0Av8NBERovJauzP7bo1ThvuhZ4shsQ1AJiu4vQpoT1AQ== - dependencies: - "@babel/code-frame" "^7.16.0" - address "^1.1.2" - browserslist "^4.18.1" - chalk "^4.1.2" - cross-spawn "^7.0.3" - detect-port-alt "^1.1.6" - escape-string-regexp "^4.0.0" - filesize "^8.0.6" - find-up "^5.0.0" - fork-ts-checker-webpack-plugin "^6.5.0" - global-modules "^2.0.0" - globby "^11.0.4" - gzip-size "^6.0.0" - immer "^9.0.7" - is-root "^2.1.0" - loader-utils "^3.2.0" - open "^8.4.0" - pkg-up "^3.1.0" - prompts "^2.4.2" - react-error-overlay "^6.0.10" - recursive-readdir "^2.2.2" - shell-quote "^1.7.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -react-dom@^16.11.0: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" - integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.19.1" - -react-draggable@^4.4.3: - version "4.4.3" - resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.3.tgz#0727f2cae5813e36b0e4962bf11b2f9ef2b406f3" - integrity sha512-jV4TE59MBuWm7gb6Ns3Q1mxX8Azffb7oTtDtBgFkxRvhDp38YAARmRplrj0+XGkhOJB5XziArX+4HUUABtyZ0w== - dependencies: - classnames "^2.2.5" - prop-types "^15.6.0" - -react-error-boundary@^3.1.0: - version "3.1.3" - resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.3.tgz#276bfa05de8ac17b863587c9e0647522c25e2a0b" - integrity sha512-A+F9HHy9fvt9t8SNDlonq01prnU8AmkjvGKV4kk8seB9kU3xMEO8J/PQlLVmoOIDODl5U2kufSBs4vrWIqhsAA== - dependencies: - "@babel/runtime" "^7.12.5" - -react-error-overlay@^6.0.10: - version "6.0.10" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.10.tgz#0fe26db4fa85d9dbb8624729580e90e7159a59a6" - integrity sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA== - -react-i18next@^11.15.4: - version "11.15.4" - resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.15.4.tgz#fe0c792ea93f038548e838cecae3ed4173822937" - integrity sha512-jKJNAcVcbPGK+yrTcXhLblgPY16n6NbpZZL3Mk8nswj1v3ayIiUBVDU09SgqnT+DluyQBS97hwSvPU5yVFG0yg== - dependencies: - "@babel/runtime" "^7.14.5" - html-escaper "^2.0.2" - html-parse-stringify "^3.0.1" - -react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6, react-is@^16.9.0: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -"react-is@^16.8.0 || ^17.0.0", react-is@^17.0.1: - version "17.0.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" - integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA== - -react-lifecycles-compat@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" - integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== - -react-query@^3.18.1: - version "3.18.1" - resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.18.1.tgz#893b5475a7b4add099e007105317446f7a2cd310" - integrity sha512-17lv3pQxU9n+cB5acUv0/cxNTjo9q8G+RsedC6Ax4V9D8xEM7Q5xf9xAbCPdEhDrrnzPjTls9fQEABKRSi7OJA== - dependencies: - "@babel/runtime" "^7.5.5" - broadcast-channel "^3.4.1" - match-sorter "^6.0.2" - -react-redux@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d" - integrity sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA== - dependencies: - "@babel/runtime" "^7.5.5" - hoist-non-react-statics "^3.3.0" - loose-envify "^1.4.0" - prop-types "^15.7.2" - react-is "^16.9.0" - -react-refresh@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" - integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A== - -react-router-dom@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.0.tgz#da1bfb535a0e89a712a93b97dd76f47ad1f32363" - integrity sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ== - dependencies: - "@babel/runtime" "^7.12.13" - history "^4.9.0" - loose-envify "^1.3.1" - prop-types "^15.6.2" - react-router "5.2.1" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - -react-router@5.2.1, react-router@^5.0.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.1.tgz#4d2e4e9d5ae9425091845b8dbc6d9d276239774d" - integrity sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ== - dependencies: - "@babel/runtime" "^7.12.13" - history "^4.9.0" - hoist-non-react-statics "^3.1.0" - loose-envify "^1.3.1" - mini-create-react-context "^0.4.0" - path-to-regexp "^1.7.0" - prop-types "^15.6.2" - react-is "^16.6.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - -react-scripts@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-5.0.0.tgz#6547a6d7f8b64364ef95273767466cc577cb4b60" - integrity sha512-3i0L2CyIlROz7mxETEdfif6Sfhh9Lfpzi10CtcGs1emDQStmZfWjJbAIMtRD0opVUjQuFWqHZyRZ9PPzKCFxWg== - dependencies: - "@babel/core" "^7.16.0" - "@pmmmwh/react-refresh-webpack-plugin" "^0.5.3" - "@svgr/webpack" "^5.5.0" - babel-jest "^27.4.2" - babel-loader "^8.2.3" - babel-plugin-named-asset-import "^0.3.8" - babel-preset-react-app "^10.0.1" - bfj "^7.0.2" - browserslist "^4.18.1" - camelcase "^6.2.1" - case-sensitive-paths-webpack-plugin "^2.4.0" - css-loader "^6.5.1" - css-minimizer-webpack-plugin "^3.2.0" - dotenv "^10.0.0" - dotenv-expand "^5.1.0" - eslint "^8.3.0" - eslint-config-react-app "^7.0.0" - eslint-webpack-plugin "^3.1.1" - file-loader "^6.2.0" - fs-extra "^10.0.0" - html-webpack-plugin "^5.5.0" - identity-obj-proxy "^3.0.0" - jest "^27.4.3" - jest-resolve "^27.4.2" - jest-watch-typeahead "^1.0.0" - mini-css-extract-plugin "^2.4.5" - postcss "^8.4.4" - postcss-flexbugs-fixes "^5.0.2" - postcss-loader "^6.2.1" - postcss-normalize "^10.0.1" - postcss-preset-env "^7.0.1" - prompts "^2.4.2" - react-app-polyfill "^3.0.0" - react-dev-utils "^12.0.0" - react-refresh "^0.11.0" - resolve "^1.20.0" - resolve-url-loader "^4.0.0" - sass-loader "^12.3.0" - semver "^7.3.5" - source-map-loader "^3.0.0" - style-loader "^3.3.1" - tailwindcss "^3.0.2" - terser-webpack-plugin "^5.2.5" - webpack "^5.64.4" - webpack-dev-server "^4.6.0" - webpack-manifest-plugin "^4.0.2" - workbox-webpack-plugin "^6.4.1" - optionalDependencies: - fsevents "^2.3.2" - -react-test-renderer@16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.13.1.tgz#de25ea358d9012606de51e012d9742e7f0deabc1" - integrity sha512-Sn2VRyOK2YJJldOqoh8Tn/lWQ+ZiKhyZTPtaO0Q6yNj+QDbmRkVFap6pZPy3YQk8DScRDfyqm/KxKYP9gCMRiQ== - dependencies: - object-assign "^4.1.1" - prop-types "^15.6.2" - react-is "^16.8.6" - scheduler "^0.19.1" - -react-test-renderer@^16.0.0-0: - version "16.12.0" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.12.0.tgz#11417ffda579306d4e841a794d32140f3da1b43f" - integrity sha512-Vj/teSqt2oayaWxkbhQ6gKis+t5JrknXfPVo+aIJ8QwYAqMPH77uptOdrlphyxl8eQI/rtkOYg86i/UWkpFu0w== - dependencies: - object-assign "^4.1.1" - prop-types "^15.6.2" - react-is "^16.8.6" - scheduler "^0.18.0" - -react-transition-group@^4.0.0, react-transition-group@^4.4.0: - version "4.4.1" - resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" - integrity sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw== - dependencies: - "@babel/runtime" "^7.5.5" - dom-helpers "^5.0.1" - loose-envify "^1.4.0" - prop-types "^15.6.2" - -react-virtualized@^9.22.3: - version "9.22.3" - resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.22.3.tgz#f430f16beb0a42db420dbd4d340403c0de334421" - integrity sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw== - dependencies: - "@babel/runtime" "^7.7.2" - clsx "^1.0.4" - dom-helpers "^5.1.3" - loose-envify "^1.4.0" - prop-types "^15.7.2" - react-lifecycles-compat "^3.0.4" - -react@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" - integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - -read-cmd-shim@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-2.0.0.tgz#4a50a71d6f0965364938e9038476f7eede3928d9" - integrity sha512-HJpV9bQpkl6KwjxlJcBoqu9Ba0PQg8TqSNIOrulGt54a0uup0HtevreFHzYzkm0lpnleRdNBzXznKrgxglEHQw== - -read-package-json-fast@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz#323ca529630da82cb34b36cc0b996693c98c2b83" - integrity sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ== - dependencies: - json-parse-even-better-errors "^2.3.0" - npm-normalize-package-bin "^1.0.1" - -read-package-json@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.0.tgz#e3d42e6c35ea5ae820d9a03ab0c7291217fc51d5" - integrity sha512-KLhu8M1ZZNkMcrq1+0UJbR8Dii8KZUqB0Sha4mOx/bknfKI/fyrQVrG/YIt2UOtG667sD8+ee4EXMM91W9dC+A== - dependencies: - glob "^7.1.1" - json-parse-better-errors "^1.0.1" - normalize-package-data "^2.0.0" - slash "^1.0.0" - optionalDependencies: - graceful-fs "^4.1.2" - -read-package-json@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-3.0.1.tgz#c7108f0b9390257b08c21e3004d2404c806744b9" - integrity sha512-aLcPqxovhJTVJcsnROuuzQvv6oziQx4zd3JvG0vGCL5MjTONUc4uJ90zCBC6R7W7oUKBNoR/F8pkyfVwlbxqng== - dependencies: - glob "^7.1.1" - json-parse-even-better-errors "^2.3.0" - normalize-package-data "^3.0.0" - npm-normalize-package-bin "^1.0.0" - -read-package-json@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-4.1.1.tgz#153be72fce801578c1c86b8ef2b21188df1b9eea" - integrity sha512-P82sbZJ3ldDrWCOSKxJT0r/CXMWR0OR3KRh55SgKo3p91GSIEEC32v3lSHAvO/UcH3/IoL7uqhOFBduAnwdldw== - dependencies: - glob "^7.1.1" - json-parse-even-better-errors "^2.3.0" - normalize-package-data "^3.0.0" - npm-normalize-package-bin "^1.0.0" - -read-package-tree@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.3.1.tgz#a32cb64c7f31eb8a6f31ef06f9cedf74068fe636" - integrity sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw== - dependencies: - read-package-json "^2.0.0" - readdir-scoped-modules "^1.0.0" - util-promisify "^2.1.0" - -read-pkg-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= - dependencies: - find-up "^2.0.0" - read-pkg "^3.0.0" - -read-pkg-up@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" - integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== - dependencies: - find-up "^4.1.0" - read-pkg "^5.2.0" - type-fest "^0.8.1" - -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= - dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" - -read-pkg@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" - integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== - dependencies: - "@types/normalize-package-data" "^2.4.0" - normalize-package-data "^2.5.0" - parse-json "^5.0.0" - type-fest "^0.6.0" - -read@1, read@~1.0.1: - version "1.0.7" - resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" - integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= - dependencies: - mute-stream "~0.0.4" - -readable-stream@3, readable-stream@^3.0.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@~2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - 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" - -readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" - integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdir-scoped-modules@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309" - integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw== - dependencies: - debuglog "^1.0.1" - dezalgo "^1.0.0" - graceful-fs "^4.1.2" - once "^1.3.0" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -recursive-readdir@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" - integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== - dependencies: - minimatch "3.0.4" - -redent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" - integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== - dependencies: - indent-string "^4.0.0" - strip-indent "^3.0.0" - -redux-logger@^3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf" - integrity sha1-91VZZvMJjzyIYExEnPC69XeCdL8= - dependencies: - deep-diff "^0.3.5" - -redux-mock-store@^1.5.4: - version "1.5.4" - resolved "https://registry.yarnpkg.com/redux-mock-store/-/redux-mock-store-1.5.4.tgz#90d02495fd918ddbaa96b83aef626287c9ab5872" - integrity sha512-xmcA0O/tjCLXhh9Fuiq6pMrJCwFRaouA8436zcikdIpYWWCjU76CRk+i2bHx8EeiSiMGnB85/lZdU3wIJVXHTA== - dependencies: - lodash.isplainobject "^4.0.6" - -redux-thunk@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.1.tgz#0dd8042cf47868f4b29699941de03c9301a75714" - integrity sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q== - -redux@^4.0.0, redux@^4.0.5, redux@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.2.tgz#140f35426d99bb4729af760afcf79eaaac407104" - integrity sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw== - dependencies: - "@babel/runtime" "^7.9.2" - -reflect.ownkeys@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460" - integrity sha1-dJrO7H8/34tj+SegSAnpDFwLNGA= - -regenerate-unicode-properties@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" - integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw== - dependencies: - regenerate "^1.4.2" - -regenerate-unicode-properties@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" - integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== - dependencies: - regenerate "^1.4.0" - -regenerate-unicode-properties@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" - integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== - dependencies: - regenerate "^1.4.0" - -regenerate@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== - -regenerate@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.9: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== - -regenerator-transform@^0.14.2: - version "0.14.4" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" - integrity sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw== - dependencies: - "@babel/runtime" "^7.8.4" - private "^0.1.8" - -regex-parser@^2.2.11: - version "2.2.11" - resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.11.tgz#3b37ec9049e19479806e878cabe7c1ca83ccfe58" - integrity sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q== - -regexp.prototype.flags@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c" - integrity sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA== - dependencies: - define-properties "^1.1.2" - -regexp.prototype.flags@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" - integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - -regexpu-core@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" - integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.1.0" - regjsgen "^0.5.0" - regjsparser "^0.6.0" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.1.0" - -regexpu-core@^4.7.1: - version "4.7.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" - integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== - 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" - -regexpu-core@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.0.1.tgz#c531122a7840de743dcf9c83e923b5560323ced3" - integrity sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw== - dependencies: - regenerate "^1.4.2" - regenerate-unicode-properties "^10.0.1" - regjsgen "^0.6.0" - regjsparser "^0.8.2" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.0.0" - -registry-auth-token@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" - integrity sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ== - dependencies: - rc "^1.1.6" - safe-buffer "^5.0.1" - -registry-url@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" - integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI= - dependencies: - rc "^1.0.1" - -regjsgen@^0.5.0, regjsgen@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" - integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== - -regjsgen@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d" - integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA== - -regjsparser@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" - integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== - dependencies: - jsesc "~0.5.0" - -regjsparser@^0.6.4: - version "0.6.4" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" - integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== - dependencies: - jsesc "~0.5.0" - -regjsparser@^0.8.2: - version "0.8.4" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.8.4.tgz#8a14285ffcc5de78c5b95d62bbf413b6bc132d5f" - integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA== - dependencies: - jsesc "~0.5.0" - -relateurl@^0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= - -remove-accents@0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5" - integrity sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U= - -renderkid@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" - integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== - dependencies: - css-select "^4.1.3" - dom-converter "^0.2.0" - htmlparser2 "^6.1.0" - lodash "^4.17.21" - strip-ansi "^6.0.1" - -request-progress@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe" - integrity sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4= - dependencies: - throttleit "^1.0.0" - -request@^2.87.0: - version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== - 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" - -request@^2.88.2: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - 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" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -resize-observer-polyfill@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" - integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve-pathname@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" - integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== - -resolve-url-loader@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz#d50d4ddc746bb10468443167acf800dcd6c3ad57" - integrity sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA== - 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" - -resolve.exports@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" - integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== - -resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.20.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" - -resolve@^1.19.0, resolve@^1.22.0: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== - dependencies: - is-core-module "^2.8.1" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@^2.0.0-next.3: - version "2.0.0-next.3" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.3.tgz#d41016293d4a8586a39ca5d9b5f15cbea1f55e46" - integrity sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -retry@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= - -retry@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" - integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rfdc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" - integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== - -rifm@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/rifm/-/rifm-0.7.0.tgz#debe951a9c83549ca6b33e5919f716044c2230be" - integrity sha512-DSOJTWHD67860I5ojetXdEQRIBvF6YcpNe53j0vn1vp9EUb9N80EiZTxgP+FkDKorWC8PZw052kTF4C1GOivCQ== - dependencies: - "@babel/runtime" "^7.3.1" - -rimraf@2: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -rollup-plugin-terser@^7.0.0: - version "7.0.2" - resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" - integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ== - dependencies: - "@babel/code-frame" "^7.10.4" - jest-worker "^26.2.1" - serialize-javascript "^4.0.0" - terser "^5.0.0" - -rollup@^2.43.1: - version "2.67.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.67.1.tgz#4402665706fa00f321d446ce45f880e02cf54f01" - integrity sha512-1Sbcs4OuW+aD+hhqpIRl+RqooIpF6uQcfzU/QSI7vGkwADY6cM4iLsBGRM2CGLXDTDN5y/yShohFmnKegSPWzg== - optionalDependencies: - fsevents "~2.3.2" - -rst-selector-parser@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91" - integrity sha1-gbIw6i/MYGbInjRy3nlChdmwPZE= - dependencies: - lodash.flattendeep "^4.4.0" - nearley "^2.7.10" - -run-async@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= - dependencies: - is-promise "^2.1.0" - -run-async@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8" - integrity sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg== - dependencies: - is-promise "^2.1.0" - -run-parallel@^1.1.9: - version "1.1.10" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef" - integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw== - -rxjs@^6.5.3: - version "6.5.4" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" - integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== - dependencies: - tslib "^1.9.0" - -rxjs@^6.6.0: - version "6.6.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" - integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== - dependencies: - tslib "^1.9.0" - -rxjs@^7.1.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.4.0.tgz#a12a44d7eebf016f5ff2441b87f28c9a51cebc68" - integrity sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w== - dependencies: - tslib "~2.1.0" - -rxjs@^7.5.1: - version "7.5.4" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.4.tgz#3d6bd407e6b7ce9a123e76b1e770dc5761aa368d" - integrity sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ== - dependencies: - tslib "^2.1.0" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sanitize.css@*: - version "13.0.0" - resolved "https://registry.yarnpkg.com/sanitize.css/-/sanitize.css-13.0.0.tgz#2675553974b27964c75562ade3bd85d79879f173" - integrity sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA== - -sass-loader@^12.3.0: - version "12.4.0" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.4.0.tgz#260b0d51a8a373bb8e88efc11f6ba5583fea0bcf" - integrity sha512-7xN+8khDIzym1oL9XyS6zP6Ges+Bo2B2xbPrjdMHEYyV3AQYhd/wXeru++3ODHF0zMjYmVadblSKrPrjEkL8mg== - dependencies: - klona "^2.0.4" - neo-async "^2.6.2" - -sax@~1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -saxes@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" - integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== - dependencies: - xmlchars "^2.2.0" - -scheduler@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" - integrity sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - -scheduler@^0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" - integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - -schema-utils@2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" - integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== - dependencies: - "@types/json-schema" "^7.0.4" - ajv "^6.12.2" - ajv-keywords "^3.4.1" - -schema-utils@^2.6.5: - version "2.6.6" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.6.tgz#299fe6bd4a3365dc23d99fd446caff8f1d6c330c" - integrity sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA== - dependencies: - ajv "^6.12.0" - ajv-keywords "^3.4.1" - -schema-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef" - integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA== - dependencies: - "@types/json-schema" "^7.0.6" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - -schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - -schema-utils@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" - 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" - -seamless-immutable@^7.1.3: - version "7.1.4" - resolved "https://registry.yarnpkg.com/seamless-immutable/-/seamless-immutable-7.1.4.tgz#6e9536def083ddc4dea0207d722e0e80d0f372f8" - integrity sha512-XiUO1QP4ki4E2PHegiGAlu6r82o5A+6tRh7IkGGTVg/h+UoeX4nFBeCGPOhb4CYjvkqsfm/TUtvOMYC1xmV30A== - -select-hose@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= - -selfsigned@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.0.tgz#e927cd5377cbb0a1075302cff8df1042cc2bce5b" - integrity sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ== - dependencies: - node-forge "^1.2.0" - -semver-compare@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" - integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= - -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.1.1, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - -semver@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= - -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - 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.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serialize-javascript@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" - integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== - dependencies: - randombytes "^2.1.0" - -serialize-javascript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - -serve-handler@6.1.3: - version "6.1.3" - resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8" - integrity sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w== - dependencies: - bytes "3.0.0" - content-disposition "0.5.2" - fast-url-parser "1.1.3" - mime-types "2.1.18" - minimatch "3.0.4" - path-is-inside "1.0.2" - path-to-regexp "2.2.1" - range-parser "1.2.0" - -serve-index@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - 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" - -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - -serve@^13.0.2: - version "13.0.2" - resolved "https://registry.yarnpkg.com/serve/-/serve-13.0.2.tgz#b19ccb854dfdf3085613cd3a4033c7807aeaf85b" - integrity sha512-71R6fKvNgKrqARAag6lYJNnxDzpH7DCNrMuvPY5PLVaC2PDhJsGTj/34o4o4tPWhTuLgEXqvgnAWbATQ9zGZTQ== - dependencies: - "@zeit/schemas" "2.6.0" - ajv "6.12.6" - arg "2.0.0" - boxen "5.1.2" - chalk "2.4.1" - clipboardy "2.3.0" - compression "1.7.3" - serve-handler "6.1.3" - update-check "1.5.2" - -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -shell-quote@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" - integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - -signal-exit@^3.0.3: - version "3.0.6" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== - -single-spa-react@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/single-spa-react/-/single-spa-react-4.3.1.tgz#7c787fe8f4da535ca46c10fae9bbace9c6567701" - integrity sha512-RD93IpUfjuHnSiPSb3zPIUYkUuDAmxj3L1fkGjVzmSCRhEcc7oZBEe68k32oN36IqyOyQPJrCiPUOMAx6aC26g== - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - -slice-ansi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" - integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -slide@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" - integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc= - -smart-buffer@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba" - integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw== - -sockjs@^0.3.21: - version "0.3.21" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" - integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw== - dependencies: - faye-websocket "^0.11.3" - uuid "^3.4.0" - websocket-driver "^0.7.4" - -socks-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz#032fb583048a29ebffec2e6a73fca0761f48177e" - integrity sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ== - dependencies: - agent-base "^6.0.2" - debug "4" - socks "^2.3.3" - -socks-proxy-agent@^6.0.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87" - integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew== - dependencies: - agent-base "^6.0.2" - debug "^4.3.1" - socks "^2.6.1" - -socks@^2.3.3, socks@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e" - integrity sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA== - dependencies: - ip "^1.1.5" - smart-buffer "^4.1.0" - -sort-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" - integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg= - dependencies: - is-plain-obj "^1.0.0" - -sort-keys@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-4.2.0.tgz#6b7638cee42c506fff8c1cecde7376d21315be18" - integrity sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg== - dependencies: - is-plain-obj "^2.0.0" - -source-list-map@^2.0.0, source-list-map@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== - -source-map-js@^1.0.1, source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -source-map-loader@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-3.0.1.tgz#9ae5edc7c2d42570934be4c95d1ccc6352eba52d" - integrity sha512-Vp1UsfyPvgujKQzi4pyDiTOnE3E4H+yHvkVRN3c/9PJmQS4CQJExvcDvaX/D+RV+xQben9HJ56jMJS3CgUeWyA== - dependencies: - abab "^2.0.5" - iconv-lite "^0.6.3" - source-map-js "^1.0.1" - -source-map-support@^0.5.6: - version "0.5.16" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" - integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - -source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@^0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.7.3, source-map@~0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - -source-map@^0.8.0-beta.0: - version "0.8.0-beta.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11" - integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA== - dependencies: - whatwg-url "^7.0.0" - -sourcemap-codec@^1.4.4: - version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== - -spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== - -spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== - -spdy-transport@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" - 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" - -spdy@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" - integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== - dependencies: - debug "^4.1.0" - handle-thing "^2.0.0" - http-deceiver "^1.2.7" - select-hose "^2.0.0" - spdy-transport "^3.0.0" - -split2@^3.0.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" - integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== - dependencies: - readable-stream "^3.0.0" - -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= - dependencies: - through "2" - -split@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== - dependencies: - through "2" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -sshpk@^1.14.1: - version "1.17.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" - integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -ssri@^8.0.0, ssri@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" - integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== - dependencies: - minipass "^3.1.1" - -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -stack-utils@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" - integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== - dependencies: - escape-string-regexp "^2.0.0" - -stackframe@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303" - integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA== - -start-server-and-test@^1.14.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-1.14.0.tgz#c57f04f73eac15dd51733b551d775b40837fdde3" - integrity sha512-on5ELuxO2K0t8EmNj9MtVlFqwBMxfWOhu4U7uZD1xccVpFlOQKR93CSe0u98iQzfNxRyaNTb/CdadbNllplTsw== - dependencies: - bluebird "3.7.2" - check-more-types "2.24.0" - debug "4.3.2" - execa "5.1.1" - lazy-ass "1.6.0" - ps-tree "1.2.0" - wait-on "6.0.0" - -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= - dependencies: - duplexer "~0.1.1" - -string-argv@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" - integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== - -string-length@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1" - integrity sha512-PKyXUd0LK0ePjSOnWn34V2uD6acUWev9uy0Ft05k0E8xRW+SKcA0F7eMr7h5xlzfn+4O3N+55rduYyet3Jk+jw== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - -string-length@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-5.0.1.tgz#3d647f497b6e8e8d41e422f7e0b23bc536c8381e" - integrity sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow== - dependencies: - char-regex "^2.0.0" - strip-ansi "^7.0.1" - -string-natural-compare@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" - integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== - -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2": - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^4.0.0, string-width@^4.2.2: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -string.prototype.matchall@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa" - integrity sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - get-intrinsic "^1.1.1" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - regexp.prototype.flags "^1.3.1" - side-channel "^1.0.4" - -string.prototype.trim@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz#141233dff32c82bfad80684d7e5f0869ee0fb782" - integrity sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" - -string.prototype.trimend@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" - integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - -string.prototype.trimend@^1.0.1, string.prototype.trimend@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" - integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string.prototype.trimleft@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== - dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" - -string.prototype.trimleft@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" - integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trimstart "^1.0.0" - -string.prototype.trimright@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== - dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" - -string.prototype.trimright@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" - integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trimend "^1.0.0" - -string.prototype.trimstart@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" - integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - -string.prototype.trimstart@^1.0.1, string.prototype.trimstart@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" - integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -stringify-object@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" - integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== - dependencies: - get-own-enumerable-property-symbols "^3.0.0" - is-obj "^1.0.1" - is-regexp "^1.0.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.0, strip-ansi@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" - integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== - dependencies: - ansi-regex "^6.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - -strip-comments@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-2.0.1.tgz#4ad11c3fbcac177a67a40ac224ca339ca1c1ba9b" - integrity sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw== - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-indent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" - integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== - dependencies: - min-indent "^1.0.0" - -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -strong-log-transformer@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" - integrity sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA== - dependencies: - duplexer "^0.1.1" - minimist "^1.2.0" - through "^2.3.4" - -style-loader@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" - integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== - -stylehacks@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.0.3.tgz#2ef3de567bfa2be716d29a93bf3d208c133e8d04" - integrity sha512-ENcUdpf4yO0E1rubu8rkxI+JGQk4CgjchynZ4bDBJDfqdy+uhTRSWb8/F3Jtu+Bw5MW45Po3/aQGeIyyxgQtxg== - dependencies: - browserslist "^4.16.6" - postcss-selector-parser "^6.0.4" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.0.0, supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0, supports-color@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-hyperlinks@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz#f663df252af5f37c5d49bbd7eeefa9e0b9e59e47" - integrity sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA== - dependencies: - has-flag "^4.0.0" - supports-color "^7.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -svg-parser@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" - integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== - -svgo@^1.2.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" - integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== - dependencies: - chalk "^2.4.1" - coa "^2.0.2" - css-select "^2.0.0" - css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.37" - csso "^4.0.2" - js-yaml "^3.13.1" - mkdirp "~0.5.1" - object.values "^1.1.0" - sax "~1.2.4" - stable "^0.1.8" - unquote "~1.1.1" - util.promisify "~1.0.0" - -svgo@^2.7.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" - integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== - 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" - -symbol-observable@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" - integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== - -symbol-tree@^3.2.4: - version "3.2.4" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" - integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== - -tailwindcss@^3.0.2: - version "3.0.19" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.19.tgz#cd789953e6762af2e80c5a3e5d6da3a975ee8215" - integrity sha512-rjsdfz/qZya5xQ0OVynEMETgWq1CacmftgMYeXXh6bRM5vxsNwRSbMJsCCIjq/w67om9VP/AFMolOwiE+5VKig== - dependencies: - arg "^5.0.1" - chalk "^4.1.2" - chokidar "^3.5.3" - color-name "^1.1.4" - cosmiconfig "^7.0.1" - detective "^5.2.0" - didyoumean "^1.2.2" - dlv "^1.1.3" - fast-glob "^3.2.11" - glob-parent "^6.0.2" - is-glob "^4.0.3" - normalize-path "^3.0.0" - object-hash "^2.2.0" - postcss-js "^4.0.0" - postcss-load-config "^3.1.0" - postcss-nested "5.0.6" - postcss-selector-parser "^6.0.9" - postcss-value-parser "^4.2.0" - quick-lru "^5.1.1" - resolve "^1.22.0" - -tapable@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" - integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== - -tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -tar@^4.4.12: - version "4.4.19" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" - integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== - 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" - -tar@^6.0.2: - version "6.1.0" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83" - integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^3.0.0" - minizlib "^2.1.1" - mkdirp "^1.0.3" - yallist "^4.0.0" - -tar@^6.1.0: - version "6.1.11" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" - integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== - 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" - -temp-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" - integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= - -temp-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" - integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== - -temp-write@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-4.0.0.tgz#cd2e0825fc826ae72d201dc26eef3bf7e6fc9320" - integrity sha512-HIeWmj77uOOHb0QX7siN3OtwV3CTntquin6TNVg6SHOqCP3hYKmox90eeFOGaY1MqJ9WYDDjkyZrW6qS5AWpbw== - dependencies: - graceful-fs "^4.1.15" - is-stream "^2.0.0" - make-dir "^3.0.0" - temp-dir "^1.0.0" - uuid "^3.3.2" - -tempy@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.6.0.tgz#65e2c35abc06f1124a97f387b08303442bde59f3" - integrity sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw== - dependencies: - is-stream "^2.0.0" - temp-dir "^2.0.0" - type-fest "^0.16.0" - unique-string "^2.0.0" - -terminal-link@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" - integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== - dependencies: - ansi-escapes "^4.2.1" - supports-hyperlinks "^2.0.0" - -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.5: - version "5.3.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz#0320dcc270ad5372c1e8993fabbd927929773e54" - integrity sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g== - dependencies: - jest-worker "^27.4.5" - schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - terser "^5.7.2" - -terser@^5.0.0, terser@^5.10.0, terser@^5.7.2: - version "5.10.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" - integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== - dependencies: - commander "^2.20.0" - source-map "~0.7.2" - source-map-support "~0.5.20" - -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - -text-extensions@^1.0.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" - integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -throat@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" - integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== - -throttleit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" - integrity sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw= - -through2@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -through2@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764" - integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw== - dependencies: - readable-stream "3" - -through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.1: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -thunky@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" - integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== - -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - -tiny-invariant@^1.0.2: - version "1.0.6" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73" - integrity sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA== - -tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" - integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== - -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -tmp@~0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" - integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== - dependencies: - rimraf "^3.0.0" - -tmpl@1.0.x: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - -tough-cookie@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" - integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== - dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.1.2" - -tough-cookie@~2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== - dependencies: - psl "^1.1.24" - punycode "^1.4.1" - -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -tr46@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" - integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= - dependencies: - punycode "^2.1.0" - -tr46@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" - integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== - dependencies: - punycode "^2.1.1" - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= - -trim-newlines@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" - integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== - -tryer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" - integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== - -ts-node@^10.4.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7" - integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A== - dependencies: - "@cspotcode/source-map-support" "0.7.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - yn "3.1.1" - -tsconfig-paths@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b" - integrity sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.1" - minimist "^1.2.0" - strip-bom "^3.0.0" - -tslib@^1.8.1, tslib@^1.9.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" - integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== - -tslib@^2.0.3, tslib@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - -tslib@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" - integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== - -tslib@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" - integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" - integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== - -type-fest@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.16.0.tgz#3240b891a78b0deae910dbeb86553e552a148860" - integrity sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg== - -type-fest@^0.18.0: - version "0.18.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" - integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.4.1.tgz#8bdf77743385d8a4f13ba95f610f5ccd68c728f8" - integrity sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw== - -type-fest@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" - integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - -type-is@~1.6.17, type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -typescript@4.5.3: - version "4.5.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.3.tgz#afaa858e68c7103317d89eb90c5d8906268d353c" - integrity sha512-eVYaEHALSt+s9LbvgEv4Ef+Tdq7hBiIZgii12xXJnukryt3pMgJf6aKhoCZ3FWQsu6sydEnkg11fYXLzhLBjeQ== - -uglify-js@^3.1.4: - version "3.14.4" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.4.tgz#68756f17d1b90b9d289341736cb9a567d6882f90" - integrity sha512-AbiSR44J0GoCeV81+oxcy/jDOElO2Bx3d0MfQCUShq7JRXaM4KtQopZsq2vFv8bCq2yMaGrw1FgygUd03RyRDA== - -uid-number@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" - integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE= - -umask@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" - integrity sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0= - -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== - dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" - which-boxed-primitive "^1.0.2" - -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== - -unicode-canonical-property-names-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" - integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== - -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== - dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" - -unicode-match-property-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" - integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== - dependencies: - unicode-canonical-property-names-ecmascript "^2.0.0" - unicode-property-aliases-ecmascript "^2.0.0" - -unicode-match-property-value-ecmascript@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" - integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== - -unicode-match-property-value-ecmascript@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" - integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== - -unicode-match-property-value-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" - integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== - -unicode-property-aliases-ecmascript@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" - integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== - -unicode-property-aliases-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" - integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== - -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - -unique-filename@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" - integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== - dependencies: - imurmurhash "^0.1.4" - -unique-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" - integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== - dependencies: - crypto-random-string "^2.0.0" - -universal-user-agent@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" - integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== - -universalify@^0.1.0, universalify@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -unload@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7" - integrity sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA== - dependencies: - "@babel/runtime" "^7.6.2" - detect-node "^2.0.4" - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -unquote@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= - -untildify@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" - integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== - -upath@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - -upath@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b" - integrity sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w== - -update-check@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/update-check/-/update-check-1.5.2.tgz#2fe09f725c543440b3d7dabe8971f2d5caaedc28" - integrity sha512-1TrmYLuLj/5ZovwUS7fFd1jMH3NnFDN1y1A8dboedIDt7zs/zJMo6TwwlhYKkSeEwzleeiSBV5/3c9ufAQWDaQ== - dependencies: - registry-auth-token "3.3.2" - registry-url "3.1.0" - -uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== - dependencies: - punycode "^2.1.0" - -url-search-params-polyfill@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/url-search-params-polyfill/-/url-search-params-polyfill-8.1.1.tgz#9e69e4dba300a71ae7ad3cead62c7717fd99329f" - integrity sha512-KmkCs6SjE6t4ihrfW9JelAPQIIIFbJweaaSLTh/4AO+c58JlDcb+GbdPt8yr5lRcFg4rPswRFRRhBGpWwh0K/Q== - -use-deep-compare-effect@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/use-deep-compare-effect/-/use-deep-compare-effect-1.8.1.tgz#ef0ce3b3271edb801da1ec23bf0754ef4189d0c6" - integrity sha512-kbeNVZ9Zkc0RFGpfMN3MNfaKNvcLNyxOAAd9O4CBZ+kCBXXscn9s/4I+8ytUER4RDpEYs5+O6Rs4PqiZ+rHr5Q== - dependencies: - "@babel/runtime" "^7.12.5" - dequal "^2.0.2" - -util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -util-promisify@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/util-promisify/-/util-promisify-2.1.0.tgz#3c2236476c4d32c5ff3c47002add7c13b9a82a53" - integrity sha1-PCI2R2xNMsX/PEcAKt18E7moKlM= - dependencies: - object.getownpropertydescriptors "^2.0.3" - -util.promisify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== - dependencies: - define-properties "^1.1.2" - object.getownpropertydescriptors "^2.0.3" - -utila@~0.4: - version "0.4.0" - resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" - integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@^3.3.2: - version "3.3.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" - integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== - -uuid@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -v8-compile-cache@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" - integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== - -v8-to-istanbul@^8.1.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" - integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^1.6.0" - source-map "^0.7.3" - -validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -validate-npm-package-name@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" - integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34= - dependencies: - builtins "^1.0.3" - -value-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" - integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -void-elements@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" - integrity sha1-YU9/v42AHwu18GYfWy9XhXUOTwk= - -w3c-hr-time@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" - integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== - dependencies: - browser-process-hrtime "^1.0.0" - -w3c-xmlserializer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" - integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== - dependencies: - xml-name-validator "^3.0.0" - -wait-on@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.0.tgz#7e9bf8e3d7fe2daecbb7a570ac8ca41e9311c7e7" - integrity sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw== - dependencies: - axios "^0.21.1" - joi "^17.4.0" - lodash "^4.17.21" - minimist "^1.2.5" - rxjs "^7.1.0" - -walker@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" - integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= - dependencies: - makeerror "1.0.x" - -watchpack@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" - integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -wbuf@^1.1.0, wbuf@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" - integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== - dependencies: - minimalistic-assert "^1.0.0" - -wcwidth@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= - dependencies: - defaults "^1.0.3" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= - -webidl-conversions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" - integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== - -webidl-conversions@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" - integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== - -webidl-conversions@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" - integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== - -webpack-dev-middleware@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz#aa079a8dedd7e58bfeab358a9af7dab304cee57f" - 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" - -webpack-dev-server@^4.6.0: - version "4.7.4" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz#d0ef7da78224578384e795ac228d8efb63d5f945" - 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" - -webpack-manifest-plugin@^4.0.2: - version "4.1.1" - resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz#10f8dbf4714ff93a215d5a45bcc416d80506f94f" - integrity sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow== - dependencies: - tapable "^2.0.0" - webpack-sources "^2.2.0" - -webpack-merge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" - integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== - dependencies: - lodash "^4.17.15" - -webpack-sources@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack-sources@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd" - integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA== - dependencies: - source-list-map "^2.0.1" - source-map "^0.6.1" - -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - -webpack@^5.64.4: - version "5.68.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.68.0.tgz#a653a58ed44280062e47257f260117e4be90d560" - integrity sha512-zUcqaUO0772UuuW2bzaES2Zjlm/y3kRBQDVFVCge+s2Y8mwuUTdperGaAv65/NtRL/1zanpSJOq/MD8u61vo6g== - dependencies: - "@types/eslint-scope" "^3.7.0" - "@types/estree" "^0.0.50" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.4.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.8.3" - es-module-lexer "^0.9.0" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-better-errors "^1.0.2" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.1.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.3.1" - webpack-sources "^3.2.3" - -websocket-driver@>=0.5.1: - version "0.7.3" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" - integrity sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg== - dependencies: - http-parser-js ">=0.4.0 <0.4.11" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-driver@^0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" - integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== - dependencies: - http-parser-js ">=0.5.1" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" - integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== - -whatwg-encoding@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" - integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== - dependencies: - iconv-lite "0.4.24" - -whatwg-fetch@^3.6.2: - version "3.6.2" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" - integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== - -whatwg-mimetype@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" - integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -whatwg-url@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" - integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - -whatwg-url@^8.0.0, whatwg-url@^8.4.0, whatwg-url@^8.5.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" - integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== - dependencies: - lodash "^4.7.0" - tr46 "^2.1.0" - webidl-conversions "^6.1.0" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which@1, which@^1.2.9, which@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1, which@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -widest-line@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" - integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== - dependencies: - string-width "^4.0.0" - -word-wrap@^1.2.3, word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= - -workbox-background-sync@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-6.4.2.tgz#bb31b95928d376abcb9bde0de3a0cef9bae46cf7" - integrity sha512-P7c8uG5X2k+DMICH9xeSA9eUlCOjHHYoB42Rq+RtUpuwBxUOflAXR1zdsMWj81LopE4gjKXlTw7BFd1BDAHo7g== - dependencies: - idb "^6.1.4" - workbox-core "6.4.2" - -workbox-broadcast-update@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-6.4.2.tgz#5094c4767dfb590532ac03ee07e9e82b2ac206bc" - integrity sha512-qnBwQyE0+PWFFc/n4ISXINE49m44gbEreJUYt2ldGH3+CNrLmJ1egJOOyUqqu9R4Eb7QrXcmB34ClXG7S37LbA== - dependencies: - workbox-core "6.4.2" - -workbox-build@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-6.4.2.tgz#47f9baa946c3491533cd5ccb1f194a7160e8a6e3" - integrity sha512-WMdYLhDIsuzViOTXDH+tJ1GijkFp5khSYolnxR/11zmfhNDtuo7jof72xPGFy+KRpsz6tug39RhivCj77qqO0w== - dependencies: - "@apideck/better-ajv-errors" "^0.3.1" - "@babel/core" "^7.11.1" - "@babel/preset-env" "^7.11.0" - "@babel/runtime" "^7.11.2" - "@rollup/plugin-babel" "^5.2.0" - "@rollup/plugin-node-resolve" "^11.2.1" - "@rollup/plugin-replace" "^2.4.1" - "@surma/rollup-plugin-off-main-thread" "^2.2.3" - ajv "^8.6.0" - common-tags "^1.8.0" - fast-json-stable-stringify "^2.1.0" - fs-extra "^9.0.1" - glob "^7.1.6" - lodash "^4.17.20" - pretty-bytes "^5.3.0" - rollup "^2.43.1" - rollup-plugin-terser "^7.0.0" - source-map "^0.8.0-beta.0" - source-map-url "^0.4.0" - stringify-object "^3.3.0" - strip-comments "^2.0.1" - tempy "^0.6.0" - upath "^1.2.0" - workbox-background-sync "6.4.2" - workbox-broadcast-update "6.4.2" - workbox-cacheable-response "6.4.2" - workbox-core "6.4.2" - workbox-expiration "6.4.2" - workbox-google-analytics "6.4.2" - workbox-navigation-preload "6.4.2" - workbox-precaching "6.4.2" - workbox-range-requests "6.4.2" - workbox-recipes "6.4.2" - workbox-routing "6.4.2" - workbox-strategies "6.4.2" - workbox-streams "6.4.2" - workbox-sw "6.4.2" - workbox-window "6.4.2" - -workbox-cacheable-response@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-6.4.2.tgz#ebcabb3667019da232e986a9927af97871e37ccb" - integrity sha512-9FE1W/cKffk1AJzImxgEN0ceWpyz1tqNjZVtA3/LAvYL3AC5SbIkhc7ZCO82WmO9IjTfu8Vut2X/C7ViMSF7TA== - dependencies: - workbox-core "6.4.2" - -workbox-core@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-6.4.2.tgz#f99fd36a211cc01dce90aa7d5f2c255e8fe9d6bc" - integrity sha512-1U6cdEYPcajRXiboSlpJx6U7TvhIKbxRRerfepAJu2hniKwJ3DHILjpU/zx3yvzSBCWcNJDoFalf7Vgd7ey/rw== - -workbox-expiration@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.4.2.tgz#61613459fd6ddd1362730767618d444c6b9c9139" - integrity sha512-0hbpBj0tDnW+DZOUmwZqntB/8xrXOgO34i7s00Si/VlFJvvpRKg1leXdHHU8ykoSBd6+F2KDcMP3swoCi5guLw== - dependencies: - idb "^6.1.4" - workbox-core "6.4.2" - -workbox-google-analytics@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-6.4.2.tgz#eea7d511b3078665a726dc2ee9f11c6b7a897530" - integrity sha512-u+gxs3jXovPb1oul4CTBOb+T9fS1oZG+ZE6AzS7l40vnyfJV79DaLBvlpEZfXGv3CjMdV1sT/ltdOrKzo7HcGw== - dependencies: - workbox-background-sync "6.4.2" - workbox-core "6.4.2" - workbox-routing "6.4.2" - workbox-strategies "6.4.2" - -workbox-navigation-preload@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-6.4.2.tgz#35cd4ba416a530796af135410ca07db5bee11668" - integrity sha512-viyejlCtlKsbJCBHwhSBbWc57MwPXvUrc8P7d+87AxBGPU+JuWkT6nvBANgVgFz6FUhCvRC8aYt+B1helo166g== - dependencies: - workbox-core "6.4.2" - -workbox-precaching@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-6.4.2.tgz#8d87c05d54f32ac140f549faebf3b4d42d63621e" - integrity sha512-CZ6uwFN/2wb4noHVlALL7UqPFbLfez/9S2GAzGAb0Sk876ul9ukRKPJJ6gtsxfE2HSTwqwuyNVa6xWyeyJ1XSA== - dependencies: - workbox-core "6.4.2" - workbox-routing "6.4.2" - workbox-strategies "6.4.2" - -workbox-range-requests@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-6.4.2.tgz#050f0dfbb61cd1231e609ed91298b6c2442ae41b" - integrity sha512-SowF3z69hr3Po/w7+xarWfzxJX/3Fo0uSG72Zg4g5FWWnHpq2zPvgbWerBZIa81zpJVUdYpMa3akJJsv+LaO1Q== - dependencies: - workbox-core "6.4.2" - -workbox-recipes@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-recipes/-/workbox-recipes-6.4.2.tgz#68de41fa3a77b444b0f93c9c01a76ba1d41fd2bf" - integrity sha512-/oVxlZFpAjFVbY+3PoGEXe8qyvtmqMrTdWhbOfbwokNFtUZ/JCtanDKgwDv9x3AebqGAoJRvQNSru0F4nG+gWA== - dependencies: - workbox-cacheable-response "6.4.2" - workbox-core "6.4.2" - workbox-expiration "6.4.2" - workbox-precaching "6.4.2" - workbox-routing "6.4.2" - workbox-strategies "6.4.2" - -workbox-routing@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-6.4.2.tgz#65b1c61e8ca79bb9152f93263c26b1f248d09dcc" - integrity sha512-0ss/n9PAcHjTy4Ad7l2puuod4WtsnRYu9BrmHcu6Dk4PgWeJo1t5VnGufPxNtcuyPGQ3OdnMdlmhMJ57sSrrSw== - dependencies: - workbox-core "6.4.2" - -workbox-strategies@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-6.4.2.tgz#50c02bf2d116918e1a8052df5f2c1e4103c62d5d" - integrity sha512-YXh9E9dZGEO1EiPC3jPe2CbztO5WT8Ruj8wiYZM56XqEJp5YlGTtqRjghV+JovWOqkWdR+amJpV31KPWQUvn1Q== - dependencies: - workbox-core "6.4.2" - -workbox-streams@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-6.4.2.tgz#3bc615cccebfd62dedf28315afb7d9ee177912a5" - integrity sha512-ROEGlZHGVEgpa5bOZefiJEVsi5PsFjJG9Xd+wnDbApsCO9xq9rYFopF+IRq9tChyYzhBnyk2hJxbQVWphz3sog== - dependencies: - workbox-core "6.4.2" - workbox-routing "6.4.2" - -workbox-sw@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-6.4.2.tgz#9a6db5f74580915dc2f0dbd47d2ffe057c94a795" - integrity sha512-A2qdu9TLktfIM5NE/8+yYwfWu+JgDaCkbo5ikrky2c7r9v2X6DcJ+zSLphNHHLwM/0eVk5XVf1mC5HGhYpMhhg== - -workbox-webpack-plugin@^6.4.1: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-webpack-plugin/-/workbox-webpack-plugin-6.4.2.tgz#aad9f11b028786d5b781420e68f4e8f570ea9936" - integrity sha512-CiEwM6kaJRkx1cP5xHksn13abTzUqMHiMMlp5Eh/v4wRcedgDTyv6Uo8+Hg9MurRbHDosO5suaPyF9uwVr4/CQ== - dependencies: - fast-json-stable-stringify "^2.1.0" - pretty-bytes "^5.4.1" - source-map-url "^0.4.0" - upath "^1.2.0" - webpack-sources "^1.4.3" - workbox-build "6.4.2" - -workbox-window@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-6.4.2.tgz#5319a3e343fa1e4bd15a1f53a07b58999d064c8a" - integrity sha512-KVyRKmrJg7iB+uym/B/CnEUEFG9CvnTU1Bq5xpXHbtgD9l+ShDekSl1wYpqw/O0JfeeQVOFb8CiNfvnwWwqnWQ== - dependencies: - "@types/trusted-types" "^2.0.2" - workbox-core "6.4.2" - -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^2.4.2: - version "2.4.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" - integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - -write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -write-json-file@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-3.2.0.tgz#65bbdc9ecd8a1458e15952770ccbadfcff5fe62a" - integrity sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ== - dependencies: - detect-indent "^5.0.0" - graceful-fs "^4.1.15" - make-dir "^2.1.0" - pify "^4.0.1" - sort-keys "^2.0.0" - write-file-atomic "^2.4.2" - -write-json-file@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-4.3.0.tgz#908493d6fd23225344af324016e4ca8f702dd12d" - integrity sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ== - dependencies: - detect-indent "^6.0.0" - graceful-fs "^4.1.15" - is-plain-obj "^2.0.0" - make-dir "^3.0.0" - sort-keys "^4.0.0" - write-file-atomic "^3.0.0" - -write-pkg@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-4.0.0.tgz#675cc04ef6c11faacbbc7771b24c0abbf2a20039" - integrity sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA== - dependencies: - sort-keys "^2.0.0" - type-fest "^0.4.1" - write-json-file "^3.2.0" - -ws@^7.4.6: - version "7.5.7" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" - integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== - -ws@^8.4.2: - version "8.5.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== - -xml-name-validator@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" - integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== - -xmlchars@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" - integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== - -xtend@^4.0.2, xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^3.0.0, yallist@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml@^1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" - integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== - -yaml@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - -yaml@^1.7.2: - version "1.8.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.8.2.tgz#a29c03f578faafd57dcb27055f9a5d569cb0c3d9" - integrity sha512-omakb0d7FjMo3R1D2EbTKVIk6dAVLRxFXdLZMEUToeAvuqgG/YuHMuQOZ5fgk+vQ8cx+cnGKwyg+8g8PNT0xQg== - dependencies: - "@babel/runtime" "^7.8.7" - -yargs-parser@20.2.4: - version "20.2.4" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" - integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== - -yargs-parser@^20.2.2, yargs-parser@^20.2.3: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - -yargs@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - 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" - -yauzl@^2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 6 + cacheKey: 8 + +"@aashutoshrathi/word-wrap@npm:^1.2.3": + version: 1.2.6 + resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" + checksum: ada901b9e7c680d190f1d012c84217ce0063d8f5c5a7725bb91ec3c5ed99bb7572680eb2d2938a531ccbaec39a95422fcd8a6b4a13110c7d98dd75402f66a0cd + languageName: node + linkType: hard + +"@adobe/css-tools@npm:^4.3.2": + version: 4.3.3 + resolution: "@adobe/css-tools@npm:4.3.3" + checksum: d21f3786b84911fee59c995a146644a85c98692979097b26484ffa9e442fb1a92ccd68ce984e3e7cf8d5933c3560fbc0ad3e3cd1de50b9a723d1c012e793bbcb + languageName: node + linkType: hard + +"@ampproject/remapping@npm:^2.1.0": + version: 2.2.0 + resolution: "@ampproject/remapping@npm:2.2.0" + dependencies: + "@jridgewell/gen-mapping": ^0.1.0 + "@jridgewell/trace-mapping": ^0.3.9 + checksum: d74d170d06468913921d72430259424b7e4c826b5a7d39ff839a29d547efb97dc577caa8ba3fb5cf023624e9af9d09651afc3d4112a45e2050328abc9b3a2292 + languageName: node + linkType: hard + +"@apideck/better-ajv-errors@npm:^0.3.1": + version: 0.3.6 + resolution: "@apideck/better-ajv-errors@npm:0.3.6" + dependencies: + json-schema: ^0.4.0 + jsonpointer: ^5.0.0 + leven: ^3.1.0 + peerDependencies: + ajv: ">=8" + checksum: b70ec9aae3b30ba1ac06948e585cd96aabbfe7ef6a1c27dc51e56c425f01290a58e9beb19ed95ee64da9f32df3e9276cd1ea58e78792741d74a519cb56955491 + languageName: node + linkType: hard + +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.18.6, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.8.3": + version: 7.22.13 + resolution: "@babel/code-frame@npm:7.22.13" + dependencies: + "@babel/highlight": ^7.22.13 + chalk: ^2.4.2 + checksum: 22e342c8077c8b77eeb11f554ecca2ba14153f707b85294fcf6070b6f6150aae88a7b7436dd88d8c9289970585f3fe5b9b941c5aa3aa26a6d5a8ef3f292da058 + languageName: node + linkType: hard + +"@babel/compat-data@npm:^7.17.7, @babel/compat-data@npm:^7.20.1, @babel/compat-data@npm:^7.20.5": + version: 7.20.14 + resolution: "@babel/compat-data@npm:7.20.14" + checksum: 6c9efe36232094e4ad0b70d165587f21ca718e5d011f7a52a77a18502a7524e90e2855aa5a2e086395bcfd21bd2c7c99128dcd8d9fdffe94316b72acf5c66f2c + languageName: node + linkType: hard + +"@babel/core@npm:^7.1.0, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3, @babel/core@npm:^7.16.0, @babel/core@npm:^7.7.2, @babel/core@npm:^7.8.0": + version: 7.20.12 + resolution: "@babel/core@npm:7.20.12" + dependencies: + "@ampproject/remapping": ^2.1.0 + "@babel/code-frame": ^7.18.6 + "@babel/generator": ^7.20.7 + "@babel/helper-compilation-targets": ^7.20.7 + "@babel/helper-module-transforms": ^7.20.11 + "@babel/helpers": ^7.20.7 + "@babel/parser": ^7.20.7 + "@babel/template": ^7.20.7 + "@babel/traverse": ^7.20.12 + "@babel/types": ^7.20.7 + convert-source-map: ^1.7.0 + debug: ^4.1.0 + gensync: ^1.0.0-beta.2 + json5: ^2.2.2 + semver: ^6.3.0 + checksum: 62e6c3e2149a70b5c9729ef5f0d3e2e97e9dcde89fc039c8d8e3463d5d7ba9b29ee84d10faf79b61532ac1645aa62f2bd42338320617e6e3a8a4d8e2a27076e7 + languageName: node + linkType: hard + +"@babel/eslint-parser@npm:7.23.3, @babel/eslint-parser@npm:^7.16.3": + version: 7.23.3 + resolution: "@babel/eslint-parser@npm:7.23.3" + dependencies: + "@nicolo-ribaudo/eslint-scope-5-internals": 5.1.1-v1 + eslint-visitor-keys: ^2.1.0 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.11.0 + eslint: ^7.5.0 || ^8.0.0 + checksum: 9573daebe21af5123c302c307be80cacf1c2bf236a9497068a14726d3944ef55e1282519d0ccf51882dfc369359a3442299c98cb22a419e209924db39d4030fd + languageName: node + linkType: hard + +"@babel/generator@npm:^7.20.7, @babel/generator@npm:^7.23.0, @babel/generator@npm:^7.7.2": + version: 7.23.0 + resolution: "@babel/generator@npm:7.23.0" + dependencies: + "@babel/types": ^7.23.0 + "@jridgewell/gen-mapping": ^0.3.2 + "@jridgewell/trace-mapping": ^0.3.17 + jsesc: ^2.5.1 + checksum: 8efe24adad34300f1f8ea2add420b28171a646edc70f2a1b3e1683842f23b8b7ffa7e35ef0119294e1901f45bfea5b3dc70abe1f10a1917ccdfb41bed69be5f1 + languageName: node + linkType: hard + +"@babel/helper-annotate-as-pure@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/helper-annotate-as-pure@npm:7.18.6" + dependencies: + "@babel/types": ^7.18.6 + checksum: 88ccd15ced475ef2243fdd3b2916a29ea54c5db3cd0cfabf9d1d29ff6e63b7f7cd1c27264137d7a40ac2e978b9b9a542c332e78f40eb72abe737a7400788fc1b + languageName: node + linkType: hard + +"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.18.6": + version: 7.18.9 + resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.18.9" + dependencies: + "@babel/helper-explode-assignable-expression": ^7.18.6 + "@babel/types": ^7.18.9 + checksum: b4bc214cb56329daff6cc18a7f7a26aeafb55a1242e5362f3d47fe3808421f8c7cd91fff95d6b9b7ccb67e14e5a67d944e49dbe026942bfcbfda19b1c72a8e72 + languageName: node + linkType: hard + +"@babel/helper-compilation-targets@npm:^7.17.7, @babel/helper-compilation-targets@npm:^7.18.9, @babel/helper-compilation-targets@npm:^7.20.0, @babel/helper-compilation-targets@npm:^7.20.7": + version: 7.20.7 + resolution: "@babel/helper-compilation-targets@npm:7.20.7" + dependencies: + "@babel/compat-data": ^7.20.5 + "@babel/helper-validator-option": ^7.18.6 + browserslist: ^4.21.3 + lru-cache: ^5.1.1 + semver: ^6.3.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 8c32c873ba86e2e1805b30e0807abd07188acbe00ebb97576f0b09061cc65007f1312b589eccb4349c5a8c7f8bb9f2ab199d41da7030bf103d9f347dcd3a3cf4 + languageName: node + linkType: hard + +"@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.20.12, @babel/helper-create-class-features-plugin@npm:^7.20.5, @babel/helper-create-class-features-plugin@npm:^7.20.7": + version: 7.20.12 + resolution: "@babel/helper-create-class-features-plugin@npm:7.20.12" + dependencies: + "@babel/helper-annotate-as-pure": ^7.18.6 + "@babel/helper-environment-visitor": ^7.18.9 + "@babel/helper-function-name": ^7.19.0 + "@babel/helper-member-expression-to-functions": ^7.20.7 + "@babel/helper-optimise-call-expression": ^7.18.6 + "@babel/helper-replace-supers": ^7.20.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.20.0 + "@babel/helper-split-export-declaration": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 1e9ed4243b75278fa24deb40dc62bf537b79307987223a2d2d2ae5abf7ba6dc8435d6e3bb55d52ceb30d3e1eba88e7eb6a1885a8bb519e5cfc3e9dedb97d43e6 + languageName: node + linkType: hard + +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.20.5": + version: 7.20.5 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.20.5" + dependencies: + "@babel/helper-annotate-as-pure": ^7.18.6 + regexpu-core: ^5.2.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 7f29c3cb7447cca047b0d394f8ab98e4923d00e86a7afa56e5df9770c48ec107891505d2d1f06b720ecc94ed24bf58d90986cc35fe4a43b549eb7b7a5077b693 + languageName: node + linkType: hard + +"@babel/helper-define-polyfill-provider@npm:^0.3.3": + version: 0.3.3 + resolution: "@babel/helper-define-polyfill-provider@npm:0.3.3" + dependencies: + "@babel/helper-compilation-targets": ^7.17.7 + "@babel/helper-plugin-utils": ^7.16.7 + debug: ^4.1.1 + lodash.debounce: ^4.0.8 + resolve: ^1.14.2 + semver: ^6.1.2 + peerDependencies: + "@babel/core": ^7.4.0-0 + checksum: 8e3fe75513302e34f6d92bd67b53890e8545e6c5bca8fe757b9979f09d68d7e259f6daea90dc9e01e332c4f8781bda31c5fe551c82a277f9bc0bec007aed497c + languageName: node + linkType: hard + +"@babel/helper-environment-visitor@npm:^7.18.9, @babel/helper-environment-visitor@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-environment-visitor@npm:7.22.20" + checksum: d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 + languageName: node + linkType: hard + +"@babel/helper-explode-assignable-expression@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/helper-explode-assignable-expression@npm:7.18.6" + dependencies: + "@babel/types": ^7.18.6 + checksum: 225cfcc3376a8799023d15dc95000609e9d4e7547b29528c7f7111a0e05493ffb12c15d70d379a0bb32d42752f340233c4115bded6d299bc0c3ab7a12be3d30f + languageName: node + linkType: hard + +"@babel/helper-function-name@npm:^7.18.9, @babel/helper-function-name@npm:^7.19.0, @babel/helper-function-name@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-function-name@npm:7.23.0" + dependencies: + "@babel/template": ^7.22.15 + "@babel/types": ^7.23.0 + checksum: e44542257b2d4634a1f979244eb2a4ad8e6d75eb6761b4cfceb56b562f7db150d134bc538c8e6adca3783e3bc31be949071527aa8e3aab7867d1ad2d84a26e10 + languageName: node + linkType: hard + +"@babel/helper-hoist-variables@npm:^7.18.6, @babel/helper-hoist-variables@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-hoist-variables@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: 394ca191b4ac908a76e7c50ab52102669efe3a1c277033e49467913c7ed6f7c64d7eacbeabf3bed39ea1f41731e22993f763b1edce0f74ff8563fd1f380d92cc + languageName: node + linkType: hard + +"@babel/helper-member-expression-to-functions@npm:^7.20.7": + version: 7.20.7 + resolution: "@babel/helper-member-expression-to-functions@npm:7.20.7" + dependencies: + "@babel/types": ^7.20.7 + checksum: cec17aab7e964830b0146e575bd141127032319f26ed864a65b35abd75ad618d264d3e11449b9b4e29cfd95bb1a7e774afddd4884fdcc29c36ac9cbd2b66359f + languageName: node + linkType: hard + +"@babel/helper-module-imports@npm:^7.10.4, @babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/helper-module-imports@npm:7.18.6" + dependencies: + "@babel/types": ^7.18.6 + checksum: f393f8a3b3304b1b7a288a38c10989de754f01d29caf62ce7c4e5835daf0a27b81f3ac687d9d2780d39685aae7b55267324b512150e7b2be967b0c493b6a1def + languageName: node + linkType: hard + +"@babel/helper-module-transforms@npm:^7.18.6, @babel/helper-module-transforms@npm:^7.20.11": + version: 7.20.11 + resolution: "@babel/helper-module-transforms@npm:7.20.11" + dependencies: + "@babel/helper-environment-visitor": ^7.18.9 + "@babel/helper-module-imports": ^7.18.6 + "@babel/helper-simple-access": ^7.20.2 + "@babel/helper-split-export-declaration": ^7.18.6 + "@babel/helper-validator-identifier": ^7.19.1 + "@babel/template": ^7.20.7 + "@babel/traverse": ^7.20.10 + "@babel/types": ^7.20.7 + checksum: 29319ebafa693d48756c6ba0d871677bb0037e0da084fbe221a17c38d57093fc8aa38543c07d76e788266a937976e37ab4901971ca7f237c5ab45f524b9ecca0 + languageName: node + linkType: hard + +"@babel/helper-optimise-call-expression@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/helper-optimise-call-expression@npm:7.18.6" + dependencies: + "@babel/types": ^7.18.6 + checksum: e518fe8418571405e21644cfb39cf694f30b6c47b10b006609a92469ae8b8775cbff56f0b19732343e2ea910641091c5a2dc73b56ceba04e116a33b0f8bd2fbd + languageName: node + linkType: hard + +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.16.7, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.18.9, @babel/helper-plugin-utils@npm:^7.19.0, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": + version: 7.20.2 + resolution: "@babel/helper-plugin-utils@npm:7.20.2" + checksum: f6cae53b7fdb1bf3abd50fa61b10b4470985b400cc794d92635da1e7077bb19729f626adc0741b69403d9b6e411cddddb9c0157a709cc7c4eeb41e663be5d74b + languageName: node + linkType: hard + +"@babel/helper-remap-async-to-generator@npm:^7.18.9": + version: 7.18.9 + resolution: "@babel/helper-remap-async-to-generator@npm:7.18.9" + dependencies: + "@babel/helper-annotate-as-pure": ^7.18.6 + "@babel/helper-environment-visitor": ^7.18.9 + "@babel/helper-wrap-function": ^7.18.9 + "@babel/types": ^7.18.9 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 4be6076192308671b046245899b703ba090dbe7ad03e0bea897bb2944ae5b88e5e85853c9d1f83f643474b54c578d8ac0800b80341a86e8538264a725fbbefec + languageName: node + linkType: hard + +"@babel/helper-replace-supers@npm:^7.18.6, @babel/helper-replace-supers@npm:^7.20.7": + version: 7.20.7 + resolution: "@babel/helper-replace-supers@npm:7.20.7" + dependencies: + "@babel/helper-environment-visitor": ^7.18.9 + "@babel/helper-member-expression-to-functions": ^7.20.7 + "@babel/helper-optimise-call-expression": ^7.18.6 + "@babel/template": ^7.20.7 + "@babel/traverse": ^7.20.7 + "@babel/types": ^7.20.7 + checksum: b8e0087c9b0c1446e3c6f3f72b73b7e03559c6b570e2cfbe62c738676d9ebd8c369a708cf1a564ef88113b4330750a50232ee1131d303d478b7a5e65e46fbc7c + languageName: node + linkType: hard + +"@babel/helper-simple-access@npm:^7.20.2": + version: 7.20.2 + resolution: "@babel/helper-simple-access@npm:7.20.2" + dependencies: + "@babel/types": ^7.20.2 + checksum: ad1e96ee2e5f654ffee2369a586e5e8d2722bf2d8b028a121b4c33ebae47253f64d420157b9f0a8927aea3a9e0f18c0103e74fdd531815cf3650a0a4adca11a1 + languageName: node + linkType: hard + +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.20.0": + version: 7.20.0 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.20.0" + dependencies: + "@babel/types": ^7.20.0 + checksum: 34da8c832d1c8a546e45d5c1d59755459ffe43629436707079989599b91e8c19e50e73af7a4bd09c95402d389266731b0d9c5f69e372d8ebd3a709c05c80d7dd + languageName: node + linkType: hard + +"@babel/helper-split-export-declaration@npm:^7.18.6, @babel/helper-split-export-declaration@npm:^7.22.6": + version: 7.22.6 + resolution: "@babel/helper-split-export-declaration@npm:7.22.6" + dependencies: + "@babel/types": ^7.22.5 + checksum: e141cace583b19d9195f9c2b8e17a3ae913b7ee9b8120246d0f9ca349ca6f03cb2c001fd5ec57488c544347c0bb584afec66c936511e447fd20a360e591ac921 + languageName: node + linkType: hard + +"@babel/helper-string-parser@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-string-parser@npm:7.22.5" + checksum: 836851ca5ec813077bbb303acc992d75a360267aa3b5de7134d220411c852a6f17de7c0d0b8c8dcc0f567f67874c00f4528672b2a4f1bc978a3ada64c8c78467 + languageName: node + linkType: hard + +"@babel/helper-validator-identifier@npm:^7.19.1, @babel/helper-validator-identifier@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-validator-identifier@npm:7.22.20" + checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc + languageName: node + linkType: hard + +"@babel/helper-validator-option@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/helper-validator-option@npm:7.18.6" + checksum: f9cc6eb7cc5d759c5abf006402180f8d5e4251e9198197428a97e05d65eb2f8ae5a0ce73b1dfd2d35af41d0eb780627a64edf98a4e71f064eeeacef8de58f2cf + languageName: node + linkType: hard + +"@babel/helper-wrap-function@npm:^7.18.9": + version: 7.20.5 + resolution: "@babel/helper-wrap-function@npm:7.20.5" + dependencies: + "@babel/helper-function-name": ^7.19.0 + "@babel/template": ^7.18.10 + "@babel/traverse": ^7.20.5 + "@babel/types": ^7.20.5 + checksum: 11a6fc28334368a193a9cb3ad16f29cd7603bab958433efc82ebe59fa6556c227faa24f07ce43983f7a85df826f71d441638442c4315e90a554fe0a70ca5005b + languageName: node + linkType: hard + +"@babel/helpers@npm:^7.20.7": + version: 7.20.13 + resolution: "@babel/helpers@npm:7.20.13" + dependencies: + "@babel/template": ^7.20.7 + "@babel/traverse": ^7.20.13 + "@babel/types": ^7.20.7 + checksum: d62076fa834f342798f8c3fd7aec0870cc1725d273d99e540cbaa8d6c3ed10258228dd14601c8e66bfeabbb9424c3b31090ecc467fe855f7bd72c4734df7fb09 + languageName: node + linkType: hard + +"@babel/highlight@npm:^7.22.13": + version: 7.22.20 + resolution: "@babel/highlight@npm:7.22.20" + dependencies: + "@babel/helper-validator-identifier": ^7.22.20 + chalk: ^2.4.2 + js-tokens: ^4.0.0 + checksum: 84bd034dca309a5e680083cd827a766780ca63cef37308404f17653d32366ea76262bd2364b2d38776232f2d01b649f26721417d507e8b4b6da3e4e739f6d134 + languageName: node + linkType: hard + +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/parser@npm:7.23.0" + bin: + parser: ./bin/babel-parser.js + checksum: 453fdf8b9e2c2b7d7b02139e0ce003d1af21947bbc03eb350fb248ee335c9b85e4ab41697ddbdd97079698de825a265e45a0846bb2ed47a2c7c1df833f42a354 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 845bd280c55a6a91d232cfa54eaf9708ec71e594676fe705794f494bb8b711d833b752b59d1a5c154695225880c23dbc9cab0e53af16fd57807976cd3ff41b8d + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.18.9": + version: 7.20.7 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.20.7" + dependencies: + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-skip-transparent-expression-wrappers": ^7.20.0 + "@babel/plugin-proposal-optional-chaining": ^7.20.7 + peerDependencies: + "@babel/core": ^7.13.0 + checksum: d610f532210bee5342f5b44a12395ccc6d904e675a297189bc1e401cc185beec09873da523466d7fec34ae1574f7a384235cba1ccc9fe7b89ba094167897c845 + languageName: node + linkType: hard + +"@babel/plugin-proposal-async-generator-functions@npm:^7.20.1": + version: 7.20.7 + resolution: "@babel/plugin-proposal-async-generator-functions@npm:7.20.7" + dependencies: + "@babel/helper-environment-visitor": ^7.18.9 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-remap-async-to-generator": ^7.18.9 + "@babel/plugin-syntax-async-generators": ^7.8.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 111109ee118c9e69982f08d5e119eab04190b36a0f40e22e873802d941956eee66d2aa5a15f5321e51e3f9aa70a91136451b987fe15185ef8cc547ac88937723 + languageName: node + linkType: hard + +"@babel/plugin-proposal-class-properties@npm:^7.16.0, @babel/plugin-proposal-class-properties@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-proposal-class-properties@npm:7.18.6" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.18.6 + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 49a78a2773ec0db56e915d9797e44fd079ab8a9b2e1716e0df07c92532f2c65d76aeda9543883916b8e0ff13606afeffa67c5b93d05b607bc87653ad18a91422 + languageName: node + linkType: hard + +"@babel/plugin-proposal-class-static-block@npm:^7.18.6": + version: 7.20.7 + resolution: "@babel/plugin-proposal-class-static-block@npm:7.20.7" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.20.7 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + peerDependencies: + "@babel/core": ^7.12.0 + checksum: ce1f3e8fd96437d820aa36323b7b3a0cb65b5f2600612665129880d5a4eb7194ce6a298ed2a5a4d3a9ea49bd33089ab95503c4c5b3ba9cea251a07d1706453d9 + languageName: node + linkType: hard + +"@babel/plugin-proposal-decorators@npm:^7.16.4": + version: 7.20.13 + resolution: "@babel/plugin-proposal-decorators@npm:7.20.13" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.20.12 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-replace-supers": ^7.20.7 + "@babel/helper-split-export-declaration": ^7.18.6 + "@babel/plugin-syntax-decorators": ^7.19.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 445723b410627d52ab2d195589eb9fe5fbd66a00ebfc9bedcf63b6cbfdfc42e163d77ac391f8738ab9f632779e6f2aa427fe468fbbd6661177ef0cdca735a7d5 + languageName: node + linkType: hard + +"@babel/plugin-proposal-dynamic-import@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-proposal-dynamic-import@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 96b1c8a8ad8171d39e9ab106be33bde37ae09b22fb2c449afee9a5edf3c537933d79d963dcdc2694d10677cb96da739cdf1b53454e6a5deab9801f28a818bb2f + languageName: node + linkType: hard + +"@babel/plugin-proposal-export-namespace-from@npm:^7.18.9": + version: 7.18.9 + resolution: "@babel/plugin-proposal-export-namespace-from@npm:7.18.9" + dependencies: + "@babel/helper-plugin-utils": ^7.18.9 + "@babel/plugin-syntax-export-namespace-from": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 84ff22bacc5d30918a849bfb7e0e90ae4c5b8d8b65f2ac881803d1cf9068dffbe53bd657b0e4bc4c20b4db301b1c85f1e74183cf29a0dd31e964bd4e97c363ef + languageName: node + linkType: hard + +"@babel/plugin-proposal-json-strings@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-proposal-json-strings@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + "@babel/plugin-syntax-json-strings": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 25ba0e6b9d6115174f51f7c6787e96214c90dd4026e266976b248a2ed417fe50fddae72843ffb3cbe324014a18632ce5648dfac77f089da858022b49fd608cb3 + languageName: node + linkType: hard + +"@babel/plugin-proposal-logical-assignment-operators@npm:^7.18.9": + version: 7.20.7 + resolution: "@babel/plugin-proposal-logical-assignment-operators@npm:7.20.7" + dependencies: + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: cdd7b8136cc4db3f47714d5266f9e7b592a2ac5a94a5878787ce08890e97c8ab1ca8e94b27bfeba7b0f2b1549a026d9fc414ca2196de603df36fb32633bbdc19 + languageName: node + linkType: hard + +"@babel/plugin-proposal-nullish-coalescing-operator@npm:^7.16.0, @babel/plugin-proposal-nullish-coalescing-operator@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-proposal-nullish-coalescing-operator@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 949c9ddcdecdaec766ee610ef98f965f928ccc0361dd87cf9f88cf4896a6ccd62fce063d4494778e50da99dea63d270a1be574a62d6ab81cbe9d85884bf55a7d + languageName: node + linkType: hard + +"@babel/plugin-proposal-numeric-separator@npm:^7.16.0, @babel/plugin-proposal-numeric-separator@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-proposal-numeric-separator@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f370ea584c55bf4040e1f78c80b4eeb1ce2e6aaa74f87d1a48266493c33931d0b6222d8cee3a082383d6bb648ab8d6b7147a06f974d3296ef3bc39c7851683ec + languageName: node + linkType: hard + +"@babel/plugin-proposal-object-rest-spread@npm:^7.20.2": + version: 7.20.7 + resolution: "@babel/plugin-proposal-object-rest-spread@npm:7.20.7" + dependencies: + "@babel/compat-data": ^7.20.5 + "@babel/helper-compilation-targets": ^7.20.7 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-transform-parameters": ^7.20.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 1329db17009964bc644484c660eab717cb3ca63ac0ab0f67c651a028d1bc2ead51dc4064caea283e46994f1b7221670a35cbc0b4beb6273f55e915494b5aa0b2 + languageName: node + linkType: hard + +"@babel/plugin-proposal-optional-catch-binding@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-proposal-optional-catch-binding@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7b5b39fb5d8d6d14faad6cb68ece5eeb2fd550fb66b5af7d7582402f974f5bc3684641f7c192a5a57e0f59acfae4aada6786be1eba030881ddc590666eff4d1e + languageName: node + linkType: hard + +"@babel/plugin-proposal-optional-chaining@npm:^7.16.0, @babel/plugin-proposal-optional-chaining@npm:^7.18.9, @babel/plugin-proposal-optional-chaining@npm:^7.20.7": + version: 7.20.7 + resolution: "@babel/plugin-proposal-optional-chaining@npm:7.20.7" + dependencies: + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-skip-transparent-expression-wrappers": ^7.20.0 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 274b8932335bd064ca24cf1a4da2b2c20c92726d4bfa8b0cb5023857479b8481feef33505c16650c7b9239334e5c6959babc924816324c4cf223dd91c7ca79bc + languageName: node + linkType: hard + +"@babel/plugin-proposal-private-methods@npm:^7.16.0, @babel/plugin-proposal-private-methods@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-proposal-private-methods@npm:7.18.6" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.18.6 + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 22d8502ee96bca99ad2c8393e8493e2b8d4507576dd054490fd8201a36824373440106f5b098b6d821b026c7e72b0424ff4aeca69ed5f42e48f029d3a156d5ad + languageName: node + linkType: hard + +"@babel/plugin-proposal-private-property-in-object@npm:^7.16.0, @babel/plugin-proposal-private-property-in-object@npm:^7.18.6": + version: 7.20.5 + resolution: "@babel/plugin-proposal-private-property-in-object@npm:7.20.5" + dependencies: + "@babel/helper-annotate-as-pure": ^7.18.6 + "@babel/helper-create-class-features-plugin": ^7.20.5 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 513b5e0e2c1b2846be5336cf680e932ae17924ef885aa1429e1a4f7924724bdd99b15f28d67187d0a006d5f18a0c4b61d96c3ecb4902fed3c8fe2f0abfc9753a + languageName: node + linkType: hard + +"@babel/plugin-proposal-unicode-property-regex@npm:^7.18.6, @babel/plugin-proposal-unicode-property-regex@npm:^7.4.4": + version: 7.18.6 + resolution: "@babel/plugin-proposal-unicode-property-regex@npm:7.18.6" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.18.6 + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a8575ecb7ff24bf6c6e94808d5c84bb5a0c6dd7892b54f09f4646711ba0ee1e1668032b3c43e3e1dfec2c5716c302e851ac756c1645e15882d73df6ad21ae951 + languageName: node + linkType: hard + +"@babel/plugin-syntax-async-generators@npm:^7.8.4": + version: 7.8.4 + resolution: "@babel/plugin-syntax-async-generators@npm:7.8.4" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7ed1c1d9b9e5b64ef028ea5e755c0be2d4e5e4e3d6cf7df757b9a8c4cfa4193d268176d0f1f7fbecdda6fe722885c7fda681f480f3741d8a2d26854736f05367 + languageName: node + linkType: hard + +"@babel/plugin-syntax-bigint@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-bigint@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3a10849d83e47aec50f367a9e56a6b22d662ddce643334b087f9828f4c3dd73bdc5909aaeabe123fed78515767f9ca43498a0e621c438d1cd2802d7fae3c9648 + languageName: node + linkType: hard + +"@babel/plugin-syntax-class-properties@npm:^7.12.13, @babel/plugin-syntax-class-properties@npm:^7.8.3": + version: 7.12.13 + resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" + dependencies: + "@babel/helper-plugin-utils": ^7.12.13 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 24f34b196d6342f28d4bad303612d7ff566ab0a013ce89e775d98d6f832969462e7235f3e7eaf17678a533d4be0ba45d3ae34ab4e5a9dcbda5d98d49e5efa2fc + languageName: node + linkType: hard + +"@babel/plugin-syntax-class-static-block@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-class-static-block@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3e80814b5b6d4fe17826093918680a351c2d34398a914ce6e55d8083d72a9bdde4fbaf6a2dcea0e23a03de26dc2917ae3efd603d27099e2b98380345703bf948 + languageName: node + linkType: hard + +"@babel/plugin-syntax-decorators@npm:^7.19.0": + version: 7.19.0 + resolution: "@babel/plugin-syntax-decorators@npm:7.19.0" + dependencies: + "@babel/helper-plugin-utils": ^7.19.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 105a13d581a8643ba145d4d0d31f34a492b352defa5b155e785702da6ce9c3ff0c1843ba9bee176e35f6e38afa19dc7bd12c120220af0495de4b128f1dd27f6e + languageName: node + linkType: hard + +"@babel/plugin-syntax-dynamic-import@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-dynamic-import@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ce307af83cf433d4ec42932329fad25fa73138ab39c7436882ea28742e1c0066626d224e0ad2988724c82644e41601cef607b36194f695cb78a1fcdc959637bd + languageName: node + linkType: hard + +"@babel/plugin-syntax-export-namespace-from@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-export-namespace-from@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 85740478be5b0de185228e7814451d74ab8ce0a26fcca7613955262a26e99e8e15e9da58f60c754b84515d4c679b590dbd3f2148f0f58025f4ae706f1c5a5d4a + languageName: node + linkType: hard + +"@babel/plugin-syntax-flow@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-syntax-flow@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: abe82062b3eef14de7d2b3c0e4fecf80a3e796ca497e9df616d12dd250968abf71495ee85a955b43a6c827137203f0c409450cf792732ed0d6907c806580ea71 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-assertions@npm:^7.20.0": + version: 7.20.0 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.20.0" + dependencies: + "@babel/helper-plugin-utils": ^7.19.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 6a86220e0aae40164cd3ffaf80e7c076a1be02a8f3480455dddbae05fda8140f429290027604df7a11b3f3f124866e8a6d69dbfa1dda61ee7377b920ad144d5b + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-meta@npm:^7.8.3": + version: 7.10.4 + resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 166ac1125d10b9c0c430e4156249a13858c0366d38844883d75d27389621ebe651115cb2ceb6dc011534d5055719fa1727b59f39e1ab3ca97820eef3dcab5b9b + languageName: node + linkType: hard + +"@babel/plugin-syntax-json-strings@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-json-strings@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: bf5aea1f3188c9a507e16efe030efb996853ca3cadd6512c51db7233cc58f3ac89ff8c6bdfb01d30843b161cfe7d321e1bf28da82f7ab8d7e6bc5464666f354a + languageName: node + linkType: hard + +"@babel/plugin-syntax-jsx@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-syntax-jsx@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 6d37ea972970195f1ffe1a54745ce2ae456e0ac6145fae9aa1480f297248b262ea6ebb93010eddb86ebfacb94f57c05a1fc5d232b9a67325b09060299d515c67 + languageName: node + linkType: hard + +"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4, @babel/plugin-syntax-logical-assignment-operators@npm:^7.8.3": + version: 7.10.4 + resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: aff33577037e34e515911255cdbb1fd39efee33658aa00b8a5fd3a4b903585112d037cce1cc9e4632f0487dc554486106b79ccd5ea63a2e00df4363f6d4ff886 + languageName: node + linkType: hard + +"@babel/plugin-syntax-nullish-coalescing-operator@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-nullish-coalescing-operator@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 87aca4918916020d1fedba54c0e232de408df2644a425d153be368313fdde40d96088feed6c4e5ab72aac89be5d07fef2ddf329a15109c5eb65df006bf2580d1 + languageName: node + linkType: hard + +"@babel/plugin-syntax-numeric-separator@npm:^7.10.4, @babel/plugin-syntax-numeric-separator@npm:^7.8.3": + version: 7.10.4 + resolution: "@babel/plugin-syntax-numeric-separator@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 01ec5547bd0497f76cc903ff4d6b02abc8c05f301c88d2622b6d834e33a5651aa7c7a3d80d8d57656a4588f7276eba357f6b7e006482f5b564b7a6488de493a1 + languageName: node + linkType: hard + +"@babel/plugin-syntax-object-rest-spread@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-object-rest-spread@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: fddcf581a57f77e80eb6b981b10658421bc321ba5f0a5b754118c6a92a5448f12a0c336f77b8abf734841e102e5126d69110a306eadb03ca3e1547cab31f5cbf + languageName: node + linkType: hard + +"@babel/plugin-syntax-optional-catch-binding@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-optional-catch-binding@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 910d90e72bc90ea1ce698e89c1027fed8845212d5ab588e35ef91f13b93143845f94e2539d831dc8d8ededc14ec02f04f7bd6a8179edd43a326c784e7ed7f0b9 + languageName: node + linkType: hard + +"@babel/plugin-syntax-optional-chaining@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-optional-chaining@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: eef94d53a1453361553c1f98b68d17782861a04a392840341bc91780838dd4e695209c783631cf0de14c635758beafb6a3a65399846ffa4386bff90639347f30 + languageName: node + linkType: hard + +"@babel/plugin-syntax-private-property-in-object@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-private-property-in-object@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b317174783e6e96029b743ccff2a67d63d38756876e7e5d0ba53a322e38d9ca452c13354a57de1ad476b4c066dbae699e0ca157441da611117a47af88985ecda + languageName: node + linkType: hard + +"@babel/plugin-syntax-top-level-await@npm:^7.14.5, @babel/plugin-syntax-top-level-await@npm:^7.8.3": + version: 7.14.5 + resolution: "@babel/plugin-syntax-top-level-await@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: bbd1a56b095be7820029b209677b194db9b1d26691fe999856462e66b25b281f031f3dfd91b1619e9dcf95bebe336211833b854d0fb8780d618e35667c2d0d7e + languageName: node + linkType: hard + +"@babel/plugin-syntax-typescript@npm:^7.20.0, @babel/plugin-syntax-typescript@npm:^7.7.2": + version: 7.20.0 + resolution: "@babel/plugin-syntax-typescript@npm:7.20.0" + dependencies: + "@babel/helper-plugin-utils": ^7.19.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 6189c0b5c32ba3c9a80a42338bd50719d783b20ef29b853d4f03929e971913d3cefd80184e924ae98ad6db09080be8fe6f1ffde9a6db8972523234f0274d36f7 + languageName: node + linkType: hard + +"@babel/plugin-transform-arrow-functions@npm:^7.18.6": + version: 7.20.7 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.20.7" + dependencies: + "@babel/helper-plugin-utils": ^7.20.2 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b43cabe3790c2de7710abe32df9a30005eddb2050dadd5d122c6872f679e5710e410f1b90c8f99a2aff7b614cccfecf30e7fd310236686f60d3ed43fd80b9847 + languageName: node + linkType: hard + +"@babel/plugin-transform-async-to-generator@npm:^7.18.6": + version: 7.20.7 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.20.7" + dependencies: + "@babel/helper-module-imports": ^7.18.6 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-remap-async-to-generator": ^7.18.9 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: fe9ee8a5471b4317c1b9ea92410ace8126b52a600d7cfbfe1920dcac6fb0fad647d2e08beb4fd03c630eb54430e6c72db11e283e3eddc49615c68abd39430904 + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoped-functions@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0a0df61f94601e3666bf39f2cc26f5f7b22a94450fb93081edbed967bd752ce3f81d1227fefd3799f5ee2722171b5e28db61379234d1bb85b6ec689589f99d7e + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoping@npm:^7.20.2": + version: 7.20.14 + resolution: "@babel/plugin-transform-block-scoping@npm:7.20.14" + dependencies: + "@babel/helper-plugin-utils": ^7.20.2 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: acf7bf7314022732e70b0b9c3cdc0fd9d158423d01d09436f020b6f87e7c63292790e1fa34fdcc7388ec453dd5e59f664d4fb3bec5e5694ff28e810baa0c9659 + languageName: node + linkType: hard + +"@babel/plugin-transform-classes@npm:^7.20.2": + version: 7.20.7 + resolution: "@babel/plugin-transform-classes@npm:7.20.7" + dependencies: + "@babel/helper-annotate-as-pure": ^7.18.6 + "@babel/helper-compilation-targets": ^7.20.7 + "@babel/helper-environment-visitor": ^7.18.9 + "@babel/helper-function-name": ^7.19.0 + "@babel/helper-optimise-call-expression": ^7.18.6 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-replace-supers": ^7.20.7 + "@babel/helper-split-export-declaration": ^7.18.6 + globals: ^11.1.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4cf55ad88e52c7c66a991add4c8e1c3324384bd52df7085962d396879561456a44352e5ab1725cc80f4e83737a2931e847c4a96c7aa4a549357f23631ff31799 + languageName: node + linkType: hard + +"@babel/plugin-transform-computed-properties@npm:^7.18.9": + version: 7.20.7 + resolution: "@babel/plugin-transform-computed-properties@npm:7.20.7" + dependencies: + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/template": ^7.20.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: be70e54bda8b469146459f429e5f2bd415023b87b2d5af8b10e48f465ffb02847a3ed162ca60378c004b82db848e4d62e90010d41ded7e7176b6d8d1c2911139 + languageName: node + linkType: hard + +"@babel/plugin-transform-destructuring@npm:^7.20.2": + version: 7.20.7 + resolution: "@babel/plugin-transform-destructuring@npm:7.20.7" + dependencies: + "@babel/helper-plugin-utils": ^7.20.2 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: bd8affdb142c77662037215e37128b2110a786c92a67e1f00b38223c438c1610bd84cbc0386e9cd3479245ea811c5ca6c9838f49be4729b592159a30ce79add2 + languageName: node + linkType: hard + +"@babel/plugin-transform-dotall-regex@npm:^7.18.6, @babel/plugin-transform-dotall-regex@npm:^7.4.4": + version: 7.18.6 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.18.6" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.18.6 + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: cbe5d7063eb8f8cca24cd4827bc97f5641166509e58781a5f8aa47fb3d2d786ce4506a30fca2e01f61f18792783a5cb5d96bf5434c3dd1ad0de8c9cc625a53da + languageName: node + linkType: hard + +"@babel/plugin-transform-duplicate-keys@npm:^7.18.9": + version: 7.18.9 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.18.9" + dependencies: + "@babel/helper-plugin-utils": ^7.18.9 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 220bf4a9fec5c4d4a7b1de38810350260e8ea08481bf78332a464a21256a95f0df8cd56025f346238f09b04f8e86d4158fafc9f4af57abaef31637e3b58bd4fe + languageName: node + linkType: hard + +"@babel/plugin-transform-exponentiation-operator@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.18.6" + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor": ^7.18.6 + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7f70222f6829c82a36005508d34ddbe6fd0974ae190683a8670dd6ff08669aaf51fef2209d7403f9bd543cb2d12b18458016c99a6ed0332ccedb3ea127b01229 + languageName: node + linkType: hard + +"@babel/plugin-transform-flow-strip-types@npm:^7.16.0": + version: 7.19.0 + resolution: "@babel/plugin-transform-flow-strip-types@npm:7.19.0" + dependencies: + "@babel/helper-plugin-utils": ^7.19.0 + "@babel/plugin-syntax-flow": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c35339bf80c2a2b9abb9e2ce0382e1d9cc3ef7db2af127f4ec3d184bad2aec3269f3fcac5fdcd565439732803acad72eb9e7d5a18e439221526fdc041c9e8e1e + languageName: node + linkType: hard + +"@babel/plugin-transform-for-of@npm:^7.18.8": + version: 7.18.8 + resolution: "@babel/plugin-transform-for-of@npm:7.18.8" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ca64c623cf0c7a80ab6f07ebd3e6e4ade95e2ae806696f70b43eafe6394fa8ce21f2b1ffdd15df2067f7363d2ecfe26472a97c6c774403d2163fa05f50c98f17 + languageName: node + linkType: hard + +"@babel/plugin-transform-function-name@npm:^7.18.9": + version: 7.18.9 + resolution: "@babel/plugin-transform-function-name@npm:7.18.9" + dependencies: + "@babel/helper-compilation-targets": ^7.18.9 + "@babel/helper-function-name": ^7.18.9 + "@babel/helper-plugin-utils": ^7.18.9 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 62dd9c6cdc9714704efe15545e782ee52d74dc73916bf954b4d3bee088fb0ec9e3c8f52e751252433656c09f744b27b757fc06ed99bcde28e8a21600a1d8e597 + languageName: node + linkType: hard + +"@babel/plugin-transform-literals@npm:^7.18.9": + version: 7.18.9 + resolution: "@babel/plugin-transform-literals@npm:7.18.9" + dependencies: + "@babel/helper-plugin-utils": ^7.18.9 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3458dd2f1a47ac51d9d607aa18f3d321cbfa8560a985199185bed5a906bb0c61ba85575d386460bac9aed43fdd98940041fae5a67dff286f6f967707cff489f8 + languageName: node + linkType: hard + +"@babel/plugin-transform-member-expression-literals@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 35a3d04f6693bc6b298c05453d85ee6e41cc806538acb6928427e0e97ae06059f97d2f07d21495fcf5f70d3c13a242e2ecbd09d5c1fcb1b1a73ff528dcb0b695 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-amd@npm:^7.19.6": + version: 7.20.11 + resolution: "@babel/plugin-transform-modules-amd@npm:7.20.11" + dependencies: + "@babel/helper-module-transforms": ^7.20.11 + "@babel/helper-plugin-utils": ^7.20.2 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 23665c1c20c8f11c89382b588fb9651c0756d130737a7625baeaadbd3b973bc5bfba1303bedffa8fb99db1e6d848afb01016e1df2b69b18303e946890c790001 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-commonjs@npm:^7.19.6": + version: 7.20.11 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.20.11" + dependencies: + "@babel/helper-module-transforms": ^7.20.11 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-simple-access": ^7.20.2 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ddd0623e2ad4b5c0faaa0ae30d3407a3fa484d911c968ed33cfb1b339ac3691321c959db60b66dc136dbd67770fff586f7e48a7ce0d7d357f92d6ef6fb7ed1a7 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-systemjs@npm:^7.19.6": + version: 7.20.11 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.20.11" + dependencies: + "@babel/helper-hoist-variables": ^7.18.6 + "@babel/helper-module-transforms": ^7.20.11 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-validator-identifier": ^7.19.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4546c47587f88156d66c7eb7808e903cf4bb3f6ba6ac9bc8e3af2e29e92eb9f0b3f44d52043bfd24eb25fa7827fd7b6c8bfeac0cac7584e019b87e1ecbd0e673 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-umd@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-modules-umd@npm:7.18.6" + dependencies: + "@babel/helper-module-transforms": ^7.18.6 + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c3b6796c6f4579f1ba5ab0cdcc73910c1e9c8e1e773c507c8bb4da33072b3ae5df73c6d68f9126dab6e99c24ea8571e1563f8710d7c421fac1cde1e434c20153 + languageName: node + linkType: hard + +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.19.1": + version: 7.20.5 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.20.5" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.20.5 + "@babel/helper-plugin-utils": ^7.20.2 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 528c95fb1087e212f17e1c6456df041b28a83c772b9c93d2e407c9d03b72182b0d9d126770c1d6e0b23aab052599ceaf25ed6a2c0627f4249be34a83f6fae853 + languageName: node + linkType: hard + +"@babel/plugin-transform-new-target@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-new-target@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: bd780e14f46af55d0ae8503b3cb81ca86dcc73ed782f177e74f498fff934754f9e9911df1f8f3bd123777eed7c1c1af4d66abab87c8daae5403e7719a6b845d1 + languageName: node + linkType: hard + +"@babel/plugin-transform-object-super@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-object-super@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-replace-supers": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0fcb04e15deea96ae047c21cb403607d49f06b23b4589055993365ebd7a7d7541334f06bf9642e90075e66efce6ebaf1eb0ef066fbbab802d21d714f1aac3aef + languageName: node + linkType: hard + +"@babel/plugin-transform-parameters@npm:^7.20.1, @babel/plugin-transform-parameters@npm:^7.20.7": + version: 7.20.7 + resolution: "@babel/plugin-transform-parameters@npm:7.20.7" + dependencies: + "@babel/helper-plugin-utils": ^7.20.2 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 6ffe0dd9afb2d2b9bc247381aa2e95dd9997ff5568a0a11900528919a4e073ac68f46409431455badb8809644d47cff180045bc2b9700e3f36e3b23554978947 + languageName: node + linkType: hard + +"@babel/plugin-transform-property-literals@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-property-literals@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 1c16e64de554703f4b547541de2edda6c01346dd3031d4d29e881aa7733785cd26d53611a4ccf5353f4d3e69097bb0111c0a93ace9e683edd94fea28c4484144 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-constant-elements@npm:^7.12.1": + version: 7.20.2 + resolution: "@babel/plugin-transform-react-constant-elements@npm:7.20.2" + dependencies: + "@babel/helper-plugin-utils": ^7.20.2 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7b041b726e7c14b8c26a0dd240defac5f93a1f449371c6bdc5e6b46d581211300cc1a79da4140bdf20347f49e175dcb4f469812399206864024d1fdc81171193 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-display-name@npm:^7.16.0, @babel/plugin-transform-react-display-name@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-react-display-name@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 51c087ab9e41ef71a29335587da28417536c6f816c292e092ffc0e0985d2f032656801d4dd502213ce32481f4ba6c69402993ffa67f0818a07606ff811e4be49 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-jsx-development@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-react-jsx-development@npm:7.18.6" + dependencies: + "@babel/plugin-transform-react-jsx": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ec9fa65db66f938b75c45e99584367779ac3e0af8afc589187262e1337c7c4205ea312877813ae4df9fb93d766627b8968d74ac2ba702e4883b1dbbe4953ecee + languageName: node + linkType: hard + +"@babel/plugin-transform-react-jsx@npm:^7.18.6": + version: 7.20.13 + resolution: "@babel/plugin-transform-react-jsx@npm:7.20.13" + dependencies: + "@babel/helper-annotate-as-pure": ^7.18.6 + "@babel/helper-module-imports": ^7.18.6 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/plugin-syntax-jsx": ^7.18.6 + "@babel/types": ^7.20.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b1daaa9b093ab59f71572dde7ad05ed3490433a47de103fc866f60347da55fa7fe84cf9b4c9fa22917517d52f70ab5e05ec631bba1c348733c0d8ebbd7de8c68 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-pure-annotations@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.18.6" + dependencies: + "@babel/helper-annotate-as-pure": ^7.18.6 + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 97c4873d409088f437f9084d084615948198dd87fc6723ada0e7e29c5a03623c2f3e03df3f52e7e7d4d23be32a08ea00818bff302812e48713c706713bd06219 + languageName: node + linkType: hard + +"@babel/plugin-transform-regenerator@npm:^7.18.6": + version: 7.20.5 + resolution: "@babel/plugin-transform-regenerator@npm:7.20.5" + dependencies: + "@babel/helper-plugin-utils": ^7.20.2 + regenerator-transform: ^0.15.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 13164861e71fb23d84c6270ef5330b03c54d5d661c2c7468f28e21c4f8598558ca0c8c3cb1d996219352946e849d270a61372bc93c8fbe9676e78e3ffd0dea07 + languageName: node + linkType: hard + +"@babel/plugin-transform-reserved-words@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-reserved-words@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0738cdc30abdae07c8ec4b233b30c31f68b3ff0eaa40eddb45ae607c066127f5fa99ddad3c0177d8e2832e3a7d3ad115775c62b431ebd6189c40a951b867a80c + languageName: node + linkType: hard + +"@babel/plugin-transform-runtime@npm:^7.16.4": + version: 7.19.6 + resolution: "@babel/plugin-transform-runtime@npm:7.19.6" + dependencies: + "@babel/helper-module-imports": ^7.18.6 + "@babel/helper-plugin-utils": ^7.19.0 + babel-plugin-polyfill-corejs2: ^0.3.3 + babel-plugin-polyfill-corejs3: ^0.6.0 + babel-plugin-polyfill-regenerator: ^0.4.1 + semver: ^6.3.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ef93efbcbb00dcf4da6dcc55bda698a2a57fca3fb05a6a13e932ecfdb7c1c5d2f0b5b245c1c4faca0318853937caba0d82442f58b7653249f64275d08052fbd8 + languageName: node + linkType: hard + +"@babel/plugin-transform-shorthand-properties@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b8e4e8acc2700d1e0d7d5dbfd4fdfb935651913de6be36e6afb7e739d8f9ca539a5150075a0f9b79c88be25ddf45abb912fe7abf525f0b80f5b9d9860de685d7 + languageName: node + linkType: hard + +"@babel/plugin-transform-spread@npm:^7.19.0": + version: 7.20.7 + resolution: "@babel/plugin-transform-spread@npm:7.20.7" + dependencies: + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-skip-transparent-expression-wrappers": ^7.20.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 8ea698a12da15718aac7489d4cde10beb8a3eea1f66167d11ab1e625033641e8b328157fd1a0b55dd6531933a160c01fc2e2e61132a385cece05f26429fd0cc2 + languageName: node + linkType: hard + +"@babel/plugin-transform-sticky-regex@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 68ea18884ae9723443ffa975eb736c8c0d751265859cd3955691253f7fee37d7a0f7efea96c8a062876af49a257a18ea0ed5fea0d95a7b3611ce40f7ee23aee3 + languageName: node + linkType: hard + +"@babel/plugin-transform-template-literals@npm:^7.18.9": + version: 7.18.9 + resolution: "@babel/plugin-transform-template-literals@npm:7.18.9" + dependencies: + "@babel/helper-plugin-utils": ^7.18.9 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3d2fcd79b7c345917f69b92a85bdc3ddd68ce2c87dc70c7d61a8373546ccd1f5cb8adc8540b49dfba08e1b82bb7b3bbe23a19efdb2b9c994db2db42906ca9fb2 + languageName: node + linkType: hard + +"@babel/plugin-transform-typeof-symbol@npm:^7.18.9": + version: 7.18.9 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.18.9" + dependencies: + "@babel/helper-plugin-utils": ^7.18.9 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: e754e0d8b8a028c52e10c148088606e3f7a9942c57bd648fc0438e5b4868db73c386a5ed47ab6d6f0594aae29ee5ffc2ffc0f7ebee7fae560a066d6dea811cd4 + languageName: node + linkType: hard + +"@babel/plugin-transform-typescript@npm:^7.18.6": + version: 7.20.13 + resolution: "@babel/plugin-transform-typescript@npm:7.20.13" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.20.12 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/plugin-syntax-typescript": ^7.20.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0b0c3a3e53268d4feb35eb17d57873f2488392e404a0b32735d51c49b08462dc738ebd860f0ff3a3dc5cd1b1fa70340bb6c072239c86afca635831b930593b3b + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-escapes@npm:^7.18.10": + version: 7.18.10 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.18.10" + dependencies: + "@babel/helper-plugin-utils": ^7.18.9 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f5baca55cb3c11bc08ec589f5f522d85c1ab509b4d11492437e45027d64ae0b22f0907bd1381e8d7f2a436384bb1f9ad89d19277314242c5c2671a0f91d0f9cd + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-regex@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.18.6" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.18.6 + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d9e18d57536a2d317fb0b7c04f8f55347f3cfacb75e636b4c6fa2080ab13a3542771b5120e726b598b815891fc606d1472ac02b749c69fd527b03847f22dc25e + languageName: node + linkType: hard + +"@babel/preset-env@npm:^7.11.0, @babel/preset-env@npm:^7.12.1, @babel/preset-env@npm:^7.16.4": + version: 7.20.2 + resolution: "@babel/preset-env@npm:7.20.2" + dependencies: + "@babel/compat-data": ^7.20.1 + "@babel/helper-compilation-targets": ^7.20.0 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-validator-option": ^7.18.6 + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.18.6 + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.18.9 + "@babel/plugin-proposal-async-generator-functions": ^7.20.1 + "@babel/plugin-proposal-class-properties": ^7.18.6 + "@babel/plugin-proposal-class-static-block": ^7.18.6 + "@babel/plugin-proposal-dynamic-import": ^7.18.6 + "@babel/plugin-proposal-export-namespace-from": ^7.18.9 + "@babel/plugin-proposal-json-strings": ^7.18.6 + "@babel/plugin-proposal-logical-assignment-operators": ^7.18.9 + "@babel/plugin-proposal-nullish-coalescing-operator": ^7.18.6 + "@babel/plugin-proposal-numeric-separator": ^7.18.6 + "@babel/plugin-proposal-object-rest-spread": ^7.20.2 + "@babel/plugin-proposal-optional-catch-binding": ^7.18.6 + "@babel/plugin-proposal-optional-chaining": ^7.18.9 + "@babel/plugin-proposal-private-methods": ^7.18.6 + "@babel/plugin-proposal-private-property-in-object": ^7.18.6 + "@babel/plugin-proposal-unicode-property-regex": ^7.18.6 + "@babel/plugin-syntax-async-generators": ^7.8.4 + "@babel/plugin-syntax-class-properties": ^7.12.13 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + "@babel/plugin-syntax-export-namespace-from": ^7.8.3 + "@babel/plugin-syntax-import-assertions": ^7.20.0 + "@babel/plugin-syntax-json-strings": ^7.8.3 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + "@babel/plugin-syntax-top-level-await": ^7.14.5 + "@babel/plugin-transform-arrow-functions": ^7.18.6 + "@babel/plugin-transform-async-to-generator": ^7.18.6 + "@babel/plugin-transform-block-scoped-functions": ^7.18.6 + "@babel/plugin-transform-block-scoping": ^7.20.2 + "@babel/plugin-transform-classes": ^7.20.2 + "@babel/plugin-transform-computed-properties": ^7.18.9 + "@babel/plugin-transform-destructuring": ^7.20.2 + "@babel/plugin-transform-dotall-regex": ^7.18.6 + "@babel/plugin-transform-duplicate-keys": ^7.18.9 + "@babel/plugin-transform-exponentiation-operator": ^7.18.6 + "@babel/plugin-transform-for-of": ^7.18.8 + "@babel/plugin-transform-function-name": ^7.18.9 + "@babel/plugin-transform-literals": ^7.18.9 + "@babel/plugin-transform-member-expression-literals": ^7.18.6 + "@babel/plugin-transform-modules-amd": ^7.19.6 + "@babel/plugin-transform-modules-commonjs": ^7.19.6 + "@babel/plugin-transform-modules-systemjs": ^7.19.6 + "@babel/plugin-transform-modules-umd": ^7.18.6 + "@babel/plugin-transform-named-capturing-groups-regex": ^7.19.1 + "@babel/plugin-transform-new-target": ^7.18.6 + "@babel/plugin-transform-object-super": ^7.18.6 + "@babel/plugin-transform-parameters": ^7.20.1 + "@babel/plugin-transform-property-literals": ^7.18.6 + "@babel/plugin-transform-regenerator": ^7.18.6 + "@babel/plugin-transform-reserved-words": ^7.18.6 + "@babel/plugin-transform-shorthand-properties": ^7.18.6 + "@babel/plugin-transform-spread": ^7.19.0 + "@babel/plugin-transform-sticky-regex": ^7.18.6 + "@babel/plugin-transform-template-literals": ^7.18.9 + "@babel/plugin-transform-typeof-symbol": ^7.18.9 + "@babel/plugin-transform-unicode-escapes": ^7.18.10 + "@babel/plugin-transform-unicode-regex": ^7.18.6 + "@babel/preset-modules": ^0.1.5 + "@babel/types": ^7.20.2 + babel-plugin-polyfill-corejs2: ^0.3.3 + babel-plugin-polyfill-corejs3: ^0.6.0 + babel-plugin-polyfill-regenerator: ^0.4.1 + core-js-compat: ^3.25.1 + semver: ^6.3.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ece2d7e9c7789db6116e962b8e1a55eb55c110c44c217f0c8f6ffea4ca234954e66557f7bd019b7affadf7fbb3a53ccc807e93fc935aacd48146234b73b6947e + languageName: node + linkType: hard + +"@babel/preset-modules@npm:^0.1.5": + version: 0.1.5 + resolution: "@babel/preset-modules@npm:0.1.5" + 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 + checksum: 8430e0e9e9d520b53e22e8c4c6a5a080a12b63af6eabe559c2310b187bd62ae113f3da82ba33e9d1d0f3230930ca702843aae9dd226dec51f7d7114dc1f51c10 + languageName: node + linkType: hard + +"@babel/preset-react@npm:^7.12.5, @babel/preset-react@npm:^7.16.0": + version: 7.18.6 + resolution: "@babel/preset-react@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-validator-option": ^7.18.6 + "@babel/plugin-transform-react-display-name": ^7.18.6 + "@babel/plugin-transform-react-jsx": ^7.18.6 + "@babel/plugin-transform-react-jsx-development": ^7.18.6 + "@babel/plugin-transform-react-pure-annotations": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 540d9cf0a0cc0bb07e6879994e6fb7152f87dafbac880b56b65e2f528134c7ba33e0cd140b58700c77b2ebf4c81fa6468fed0ba391462d75efc7f8c1699bb4c3 + languageName: node + linkType: hard + +"@babel/preset-typescript@npm:^7.16.0": + version: 7.18.6 + resolution: "@babel/preset-typescript@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-validator-option": ^7.18.6 + "@babel/plugin-transform-typescript": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7fe0da5103eb72d3cf39cf3e138a794c8cdd19c0b38e3e101507eef519c46a87a0d6d0e8bc9e28a13ea2364001ebe7430b9d75758aab4c3c3a8db9a487b9dc7c + languageName: node + linkType: hard + +"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.2, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.6, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.2, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": + version: 7.23.8 + resolution: "@babel/runtime@npm:7.23.8" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: 0bd5543c26811153822a9f382fd39886f66825ff2a397a19008011376533747cd05c33a91f6248c0b8b0edf0448d7c167ebfba34786088f1b7eb11c65be7dfc3 + languageName: node + linkType: hard + +"@babel/runtime@npm:^7.14.6": + version: 7.22.6 + resolution: "@babel/runtime@npm:7.22.6" + dependencies: + regenerator-runtime: ^0.13.11 + checksum: e585338287c4514a713babf4fdb8fc2a67adcebab3e7723a739fc62c79cfda875b314c90fd25f827afb150d781af97bc16c85bfdbfa2889f06053879a1ddb597 + languageName: node + linkType: hard + +"@babel/template@npm:^7.18.10, @babel/template@npm:^7.20.7, @babel/template@npm:^7.3.3": + version: 7.20.7 + resolution: "@babel/template@npm:7.20.7" + dependencies: + "@babel/code-frame": ^7.18.6 + "@babel/parser": ^7.20.7 + "@babel/types": ^7.20.7 + checksum: 2eb1a0ab8d415078776bceb3473d07ab746e6bb4c2f6ca46ee70efb284d75c4a32bb0cd6f4f4946dec9711f9c0780e8e5d64b743208deac6f8e9858afadc349e + languageName: node + linkType: hard + +"@babel/template@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/template@npm:7.22.15" + dependencies: + "@babel/code-frame": ^7.22.13 + "@babel/parser": ^7.22.15 + "@babel/types": ^7.22.15 + checksum: 1f3e7dcd6c44f5904c184b3f7fe280394b191f2fed819919ffa1e529c259d5b197da8981b6ca491c235aee8dbad4a50b7e31304aa531271cb823a4a24a0dd8fd + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.20.10, @babel/traverse@npm:^7.20.12, @babel/traverse@npm:^7.20.13, @babel/traverse@npm:^7.20.5, @babel/traverse@npm:^7.20.7, @babel/traverse@npm:^7.7.2": + version: 7.23.2 + resolution: "@babel/traverse@npm:7.23.2" + dependencies: + "@babel/code-frame": ^7.22.13 + "@babel/generator": ^7.23.0 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-hoist-variables": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + "@babel/parser": ^7.23.0 + "@babel/types": ^7.23.0 + debug: ^4.1.0 + globals: ^11.1.0 + checksum: 26a1eea0dde41ab99dde8b9773a013a0dc50324e5110a049f5d634e721ff08afffd54940b3974a20308d7952085ac769689369e9127dea655f868c0f6e1ab35d + languageName: node + linkType: hard + +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.12.6, @babel/types@npm:^7.18.6, @babel/types@npm:^7.18.9, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.2, @babel/types@npm:^7.20.5, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.23.0 + resolution: "@babel/types@npm:7.23.0" + dependencies: + "@babel/helper-string-parser": ^7.22.5 + "@babel/helper-validator-identifier": ^7.22.20 + to-fast-properties: ^2.0.0 + checksum: 215fe04bd7feef79eeb4d33374b39909ce9cad1611c4135a4f7fdf41fe3280594105af6d7094354751514625ea92d0875aba355f53e86a92600f290e77b0e604 + languageName: node + linkType: hard + +"@bcoe/v8-coverage@npm:^0.2.3": + version: 0.2.3 + resolution: "@bcoe/v8-coverage@npm:0.2.3" + checksum: 850f9305536d0f2bd13e9e0881cb5f02e4f93fad1189f7b2d4bebf694e3206924eadee1068130d43c11b750efcc9405f88a8e42ef098b6d75239c0f047de1a27 + languageName: node + linkType: hard + +"@colors/colors@npm:1.5.0": + version: 1.5.0 + resolution: "@colors/colors@npm:1.5.0" + checksum: d64d5260bed1d5012ae3fc617d38d1afc0329fec05342f4e6b838f46998855ba56e0a73833f4a80fa8378c84810da254f76a8a19c39d038260dc06dc4e007425 + languageName: node + linkType: hard + +"@craco/craco@npm:7.1.0": + version: 7.1.0 + resolution: "@craco/craco@npm:7.1.0" + dependencies: + autoprefixer: ^10.4.12 + cosmiconfig: ^7.0.1 + cosmiconfig-typescript-loader: ^1.0.0 + cross-spawn: ^7.0.3 + lodash: ^4.17.21 + semver: ^7.3.7 + webpack-merge: ^5.8.0 + peerDependencies: + react-scripts: ^5.0.0 + bin: + craco: dist/bin/craco.js + checksum: d534d1ea7814e7bd9f2e2aef17821fcdb1d9cac8308e8eb04809f8f3371180086b8f673dedce1ffbefba9ded566e91e4c9663464e488bf6291461091cbd95c4e + languageName: node + linkType: hard + +"@cspotcode/source-map-support@npm:^0.8.0": + version: 0.8.1 + resolution: "@cspotcode/source-map-support@npm:0.8.1" + dependencies: + "@jridgewell/trace-mapping": 0.3.9 + checksum: 5718f267085ed8edb3e7ef210137241775e607ee18b77d95aa5bd7514f47f5019aa2d82d96b3bf342ef7aa890a346fa1044532ff7cc3009e7d24fce3ce6200fa + languageName: node + linkType: hard + +"@csstools/normalize.css@npm:*": + version: 12.0.0 + resolution: "@csstools/normalize.css@npm:12.0.0" + checksum: fbef0f7fe4edbc3ce31b41257f0fa06e0442f11260e41c082a98de9b824997786a16900e7a5c0f4ca8f736dcd25dfd01c153d1c994a07d42c93c0a526ce0774d + languageName: node + linkType: hard + +"@csstools/postcss-cascade-layers@npm:^1.1.1": + version: 1.1.1 + resolution: "@csstools/postcss-cascade-layers@npm:1.1.1" + dependencies: + "@csstools/selector-specificity": ^2.0.2 + postcss-selector-parser: ^6.0.10 + peerDependencies: + postcss: ^8.2 + checksum: 8ecd6a929e8ddee3ad0834ab5017f50a569817ba8490d152b11c705c13cf3d9701f74792f375cbd72d8f33a4eeaabb3f984f1514adf8c5a530eb91be70c14cf4 + languageName: node + linkType: hard + +"@csstools/postcss-color-function@npm:^1.1.1": + version: 1.1.1 + resolution: "@csstools/postcss-color-function@npm:1.1.1" + dependencies: + "@csstools/postcss-progressive-custom-properties": ^1.1.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: 087595985ebcc2fc42013d6305185d4cdc842d87fb261185db905dc31eaa24fc23a7cc068fa3da814b3c8b98164107ddaf1b4ab24f4ff5b2a7b5fbcd4c6ceec9 + languageName: node + linkType: hard + +"@csstools/postcss-font-format-keywords@npm:^1.0.1": + version: 1.0.1 + resolution: "@csstools/postcss-font-format-keywords@npm:1.0.1" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: ed8d9eab9793f0184e000709bcb155d4eb96c49a312e3ea9e549e006b74fd4aafac63cb9f9f01bec5b717a833539ff085c3f1ef7d273b97d587769ef637d50c1 + languageName: node + linkType: hard + +"@csstools/postcss-hwb-function@npm:^1.0.2": + version: 1.0.2 + resolution: "@csstools/postcss-hwb-function@npm:1.0.2" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: 352ead754a692f7ed33a712c491012cab5c2f2946136a669a354237cfe8e6faca90c7389ee793cb329b9b0ddec984faa06d47e2f875933aaca417afff74ce6aa + languageName: node + linkType: hard + +"@csstools/postcss-ic-unit@npm:^1.0.1": + version: 1.0.1 + resolution: "@csstools/postcss-ic-unit@npm:1.0.1" + dependencies: + "@csstools/postcss-progressive-custom-properties": ^1.1.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: 09c414c9b7762b5fbe837ff451d7a11e4890f1ed3c92edc3573f02f3d89747f6ac3f2270799b68a332bd7f5de05bb0dfffddb6323fc4020c2bea33ff58314533 + languageName: node + linkType: hard + +"@csstools/postcss-is-pseudo-class@npm:^2.0.7": + version: 2.0.7 + resolution: "@csstools/postcss-is-pseudo-class@npm:2.0.7" + dependencies: + "@csstools/selector-specificity": ^2.0.0 + postcss-selector-parser: ^6.0.10 + peerDependencies: + postcss: ^8.2 + checksum: a4494bb8e9a34826944ba6872c91c1e88268caab6d06968897f1a0cc75ca5cfc4989435961fc668a9c6842a6d17f4cda0055fa256d23e598b8bbc6f022956125 + languageName: node + linkType: hard + +"@csstools/postcss-nested-calc@npm:^1.0.0": + version: 1.0.0 + resolution: "@csstools/postcss-nested-calc@npm:1.0.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: 53bb783dd61621c11c1e6e352f079577e2eb908de67947ceef31a178e070c06c223baae87acd5c3bd51c664515d2adc16166a129159168626111aff548583790 + languageName: node + linkType: hard + +"@csstools/postcss-normalize-display-values@npm:^1.0.1": + version: 1.0.1 + resolution: "@csstools/postcss-normalize-display-values@npm:1.0.1" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: 75901daec3869ba15e0adfd50d8e2e754ec06d55ac44fbd540748476388d223d53710fb3a3cbfe6695a2bab015a489fb47d9e3914ff211736923f8deb818dc0b + languageName: node + linkType: hard + +"@csstools/postcss-oklab-function@npm:^1.1.1": + version: 1.1.1 + resolution: "@csstools/postcss-oklab-function@npm:1.1.1" + dependencies: + "@csstools/postcss-progressive-custom-properties": ^1.1.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: d66b789060b37ed810450d9a7d8319a0ae14e913c091f3e0ee482b3471538762e801d5eae3d62fda2f1eb1e88c76786d2c2b06c1172166eba1cca5e2a0dc95f2 + languageName: node + linkType: hard + +"@csstools/postcss-progressive-custom-properties@npm:^1.1.0, @csstools/postcss-progressive-custom-properties@npm:^1.3.0": + version: 1.3.0 + resolution: "@csstools/postcss-progressive-custom-properties@npm:1.3.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.3 + checksum: e281845fde5b8a80d06ec20147bd74e96a9351bebbec5e5c3a6fb37ea30a597ff84172601786a8a270662f58f708b4a3bf8d822d6318023def9773d2f6589962 + languageName: node + linkType: hard + +"@csstools/postcss-stepped-value-functions@npm:^1.0.1": + version: 1.0.1 + resolution: "@csstools/postcss-stepped-value-functions@npm:1.0.1" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: 2fc88713a0d49d142010652be8139b00719e407df1173e46047284f1befd0647e1fff67f259f9f55ac3b46bba6462b21f0aa192bd10a2989c51a8ce0d25fc495 + languageName: node + linkType: hard + +"@csstools/postcss-text-decoration-shorthand@npm:^1.0.0": + version: 1.0.0 + resolution: "@csstools/postcss-text-decoration-shorthand@npm:1.0.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: d27aaf97872c42bec9f6fde4d8bf924e89f7886f0aca8e4fc5aaf2f9083b09bb43dbbfa29124fa36fcdeb2d4d3e0459a095acf62188260cd1577e9811bb1276e + languageName: node + linkType: hard + +"@csstools/postcss-trigonometric-functions@npm:^1.0.2": + version: 1.0.2 + resolution: "@csstools/postcss-trigonometric-functions@npm:1.0.2" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: f7f5b5f2492606b79a56f09e814ae8f10a2ae9e9c5fb8019f0e347a4a6c07953b2cc663fd4fa43a60e6994dfd958958f39df8ec760e2a646cfe71fe2bb119382 + languageName: node + linkType: hard + +"@csstools/postcss-unset-value@npm:^1.0.2": + version: 1.0.2 + resolution: "@csstools/postcss-unset-value@npm:1.0.2" + peerDependencies: + postcss: ^8.2 + checksum: 3facdae154d6516ffd964f7582696f406465f11cf8dead503e0afdfecc99ebc25638ab2830affce4516131aa2db004458a235e439f575b04e9ef72ad82f55835 + languageName: node + linkType: hard + +"@csstools/selector-specificity@npm:^2.0.0, @csstools/selector-specificity@npm:^2.0.2": + version: 2.1.1 + resolution: "@csstools/selector-specificity@npm:2.1.1" + peerDependencies: + postcss: ^8.4 + postcss-selector-parser: ^6.0.10 + checksum: 392ab62732e93aa8cbea445bf3485c1acbbecc8ec087b200e06c9ddd2acf740fd1fe46abdacf813e7a50a95a60346377ee3eecb4e1fe3709582e2851430b376a + languageName: node + linkType: hard + +"@cypress/request@npm:^3.0.0": + version: 3.0.1 + resolution: "@cypress/request@npm:3.0.1" + 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 + http-signature: ~1.3.6 + is-typedarray: ~1.0.0 + isstream: ~0.1.2 + json-stringify-safe: ~5.0.1 + mime-types: ~2.1.19 + performance-now: ^2.1.0 + qs: 6.10.4 + safe-buffer: ^5.1.2 + tough-cookie: ^4.1.3 + tunnel-agent: ^0.6.0 + uuid: ^8.3.2 + checksum: 7175522ebdbe30e3c37973e204c437c23ce659e58d5939466615bddcd58d778f3a8ea40f087b965ae8b8138ea8d102b729c6eb18c6324f121f3778f4a2e8e727 + languageName: node + linkType: hard + +"@cypress/xvfb@npm:^1.2.4": + version: 1.2.4 + resolution: "@cypress/xvfb@npm:1.2.4" + dependencies: + debug: ^3.1.0 + lodash.once: ^4.1.1 + checksum: 7bdcdaeb1bb692ec9d9bf8ec52538aa0bead6764753f4a067a171a511807a43fab016f7285a56bef6a606c2467ff3f1365e1ad2d2d583b81beed849ee1573fd1 + languageName: node + linkType: hard + +"@date-io/core@npm:^2.17.0": + version: 2.17.0 + resolution: "@date-io/core@npm:2.17.0" + checksum: 008dfc79eb54256805113d76feca82fe0b08a245ecbfb2d53809e6a129dc201f9dbd053c8ad63512203ab1a13ff7f76de0edc31829588ef507d53307974c29a8 + languageName: node + linkType: hard + +"@date-io/date-fns@npm:2.17.0": + version: 2.17.0 + resolution: "@date-io/date-fns@npm:2.17.0" + dependencies: + "@date-io/core": ^2.17.0 + peerDependencies: + date-fns: ^2.0.0 + peerDependenciesMeta: + date-fns: + optional: true + checksum: bfab634c985a98dd44fdfc5f982b0348da2886c9ad79a8d71fd7bfa05b740af7f5cf340508cd7ce51d67c141fb8766998c8efdf50653252c68ec078471cd76e6 + languageName: node + linkType: hard + +"@emotion/babel-plugin@npm:^11.11.0": + version: 11.11.0 + resolution: "@emotion/babel-plugin@npm:11.11.0" + dependencies: + "@babel/helper-module-imports": ^7.16.7 + "@babel/runtime": ^7.18.3 + "@emotion/hash": ^0.9.1 + "@emotion/memoize": ^0.8.1 + "@emotion/serialize": ^1.1.2 + babel-plugin-macros: ^3.1.0 + convert-source-map: ^1.5.0 + escape-string-regexp: ^4.0.0 + find-root: ^1.1.0 + source-map: ^0.5.7 + stylis: 4.2.0 + checksum: 6b363edccc10290f7a23242c06f88e451b5feb2ab94152b18bb8883033db5934fb0e421e2d67d09907c13837c21218a3ac28c51707778a54d6cd3706c0c2f3f9 + languageName: node + linkType: hard + +"@emotion/cache@npm:^11.10.5, @emotion/cache@npm:^11.11.0": + version: 11.11.0 + resolution: "@emotion/cache@npm:11.11.0" + dependencies: + "@emotion/memoize": ^0.8.1 + "@emotion/sheet": ^1.2.2 + "@emotion/utils": ^1.2.1 + "@emotion/weak-memoize": ^0.3.1 + stylis: 4.2.0 + checksum: 8eb1dc22beaa20c21a2e04c284d5a2630a018a9d51fb190e52de348c8d27f4e8ca4bbab003d68b4f6cd9cc1c569ca747a997797e0f76d6c734a660dc29decf08 + languageName: node + linkType: hard + +"@emotion/hash@npm:^0.9.1": + version: 0.9.1 + resolution: "@emotion/hash@npm:0.9.1" + checksum: 716e17e48bf9047bf9383982c071de49f2615310fb4e986738931776f5a823bc1f29c84501abe0d3df91a3803c80122d24e28b57351bca9e01356ebb33d89876 + languageName: node + linkType: hard + +"@emotion/is-prop-valid@npm:^1.2.0, @emotion/is-prop-valid@npm:^1.2.1": + version: 1.2.1 + resolution: "@emotion/is-prop-valid@npm:1.2.1" + dependencies: + "@emotion/memoize": ^0.8.1 + checksum: 8f42dc573a3fad79b021479becb639b8fe3b60bdd1081a775d32388bca418ee53074c7602a4c845c5f75fa6831eb1cbdc4d208cc0299f57014ed3a02abcad16a + languageName: node + linkType: hard + +"@emotion/memoize@npm:^0.8.1": + version: 0.8.1 + resolution: "@emotion/memoize@npm:0.8.1" + checksum: a19cc01a29fcc97514948eaab4dc34d8272e934466ed87c07f157887406bc318000c69ae6f813a9001c6a225364df04249842a50e692ef7a9873335fbcc141b0 + languageName: node + linkType: hard + +"@emotion/react@npm:11.11.1": + version: 11.11.1 + resolution: "@emotion/react@npm:11.11.1" + dependencies: + "@babel/runtime": ^7.18.3 + "@emotion/babel-plugin": ^11.11.0 + "@emotion/cache": ^11.11.0 + "@emotion/serialize": ^1.1.2 + "@emotion/use-insertion-effect-with-fallbacks": ^1.0.1 + "@emotion/utils": ^1.2.1 + "@emotion/weak-memoize": ^0.3.1 + hoist-non-react-statics: ^3.3.1 + peerDependencies: + react: ">=16.8.0" + peerDependenciesMeta: + "@types/react": + optional: true + checksum: aec3c36650f5f0d3d4445ff44d73dd88712b1609645b6af3e6d08049cfbc51f1785fe13dea1a1d4ab1b0800d68f2339ab11e459687180362b1ef98863155aae5 + languageName: node + linkType: hard + +"@emotion/serialize@npm:^1.1.2": + version: 1.1.2 + resolution: "@emotion/serialize@npm:1.1.2" + dependencies: + "@emotion/hash": ^0.9.1 + "@emotion/memoize": ^0.8.1 + "@emotion/unitless": ^0.8.1 + "@emotion/utils": ^1.2.1 + csstype: ^3.0.2 + checksum: 413c352e657f1b5e27ea6437b3ef7dcc3860669b7ae17fd5c18bfbd44e033af1acc56b64d252284a813ca4f3b3e1b0841c42d3fb08e02d2df56fd3cd63d72986 + languageName: node + linkType: hard + +"@emotion/sheet@npm:^1.2.2": + version: 1.2.2 + resolution: "@emotion/sheet@npm:1.2.2" + checksum: d973273c9c15f1c291ca2269728bf044bd3e92a67bca87943fa9ec6c3cd2b034f9a6bfe95ef1b5d983351d128c75b547b43ff196a00a3875f7e1d269793cecfe + languageName: node + linkType: hard + +"@emotion/styled@npm:11.11.0": + version: 11.11.0 + resolution: "@emotion/styled@npm:11.11.0" + dependencies: + "@babel/runtime": ^7.18.3 + "@emotion/babel-plugin": ^11.11.0 + "@emotion/is-prop-valid": ^1.2.1 + "@emotion/serialize": ^1.1.2 + "@emotion/use-insertion-effect-with-fallbacks": ^1.0.1 + "@emotion/utils": ^1.2.1 + peerDependencies: + "@emotion/react": ^11.0.0-rc.0 + react: ">=16.8.0" + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 904f641aad3892c65d7d6c0808b036dae1e6d6dad4861c1c7dc0baa59977047c6cad220691206eba7b4059f1a1c6e6c1ef4ebb8c829089e280fa0f2164a01e6b + languageName: node + linkType: hard + +"@emotion/unitless@npm:^0.8.1": + version: 0.8.1 + resolution: "@emotion/unitless@npm:0.8.1" + checksum: 385e21d184d27853bb350999471f00e1429fa4e83182f46cd2c164985999d9b46d558dc8b9cc89975cb337831ce50c31ac2f33b15502e85c299892e67e7b4a88 + languageName: node + linkType: hard + +"@emotion/use-insertion-effect-with-fallbacks@npm:^1.0.1": + version: 1.0.1 + resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.0.1" + peerDependencies: + react: ">=16.8.0" + checksum: 700b6e5bbb37a9231f203bb3af11295eed01d73b2293abece0bc2a2237015e944d7b5114d4887ad9a79776504aa51ed2a8b0ddbc117c54495dd01a6b22f93786 + languageName: node + linkType: hard + +"@emotion/utils@npm:^1.2.1": + version: 1.2.1 + resolution: "@emotion/utils@npm:1.2.1" + checksum: e0b44be0705b56b079c55faff93952150be69e79b660ae70ddd5b6e09fc40eb1319654315a9f34bb479d7f4ec94be6068c061abbb9e18b9778ae180ad5d97c73 + languageName: node + linkType: hard + +"@emotion/weak-memoize@npm:^0.3.1": + version: 0.3.1 + resolution: "@emotion/weak-memoize@npm:0.3.1" + checksum: b2be47caa24a8122622ea18cd2d650dbb4f8ad37b636dc41ed420c2e082f7f1e564ecdea68122b546df7f305b159bf5ab9ffee872abd0f052e687428459af594 + languageName: node + linkType: hard + +"@eslint-community/eslint-utils@npm:^4.2.0": + version: 4.4.0 + resolution: "@eslint-community/eslint-utils@npm:4.4.0" + dependencies: + eslint-visitor-keys: ^3.3.0 + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + checksum: cdfe3ae42b4f572cbfb46d20edafe6f36fc5fb52bf2d90875c58aefe226892b9677fef60820e2832caf864a326fe4fc225714c46e8389ccca04d5f9288aabd22 + languageName: node + linkType: hard + +"@eslint-community/regexpp@npm:^4.4.0, @eslint-community/regexpp@npm:^4.6.1": + version: 4.10.0 + resolution: "@eslint-community/regexpp@npm:4.10.0" + checksum: 2a6e345429ea8382aaaf3a61f865cae16ed44d31ca917910033c02dc00d505d939f10b81e079fa14d43b51499c640138e153b7e40743c4c094d9df97d4e56f7b + languageName: node + linkType: hard + +"@eslint/eslintrc@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" + dependencies: + ajv: ^6.12.4 + debug: ^4.3.2 + espree: ^9.6.0 + globals: ^13.19.0 + ignore: ^5.2.0 + import-fresh: ^3.2.1 + js-yaml: ^4.1.0 + minimatch: ^3.1.2 + strip-json-comments: ^3.1.1 + checksum: 10957c7592b20ca0089262d8c2a8accbad14b4f6507e35416c32ee6b4dbf9cad67dfb77096bbd405405e9ada2b107f3797fe94362e1c55e0b09d6e90dd149127 + languageName: node + linkType: hard + +"@eslint/js@npm:8.56.0": + version: 8.56.0 + resolution: "@eslint/js@npm:8.56.0" + checksum: 5804130574ef810207bdf321c265437814e7a26f4e6fac9b496de3206afd52f533e09ec002a3be06cd9adcc9da63e727f1883938e663c4e4751c007d5b58e539 + languageName: node + linkType: hard + +"@gar/promisify@npm:^1.1.3": + version: 1.1.3 + resolution: "@gar/promisify@npm:1.1.3" + checksum: 4059f790e2d07bf3c3ff3e0fec0daa8144fe35c1f6e0111c9921bd32106adaa97a4ab096ad7dab1e28ee6a9060083c4d1a4ada42a7f5f3f7a96b8812e2b757c1 + languageName: node + linkType: hard + +"@hapi/hoek@npm:^9.0.0": + version: 9.3.0 + resolution: "@hapi/hoek@npm:9.3.0" + checksum: 4771c7a776242c3c022b168046af4e324d116a9d2e1d60631ee64f474c6e38d1bb07092d898bf95c7bc5d334c5582798a1456321b2e53ca817d4e7c88bc25b43 + languageName: node + linkType: hard + +"@hapi/topo@npm:^5.0.0": + version: 5.1.0 + resolution: "@hapi/topo@npm:5.1.0" + dependencies: + "@hapi/hoek": ^9.0.0 + checksum: 604dfd5dde76d5c334bd03f9001fce69c7ce529883acf92da96f4fe7e51221bf5e5110e964caca287a6a616ba027c071748ab636ff178ad750547fba611d6014 + languageName: node + linkType: hard + +"@humanwhocodes/config-array@npm:^0.11.13": + version: 0.11.14 + resolution: "@humanwhocodes/config-array@npm:0.11.14" + dependencies: + "@humanwhocodes/object-schema": ^2.0.2 + debug: ^4.3.1 + minimatch: ^3.0.5 + checksum: 861ccce9eaea5de19546653bccf75bf09fe878bc39c3aab00aeee2d2a0e654516adad38dd1098aab5e3af0145bbcbf3f309bdf4d964f8dab9dcd5834ae4c02f2 + languageName: node + linkType: hard + +"@humanwhocodes/module-importer@npm:^1.0.1": + version: 1.0.1 + resolution: "@humanwhocodes/module-importer@npm:1.0.1" + checksum: 0fd22007db8034a2cdf2c764b140d37d9020bbfce8a49d3ec5c05290e77d4b0263b1b972b752df8c89e5eaa94073408f2b7d977aed131faf6cf396ebb5d7fb61 + languageName: node + linkType: hard + +"@humanwhocodes/object-schema@npm:^2.0.2": + version: 2.0.2 + resolution: "@humanwhocodes/object-schema@npm:2.0.2" + checksum: 2fc11503361b5fb4f14714c700c02a3f4c7c93e9acd6b87a29f62c522d90470f364d6161b03d1cc618b979f2ae02aed1106fd29d302695d8927e2fc8165ba8ee + languageName: node + linkType: hard + +"@istanbuljs/load-nyc-config@npm:^1.0.0": + version: 1.1.0 + resolution: "@istanbuljs/load-nyc-config@npm:1.1.0" + dependencies: + camelcase: ^5.3.1 + find-up: ^4.1.0 + get-package-type: ^0.1.0 + js-yaml: ^3.13.1 + resolve-from: ^5.0.0 + checksum: d578da5e2e804d5c93228450a1380e1a3c691de4953acc162f387b717258512a3e07b83510a936d9fab03eac90817473917e24f5d16297af3867f59328d58568 + languageName: node + linkType: hard + +"@istanbuljs/schema@npm:^0.1.2": + version: 0.1.3 + resolution: "@istanbuljs/schema@npm:0.1.3" + checksum: 5282759d961d61350f33d9118d16bcaed914ebf8061a52f4fa474b2cb08720c9c81d165e13b82f2e5a8a212cc5af482f0c6fc1ac27b9e067e5394c9a6ed186c9 + languageName: node + linkType: hard + +"@jest/console@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/console@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + "@types/node": "*" + chalk: ^4.0.0 + jest-message-util: ^27.5.1 + jest-util: ^27.5.1 + slash: ^3.0.0 + checksum: 7cb20f06a34b09734c0342685ec53aa4c401fe3757c13a9c58fce76b971a322eb884f6de1068ef96f746e5398e067371b89515a07c268d4440a867c87748a706 + languageName: node + linkType: hard + +"@jest/console@npm:^28.1.3": + version: 28.1.3 + resolution: "@jest/console@npm:28.1.3" + dependencies: + "@jest/types": ^28.1.3 + "@types/node": "*" + chalk: ^4.0.0 + jest-message-util: ^28.1.3 + jest-util: ^28.1.3 + slash: ^3.0.0 + checksum: fe50d98d26d02ce2901c76dff4bd5429a33c13affb692c9ebf8a578ca2f38a5dd854363d40d6c394f215150791fd1f692afd8e730a4178dda24107c8dfd9750a + languageName: node + linkType: hard + +"@jest/core@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/core@npm:27.5.1" + dependencies: + "@jest/console": ^27.5.1 + "@jest/reporters": ^27.5.1 + "@jest/test-result": ^27.5.1 + "@jest/transform": ^27.5.1 + "@jest/types": ^27.5.1 + "@types/node": "*" + ansi-escapes: ^4.2.1 + chalk: ^4.0.0 + emittery: ^0.8.1 + exit: ^0.1.2 + graceful-fs: ^4.2.9 + jest-changed-files: ^27.5.1 + jest-config: ^27.5.1 + jest-haste-map: ^27.5.1 + jest-message-util: ^27.5.1 + jest-regex-util: ^27.5.1 + jest-resolve: ^27.5.1 + jest-resolve-dependencies: ^27.5.1 + jest-runner: ^27.5.1 + jest-runtime: ^27.5.1 + jest-snapshot: ^27.5.1 + jest-util: ^27.5.1 + jest-validate: ^27.5.1 + jest-watcher: ^27.5.1 + micromatch: ^4.0.4 + rimraf: ^3.0.0 + slash: ^3.0.0 + strip-ansi: ^6.0.0 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 904a94ad8f1b43cd6b48de3b0226659bff3696150ff8cf7680fc2faffdc8a115203bb9ab6e817c1f79f9d6a81f67953053cbc64d8a4604f2e0c42a04c28cf126 + languageName: node + linkType: hard + +"@jest/environment@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/environment@npm:27.5.1" + dependencies: + "@jest/fake-timers": ^27.5.1 + "@jest/types": ^27.5.1 + "@types/node": "*" + jest-mock: ^27.5.1 + checksum: 2a9e18c35a015508dbec5b90b21c150230fa6c1c8cb8fabe029d46ee2ca4c40eb832fb636157da14c66590d0a4c8a2c053226b041f54a44507d6f6a89abefd66 + languageName: node + linkType: hard + +"@jest/expect-utils@npm:^29.4.1": + version: 29.4.1 + resolution: "@jest/expect-utils@npm:29.4.1" + dependencies: + jest-get-type: ^29.2.0 + checksum: 865b4ee79d43e2457efb8ce3f58108f2fe141ce620350fe21d0baaf7e2f00b9b67f6e9c1c89760b1008c100e844fb03a6dda264418ed378243956904d9a88c69 + languageName: node + linkType: hard + +"@jest/fake-timers@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/fake-timers@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + "@sinonjs/fake-timers": ^8.0.1 + "@types/node": "*" + jest-message-util: ^27.5.1 + jest-mock: ^27.5.1 + jest-util: ^27.5.1 + checksum: 02a0561ed2f4586093facd4ae500b74694f187ac24d4a00e949a39a1c5325bca8932b4fcb0388a2c5ed0656506fc1cf51fd3e32cdd48cea7497ad9c6e028aba8 + languageName: node + linkType: hard + +"@jest/globals@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/globals@npm:27.5.1" + dependencies: + "@jest/environment": ^27.5.1 + "@jest/types": ^27.5.1 + expect: ^27.5.1 + checksum: 087f97047e9dcf555f76fe2ce54aee681e005eaa837a0c0c2d251df6b6412c892c9df54cb871b180342114389a5ff895a4e52e6e6d3d0015bf83c02a54f64c3c + languageName: node + linkType: hard + +"@jest/reporters@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/reporters@npm:27.5.1" + dependencies: + "@bcoe/v8-coverage": ^0.2.3 + "@jest/console": ^27.5.1 + "@jest/test-result": ^27.5.1 + "@jest/transform": ^27.5.1 + "@jest/types": ^27.5.1 + "@types/node": "*" + chalk: ^4.0.0 + collect-v8-coverage: ^1.0.0 + exit: ^0.1.2 + glob: ^7.1.2 + graceful-fs: ^4.2.9 + istanbul-lib-coverage: ^3.0.0 + istanbul-lib-instrument: ^5.1.0 + istanbul-lib-report: ^3.0.0 + istanbul-lib-source-maps: ^4.0.0 + istanbul-reports: ^3.1.3 + jest-haste-map: ^27.5.1 + jest-resolve: ^27.5.1 + jest-util: ^27.5.1 + jest-worker: ^27.5.1 + slash: ^3.0.0 + source-map: ^0.6.0 + string-length: ^4.0.1 + terminal-link: ^2.0.0 + v8-to-istanbul: ^8.1.0 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: faba5eafb86e62b62e152cafc8812d56308f9d1e8b77f3a7dcae4a8803a20a60a0909cc43ed73363ef649bf558e4fb181c7a336d144c89f7998279d1882bb69e + languageName: node + linkType: hard + +"@jest/schemas@npm:^28.1.3": + version: 28.1.3 + resolution: "@jest/schemas@npm:28.1.3" + dependencies: + "@sinclair/typebox": ^0.24.1 + checksum: 3cf1d4b66c9c4ffda58b246de1ddcba8e6ad085af63dccdf07922511f13b68c0cc480a7bc620cb4f3099a6f134801c747e1df7bfc7a4ef4dceefbdea3e31e1de + languageName: node + linkType: hard + +"@jest/schemas@npm:^29.4.0": + version: 29.4.0 + resolution: "@jest/schemas@npm:29.4.0" + dependencies: + "@sinclair/typebox": ^0.25.16 + checksum: 005c90b7b641af029133fa390c0c8a75b63edf651da6253d7c472a8f15ddd18aa139edcd4236e57f974006e39c67217925768115484dbd7bfed2eba224de8b7d + languageName: node + linkType: hard + +"@jest/source-map@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/source-map@npm:27.5.1" + dependencies: + callsites: ^3.0.0 + graceful-fs: ^4.2.9 + source-map: ^0.6.0 + checksum: 4fb1e743b602841babf7e22bd84eca34676cb05d4eb3b604cae57fc59e406099f5ac759ac1a0d04d901237d143f0f4f234417306e823bde732a1d19982230862 + languageName: node + linkType: hard + +"@jest/test-result@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/test-result@npm:27.5.1" + dependencies: + "@jest/console": ^27.5.1 + "@jest/types": ^27.5.1 + "@types/istanbul-lib-coverage": ^2.0.0 + collect-v8-coverage: ^1.0.0 + checksum: 338f7c509d6a3bc6d7dd7388c8f6f548b87638e171dc1fddfedcacb4e8950583288832223ba688058cbcf874b937d22bdc0fa88f79f5fc666f77957e465c06a5 + languageName: node + linkType: hard + +"@jest/test-result@npm:^28.1.3": + version: 28.1.3 + resolution: "@jest/test-result@npm:28.1.3" + dependencies: + "@jest/console": ^28.1.3 + "@jest/types": ^28.1.3 + "@types/istanbul-lib-coverage": ^2.0.0 + collect-v8-coverage: ^1.0.0 + checksum: 957a5dd2fd2e84aabe86698f93c0825e96128ccaa23abf548b159a9b08ac74e4bde7acf4bec48479243dbdb27e4ea1b68c171846d21fb64855c6b55cead9ef27 + languageName: node + linkType: hard + +"@jest/test-sequencer@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/test-sequencer@npm:27.5.1" + dependencies: + "@jest/test-result": ^27.5.1 + graceful-fs: ^4.2.9 + jest-haste-map: ^27.5.1 + jest-runtime: ^27.5.1 + checksum: f21f9c8bb746847f7f89accfd29d6046eec1446f0b54e4694444feaa4df379791f76ef0f5a4360aafcbc73b50bc979f68b8a7620de404019d3de166be6720cb0 + languageName: node + linkType: hard + +"@jest/transform@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/transform@npm:27.5.1" + dependencies: + "@babel/core": ^7.1.0 + "@jest/types": ^27.5.1 + babel-plugin-istanbul: ^6.1.1 + chalk: ^4.0.0 + convert-source-map: ^1.4.0 + fast-json-stable-stringify: ^2.0.0 + graceful-fs: ^4.2.9 + jest-haste-map: ^27.5.1 + jest-regex-util: ^27.5.1 + jest-util: ^27.5.1 + micromatch: ^4.0.4 + pirates: ^4.0.4 + slash: ^3.0.0 + source-map: ^0.6.1 + write-file-atomic: ^3.0.0 + checksum: a22079121aedea0f20a03a9c026be971f7b92adbfb4d5fd1fb67be315741deac4f056936d7c72a53b24aa5a1071bc942c003925fd453bf3f6a0ae5da6384e137 + languageName: node + linkType: hard + +"@jest/types@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/types@npm:27.5.1" + dependencies: + "@types/istanbul-lib-coverage": ^2.0.0 + "@types/istanbul-reports": ^3.0.0 + "@types/node": "*" + "@types/yargs": ^16.0.0 + chalk: ^4.0.0 + checksum: d1f43cc946d87543ddd79d49547aab2399481d34025d5c5f2025d3d99c573e1d9832fa83cef25e9d9b07a8583500229d15bbb07b8e233d127d911d133e2f14b1 + languageName: node + linkType: hard + +"@jest/types@npm:^28.1.3": + version: 28.1.3 + resolution: "@jest/types@npm:28.1.3" + dependencies: + "@jest/schemas": ^28.1.3 + "@types/istanbul-lib-coverage": ^2.0.0 + "@types/istanbul-reports": ^3.0.0 + "@types/node": "*" + "@types/yargs": ^17.0.8 + chalk: ^4.0.0 + checksum: 1e258d9c063fcf59ebc91e46d5ea5984674ac7ae6cae3e50aa780d22b4405bf2c925f40350bf30013839eb5d4b5e521d956ddf8f3b7c78debef0e75a07f57350 + languageName: node + linkType: hard + +"@jest/types@npm:^29.4.1": + version: 29.4.1 + resolution: "@jest/types@npm:29.4.1" + dependencies: + "@jest/schemas": ^29.4.0 + "@types/istanbul-lib-coverage": ^2.0.0 + "@types/istanbul-reports": ^3.0.0 + "@types/node": "*" + "@types/yargs": ^17.0.8 + chalk: ^4.0.0 + checksum: 0aa0b6a210b3474289e5dcaa8e7abb2238dba8d0baf2eb5a3f080fb95e9a39e71e8abc96811d4ef7011f5d993755bb54515e9d827d7ebc2a2d4d9579d84f5a04 + languageName: node + linkType: hard + +"@jridgewell/gen-mapping@npm:^0.1.0": + version: 0.1.1 + resolution: "@jridgewell/gen-mapping@npm:0.1.1" + dependencies: + "@jridgewell/set-array": ^1.0.0 + "@jridgewell/sourcemap-codec": ^1.4.10 + checksum: 3bcc21fe786de6ffbf35c399a174faab05eb23ce6a03e8769569de28abbf4facc2db36a9ddb0150545ae23a8d35a7cf7237b2aa9e9356a7c626fb4698287d5cc + languageName: node + linkType: hard + +"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": + version: 0.3.2 + resolution: "@jridgewell/gen-mapping@npm:0.3.2" + dependencies: + "@jridgewell/set-array": ^1.0.1 + "@jridgewell/sourcemap-codec": ^1.4.10 + "@jridgewell/trace-mapping": ^0.3.9 + checksum: 1832707a1c476afebe4d0fbbd4b9434fdb51a4c3e009ab1e9938648e21b7a97049fa6009393bdf05cab7504108413441df26d8a3c12193996e65493a4efb6882 + languageName: node + linkType: hard + +"@jridgewell/resolve-uri@npm:^3.0.3, @jridgewell/resolve-uri@npm:^3.1.0": + version: 3.1.1 + resolution: "@jridgewell/resolve-uri@npm:3.1.1" + checksum: f5b441fe7900eab4f9155b3b93f9800a916257f4e8563afbcd3b5a5337b55e52bd8ae6735453b1b745457d9f6cdb16d74cd6220bbdd98cf153239e13f6cbb653 + languageName: node + linkType: hard + +"@jridgewell/set-array@npm:^1.0.0, @jridgewell/set-array@npm:^1.0.1": + version: 1.1.2 + resolution: "@jridgewell/set-array@npm:1.1.2" + checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e + languageName: node + linkType: hard + +"@jridgewell/source-map@npm:^0.3.2": + version: 0.3.2 + resolution: "@jridgewell/source-map@npm:0.3.2" + dependencies: + "@jridgewell/gen-mapping": ^0.3.0 + "@jridgewell/trace-mapping": ^0.3.9 + checksum: 1b83f0eb944e77b70559a394d5d3b3f98a81fcc186946aceb3ef42d036762b52ef71493c6c0a3b7c1d2f08785f53ba2df1277fe629a06e6109588ff4cdcf7482 + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": + version: 1.4.15 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" + checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:0.3.9": + version: 0.3.9 + resolution: "@jridgewell/trace-mapping@npm:0.3.9" + dependencies: + "@jridgewell/resolve-uri": ^3.0.3 + "@jridgewell/sourcemap-codec": ^1.4.10 + checksum: d89597752fd88d3f3480845691a05a44bd21faac18e2185b6f436c3b0fd0c5a859fbbd9aaa92050c4052caf325ad3e10e2e1d1b64327517471b7d51babc0ddef + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.14, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.9": + version: 0.3.20 + resolution: "@jridgewell/trace-mapping@npm:0.3.20" + dependencies: + "@jridgewell/resolve-uri": ^3.1.0 + "@jridgewell/sourcemap-codec": ^1.4.14 + checksum: cd1a7353135f385909468ff0cf20bdd37e59f2ee49a13a966dedf921943e222082c583ade2b579ff6cd0d8faafcb5461f253e1bf2a9f48fec439211fdbe788f5 + languageName: node + linkType: hard + +"@leichtgewicht/ip-codec@npm:^2.0.1": + version: 2.0.4 + resolution: "@leichtgewicht/ip-codec@npm:2.0.4" + checksum: 468de1f04d33de6d300892683d7c8aecbf96d1e2c5fe084f95f816e50a054d45b7c1ebfb141a1447d844b86a948733f6eebd92234da8581c84a1ad4de2946a2d + languageName: node + linkType: hard + +"@mui/base@npm:5.0.0-alpha.110": + version: 5.0.0-alpha.110 + resolution: "@mui/base@npm:5.0.0-alpha.110" + dependencies: + "@babel/runtime": ^7.20.6 + "@emotion/is-prop-valid": ^1.2.0 + "@mui/types": ^7.2.3 + "@mui/utils": ^5.11.0 + "@popperjs/core": ^2.11.6 + clsx: ^1.2.1 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: b1342de322fed691a5f60b794cd63b220d30ac1c5b151861562f6c796b406e7b74b6be65115db6d5763c4b32a92034b3b5641db6f110ad50da7cb53680dbcfcb + languageName: node + linkType: hard + +"@mui/core-downloads-tracker@npm:^5.11.0": + version: 5.11.6 + resolution: "@mui/core-downloads-tracker@npm:5.11.6" + checksum: e1a5c4c8fe767273d1c33a9d022bfd3263f07e1bf16ff9fecddb0b790a89e618badda8d59046141b9c1cfe5c7732fec202725fc5c545af29511a7f6279b91468 + languageName: node + linkType: hard + +"@mui/icons-material@npm:5.11.0": + version: 5.11.0 + resolution: "@mui/icons-material@npm:5.11.0" + dependencies: + "@babel/runtime": ^7.20.6 + peerDependencies: + "@mui/material": ^5.0.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 764c1185b3432f0228f3c5217b0e218b10f106fa96d305dfc62c0ef5afd2a7a087b0d664fd0a8171282e195c18d3ee073d5f037901a2bed1a1519a70fbb0501c + languageName: node + linkType: hard + +"@mui/material@npm:5.11.0": + version: 5.11.0 + resolution: "@mui/material@npm:5.11.0" + dependencies: + "@babel/runtime": ^7.20.6 + "@mui/base": 5.0.0-alpha.110 + "@mui/core-downloads-tracker": ^5.11.0 + "@mui/system": ^5.11.0 + "@mui/types": ^7.2.3 + "@mui/utils": ^5.11.0 + "@types/react-transition-group": ^4.4.5 + clsx: ^1.2.1 + csstype: ^3.1.1 + prop-types: ^15.8.1 + react-is: ^18.2.0 + react-transition-group: ^4.4.5 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: 8a38b657202f93f3a746916714479b768e72359fb4534786da363ac8dc1409aeb83e08d404bdf89f45e4102178ac4a93f73dd3ae51c9a7d2487eae6b854b1673 + languageName: node + linkType: hard + +"@mui/private-theming@npm:^5.11.2": + version: 5.11.2 + resolution: "@mui/private-theming@npm:5.11.2" + dependencies: + "@babel/runtime": ^7.20.7 + "@mui/utils": ^5.11.2 + prop-types: ^15.8.1 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 4a36ca48a7a8187d46c3e0d21ec08f7cb732bd4a5bac91c959337c8b0af031beb3a6c5ceac979b685c2e0e66321273d55dd54648f925bfdb946d6513fc6150e6 + languageName: node + linkType: hard + +"@mui/styled-engine@npm:^5.11.0": + version: 5.11.0 + resolution: "@mui/styled-engine@npm:5.11.0" + dependencies: + "@babel/runtime": ^7.20.6 + "@emotion/cache": ^11.10.5 + csstype: ^3.1.1 + prop-types: ^15.8.1 + peerDependencies: + "@emotion/react": ^11.4.1 + "@emotion/styled": ^11.3.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + checksum: ddc486bc5e0e8e7b683e4c3bffecd11c2ce1e6c67a485354c5fc5a6fe04ed5ce76db737609a2ae04779e9d5f57c7936174d458a3795eab62291c2d7681184062 + languageName: node + linkType: hard + +"@mui/system@npm:^5.11.0": + version: 5.11.5 + resolution: "@mui/system@npm:5.11.5" + dependencies: + "@babel/runtime": ^7.20.7 + "@mui/private-theming": ^5.11.2 + "@mui/styled-engine": ^5.11.0 + "@mui/types": ^7.2.3 + "@mui/utils": ^5.11.2 + clsx: ^1.2.1 + csstype: ^3.1.1 + prop-types: ^15.8.1 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: 1c896d18f8a8cc4f27d0700046e2dfe3d59d3a81d363ba2ed01341415fce675e5651aafe5c548436fa459dfda2a0c44b6e00fd6917111f388701a64303973532 + languageName: node + linkType: hard + +"@mui/types@npm:^7.2.3": + version: 7.2.3 + resolution: "@mui/types@npm:7.2.3" + peerDependencies: + "@types/react": "*" + peerDependenciesMeta: + "@types/react": + optional: true + checksum: b8511cb78f8df25c8978317ad3fd585c782116b657f2d32233352c09d415c77040e532f41bbe96de6ad46be87138767d3129a9f0de3561900a9a64db7693bce4 + languageName: node + linkType: hard + +"@mui/utils@npm:^5.11.0, @mui/utils@npm:^5.11.2, @mui/utils@npm:^5.14.5": + version: 5.14.5 + resolution: "@mui/utils@npm:5.14.5" + dependencies: + "@babel/runtime": ^7.22.6 + "@types/prop-types": ^15.7.5 + "@types/react-is": ^18.2.1 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + react: ^17.0.0 || ^18.0.0 + checksum: 7044d73ae41bdfd9c7c6287a3c1391ec4c5395c8f0092eac3ca4f1fd5359068fad29366f39d8072f68493eb5225399463935bbca266c879d630f8ebaa3db96d7 + languageName: node + linkType: hard + +"@mui/x-date-pickers@npm:6.11.2": + version: 6.11.2 + resolution: "@mui/x-date-pickers@npm:6.11.2" + dependencies: + "@babel/runtime": ^7.22.6 + "@mui/utils": ^5.14.5 + "@types/react-transition-group": ^4.4.6 + clsx: ^2.0.0 + prop-types: ^15.8.1 + react-transition-group: ^4.4.5 + peerDependencies: + "@emotion/react": ^11.9.0 + "@emotion/styled": ^11.8.1 + "@mui/base": ^5.0.0-alpha.87 + "@mui/material": ^5.8.6 + "@mui/system": ^5.8.0 + date-fns: ^2.25.0 + date-fns-jalali: ^2.13.0-0 + dayjs: ^1.10.7 + luxon: ^3.0.2 + moment: ^2.29.4 + moment-hijri: ^2.1.2 + moment-jalaali: ^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + date-fns: + optional: true + date-fns-jalali: + optional: true + dayjs: + optional: true + luxon: + optional: true + moment: + optional: true + moment-hijri: + optional: true + moment-jalaali: + optional: true + checksum: 389932d3e990d596a24d593086a02960a1111217745587ef9ac35a2e419bfbc3b7c112d50df591ff80ee864731acecb6cfe2945274796c52856f87275d1b4b10 + languageName: node + linkType: hard + +"@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1": + version: 5.1.1-v1 + resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1" + dependencies: + eslint-scope: 5.1.1 + checksum: f2e3b2d6a6e2d9f163ca22105910c9f850dc4897af0aea3ef0a5886b63d8e1ba6505b71c99cb78a3bba24a09557d601eb21c8dede3f3213753fcfef364eb0e57 + languageName: node + linkType: hard + +"@nodelib/fs.scandir@npm:2.1.5": + version: 2.1.5 + resolution: "@nodelib/fs.scandir@npm:2.1.5" + dependencies: + "@nodelib/fs.stat": 2.0.5 + run-parallel: ^1.1.9 + checksum: a970d595bd23c66c880e0ef1817791432dbb7acbb8d44b7e7d0e7a22f4521260d4a83f7f9fd61d44fda4610105577f8f58a60718105fb38352baed612fd79e59 + languageName: node + linkType: hard + +"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": + version: 2.0.5 + resolution: "@nodelib/fs.stat@npm:2.0.5" + checksum: 012480b5ca9d97bff9261571dbbec7bbc6033f69cc92908bc1ecfad0792361a5a1994bc48674b9ef76419d056a03efadfce5a6cf6dbc0a36559571a7a483f6f0 + languageName: node + linkType: hard + +"@nodelib/fs.walk@npm:^1.2.3, @nodelib/fs.walk@npm:^1.2.8": + version: 1.2.8 + resolution: "@nodelib/fs.walk@npm:1.2.8" + dependencies: + "@nodelib/fs.scandir": 2.1.5 + fastq: ^1.6.0 + checksum: 190c643f156d8f8f277bf2a6078af1ffde1fd43f498f187c2db24d35b4b4b5785c02c7dc52e356497b9a1b65b13edc996de08de0b961c32844364da02986dc53 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^2.1.0": + version: 2.1.2 + resolution: "@npmcli/fs@npm:2.1.2" + dependencies: + "@gar/promisify": ^1.1.3 + semver: ^7.3.5 + checksum: 405074965e72d4c9d728931b64d2d38e6ea12066d4fad651ac253d175e413c06fe4350970c783db0d749181da8fe49c42d3880bd1cbc12cd68e3a7964d820225 + languageName: node + linkType: hard + +"@npmcli/move-file@npm:^2.0.0": + version: 2.0.1 + resolution: "@npmcli/move-file@npm:2.0.1" + dependencies: + mkdirp: ^1.0.4 + rimraf: ^3.0.2 + checksum: 52dc02259d98da517fae4cb3a0a3850227bdae4939dda1980b788a7670636ca2b4a01b58df03dd5f65c1e3cb70c50fa8ce5762b582b3f499ec30ee5ce1fd9380 + languageName: node + linkType: hard + +"@pmmmwh/react-refresh-webpack-plugin@npm:^0.5.3": + version: 0.5.10 + resolution: "@pmmmwh/react-refresh-webpack-plugin@npm:0.5.10" + dependencies: + ansi-html-community: ^0.0.8 + common-path-prefix: ^3.0.0 + core-js-pure: ^3.23.3 + error-stack-parser: ^2.0.6 + find-up: ^5.0.0 + html-entities: ^2.1.0 + loader-utils: ^2.0.4 + schema-utils: ^3.0.0 + source-map: ^0.7.3 + peerDependencies: + "@types/webpack": 4.x || 5.x + react-refresh: ">=0.10.0 <1.0.0" + sockjs-client: ^1.4.0 + type-fest: ">=0.17.0 <4.0.0" + webpack: ">=4.43.0 <6.0.0" + webpack-dev-server: 3.x || 4.x + webpack-hot-middleware: 2.x + webpack-plugin-serve: 0.x || 1.x + peerDependenciesMeta: + "@types/webpack": + optional: true + sockjs-client: + optional: true + type-fest: + optional: true + webpack-dev-server: + optional: true + webpack-hot-middleware: + optional: true + webpack-plugin-serve: + optional: true + checksum: c45beded9c56fbbdc7213a2c36131ace5db360ed704d462cc39d6678f980173a91c9a3f691e6bd3a026f25486644cd0027e8a12a0a4eced8e8b886a0472e7d34 + languageName: node + linkType: hard + +"@popperjs/core@npm:^2.11.6": + version: 2.11.6 + resolution: "@popperjs/core@npm:2.11.6" + checksum: 47fb328cec1924559d759b48235c78574f2d71a8a6c4c03edb6de5d7074078371633b91e39bbf3f901b32aa8af9b9d8f82834856d2f5737a23475036b16817f0 + languageName: node + linkType: hard + +"@rollup/plugin-babel@npm:^5.2.0": + version: 5.3.1 + resolution: "@rollup/plugin-babel@npm:5.3.1" + dependencies: + "@babel/helper-module-imports": ^7.10.4 + "@rollup/pluginutils": ^3.1.0 + peerDependencies: + "@babel/core": ^7.0.0 + "@types/babel__core": ^7.1.9 + rollup: ^1.20.0||^2.0.0 + peerDependenciesMeta: + "@types/babel__core": + optional: true + checksum: 220d71e4647330f252ef33d5f29700aef2e8284a0b61acfcceb47617a7f96208aa1ed16eae75619424bf08811ede5241e271a6d031f07026dee6b3a2bdcdc638 + languageName: node + linkType: hard + +"@rollup/plugin-node-resolve@npm:^11.2.1": + version: 11.2.1 + resolution: "@rollup/plugin-node-resolve@npm:11.2.1" + dependencies: + "@rollup/pluginutils": ^3.1.0 + "@types/resolve": 1.17.1 + builtin-modules: ^3.1.0 + deepmerge: ^4.2.2 + is-module: ^1.0.0 + resolve: ^1.19.0 + peerDependencies: + rollup: ^1.20.0||^2.0.0 + checksum: 6f3b3ecf9a0596a5db4212984bdeb13bb7612693602407e9457ada075dea5a5f2e4e124c592352cf27066a88b194de9b9a95390149b52cf335d5b5e17b4e265b + languageName: node + linkType: hard + +"@rollup/plugin-replace@npm:^2.4.1": + version: 2.4.2 + resolution: "@rollup/plugin-replace@npm:2.4.2" + dependencies: + "@rollup/pluginutils": ^3.1.0 + magic-string: ^0.25.7 + peerDependencies: + rollup: ^1.20.0 || ^2.0.0 + checksum: b2f1618ee5526d288e2f8ae328dcb326e20e8dc8bd1f60d3e14d6708a5832e4aa44811f7d493f4aed2deeadca86e3b6b0503cd39bf50cfb4b595bb9da027fad0 + languageName: node + linkType: hard + +"@rollup/pluginutils@npm:^3.1.0": + version: 3.1.0 + resolution: "@rollup/pluginutils@npm:3.1.0" + dependencies: + "@types/estree": 0.0.39 + estree-walker: ^1.0.1 + picomatch: ^2.2.2 + peerDependencies: + rollup: ^1.20.0||^2.0.0 + checksum: 8be16e27863c219edbb25a4e6ec2fe0e1e451d9e917b6a43cf2ae5bc025a6b8faaa40f82a6e53b66d0de37b58ff472c6c3d57a83037ae635041f8df959d6d9aa + languageName: node + linkType: hard + +"@rushstack/eslint-patch@npm:^1.1.0": + version: 1.2.0 + resolution: "@rushstack/eslint-patch@npm:1.2.0" + checksum: faa749faae0e83c26ae9eb00ad36a897ac78f3cf27da8e8ff21c00bcf7973b598d823d8f2b3957ef66079288bcf577f94df831eae2d65f3f68d8ca32f18b6aff + languageName: node + linkType: hard + +"@sideway/address@npm:^4.1.3": + version: 4.1.4 + resolution: "@sideway/address@npm:4.1.4" + dependencies: + "@hapi/hoek": ^9.0.0 + checksum: b9fca2a93ac2c975ba12e0a6d97853832fb1f4fb02393015e012b47fa916a75ca95102d77214b2a29a2784740df2407951af8c5dde054824c65577fd293c4cdb + languageName: node + linkType: hard + +"@sideway/formula@npm:^3.0.1": + version: 3.0.1 + resolution: "@sideway/formula@npm:3.0.1" + checksum: e4beeebc9dbe2ff4ef0def15cec0165e00d1612e3d7cea0bc9ce5175c3263fc2c818b679bd558957f49400ee7be9d4e5ac90487e1625b4932e15c4aa7919c57a + languageName: node + linkType: hard + +"@sideway/pinpoint@npm:^2.0.0": + version: 2.0.0 + resolution: "@sideway/pinpoint@npm:2.0.0" + checksum: 0f4491e5897fcf5bf02c46f5c359c56a314e90ba243f42f0c100437935daa2488f20482f0f77186bd6bf43345095a95d8143ecf8b1f4d876a7bc0806aba9c3d2 + languageName: node + linkType: hard + +"@sinclair/typebox@npm:^0.24.1": + version: 0.24.51 + resolution: "@sinclair/typebox@npm:0.24.51" + checksum: fd0d855e748ef767eb19da1a60ed0ab928e91e0f358c1dd198d600762c0015440b15755e96d1176e2a0db7e09c6a64ed487828ee10dd0c3e22f61eb09c478cd0 + languageName: node + linkType: hard + +"@sinclair/typebox@npm:^0.25.16": + version: 0.25.21 + resolution: "@sinclair/typebox@npm:0.25.21" + checksum: 763af1163fe4eabee9b914d4e4548a39fbba3287d2b3b1ff043c1da3c5a321e99d50a3ca94eb182988131e00b006a6f019799cde8da2f61e2f118b30b0276a00 + languageName: node + linkType: hard + +"@sinonjs/commons@npm:^1.7.0": + version: 1.8.6 + resolution: "@sinonjs/commons@npm:1.8.6" + dependencies: + type-detect: 4.0.8 + checksum: 7d3f8c1e85f30cd4e83594fc19b7a657f14d49eb8d95a30095631ce15e906c869e0eff96c5b93dffea7490c00418b07f54582ba49c6560feb2a8c34c0b16832d + languageName: node + linkType: hard + +"@sinonjs/fake-timers@npm:^8.0.1": + version: 8.1.0 + resolution: "@sinonjs/fake-timers@npm:8.1.0" + dependencies: + "@sinonjs/commons": ^1.7.0 + checksum: 09b5a158ce013a6c37613258bad79ca4efeb99b1f59c41c73cca36cac00b258aefcf46eeea970fccf06b989414d86fe9f54c1102272c0c3bdd51a313cea80949 + languageName: node + linkType: hard + +"@surma/rollup-plugin-off-main-thread@npm:^2.2.3": + version: 2.2.3 + resolution: "@surma/rollup-plugin-off-main-thread@npm:2.2.3" + dependencies: + ejs: ^3.1.6 + json5: ^2.2.0 + magic-string: ^0.25.0 + string.prototype.matchall: ^4.0.6 + checksum: 2c021349442e2e2cec96bb50fd82ec8bf8514d909bc73594f6cfc89b3b68f2feed909a8161d7d307d9455585c97e6b66853ce334db432626c7596836d4549c0c + languageName: node + linkType: hard + +"@svgr/babel-plugin-add-jsx-attribute@npm:^5.4.0": + version: 5.4.0 + resolution: "@svgr/babel-plugin-add-jsx-attribute@npm:5.4.0" + checksum: 1c538cf312b486598c6aea17f9b72d7fc308eb5dd32effd804630206a185493b8a828ff980ceb29d57d8319c085614c7cea967be709c71ae77702a4c30037011 + languageName: node + linkType: hard + +"@svgr/babel-plugin-remove-jsx-attribute@npm:^5.4.0": + version: 5.4.0 + resolution: "@svgr/babel-plugin-remove-jsx-attribute@npm:5.4.0" + checksum: ad2231bfcb14daa944201df66236c222cde05a07c4cffaecab1d36d33f606b6caf17bda21844fc435780c1a27195e49beb8397536fe5e7545dfffcfbbcecb7f8 + languageName: node + linkType: hard + +"@svgr/babel-plugin-remove-jsx-empty-expression@npm:^5.0.1": + version: 5.0.1 + resolution: "@svgr/babel-plugin-remove-jsx-empty-expression@npm:5.0.1" + checksum: 175c8f13ddcb0744f7c3910ebed3799cfb961a75bff130e1ed2071c87ca8b8df8964825c988e511b2e3c5dbf48ad3d4fbbb6989edc53294253df40cf2a24375e + languageName: node + linkType: hard + +"@svgr/babel-plugin-replace-jsx-attribute-value@npm:^5.0.1": + version: 5.0.1 + resolution: "@svgr/babel-plugin-replace-jsx-attribute-value@npm:5.0.1" + checksum: 68f4e2a5b95eca44e22fce485dc2ddd10adabe2b38f6db3ef9071b35e84bf379685f7acab6c05b7a82f722328c02f6424f8252c6dd5c2c4ed2f00104072b1dfe + languageName: node + linkType: hard + +"@svgr/babel-plugin-svg-dynamic-title@npm:^5.4.0": + version: 5.4.0 + resolution: "@svgr/babel-plugin-svg-dynamic-title@npm:5.4.0" + checksum: c46feb52454acea32031d1d881a81334f2e5f838ed25a2d9014acb5e9541d404405911e86dbee8bee9f1e43c9e07118123a07dc297962dbed0c4c5a86bdc4be9 + languageName: node + linkType: hard + +"@svgr/babel-plugin-svg-em-dimensions@npm:^5.4.0": + version: 5.4.0 + resolution: "@svgr/babel-plugin-svg-em-dimensions@npm:5.4.0" + checksum: 0d19b26147bbba932bd973258dab4a80a7ea6b9d674713186f0e10fa21a9e3aa4327326b2bf1892e8051712bce0ea30561eb187ca27bb241d33c350cea51ac88 + languageName: node + linkType: hard + +"@svgr/babel-plugin-transform-react-native-svg@npm:^5.4.0": + version: 5.4.0 + resolution: "@svgr/babel-plugin-transform-react-native-svg@npm:5.4.0" + checksum: 8ac5dc9fb2dee24addc74dbcb169860c95a69247606f986eabb0618fb300dd08e8f220891b758e62c051428ba04d8dd50f2c2bf877e15fa190e6d384d1ccd2ad + languageName: node + linkType: hard + +"@svgr/babel-plugin-transform-svg-component@npm:^5.5.0": + version: 5.5.0 + resolution: "@svgr/babel-plugin-transform-svg-component@npm:5.5.0" + checksum: 94c3fed490deb8544af4ea32a5d78a840334cdcc8a5a33fe8ea9f1c220a4d714d57c9e10934492de99b7e1acc17963b1749a49927e27b1e839a4dc3c893605c7 + languageName: node + linkType: hard + +"@svgr/babel-preset@npm:^5.5.0": + version: 5.5.0 + resolution: "@svgr/babel-preset@npm:5.5.0" + dependencies: + "@svgr/babel-plugin-add-jsx-attribute": ^5.4.0 + "@svgr/babel-plugin-remove-jsx-attribute": ^5.4.0 + "@svgr/babel-plugin-remove-jsx-empty-expression": ^5.0.1 + "@svgr/babel-plugin-replace-jsx-attribute-value": ^5.0.1 + "@svgr/babel-plugin-svg-dynamic-title": ^5.4.0 + "@svgr/babel-plugin-svg-em-dimensions": ^5.4.0 + "@svgr/babel-plugin-transform-react-native-svg": ^5.4.0 + "@svgr/babel-plugin-transform-svg-component": ^5.5.0 + checksum: 5d396c4499c9ff2df9db6d08a160d10386b9f459cb9c2bb5ee183ab03b2f46c8ef3c9a070f1eee93f4e4433a5f00704e7632b1386078eb697ad8a2b38edb8522 + languageName: node + linkType: hard + +"@svgr/core@npm:^5.5.0": + version: 5.5.0 + resolution: "@svgr/core@npm:5.5.0" + dependencies: + "@svgr/plugin-jsx": ^5.5.0 + camelcase: ^6.2.0 + cosmiconfig: ^7.0.0 + checksum: 39b230151e30b9ca8551d10674e50efb821d1a49ce10969b09587af130780eba581baa1e321b0922f48331943096f05590aa6ae92d88d011d58093a89dd34158 + languageName: node + linkType: hard + +"@svgr/hast-util-to-babel-ast@npm:^5.5.0": + version: 5.5.0 + resolution: "@svgr/hast-util-to-babel-ast@npm:5.5.0" + dependencies: + "@babel/types": ^7.12.6 + checksum: a03c1c7ab92b1a6dbd7671b0b78df4c07e8d808ff092671554a78752ec0c0425c03b6c82569a5f33903d191c73379eedf631f23aeb30b7a70185f5f2fc67fae6 + languageName: node + linkType: hard + +"@svgr/plugin-jsx@npm:^5.5.0": + version: 5.5.0 + resolution: "@svgr/plugin-jsx@npm:5.5.0" + dependencies: + "@babel/core": ^7.12.3 + "@svgr/babel-preset": ^5.5.0 + "@svgr/hast-util-to-babel-ast": ^5.5.0 + svg-parser: ^2.0.2 + checksum: e053f8dd6bfcd72377b432dd5b1db3c89d503d29839639a87f85b597a680d0b69e33a4db376f5a1074a89615f7157cd36f63f94bdb4083a0fd5bbe918c7fcb9b + languageName: node + linkType: hard + +"@svgr/plugin-svgo@npm:^5.5.0": + version: 5.5.0 + resolution: "@svgr/plugin-svgo@npm:5.5.0" + dependencies: + cosmiconfig: ^7.0.0 + deepmerge: ^4.2.2 + svgo: ^1.2.2 + checksum: bef5d09581349afdf654209f82199670649cc749b81ff5f310ce4a3bbad749cde877c9b1a711dd9ced51224e2b5b5a720d242bdf183fa0f83e08e8d5e069b0b6 + languageName: node + linkType: hard + +"@svgr/webpack@npm:^5.5.0": + version: 5.5.0 + resolution: "@svgr/webpack@npm:5.5.0" + dependencies: + "@babel/core": ^7.12.3 + "@babel/plugin-transform-react-constant-elements": ^7.12.1 + "@babel/preset-env": ^7.12.1 + "@babel/preset-react": ^7.12.5 + "@svgr/core": ^5.5.0 + "@svgr/plugin-jsx": ^5.5.0 + "@svgr/plugin-svgo": ^5.5.0 + loader-utils: ^2.0.0 + checksum: 540391bd63791625d26d6b5e0dd3c716ef51176bfba53bf0979a1ac4781afd2672f4bef2d76cf3d9cdc8e9ee61bda6863ed405a237b10406633ede4cd524f1cc + languageName: node + linkType: hard + +"@testing-library/cypress@npm:8.0.7": + version: 8.0.7 + resolution: "@testing-library/cypress@npm:8.0.7" + dependencies: + "@babel/runtime": ^7.14.6 + "@testing-library/dom": ^8.1.0 + peerDependencies: + cypress: ^2.1.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 + checksum: e005bc1a7ec808706c57e95ed312069fb5be39ea7362900dc2a32c09f124d478ade69ebcd7df88c076e3867ab328ae6e6ce13791bdf042621ff66b56552bf74b + languageName: node + linkType: hard + +"@testing-library/dom@npm:^8.0.0": + version: 8.20.0 + resolution: "@testing-library/dom@npm:8.20.0" + dependencies: + "@babel/code-frame": ^7.10.4 + "@babel/runtime": ^7.12.5 + "@types/aria-query": ^5.0.1 + aria-query: ^5.0.0 + chalk: ^4.1.0 + dom-accessibility-api: ^0.5.9 + lz-string: ^1.4.4 + pretty-format: ^27.0.2 + checksum: 1e599129a2fe91959ce80900a0a4897232b89e2a8e22c1f5950c36d39c97629ea86b4986b60b173b5525a05de33fde1e35836ea597b03de78cc51b122835c6f0 + languageName: node + linkType: hard + +"@testing-library/dom@npm:^8.1.0": + version: 8.20.1 + resolution: "@testing-library/dom@npm:8.20.1" + dependencies: + "@babel/code-frame": ^7.10.4 + "@babel/runtime": ^7.12.5 + "@types/aria-query": ^5.0.1 + aria-query: 5.1.3 + chalk: ^4.1.0 + dom-accessibility-api: ^0.5.9 + lz-string: ^1.5.0 + pretty-format: ^27.0.2 + checksum: 06fc8dc67849aadb726cbbad0e7546afdf8923bd39acb64c576d706249bd7d0d05f08e08a31913fb621162e3b9c2bd0dce15964437f030f9fa4476326fdd3007 + languageName: node + linkType: hard + +"@testing-library/jest-dom@npm:6.4.1": + version: 6.4.1 + resolution: "@testing-library/jest-dom@npm:6.4.1" + dependencies: + "@adobe/css-tools": ^4.3.2 + "@babel/runtime": ^7.9.2 + aria-query: ^5.0.0 + chalk: ^3.0.0 + css.escape: ^1.5.1 + dom-accessibility-api: ^0.6.3 + lodash: ^4.17.15 + redent: ^3.0.0 + peerDependencies: + "@jest/globals": ">= 28" + "@types/bun": "*" + "@types/jest": ">= 28" + jest: ">= 28" + vitest: ">= 0.32" + peerDependenciesMeta: + "@jest/globals": + optional: true + "@types/bun": + optional: true + "@types/jest": + optional: true + jest: + optional: true + vitest: + optional: true + checksum: 66cd945fc81181289835f24791ae4de4913ac4e4fd8bc2e2ee7393ad7298bc3c2fc5acd6951c5b2212a03ebe914c6924c3da6e46225126387cb2200554004b67 + languageName: node + linkType: hard + +"@testing-library/react-hooks@npm:8.0.1": + version: 8.0.1 + resolution: "@testing-library/react-hooks@npm:8.0.1" + dependencies: + "@babel/runtime": ^7.12.5 + react-error-boundary: ^3.1.0 + peerDependencies: + "@types/react": ^16.9.0 || ^17.0.0 + react: ^16.9.0 || ^17.0.0 + react-dom: ^16.9.0 || ^17.0.0 + react-test-renderer: ^16.9.0 || ^17.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + react-dom: + optional: true + react-test-renderer: + optional: true + checksum: 7fe44352e920deb5cb1876f80d64e48615232072c9d5382f1e0284b3aab46bb1c659a040b774c45cdf084a5257b8fe463f7e08695ad8480d8a15635d4d3d1f6d + languageName: node + linkType: hard + +"@testing-library/react@npm:12.1.3": + version: 12.1.3 + resolution: "@testing-library/react@npm:12.1.3" + dependencies: + "@babel/runtime": ^7.12.5 + "@testing-library/dom": ^8.0.0 + "@types/react-dom": "*" + peerDependencies: + react: "*" + react-dom: "*" + checksum: 2f059e93dc3f161c4d15910d1fa80cd4f5cfb6eff8a733939a72ac720c2499b74761e8980c02983a6e49153b776e82bd770a1c3e66e05c4429db0e01612f7d0a + languageName: node + linkType: hard + +"@testing-library/user-event@npm:14.5.2": + version: 14.5.2 + resolution: "@testing-library/user-event@npm:14.5.2" + peerDependencies: + "@testing-library/dom": ">=7.21.4" + checksum: d76937dffcf0082fbf3bb89eb2b81a31bf5448048dd61c33928c5f10e33a58e035321d39145cefd469bb5a499c68a5b4086b22f1a44e3e7c7e817dc5f6782867 + languageName: node + linkType: hard + +"@tootallnate/once@npm:1": + version: 1.1.2 + resolution: "@tootallnate/once@npm:1.1.2" + checksum: e1fb1bbbc12089a0cb9433dc290f97bddd062deadb6178ce9bcb93bb7c1aecde5e60184bc7065aec42fe1663622a213493c48bbd4972d931aae48315f18e1be9 + languageName: node + linkType: hard + +"@tootallnate/once@npm:2": + version: 2.0.0 + resolution: "@tootallnate/once@npm:2.0.0" + checksum: ad87447820dd3f24825d2d947ebc03072b20a42bfc96cbafec16bff8bbda6c1a81fcb0be56d5b21968560c5359a0af4038a68ba150c3e1694fe4c109a063bed8 + languageName: node + linkType: hard + +"@trysound/sax@npm:0.2.0": + version: 0.2.0 + resolution: "@trysound/sax@npm:0.2.0" + checksum: 11226c39b52b391719a2a92e10183e4260d9651f86edced166da1d95f39a0a1eaa470e44d14ac685ccd6d3df7e2002433782872c0feeb260d61e80f21250e65c + languageName: node + linkType: hard + +"@tsconfig/node10@npm:^1.0.7": + version: 1.0.9 + resolution: "@tsconfig/node10@npm:1.0.9" + checksum: a33ae4dc2a621c0678ac8ac4bceb8e512ae75dac65417a2ad9b022d9b5411e863c4c198b6ba9ef659e14b9fb609bbec680841a2e84c1172df7a5ffcf076539df + languageName: node + linkType: hard + +"@tsconfig/node12@npm:^1.0.7": + version: 1.0.11 + resolution: "@tsconfig/node12@npm:1.0.11" + checksum: 5ce29a41b13e7897a58b8e2df11269c5395999e588b9a467386f99d1d26f6c77d1af2719e407621412520ea30517d718d5192a32403b8dfcc163bf33e40a338a + languageName: node + linkType: hard + +"@tsconfig/node14@npm:^1.0.0": + version: 1.0.3 + resolution: "@tsconfig/node14@npm:1.0.3" + checksum: 19275fe80c4c8d0ad0abed6a96dbf00642e88b220b090418609c4376e1cef81bf16237bf170ad1b341452feddb8115d8dd2e5acdfdea1b27422071163dc9ba9d + languageName: node + linkType: hard + +"@tsconfig/node16@npm:^1.0.2": + version: 1.0.3 + resolution: "@tsconfig/node16@npm:1.0.3" + checksum: 3a8b657dd047495b7ad23437d6afd20297ce90380ff0bdee93fc7d39a900dbd8d9e26e53ff6b465e7967ce2adf0b218782590ce9013285121e6a5928fbd6819f + languageName: node + linkType: hard + +"@types/aria-query@npm:^5.0.1": + version: 5.0.1 + resolution: "@types/aria-query@npm:5.0.1" + checksum: 69fd7cceb6113ed370591aef04b3fd0742e9a1b06dd045c43531448847b85de181495e4566f98e776b37c422a12fd71866e0a1dfd904c5ec3f84d271682901de + languageName: node + linkType: hard + +"@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.14": + version: 7.20.0 + resolution: "@types/babel__core@npm:7.20.0" + dependencies: + "@babel/parser": ^7.20.7 + "@babel/types": ^7.20.7 + "@types/babel__generator": "*" + "@types/babel__template": "*" + "@types/babel__traverse": "*" + checksum: 49b601a0a7637f1f387442c8156bd086cfd10ff4b82b0e1994e73a6396643b5435366fb33d6b604eade8467cca594ef97adcbc412aede90bb112ebe88d0ad6df + languageName: node + linkType: hard + +"@types/babel__generator@npm:*": + version: 7.6.4 + resolution: "@types/babel__generator@npm:7.6.4" + dependencies: + "@babel/types": ^7.0.0 + checksum: 20effbbb5f8a3a0211e95959d06ae70c097fb6191011b73b38fe86deebefad8e09ee014605e0fd3cdaedc73d158be555866810e9166e1f09e4cfd880b874dcb0 + languageName: node + linkType: hard + +"@types/babel__template@npm:*": + version: 7.4.1 + resolution: "@types/babel__template@npm:7.4.1" + dependencies: + "@babel/parser": ^7.1.0 + "@babel/types": ^7.0.0 + checksum: 649fe8b42c2876be1fd28c6ed9b276f78152d5904ec290b6c861d9ef324206e0a5c242e8305c421ac52ecf6358fa7e32ab7a692f55370484825c1df29b1596ee + languageName: node + linkType: hard + +"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.4, @types/babel__traverse@npm:^7.0.6": + version: 7.18.3 + resolution: "@types/babel__traverse@npm:7.18.3" + dependencies: + "@babel/types": ^7.3.0 + checksum: d20953338b2f012ab7750932ece0a78e7d1645b0a6ff42d49be90f55e9998085da1374a9786a7da252df89555c6586695ba4d1d4b4e88ab2b9f306bcd35e00d3 + languageName: node + linkType: hard + +"@types/body-parser@npm:*": + version: 1.19.2 + resolution: "@types/body-parser@npm:1.19.2" + dependencies: + "@types/connect": "*" + "@types/node": "*" + checksum: e17840c7d747a549f00aebe72c89313d09fbc4b632b949b2470c5cb3b1cb73863901ae84d9335b567a79ec5efcfb8a28ff8e3f36bc8748a9686756b6d5681f40 + languageName: node + linkType: hard + +"@types/bonjour@npm:^3.5.9": + version: 3.5.10 + resolution: "@types/bonjour@npm:3.5.10" + dependencies: + "@types/node": "*" + checksum: bfcadb042a41b124c4e3de4925e3be6d35b78f93f27c4535d5ff86980dc0f8bc407ed99b9b54528952dc62834d5a779392f7a12c2947dd19330eb05a6bcae15a + languageName: node + linkType: hard + +"@types/connect-history-api-fallback@npm:^1.3.5": + version: 1.3.5 + resolution: "@types/connect-history-api-fallback@npm:1.3.5" + dependencies: + "@types/express-serve-static-core": "*" + "@types/node": "*" + checksum: 464d06e5ab00f113fa89978633d5eb00d225aeb4ebbadc07f6f3bc337aa7cbfcd74957b2a539d6d47f2e128e956a17819973ec7ae62ade2e16e367a6c38b8d3a + languageName: node + linkType: hard + +"@types/connect@npm:*": + version: 3.4.35 + resolution: "@types/connect@npm:3.4.35" + dependencies: + "@types/node": "*" + checksum: fe81351470f2d3165e8b12ce33542eef89ea893e36dd62e8f7d72566dfb7e448376ae962f9f3ea888547ce8b55a40020ca0e01d637fab5d99567673084542641 + languageName: node + linkType: hard + +"@types/eslint-scope@npm:^3.7.3": + version: 3.7.4 + resolution: "@types/eslint-scope@npm:3.7.4" + dependencies: + "@types/eslint": "*" + "@types/estree": "*" + checksum: ea6a9363e92f301cd3888194469f9ec9d0021fe0a397a97a6dd689e7545c75de0bd2153dfb13d3ab532853a278b6572c6f678ce846980669e41029d205653460 + languageName: node + linkType: hard + +"@types/eslint@npm:*, @types/eslint@npm:^7.29.0 || ^8.4.1": + version: 8.4.10 + resolution: "@types/eslint@npm:8.4.10" + dependencies: + "@types/estree": "*" + "@types/json-schema": "*" + checksum: 21e009ed9ed9bc8920fdafc6e11ff321c4538b4cc18a56fdd59dc5184ea7bbf363c71638c9bdb59fc1254dddcdd567485136ed68b0ee4750948d4e32cb79c689 + languageName: node + linkType: hard + +"@types/estree@npm:*": + version: 1.0.0 + resolution: "@types/estree@npm:1.0.0" + checksum: 910d97fb7092c6738d30a7430ae4786a38542023c6302b95d46f49420b797f21619cdde11fa92b338366268795884111c2eb10356e4bd2c8ad5b92941e9e6443 + languageName: node + linkType: hard + +"@types/estree@npm:0.0.39": + version: 0.0.39 + resolution: "@types/estree@npm:0.0.39" + checksum: 412fb5b9868f2c418126451821833414189b75cc6bf84361156feed733e3d92ec220b9d74a89e52722e03d5e241b2932732711b7497374a404fad49087adc248 + languageName: node + linkType: hard + +"@types/estree@npm:^0.0.51": + version: 0.0.51 + resolution: "@types/estree@npm:0.0.51" + checksum: e56a3bcf759fd9185e992e7fdb3c6a5f81e8ff120e871641607581fb3728d16c811702a7d40fa5f869b7f7b4437ab6a87eb8d98ffafeee51e85bbe955932a189 + languageName: node + linkType: hard + +"@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.31": + version: 4.17.33 + resolution: "@types/express-serve-static-core@npm:4.17.33" + dependencies: + "@types/node": "*" + "@types/qs": "*" + "@types/range-parser": "*" + checksum: dce580d16b85f207445af9d4053d66942b27d0c72e86153089fa00feee3e96ae336b7bedb31ed4eea9e553c99d6dd356ed6e0928f135375d9f862a1a8015adf2 + languageName: node + linkType: hard + +"@types/express@npm:*, @types/express@npm:^4.17.13": + version: 4.17.16 + resolution: "@types/express@npm:4.17.16" + dependencies: + "@types/body-parser": "*" + "@types/express-serve-static-core": ^4.17.31 + "@types/qs": "*" + "@types/serve-static": "*" + checksum: 43f3ed2cea6e5e83c7c1098c5152f644e975fd764443717ff9c812a1518416a9e7e9f824ffe852c118888cbfb994ed023cad08331f49b19ced469bb185cdd5cd + languageName: node + linkType: hard + +"@types/graceful-fs@npm:^4.1.2": + version: 4.1.6 + resolution: "@types/graceful-fs@npm:4.1.6" + dependencies: + "@types/node": "*" + checksum: c3070ccdc9ca0f40df747bced1c96c71a61992d6f7c767e8fd24bb6a3c2de26e8b84135ede000b7e79db530a23e7e88dcd9db60eee6395d0f4ce1dae91369dd4 + languageName: node + linkType: hard + +"@types/history@npm:4.7.11, @types/history@npm:^4.7.11": + version: 4.7.11 + resolution: "@types/history@npm:4.7.11" + checksum: c92e2ba407dcab0581a9afdf98f533aa41b61a71133420a6d92b1ca9839f741ab1f9395b17454ba5b88cb86020b70b22d74a1950ccfbdfd9beeaa5459fdc3464 + languageName: node + linkType: hard + +"@types/hoist-non-react-statics@npm:^3.3.0, @types/hoist-non-react-statics@npm:^3.3.1": + version: 3.3.1 + resolution: "@types/hoist-non-react-statics@npm:3.3.1" + dependencies: + "@types/react": "*" + hoist-non-react-statics: ^3.3.0 + checksum: 2c0778570d9a01d05afabc781b32163f28409bb98f7245c38d5eaf082416fdb73034003f5825eb5e21313044e8d2d9e1f3fe2831e345d3d1b1d20bcd12270719 + languageName: node + linkType: hard + +"@types/html-minifier-terser@npm:^6.0.0": + version: 6.1.0 + resolution: "@types/html-minifier-terser@npm:6.1.0" + checksum: eb843f6a8d662d44fb18ec61041117734c6aae77aa38df1be3b4712e8e50ffaa35f1e1c92fdd0fde14a5675fecf457abcd0d15a01fae7506c91926176967f452 + languageName: node + linkType: hard + +"@types/http-proxy@npm:^1.17.8": + version: 1.17.9 + resolution: "@types/http-proxy@npm:1.17.9" + dependencies: + "@types/node": "*" + checksum: 7a6746d00729b2a9fe9f9dd3453430b099931df879ec8f7a7b5f07b1795f6d99b0512640c45a67390b1e4bacb9401e36824952aeeaf089feba8627a063cf8e00 + languageName: node + linkType: hard + +"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": + version: 2.0.4 + resolution: "@types/istanbul-lib-coverage@npm:2.0.4" + checksum: a25d7589ee65c94d31464c16b72a9dc81dfa0bea9d3e105ae03882d616e2a0712a9c101a599ec482d297c3591e16336962878cb3eb1a0a62d5b76d277a890ce7 + languageName: node + linkType: hard + +"@types/istanbul-lib-report@npm:*": + version: 3.0.0 + resolution: "@types/istanbul-lib-report@npm:3.0.0" + dependencies: + "@types/istanbul-lib-coverage": "*" + checksum: 656398b62dc288e1b5226f8880af98087233cdb90100655c989a09f3052b5775bf98ba58a16c5ae642fb66c61aba402e07a9f2bff1d1569e3b306026c59f3f36 + languageName: node + linkType: hard + +"@types/istanbul-reports@npm:^3.0.0": + version: 3.0.1 + resolution: "@types/istanbul-reports@npm:3.0.1" + dependencies: + "@types/istanbul-lib-report": "*" + checksum: f1ad54bc68f37f60b30c7915886b92f86b847033e597f9b34f2415acdbe5ed742fa559a0a40050d74cdba3b6a63c342cac1f3a64dba5b68b66a6941f4abd7903 + languageName: node + linkType: hard + +"@types/jest@npm:29.5.2": + version: 29.5.2 + resolution: "@types/jest@npm:29.5.2" + dependencies: + expect: ^29.0.0 + pretty-format: ^29.0.0 + checksum: 7d205599ea3cccc262bad5cc173d3242d6bf8138c99458509230e4ecef07a52d6ddcde5a1dbd49ace655c0af51d2dbadef3748697292ea4d86da19d9e03e19c0 + languageName: node + linkType: hard + +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": + version: 7.0.11 + resolution: "@types/json-schema@npm:7.0.11" + checksum: 527bddfe62db9012fccd7627794bd4c71beb77601861055d87e3ee464f2217c85fca7a4b56ae677478367bbd248dbde13553312b7d4dbc702a2f2bbf60c4018d + languageName: node + linkType: hard + +"@types/json5@npm:^0.0.29": + version: 0.0.29 + resolution: "@types/json5@npm:0.0.29" + checksum: e60b153664572116dfea673c5bda7778dbff150498f44f998e34b5886d8afc47f16799280e4b6e241c0472aef1bc36add771c569c68fc5125fc2ae519a3eb9ac + languageName: node + linkType: hard + +"@types/jsrsasign@npm:10.5.2": + version: 10.5.2 + resolution: "@types/jsrsasign@npm:10.5.2" + checksum: 390e54b8950efaa30305934d1f59d061c39b0a70318dae6f808cc5a3cec71ad020da51ded9fd63d438fce4914af3568f4e252e36f503f0e840e7bf00b515498e + languageName: node + linkType: hard + +"@types/lodash.chunk@npm:4.2.6": + version: 4.2.6 + resolution: "@types/lodash.chunk@npm:4.2.6" + dependencies: + "@types/lodash": "*" + checksum: 18afe616730bc28de1280939923e2433ca70334f409d132917ddb2e513ad4a796053ef6282546be9601bce88eac3fe3ec595137eae87d65a728eca5acaea6066 + languageName: node + linkType: hard + +"@types/lodash.debounce@npm:4.0.6": + version: 4.0.6 + resolution: "@types/lodash.debounce@npm:4.0.6" + dependencies: + "@types/lodash": "*" + checksum: 54b181c65009d2523ad13a608e1db22950467573bf6e10adaccdf46b5c2c68e7d109ff352e7e95c0035a6dd30eafd06f59356c893373098c4fb60db368158595 + languageName: node + linkType: hard + +"@types/lodash.isequal@npm:4.5.8": + version: 4.5.8 + resolution: "@types/lodash.isequal@npm:4.5.8" + dependencies: + "@types/lodash": "*" + checksum: f3180c2d2925514fff1908a1303c11468c9f39b47fd7b053416aad3f1447f8e4a9894dd0460187ac9ac19387e25aec8dd8214d13a50a0967e0dc9cca8e4c5353 + languageName: node + linkType: hard + +"@types/lodash.memoize@npm:4.1.6": + version: 4.1.6 + resolution: "@types/lodash.memoize@npm:4.1.6" + dependencies: + "@types/lodash": "*" + checksum: 5f2ea5da8c8f5caee458cd07ad476e40af08d0908dc00f97f2c0dd814ee99278d28c18f7198180c1d7fa719307e8bdbbbe3651092269f31e487e4159e1a37786 + languageName: node + linkType: hard + +"@types/lodash@npm:*": + version: 4.14.191 + resolution: "@types/lodash@npm:4.14.191" + checksum: ba0d5434e10690869f32d5ea49095250157cae502f10d57de0a723fd72229ce6c6a4979576f0f13e0aa9fbe3ce2457bfb9fa7d4ec3d6daba56730a51906d1491 + languageName: node + linkType: hard + +"@types/mime@npm:*": + version: 3.0.1 + resolution: "@types/mime@npm:3.0.1" + checksum: 4040fac73fd0cea2460e29b348c1a6173da747f3a87da0dbce80dd7a9355a3d0e51d6d9a401654f3e5550620e3718b5a899b2ec1debf18424e298a2c605346e7 + languageName: node + linkType: hard + +"@types/node@npm:*, @types/node@npm:20.11.5": + version: 20.11.5 + resolution: "@types/node@npm:20.11.5" + dependencies: + undici-types: ~5.26.4 + checksum: a542727de1334ae20a3ca034b0ecf4b464a57ca01efc4f9cf43bd9ab93896125ab3c2de060ecd8f6ae23b86c6bf3463f681b643e69c032c6a662d376c98a6092 + languageName: node + linkType: hard + +"@types/parse-json@npm:^4.0.0": + version: 4.0.0 + resolution: "@types/parse-json@npm:4.0.0" + checksum: fd6bce2b674b6efc3db4c7c3d336bd70c90838e8439de639b909ce22f3720d21344f52427f1d9e57b265fcb7f6c018699b99e5e0c208a1a4823014269a6bf35b + languageName: node + linkType: hard + +"@types/prettier@npm:^2.1.5": + version: 2.7.2 + resolution: "@types/prettier@npm:2.7.2" + checksum: b47d76a5252265f8d25dd2fe2a5a61dc43ba0e6a96ffdd00c594cb4fd74c1982c2e346497e3472805d97915407a09423804cc2110a0b8e1b22cffcab246479b7 + languageName: node + linkType: hard + +"@types/prop-types@npm:*, @types/prop-types@npm:^15.7.5": + version: 15.7.5 + resolution: "@types/prop-types@npm:15.7.5" + checksum: 5b43b8b15415e1f298243165f1d44390403bb2bd42e662bca3b5b5633fdd39c938e91b7fce3a9483699db0f7a715d08cef220c121f723a634972fdf596aec980 + languageName: node + linkType: hard + +"@types/q@npm:^1.5.1": + version: 1.5.5 + resolution: "@types/q@npm:1.5.5" + checksum: 3bd386fb97a0e5f1ce1ed7a14e39b60e469b5ca9d920a7f69e0cdb58d22c0f5bdd16637d8c3a5bfeda76663c023564dd47a65389ee9aaabd65aee54803d5ba45 + languageName: node + linkType: hard + +"@types/qs@npm:*": + version: 6.9.7 + resolution: "@types/qs@npm:6.9.7" + checksum: 7fd6f9c25053e9b5bb6bc9f9f76c1d89e6c04f7707a7ba0e44cc01f17ef5284adb82f230f542c2d5557d69407c9a40f0f3515e8319afd14e1e16b5543ac6cdba + languageName: node + linkType: hard + +"@types/range-parser@npm:*": + version: 1.2.4 + resolution: "@types/range-parser@npm:1.2.4" + checksum: b7c0dfd5080a989d6c8bb0b6750fc0933d9acabeb476da6fe71d8bdf1ab65e37c136169d84148034802f48378ab94e3c37bb4ef7656b2bec2cb9c0f8d4146a95 + languageName: node + linkType: hard + +"@types/react-dom@npm:*": + version: 18.0.10 + resolution: "@types/react-dom@npm:18.0.10" + dependencies: + "@types/react": "*" + checksum: ff8282d5005a0b1cd95fb65bf79d3d8485e4cfe2aaf052129033a178684b940014a3f4536bc20d573f8a01cf4c6f4770c74988cef7c2b5cac3041d9f172647e3 + languageName: node + linkType: hard + +"@types/react-dom@npm:17.0.11": + version: 17.0.11 + resolution: "@types/react-dom@npm:17.0.11" + dependencies: + "@types/react": "*" + checksum: 4d5730dffbef86c887cecad7e3cecda424ce6a64d0b5441c63b5b015d48219868660a2bb1aa15e897e565ad8867fa6b885d4358b04e1c4e589ba4c07c3fda55c + languageName: node + linkType: hard + +"@types/react-is@npm:^18.2.1": + version: 18.2.1 + resolution: "@types/react-is@npm:18.2.1" + dependencies: + "@types/react": "*" + checksum: b44c3262efa2c68fa6fe2beb9ef86170b18305469461a3f97aa14943cc033cb21a26944f718bdb6434eea6e8f7fcba251c4f45b65b897a3fcf751b5a6003cf82 + languageName: node + linkType: hard + +"@types/react-redux@npm:7.1.22": + version: 7.1.22 + resolution: "@types/react-redux@npm:7.1.22" + dependencies: + "@types/hoist-non-react-statics": ^3.3.0 + "@types/react": "*" + hoist-non-react-statics: ^3.3.0 + redux: ^4.0.0 + checksum: eef458c0cda27eabd8d458b7fc40553aab8d2f218145b896b9059b86d88680ae479079aee13683f2a0f35774f20346b732e91182252402bd8777455e004561c9 + languageName: node + linkType: hard + +"@types/react-router-dom@npm:5.3.3": + version: 5.3.3 + resolution: "@types/react-router-dom@npm:5.3.3" + dependencies: + "@types/history": ^4.7.11 + "@types/react": "*" + "@types/react-router": "*" + checksum: 28c4ea48909803c414bf5a08502acbb8ba414669b4b43bb51297c05fe5addc4df0b8fd00e0a9d1e3535ec4073ef38aaafac2c4a2b95b787167d113bc059beff3 + languageName: node + linkType: hard + +"@types/react-router@npm:*": + version: 5.1.20 + resolution: "@types/react-router@npm:5.1.20" + dependencies: + "@types/history": ^4.7.11 + "@types/react": "*" + checksum: 128764143473a5e9457ddc715436b5d49814b1c214dde48939b9bef23f0e77f52ffcdfa97eb8d3cc27e2c229869c0cdd90f637d887b62f2c9f065a87d6425419 + languageName: node + linkType: hard + +"@types/react-transition-group@npm:^4.4.5, @types/react-transition-group@npm:^4.4.6": + version: 4.4.6 + resolution: "@types/react-transition-group@npm:4.4.6" + dependencies: + "@types/react": "*" + checksum: 0872143821d7ee20a1d81e965f8b1e837837f11cd2206973f1f98655751992d9390304d58bac192c9cd923eca95bff107d8c9e3364a180240d5c2a6fd70fd7c3 + languageName: node + linkType: hard + +"@types/react-virtualized@npm:9.21.10": + version: 9.21.10 + resolution: "@types/react-virtualized@npm:9.21.10" + dependencies: + "@types/prop-types": "*" + "@types/react": "*" + checksum: 7beb56a0f9f2fad8ddc64bbeaed18be294380a5ac390b1f0343d7c1c80685e7adfa4b955bac0e50181c2412d90d18e7002a582c768f38ac7e8ed00950427241d + languageName: node + linkType: hard + +"@types/react@npm:17.0.39": + version: 17.0.39 + resolution: "@types/react@npm:17.0.39" + dependencies: + "@types/prop-types": "*" + "@types/scheduler": "*" + csstype: ^3.0.2 + checksum: bf04d3c2894559012710d595553e12b422d3b91cd8f4f7e122d8cb044ba9c2ba17f6e8a4e09581359cc5509ddc59cd8c8fabd6774f3505a40a45393f074d6e6e + languageName: node + linkType: hard + +"@types/redux-logger@npm:3.0.8": + version: 3.0.8 + resolution: "@types/redux-logger@npm:3.0.8" + dependencies: + redux: ^4.0.0 + checksum: 68dee8799db09aab2625435008230543f23a6dcf4f29cb8f74d2ec3c723c98765d6ed8fbf1edf2deb440f4a1969082b7d35d9548ab810e9054aa381bc925874c + languageName: node + linkType: hard + +"@types/redux-mock-store@npm:1.0.3": + version: 1.0.3 + resolution: "@types/redux-mock-store@npm:1.0.3" + dependencies: + redux: ^4.0.5 + checksum: b8c76be560fb06c0b5fc8b8874001f0b0219a7a5d0bbbf8f06ebfc437a1300df49f079b30199a9fa99c738817145895a4f0297b8f614edadd1d9e110e917cd0a + languageName: node + linkType: hard + +"@types/resolve@npm:1.17.1": + version: 1.17.1 + resolution: "@types/resolve@npm:1.17.1" + dependencies: + "@types/node": "*" + checksum: dc6a6df507656004e242dcb02c784479deca516d5f4b58a1707e708022b269ae147e1da0521f3e8ad0d63638869d87e0adc023f0bd5454aa6f72ac66c7525cf5 + languageName: node + linkType: hard + +"@types/retry@npm:0.12.0": + version: 0.12.0 + resolution: "@types/retry@npm:0.12.0" + checksum: 61a072c7639f6e8126588bf1eb1ce8835f2cb9c2aba795c4491cf6310e013267b0c8488039857c261c387e9728c1b43205099223f160bb6a76b4374f741b5603 + languageName: node + linkType: hard + +"@types/scheduler@npm:*": + version: 0.16.2 + resolution: "@types/scheduler@npm:0.16.2" + checksum: b6b4dcfeae6deba2e06a70941860fb1435730576d3689225a421280b7742318d1548b3d22c1f66ab68e414f346a9542f29240bc955b6332c5b11e561077583bc + languageName: node + linkType: hard + +"@types/semver@npm:^7.3.12": + version: 7.3.13 + resolution: "@types/semver@npm:7.3.13" + checksum: 00c0724d54757c2f4bc60b5032fe91cda6410e48689633d5f35ece8a0a66445e3e57fa1d6e07eb780f792e82ac542948ec4d0b76eb3484297b79bd18b8cf1cb0 + languageName: node + linkType: hard + +"@types/serve-index@npm:^1.9.1": + version: 1.9.1 + resolution: "@types/serve-index@npm:1.9.1" + dependencies: + "@types/express": "*" + checksum: 026f3995fb500f6df7c3fe5009e53bad6d739e20b84089f58ebfafb2f404bbbb6162bbe33f72d2f2af32d5b8d3799c8e179793f90d9ed5871fb8591190bb6056 + languageName: node + linkType: hard + +"@types/serve-static@npm:*, @types/serve-static@npm:^1.13.10": + version: 1.15.0 + resolution: "@types/serve-static@npm:1.15.0" + dependencies: + "@types/mime": "*" + "@types/node": "*" + checksum: b6ac93d471fb0f53ddcac1f9b67572a09cd62806f7db5855244b28f6f421139626f24799392566e97d1ffc61b12f9de7f30380c39fcae3c8a161fe161d44edf2 + languageName: node + linkType: hard + +"@types/sinonjs__fake-timers@npm:8.1.1": + version: 8.1.1 + resolution: "@types/sinonjs__fake-timers@npm:8.1.1" + checksum: ca09d54d47091d87020824a73f026300fa06b17cd9f2f9b9387f28b549364b141ef194ee28db762f6588de71d8febcd17f753163cb7ea116b8387c18e80ebd5c + languageName: node + linkType: hard + +"@types/sizzle@npm:^2.3.2": + version: 2.3.3 + resolution: "@types/sizzle@npm:2.3.3" + checksum: 586a9fb1f6ff3e325e0f2cc1596a460615f0bc8a28f6e276ac9b509401039dd242fa8b34496d3a30c52f5b495873922d09a9e76c50c2ab2bcc70ba3fb9c4e160 + languageName: node + linkType: hard + +"@types/sockjs@npm:^0.3.33": + version: 0.3.33 + resolution: "@types/sockjs@npm:0.3.33" + dependencies: + "@types/node": "*" + checksum: b9bbb2b5c5ead2fb884bb019f61a014e37410bddd295de28184e1b2e71ee6b04120c5ba7b9954617f0bdf962c13d06249ce65004490889c747c80d3f628ea842 + languageName: node + linkType: hard + +"@types/stack-utils@npm:^2.0.0": + version: 2.0.1 + resolution: "@types/stack-utils@npm:2.0.1" + checksum: 205fdbe3326b7046d7eaf5e494d8084f2659086a266f3f9cf00bccc549c8e36e407f88168ad4383c8b07099957ad669f75f2532ed4bc70be2b037330f7bae019 + languageName: node + linkType: hard + +"@types/trusted-types@npm:^2.0.2": + version: 2.0.2 + resolution: "@types/trusted-types@npm:2.0.2" + checksum: 3371eef5f1c50e1c3c07a127c1207b262ba65b83dd167a1c460fc1b135a3fb0c97b9f508efebd383f239cc5dd5b7169093686a692a501fde9c3f7208657d9b0d + languageName: node + linkType: hard + +"@types/use-sync-external-store@npm:^0.0.3": + version: 0.0.3 + resolution: "@types/use-sync-external-store@npm:0.0.3" + checksum: 161ddb8eec5dbe7279ac971531217e9af6b99f7783213566d2b502e2e2378ea19cf5e5ea4595039d730aa79d3d35c6567d48599f69773a02ffcff1776ec2a44e + languageName: node + linkType: hard + +"@types/ws@npm:^8.5.1": + version: 8.5.4 + resolution: "@types/ws@npm:8.5.4" + dependencies: + "@types/node": "*" + checksum: fefbad20d211929bb996285c4e6f699b12192548afedbe4930ab4384f8a94577c9cd421acaad163cacd36b88649509970a05a0b8f20615b30c501ed5269038d1 + languageName: node + linkType: hard + +"@types/yargs-parser@npm:*": + version: 21.0.0 + resolution: "@types/yargs-parser@npm:21.0.0" + checksum: b2f4c8d12ac18a567440379909127cf2cec393daffb73f246d0a25df36ea983b93b7e9e824251f959e9f928cbc7c1aab6728d0a0ff15d6145f66cec2be67d9a2 + languageName: node + linkType: hard + +"@types/yargs@npm:^16.0.0": + version: 16.0.5 + resolution: "@types/yargs@npm:16.0.5" + dependencies: + "@types/yargs-parser": "*" + checksum: 22697f7cc8aa32dcc10981a87f035e183303a58351c537c81fb450270d5c494b1d918186210e445b0eb2e4a8b34a8bda2a595f346bdb1c9ed2b63d193cb00430 + languageName: node + linkType: hard + +"@types/yargs@npm:^17.0.8": + version: 17.0.20 + resolution: "@types/yargs@npm:17.0.20" + dependencies: + "@types/yargs-parser": "*" + checksum: dc2edbb0e4b6bfe5189b86c057bb6991139af02372b1d3591083e4ce8f9605b19d598e56413e30f41453733f7a048f732f899cb637f3938f90ed3eb13f23cc90 + languageName: node + linkType: hard + +"@types/yauzl@npm:^2.9.1": + version: 2.10.0 + resolution: "@types/yauzl@npm:2.10.0" + dependencies: + "@types/node": "*" + checksum: 55d27ae5d346ea260e40121675c24e112ef0247649073848e5d4e03182713ae4ec8142b98f61a1c6cbe7d3b72fa99bbadb65d8b01873e5e605cdc30f1ff70ef2 + languageName: node + linkType: hard + +"@typescript-eslint/eslint-plugin@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/eslint-plugin@npm:5.62.0" + dependencies: + "@eslint-community/regexpp": ^4.4.0 + "@typescript-eslint/scope-manager": 5.62.0 + "@typescript-eslint/type-utils": 5.62.0 + "@typescript-eslint/utils": 5.62.0 + debug: ^4.3.4 + graphemer: ^1.4.0 + ignore: ^5.2.0 + natural-compare-lite: ^1.4.0 + semver: ^7.3.7 + tsutils: ^3.21.0 + peerDependencies: + "@typescript-eslint/parser": ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: fc104b389c768f9fa7d45a48c86d5c1ad522c1d0512943e782a56b1e3096b2cbcc1eea3fcc590647bf0658eef61aac35120a9c6daf979bf629ad2956deb516a1 + languageName: node + linkType: hard + +"@typescript-eslint/experimental-utils@npm:^5.0.0": + version: 5.49.0 + resolution: "@typescript-eslint/experimental-utils@npm:5.49.0" + dependencies: + "@typescript-eslint/utils": 5.49.0 + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: e0deb9c4d839a6876958e4a47cf716e670aba2e55c20ba9a4ba88301348b41448f778a62225598a5253c41d90a9c5252c9e36f982904ac58e12967c23e67a374 + languageName: node + linkType: hard + +"@typescript-eslint/parser@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/parser@npm:5.62.0" + dependencies: + "@typescript-eslint/scope-manager": 5.62.0 + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/typescript-estree": 5.62.0 + debug: ^4.3.4 + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: d168f4c7f21a7a63f47002e2d319bcbb6173597af5c60c1cf2de046b46c76b4930a093619e69faf2d30214c29ab27b54dcf1efc7046a6a6bd6f37f59a990e752 + languageName: node + linkType: hard + +"@typescript-eslint/scope-manager@npm:5.49.0": + version: 5.49.0 + resolution: "@typescript-eslint/scope-manager@npm:5.49.0" + dependencies: + "@typescript-eslint/types": 5.49.0 + "@typescript-eslint/visitor-keys": 5.49.0 + checksum: 466047e24ff8a4195f14aadde39375f22891bdaced09e58c89f2c32af0aa4a0d87e71a5f006f6ab76858e6f30c4b764b1e0ef7bc26713bb78add30638108c45f + languageName: node + linkType: hard + +"@typescript-eslint/scope-manager@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/scope-manager@npm:5.62.0" + dependencies: + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/visitor-keys": 5.62.0 + checksum: 6062d6b797fe1ce4d275bb0d17204c827494af59b5eaf09d8a78cdd39dadddb31074dded4297aaf5d0f839016d601032857698b0e4516c86a41207de606e9573 + languageName: node + linkType: hard + +"@typescript-eslint/type-utils@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/type-utils@npm:5.62.0" + dependencies: + "@typescript-eslint/typescript-estree": 5.62.0 + "@typescript-eslint/utils": 5.62.0 + debug: ^4.3.4 + tsutils: ^3.21.0 + peerDependencies: + eslint: "*" + peerDependenciesMeta: + typescript: + optional: true + checksum: fc41eece5f315dfda14320be0da78d3a971d650ea41300be7196934b9715f3fe1120a80207551eb71d39568275dbbcf359bde540d1ca1439d8be15e9885d2739 + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:5.49.0": + version: 5.49.0 + resolution: "@typescript-eslint/types@npm:5.49.0" + checksum: 41f72a043007fc3f3356b5a38d7bfa54871545b4a309810a062f044cff25122413a9660ce6d83d1221762f60d067351d020b0cb68f7e1279817f53e77ce8f33d + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/types@npm:5.62.0" + checksum: 48c87117383d1864766486f24de34086155532b070f6264e09d0e6139449270f8a9559cfef3c56d16e3bcfb52d83d42105d61b36743626399c7c2b5e0ac3b670 + languageName: node + linkType: hard + +"@typescript-eslint/typescript-estree@npm:5.49.0": + version: 5.49.0 + resolution: "@typescript-eslint/typescript-estree@npm:5.49.0" + dependencies: + "@typescript-eslint/types": 5.49.0 + "@typescript-eslint/visitor-keys": 5.49.0 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + semver: ^7.3.7 + tsutils: ^3.21.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: f331af9f0ef3ce3157c421b8cc727dec5aa0a60add305aa4c676a02c63ec07799105268af192c5ed193a682b7ed804564d29d49bdbd2019678e495d80e65e29a + languageName: node + linkType: hard + +"@typescript-eslint/typescript-estree@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/typescript-estree@npm:5.62.0" + dependencies: + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/visitor-keys": 5.62.0 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + semver: ^7.3.7 + tsutils: ^3.21.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 3624520abb5807ed8f57b1197e61c7b1ed770c56dfcaca66372d584ff50175225798bccb701f7ef129d62c5989070e1ee3a0aa2d84e56d9524dcf011a2bb1a52 + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:5.49.0": + version: 5.49.0 + resolution: "@typescript-eslint/utils@npm:5.49.0" + dependencies: + "@types/json-schema": ^7.0.9 + "@types/semver": ^7.3.12 + "@typescript-eslint/scope-manager": 5.49.0 + "@typescript-eslint/types": 5.49.0 + "@typescript-eslint/typescript-estree": 5.49.0 + eslint-scope: ^5.1.1 + eslint-utils: ^3.0.0 + semver: ^7.3.7 + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: 8218c566637d5104dfb2346216f8cb4c244f31c2a39e261aafe554b8abd48bd630a0d0807a0a8d776af8f9d9914c8776d86abf0a523049f3c5619c498a7e5b1e + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:5.62.0, @typescript-eslint/utils@npm:^5.43.0": + version: 5.62.0 + resolution: "@typescript-eslint/utils@npm:5.62.0" + dependencies: + "@eslint-community/eslint-utils": ^4.2.0 + "@types/json-schema": ^7.0.9 + "@types/semver": ^7.3.12 + "@typescript-eslint/scope-manager": 5.62.0 + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/typescript-estree": 5.62.0 + eslint-scope: ^5.1.1 + semver: ^7.3.7 + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: ee9398c8c5db6d1da09463ca7bf36ed134361e20131ea354b2da16a5fdb6df9ba70c62a388d19f6eebb421af1786dbbd79ba95ddd6ab287324fc171c3e28d931 + languageName: node + linkType: hard + +"@typescript-eslint/visitor-keys@npm:5.49.0": + version: 5.49.0 + resolution: "@typescript-eslint/visitor-keys@npm:5.49.0" + dependencies: + "@typescript-eslint/types": 5.49.0 + eslint-visitor-keys: ^3.3.0 + checksum: 46dc7bc713e8825d1fccba521fdf7c6e2f8829e491c2afd44dbe4105c6432e3c3dfe7e1ecb221401269d639264bb4af77b60a7b65521fcff9ab02cd31d8ef782 + languageName: node + linkType: hard + +"@typescript-eslint/visitor-keys@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/visitor-keys@npm:5.62.0" + dependencies: + "@typescript-eslint/types": 5.62.0 + eslint-visitor-keys: ^3.3.0 + checksum: 976b05d103fe8335bef5c93ad3f76d781e3ce50329c0243ee0f00c0fcfb186c81df50e64bfdd34970148113f8ade90887f53e3c4938183afba830b4ba8e30a35 + languageName: node + linkType: hard + +"@ungap/structured-clone@npm:^1.2.0": + version: 1.2.0 + resolution: "@ungap/structured-clone@npm:1.2.0" + checksum: 4f656b7b4672f2ce6e272f2427d8b0824ed11546a601d8d5412b9d7704e83db38a8d9f402ecdf2b9063fc164af842ad0ec4a55819f621ed7e7ea4d1efcc74524 + languageName: node + linkType: hard + +"@webassemblyjs/ast@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/ast@npm:1.11.1" + dependencies: + "@webassemblyjs/helper-numbers": 1.11.1 + "@webassemblyjs/helper-wasm-bytecode": 1.11.1 + checksum: 1eee1534adebeece635362f8e834ae03e389281972611408d64be7895fc49f48f98fddbbb5339bf8a72cb101bcb066e8bca3ca1bf1ef47dadf89def0395a8d87 + languageName: node + linkType: hard + +"@webassemblyjs/floating-point-hex-parser@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.11.1" + checksum: b8efc6fa08e4787b7f8e682182d84dfdf8da9d9c77cae5d293818bc4a55c1f419a87fa265ab85252b3e6c1fd323d799efea68d825d341a7c365c64bc14750e97 + languageName: node + linkType: hard + +"@webassemblyjs/helper-api-error@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/helper-api-error@npm:1.11.1" + checksum: 0792813f0ed4a0e5ee0750e8b5d0c631f08e927f4bdfdd9fe9105dc410c786850b8c61bff7f9f515fdfb149903bec3c976a1310573a4c6866a94d49bc7271959 + languageName: node + linkType: hard + +"@webassemblyjs/helper-buffer@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/helper-buffer@npm:1.11.1" + checksum: a337ee44b45590c3a30db5a8b7b68a717526cf967ada9f10253995294dbd70a58b2da2165222e0b9830cd4fc6e4c833bf441a721128d1fe2e9a7ab26b36003ce + languageName: node + linkType: hard + +"@webassemblyjs/helper-numbers@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/helper-numbers@npm:1.11.1" + dependencies: + "@webassemblyjs/floating-point-hex-parser": 1.11.1 + "@webassemblyjs/helper-api-error": 1.11.1 + "@xtuc/long": 4.2.2 + checksum: 44d2905dac2f14d1e9b5765cf1063a0fa3d57295c6d8930f6c59a36462afecc6e763e8a110b97b342a0f13376166c5d41aa928e6ced92e2f06b071fd0db59d3a + languageName: node + linkType: hard + +"@webassemblyjs/helper-wasm-bytecode@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.11.1" + checksum: eac400113127832c88f5826bcc3ad1c0db9b3dbd4c51a723cfdb16af6bfcbceb608170fdaac0ab7731a7e18b291be7af68a47fcdb41cfe0260c10857e7413d97 + languageName: node + linkType: hard + +"@webassemblyjs/helper-wasm-section@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/helper-wasm-section@npm:1.11.1" + dependencies: + "@webassemblyjs/ast": 1.11.1 + "@webassemblyjs/helper-buffer": 1.11.1 + "@webassemblyjs/helper-wasm-bytecode": 1.11.1 + "@webassemblyjs/wasm-gen": 1.11.1 + checksum: 617696cfe8ecaf0532763162aaf748eb69096fb27950219bb87686c6b2e66e11cd0614d95d319d0ab1904bc14ebe4e29068b12c3e7c5e020281379741fe4bedf + languageName: node + linkType: hard + +"@webassemblyjs/ieee754@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/ieee754@npm:1.11.1" + dependencies: + "@xtuc/ieee754": ^1.2.0 + checksum: 23a0ac02a50f244471631802798a816524df17e56b1ef929f0c73e3cde70eaf105a24130105c60aff9d64a24ce3b640dad443d6f86e5967f922943a7115022ec + languageName: node + linkType: hard + +"@webassemblyjs/leb128@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/leb128@npm:1.11.1" + dependencies: + "@xtuc/long": 4.2.2 + checksum: 33ccc4ade2f24de07bf31690844d0b1ad224304ee2062b0e464a610b0209c79e0b3009ac190efe0e6bd568b0d1578d7c3047fc1f9d0197c92fc061f56224ff4a + languageName: node + linkType: hard + +"@webassemblyjs/utf8@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/utf8@npm:1.11.1" + checksum: 972c5cfc769d7af79313a6bfb96517253a270a4bf0c33ba486aa43cac43917184fb35e51dfc9e6b5601548cd5931479a42e42c89a13bb591ffabebf30c8a6a0b + languageName: node + linkType: hard + +"@webassemblyjs/wasm-edit@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/wasm-edit@npm:1.11.1" + dependencies: + "@webassemblyjs/ast": 1.11.1 + "@webassemblyjs/helper-buffer": 1.11.1 + "@webassemblyjs/helper-wasm-bytecode": 1.11.1 + "@webassemblyjs/helper-wasm-section": 1.11.1 + "@webassemblyjs/wasm-gen": 1.11.1 + "@webassemblyjs/wasm-opt": 1.11.1 + "@webassemblyjs/wasm-parser": 1.11.1 + "@webassemblyjs/wast-printer": 1.11.1 + checksum: 6d7d9efaec1227e7ef7585a5d7ff0be5f329f7c1c6b6c0e906b18ed2e9a28792a5635e450aca2d136770d0207225f204eff70a4b8fd879d3ac79e1dcc26dbeb9 + languageName: node + linkType: hard + +"@webassemblyjs/wasm-gen@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/wasm-gen@npm:1.11.1" + dependencies: + "@webassemblyjs/ast": 1.11.1 + "@webassemblyjs/helper-wasm-bytecode": 1.11.1 + "@webassemblyjs/ieee754": 1.11.1 + "@webassemblyjs/leb128": 1.11.1 + "@webassemblyjs/utf8": 1.11.1 + checksum: 1f6921e640293bf99fb16b21e09acb59b340a79f986c8f979853a0ae9f0b58557534b81e02ea2b4ef11e929d946708533fd0693c7f3712924128fdafd6465f5b + languageName: node + linkType: hard + +"@webassemblyjs/wasm-opt@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/wasm-opt@npm:1.11.1" + dependencies: + "@webassemblyjs/ast": 1.11.1 + "@webassemblyjs/helper-buffer": 1.11.1 + "@webassemblyjs/wasm-gen": 1.11.1 + "@webassemblyjs/wasm-parser": 1.11.1 + checksum: 21586883a20009e2b20feb67bdc451bbc6942252e038aae4c3a08e6f67b6bae0f5f88f20bfc7bd0452db5000bacaf5ab42b98cf9aa034a6c70e9fc616142e1db + languageName: node + linkType: hard + +"@webassemblyjs/wasm-parser@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/wasm-parser@npm:1.11.1" + dependencies: + "@webassemblyjs/ast": 1.11.1 + "@webassemblyjs/helper-api-error": 1.11.1 + "@webassemblyjs/helper-wasm-bytecode": 1.11.1 + "@webassemblyjs/ieee754": 1.11.1 + "@webassemblyjs/leb128": 1.11.1 + "@webassemblyjs/utf8": 1.11.1 + checksum: 1521644065c360e7b27fad9f4bb2df1802d134dd62937fa1f601a1975cde56bc31a57b6e26408b9ee0228626ff3ba1131ae6f74ffb7d718415b6528c5a6dbfc2 + languageName: node + linkType: hard + +"@webassemblyjs/wast-printer@npm:1.11.1": + version: 1.11.1 + resolution: "@webassemblyjs/wast-printer@npm:1.11.1" + dependencies: + "@webassemblyjs/ast": 1.11.1 + "@xtuc/long": 4.2.2 + checksum: f15ae4c2441b979a3b4fce78f3d83472fb22350c6dc3fd34bfe7c3da108e0b2360718734d961bba20e7716cb8578e964b870da55b035e209e50ec9db0378a3f7 + languageName: node + linkType: hard + +"@xtuc/ieee754@npm:^1.2.0": + version: 1.2.0 + resolution: "@xtuc/ieee754@npm:1.2.0" + checksum: ac56d4ca6e17790f1b1677f978c0c6808b1900a5b138885d3da21732f62e30e8f0d9120fcf8f6edfff5100ca902b46f8dd7c1e3f903728634523981e80e2885a + languageName: node + linkType: hard + +"@xtuc/long@npm:4.2.2": + version: 4.2.2 + resolution: "@xtuc/long@npm:4.2.2" + checksum: 8ed0d477ce3bc9c6fe2bf6a6a2cc316bb9c4127c5a7827bae947fa8ec34c7092395c5a283cc300c05b5fa01cbbfa1f938f410a7bf75db7c7846fea41949989ec + languageName: node + linkType: hard + +"@zeit/schemas@npm:2.29.0": + version: 2.29.0 + resolution: "@zeit/schemas@npm:2.29.0" + checksum: 3cea06bb67d790336aca0cc17580fd492ff3fc66ef4d180dce7053ff7ff54ab81b56bf718ba6f537148c581161d06306a481ec218d540bff922e0e009844ffd1 + languageName: node + linkType: hard + +"abab@npm:^2.0.3, abab@npm:^2.0.5": + version: 2.0.6 + resolution: "abab@npm:2.0.6" + checksum: 6ffc1af4ff315066c62600123990d87551ceb0aafa01e6539da77b0f5987ac7019466780bf480f1787576d4385e3690c81ccc37cfda12819bf510b8ab47e5a3e + languageName: node + linkType: hard + +"abbrev@npm:^1.0.0": + version: 1.1.1 + resolution: "abbrev@npm:1.1.1" + checksum: a4a97ec07d7ea112c517036882b2ac22f3109b7b19077dc656316d07d308438aac28e4d9746dc4d84bf6b1e75b4a7b0a5f3cb30592419f128ca9a8cee3bcfa17 + languageName: node + linkType: hard + +"accepts@npm:~1.3.4, accepts@npm:~1.3.5, accepts@npm:~1.3.8": + version: 1.3.8 + resolution: "accepts@npm:1.3.8" + dependencies: + mime-types: ~2.1.34 + negotiator: 0.6.3 + checksum: 50c43d32e7b50285ebe84b613ee4a3aa426715a7d131b65b786e2ead0fd76b6b60091b9916d3478a75f11f162628a2139991b6c03ab3f1d9ab7c86075dc8eab4 + languageName: node + linkType: hard + +"acorn-globals@npm:^6.0.0": + version: 6.0.0 + resolution: "acorn-globals@npm:6.0.0" + dependencies: + acorn: ^7.1.1 + acorn-walk: ^7.1.1 + checksum: 72d95e5b5e585f9acd019b993ab8bbba68bb3cbc9d9b5c1ebb3c2f1fe5981f11deababfb4949f48e6262f9c57878837f5958c0cca396f81023814680ca878042 + languageName: node + linkType: hard + +"acorn-import-assertions@npm:^1.7.6": + version: 1.8.0 + resolution: "acorn-import-assertions@npm:1.8.0" + peerDependencies: + acorn: ^8 + checksum: 5c4cf7c850102ba7ae0eeae0deb40fb3158c8ca5ff15c0bca43b5c47e307a1de3d8ef761788f881343680ea374631ae9e9615ba8876fee5268dbe068c98bcba6 + languageName: node + linkType: hard + +"acorn-jsx@npm:^5.3.2": + version: 5.3.2 + resolution: "acorn-jsx@npm:5.3.2" + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: c3d3b2a89c9a056b205b69530a37b972b404ee46ec8e5b341666f9513d3163e2a4f214a71f4dfc7370f5a9c07472d2fd1c11c91c3f03d093e37637d95da98950 + languageName: node + linkType: hard + +"acorn-node@npm:^1.8.2": + version: 1.8.2 + resolution: "acorn-node@npm:1.8.2" + dependencies: + acorn: ^7.0.0 + acorn-walk: ^7.0.0 + xtend: ^4.0.2 + checksum: 02e1564a1ccf8bd1fcefcd01235398af4a9effaf032c5397994ddd275590a72894cb3e26e4b82579ccdda1e48ade7486aef61e771ddae3563ca452b927f443d8 + languageName: node + linkType: hard + +"acorn-walk@npm:^7.0.0, acorn-walk@npm:^7.1.1": + version: 7.2.0 + resolution: "acorn-walk@npm:7.2.0" + checksum: 9252158a79b9d92f1bc0dd6acc0fcfb87a67339e84bcc301bb33d6078936d27e35d606b4d35626d2962cd43c256d6f27717e70cbe15c04fff999ab0b2260b21f + languageName: node + linkType: hard + +"acorn-walk@npm:^8.1.1": + version: 8.2.0 + resolution: "acorn-walk@npm:8.2.0" + checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1 + languageName: node + linkType: hard + +"acorn@npm:^7.0.0, acorn@npm:^7.1.1": + version: 7.4.1 + resolution: "acorn@npm:7.4.1" + bin: + acorn: bin/acorn + checksum: 1860f23c2107c910c6177b7b7be71be350db9e1080d814493fae143ae37605189504152d1ba8743ba3178d0b37269ce1ffc42b101547fdc1827078f82671e407 + languageName: node + linkType: hard + +"acorn@npm:^8.2.4, acorn@npm:^8.4.1, acorn@npm:^8.5.0, acorn@npm:^8.7.1, acorn@npm:^8.9.0": + version: 8.9.0 + resolution: "acorn@npm:8.9.0" + bin: + acorn: bin/acorn + checksum: 25dfb94952386ecfb847e61934de04a4e7c2dc21c2e700fc4e2ef27ce78cb717700c4c4f279cd630bb4774948633c3859fc16063ec8573bda4568e0a312e6744 + languageName: node + linkType: hard + +"address@npm:^1.0.1, address@npm:^1.1.2": + version: 1.2.2 + resolution: "address@npm:1.2.2" + checksum: ace439960c1e3564d8f523aff23a841904bf33a2a7c2e064f7f60a064194075758b9690e65bd9785692a4ef698a998c57eb74d145881a1cecab8ba658ddb1607 + languageName: node + linkType: hard + +"adjust-sourcemap-loader@npm:^4.0.0": + version: 4.0.0 + resolution: "adjust-sourcemap-loader@npm:4.0.0" + dependencies: + loader-utils: ^2.0.0 + regex-parser: ^2.2.11 + checksum: d524ae23582f41e2275af5d88faab7a9dc09770ed588244e0a76d3196d0d6a90bf02760c71bc6213dbfef3aef4a86232ac9521bfd629752c32b7af37bc74c660 + languageName: node + linkType: hard + +"agent-base@npm:6, agent-base@npm:^6.0.2": + version: 6.0.2 + resolution: "agent-base@npm:6.0.2" + dependencies: + debug: 4 + checksum: f52b6872cc96fd5f622071b71ef200e01c7c4c454ee68bc9accca90c98cfb39f2810e3e9aa330435835eedc8c23f4f8a15267f67c6e245d2b33757575bdac49d + languageName: node + linkType: hard + +"agentkeepalive@npm:^4.2.1": + version: 4.2.1 + resolution: "agentkeepalive@npm:4.2.1" + dependencies: + debug: ^4.1.0 + depd: ^1.1.2 + humanize-ms: ^1.2.1 + checksum: 39cb49ed8cf217fd6da058a92828a0a84e0b74c35550f82ee0a10e1ee403c4b78ade7948be2279b188b7a7303f5d396ea2738b134731e464bf28de00a4f72a18 + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: ^2.0.0 + indent-string: ^4.0.0 + checksum: 1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 + languageName: node + linkType: hard + +"ajv-formats@npm:^2.1.1": + version: 2.1.1 + resolution: "ajv-formats@npm:2.1.1" + dependencies: + ajv: ^8.0.0 + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + checksum: 4a287d937f1ebaad4683249a4c40c0fa3beed30d9ddc0adba04859026a622da0d317851316ea64b3680dc60f5c3c708105ddd5d5db8fe595d9d0207fd19f90b7 + languageName: node + linkType: hard + +"ajv-keywords@npm:^3.4.1, ajv-keywords@npm:^3.5.2": + version: 3.5.2 + resolution: "ajv-keywords@npm:3.5.2" + peerDependencies: + ajv: ^6.9.1 + checksum: 7dc5e5931677a680589050f79dcbe1fefbb8fea38a955af03724229139175b433c63c68f7ae5f86cf8f65d55eb7c25f75a046723e2e58296707617ca690feae9 + languageName: node + linkType: hard + +"ajv-keywords@npm:^5.0.0": + version: 5.1.0 + resolution: "ajv-keywords@npm:5.1.0" + dependencies: + fast-deep-equal: ^3.1.3 + peerDependencies: + ajv: ^8.8.2 + checksum: c35193940b853119242c6757787f09ecf89a2c19bcd36d03ed1a615e710d19d450cb448bfda407b939aba54b002368c8bff30529cc50a0536a8e10bcce300421 + languageName: node + linkType: hard + +"ajv@npm:8.11.0": + version: 8.11.0 + resolution: "ajv@npm:8.11.0" + dependencies: + fast-deep-equal: ^3.1.1 + json-schema-traverse: ^1.0.0 + require-from-string: ^2.0.2 + uri-js: ^4.2.2 + checksum: 5e0ff226806763be73e93dd7805b634f6f5921e3e90ca04acdf8db81eed9d8d3f0d4c5f1213047f45ebbf8047ffe0c840fa1ef2ec42c3a644899f69aa72b5bef + languageName: node + linkType: hard + +"ajv@npm:^6.12.2, ajv@npm:^6.12.4, ajv@npm:^6.12.5": + version: 6.12.6 + resolution: "ajv@npm:6.12.6" + 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 + checksum: 874972efe5c4202ab0a68379481fbd3d1b5d0a7bd6d3cc21d40d3536ebff3352a2a1fabb632d4fd2cc7fe4cbdcd5ed6782084c9bbf7f32a1536d18f9da5007d4 + languageName: node + linkType: hard + +"ajv@npm:^8.0.0, ajv@npm:^8.6.0, ajv@npm:^8.8.0": + version: 8.12.0 + resolution: "ajv@npm:8.12.0" + dependencies: + fast-deep-equal: ^3.1.1 + json-schema-traverse: ^1.0.0 + require-from-string: ^2.0.2 + uri-js: ^4.2.2 + checksum: 4dc13714e316e67537c8b31bc063f99a1d9d9a497eb4bbd55191ac0dcd5e4985bbb71570352ad6f1e76684fb6d790928f96ba3b2d4fd6e10024be9612fe3f001 + languageName: node + linkType: hard + +"ansi-align@npm:^3.0.1": + version: 3.0.1 + resolution: "ansi-align@npm:3.0.1" + dependencies: + string-width: ^4.1.0 + checksum: 6abfa08f2141d231c257162b15292467081fa49a208593e055c866aa0455b57f3a86b5a678c190c618faa79b4c59e254493099cb700dd9cf2293c6be2c8f5d8d + languageName: node + linkType: hard + +"ansi-colors@npm:^4.1.1": + version: 4.1.3 + resolution: "ansi-colors@npm:4.1.3" + checksum: a9c2ec842038a1fabc7db9ece7d3177e2fe1c5dc6f0c51ecfbf5f39911427b89c00b5dc6b8bd95f82a26e9b16aaae2e83d45f060e98070ce4d1333038edceb0e + languageName: node + linkType: hard + +"ansi-escapes@npm:^4.2.1, ansi-escapes@npm:^4.3.0, ansi-escapes@npm:^4.3.1": + version: 4.3.2 + resolution: "ansi-escapes@npm:4.3.2" + dependencies: + type-fest: ^0.21.3 + checksum: 93111c42189c0a6bed9cdb4d7f2829548e943827ee8479c74d6e0b22ee127b2a21d3f8b5ca57723b8ef78ce011fbfc2784350eb2bde3ccfccf2f575fa8489815 + languageName: node + linkType: hard + +"ansi-escapes@npm:^5.0.0": + version: 5.0.0 + resolution: "ansi-escapes@npm:5.0.0" + dependencies: + type-fest: ^1.0.2 + checksum: d4b5eb8207df38367945f5dd2ef41e08c28edc192dc766ef18af6b53736682f49d8bfcfa4e4d6ecbc2e2f97c258fda084fb29a9e43b69170b71090f771afccac + languageName: node + linkType: hard + +"ansi-html-community@npm:^0.0.8": + version: 0.0.8 + resolution: "ansi-html-community@npm:0.0.8" + bin: + ansi-html: bin/ansi-html + checksum: 04c568e8348a636963f915e48eaa3e01218322e1169acafdd79c384f22e5558c003f79bbc480c1563865497482817c7eed025f0653ebc17642fededa5cb42089 + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.0.1 + resolution: "ansi-regex@npm:6.0.1" + checksum: 1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 + languageName: node + linkType: hard + +"ansi-styles@npm:^3.2.1": + version: 3.2.1 + resolution: "ansi-styles@npm:3.2.1" + dependencies: + color-convert: ^1.9.0 + checksum: d85ade01c10e5dd77b6c89f34ed7531da5830d2cb5882c645f330079975b716438cd7ebb81d0d6e6b4f9c577f19ae41ab55f07f19786b02f9dfd9e0377395665 + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: ^2.0.1 + checksum: 513b44c3b2105dd14cc42a19271e80f386466c4be574bccf60b627432f9198571ebf4ab1e4c3ba17347658f4ee1711c163d574248c0c1cdc2d5917a0ad582ec4 + languageName: node + linkType: hard + +"ansi-styles@npm:^5.0.0": + version: 5.2.0 + resolution: "ansi-styles@npm:5.2.0" + checksum: d7f4e97ce0623aea6bc0d90dcd28881ee04cba06c570b97fd3391bd7a268eedfd9d5e2dd4fdcbdd82b8105df5faf6f24aaedc08eaf3da898e702db5948f63469 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.0.0, ansi-styles@npm:^6.1.0": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 + languageName: node + linkType: hard + +"anymatch@npm:^3.0.3, anymatch@npm:~3.1.2": + version: 3.1.3 + resolution: "anymatch@npm:3.1.3" + dependencies: + normalize-path: ^3.0.0 + picomatch: ^2.0.4 + checksum: 3e044fd6d1d26545f235a9fe4d7a534e2029d8e59fa7fd9f2a6eb21230f6b5380ea1eaf55136e60cbf8e613544b3b766e7a6fa2102e2a3a117505466e3025dc2 + languageName: node + linkType: hard + +"aproba@npm:^1.0.3 || ^2.0.0": + version: 2.0.0 + resolution: "aproba@npm:2.0.0" + checksum: 5615cadcfb45289eea63f8afd064ab656006361020e1735112e346593856f87435e02d8dcc7ff0d11928bc7d425f27bc7c2a84f6c0b35ab0ff659c814c138a24 + languageName: node + linkType: hard + +"arch@npm:^2.2.0": + version: 2.2.0 + resolution: "arch@npm:2.2.0" + checksum: e21b7635029fe8e9cdd5a026f9a6c659103e63fff423834323cdf836a1bb240a72d0c39ca8c470f84643385cf581bd8eda2cad8bf493e27e54bd9783abe9101f + languageName: node + linkType: hard + +"are-we-there-yet@npm:^3.0.0": + version: 3.0.1 + resolution: "are-we-there-yet@npm:3.0.1" + dependencies: + delegates: ^1.0.0 + readable-stream: ^3.6.0 + checksum: 52590c24860fa7173bedeb69a4c05fb573473e860197f618b9a28432ee4379049336727ae3a1f9c4cb083114601c1140cee578376164d0e651217a9843f9fe83 + languageName: node + linkType: hard + +"arg@npm:5.0.2, arg@npm:^5.0.2": + version: 5.0.2 + resolution: "arg@npm:5.0.2" + checksum: 6c69ada1a9943d332d9e5382393e897c500908d91d5cb735a01120d5f71daf1b339b7b8980cbeaba8fd1afc68e658a739746179e4315a26e8a28951ff9930078 + languageName: node + linkType: hard + +"arg@npm:^4.1.0": + version: 4.1.3 + resolution: "arg@npm:4.1.3" + checksum: 544af8dd3f60546d3e4aff084d451b96961d2267d668670199692f8d054f0415d86fc5497d0e641e91546f0aa920e7c29e5250e99fc89f5552a34b5d93b77f43 + languageName: node + linkType: hard + +"argparse@npm:^1.0.7": + version: 1.0.10 + resolution: "argparse@npm:1.0.10" + dependencies: + sprintf-js: ~1.0.2 + checksum: 7ca6e45583a28de7258e39e13d81e925cfa25d7d4aacbf806a382d3c02fcb13403a07fb8aeef949f10a7cfe4a62da0e2e807b348a5980554cc28ee573ef95945 + languageName: node + linkType: hard + +"argparse@npm:^2.0.1": + version: 2.0.1 + resolution: "argparse@npm:2.0.1" + checksum: 83644b56493e89a254bae05702abf3a1101b4fa4d0ca31df1c9985275a5a5bd47b3c27b7fa0b71098d41114d8ca000e6ed90cad764b306f8a503665e4d517ced + languageName: node + linkType: hard + +"aria-query@npm:5.1.3, aria-query@npm:^5.0.0, aria-query@npm:^5.1.3": + version: 5.1.3 + resolution: "aria-query@npm:5.1.3" + dependencies: + deep-equal: ^2.0.5 + checksum: 929ff95f02857b650fb4cbcd2f41072eee2f46159a6605ea03bf63aa572e35ffdff43d69e815ddc462e16e07de8faba3978afc2813650b4448ee18c9895d982b + languageName: node + linkType: hard + +"array-flatten@npm:1.1.1": + version: 1.1.1 + resolution: "array-flatten@npm:1.1.1" + checksum: a9925bf3512d9dce202112965de90c222cd59a4fbfce68a0951d25d965cf44642931f40aac72309c41f12df19afa010ecadceb07cfff9ccc1621e99d89ab5f3b + languageName: node + linkType: hard + +"array-flatten@npm:^2.1.2": + version: 2.1.2 + resolution: "array-flatten@npm:2.1.2" + checksum: e8988aac1fbfcdaae343d08c9a06a6fddd2c6141721eeeea45c3cf523bf4431d29a46602929455ed548c7a3e0769928cdc630405427297e7081bd118fdec9262 + languageName: node + linkType: hard + +"array-includes@npm:^3.1.5, array-includes@npm:^3.1.6": + version: 3.1.6 + resolution: "array-includes@npm:3.1.6" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + get-intrinsic: ^1.1.3 + is-string: ^1.0.7 + checksum: f22f8cd8ba8a6448d91eebdc69f04e4e55085d09232b5216ee2d476dab3ef59984e8d1889e662c6a0ed939dcb1b57fd05b2c0209c3370942fc41b752c82a2ca5 + languageName: node + linkType: hard + +"array-union@npm:^2.1.0": + version: 2.1.0 + resolution: "array-union@npm:2.1.0" + checksum: 5bee12395cba82da674931df6d0fea23c4aa4660cb3b338ced9f828782a65caa232573e6bf3968f23e0c5eb301764a382cef2f128b170a9dc59de0e36c39f98d + languageName: node + linkType: hard + +"array.prototype.flat@npm:^1.3.1": + version: 1.3.1 + resolution: "array.prototype.flat@npm:1.3.1" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + es-shim-unscopables: ^1.0.0 + checksum: 5a8415949df79bf6e01afd7e8839bbde5a3581300e8ad5d8449dea52639e9e59b26a467665622783697917b43bf39940a6e621877c7dd9b3d1c1f97484b9b88b + languageName: node + linkType: hard + +"array.prototype.flatmap@npm:^1.3.1": + version: 1.3.1 + resolution: "array.prototype.flatmap@npm:1.3.1" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + es-shim-unscopables: ^1.0.0 + checksum: 8c1c43a4995f12cf12523436da28515184c753807b3f0bc2ca6c075f71c470b099e2090cc67dba8e5280958fea401c1d0c59e1db0143272aef6cd1103921a987 + languageName: node + linkType: hard + +"array.prototype.reduce@npm:^1.0.5": + version: 1.0.5 + resolution: "array.prototype.reduce@npm:1.0.5" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + es-array-method-boxes-properly: ^1.0.0 + is-string: ^1.0.7 + checksum: f44691395f9202aba5ec2446468d4c27209bfa81464f342ae024b7157dbf05b164e47cca01250b8c7c2a8219953fb57651cca16aab3d16f43b85c0d92c26eef3 + languageName: node + linkType: hard + +"array.prototype.tosorted@npm:^1.1.1": + version: 1.1.1 + resolution: "array.prototype.tosorted@npm:1.1.1" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + es-shim-unscopables: ^1.0.0 + get-intrinsic: ^1.1.3 + checksum: 7923324a67e70a2fc0a6e40237405d92395e45ebd76f5cb89c2a5cf1e66b47aca6baacd0cd628ffd88830b90d47fff268071493d09c9ae123645613dac2c2ca3 + languageName: node + linkType: hard + +"asap@npm:~2.0.6": + version: 2.0.6 + resolution: "asap@npm:2.0.6" + checksum: b296c92c4b969e973260e47523207cd5769abd27c245a68c26dc7a0fe8053c55bb04360237cb51cab1df52be939da77150ace99ad331fb7fb13b3423ed73ff3d + languageName: node + linkType: hard + +"asn1@npm:~0.2.3": + version: 0.2.6 + resolution: "asn1@npm:0.2.6" + dependencies: + safer-buffer: ~2.1.0 + checksum: 39f2ae343b03c15ad4f238ba561e626602a3de8d94ae536c46a4a93e69578826305366dc09fbb9b56aec39b4982a463682f259c38e59f6fa380cd72cd61e493d + languageName: node + linkType: hard + +"assert-plus@npm:1.0.0, assert-plus@npm:^1.0.0": + version: 1.0.0 + resolution: "assert-plus@npm:1.0.0" + checksum: 19b4340cb8f0e6a981c07225eacac0e9d52c2644c080198765d63398f0075f83bbc0c8e95474d54224e297555ad0d631c1dcd058adb1ddc2437b41a6b424ac64 + languageName: node + linkType: hard + +"ast-types-flow@npm:^0.0.7": + version: 0.0.7 + resolution: "ast-types-flow@npm:0.0.7" + checksum: a26dcc2182ffee111cad7c471759b0bda22d3b7ebacf27c348b22c55f16896b18ab0a4d03b85b4020dce7f3e634b8f00b593888f622915096ea1927fa51866c4 + languageName: node + linkType: hard + +"astral-regex@npm:^2.0.0": + version: 2.0.0 + resolution: "astral-regex@npm:2.0.0" + checksum: 876231688c66400473ba505731df37ea436e574dd524520294cc3bbc54ea40334865e01fa0d074d74d036ee874ee7e62f486ea38bc421ee8e6a871c06f011766 + languageName: node + linkType: hard + +"async@npm:^3.2.0, async@npm:^3.2.3": + version: 3.2.4 + resolution: "async@npm:3.2.4" + checksum: 43d07459a4e1d09b84a20772414aa684ff4de085cbcaec6eea3c7a8f8150e8c62aa6cd4e699fe8ee93c3a5b324e777d34642531875a0817a35697522c1b02e89 + languageName: node + linkType: hard + +"asynckit@npm:^0.4.0": + version: 0.4.0 + resolution: "asynckit@npm:0.4.0" + checksum: 7b78c451df768adba04e2d02e63e2d0bf3b07adcd6e42b4cf665cb7ce899bedd344c69a1dcbce355b5f972d597b25aaa1c1742b52cffd9caccb22f348114f6be + languageName: node + linkType: hard + +"at-least-node@npm:^1.0.0": + version: 1.0.0 + resolution: "at-least-node@npm:1.0.0" + checksum: 463e2f8e43384f1afb54bc68485c436d7622acec08b6fad269b421cb1d29cebb5af751426793d0961ed243146fe4dc983402f6d5a51b720b277818dbf6f2e49e + languageName: node + linkType: hard + +"autoprefixer@npm:^10.4.12, autoprefixer@npm:^10.4.13": + version: 10.4.13 + resolution: "autoprefixer@npm:10.4.13" + dependencies: + browserslist: ^4.21.4 + caniuse-lite: ^1.0.30001426 + fraction.js: ^4.2.0 + normalize-range: ^0.1.2 + picocolors: ^1.0.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.1.0 + bin: + autoprefixer: bin/autoprefixer + checksum: dcb1cb7ae96a3363d65d82e52f9a0a7d8c982256f6fd032d7e1ec311f099c23acfebfd517ff8e96bf93f716a66c4ea2b80c60aa19efd2f474ce434bd75ef7b79 + languageName: node + linkType: hard + +"available-typed-arrays@npm:^1.0.5": + version: 1.0.5 + resolution: "available-typed-arrays@npm:1.0.5" + checksum: 20eb47b3cefd7db027b9bbb993c658abd36d4edd3fe1060e83699a03ee275b0c9b216cc076ff3f2db29073225fb70e7613987af14269ac1fe2a19803ccc97f1a + languageName: node + linkType: hard + +"aws-sign2@npm:~0.7.0": + version: 0.7.0 + resolution: "aws-sign2@npm:0.7.0" + checksum: b148b0bb0778098ad8cf7e5fc619768bcb51236707ca1d3e5b49e41b171166d8be9fdc2ea2ae43d7decf02989d0aaa3a9c4caa6f320af95d684de9b548a71525 + languageName: node + linkType: hard + +"aws4@npm:^1.8.0": + version: 1.12.0 + resolution: "aws4@npm:1.12.0" + checksum: 68f79708ac7c335992730bf638286a3ee0a645cf12575d557860100767c500c08b30e24726b9f03265d74116417f628af78509e1333575e9f8d52a80edfe8cbc + languageName: node + linkType: hard + +"axe-core@npm:^4.6.2": + version: 4.6.3 + resolution: "axe-core@npm:4.6.3" + checksum: d0c46be92b9707c48b88a53cd5f471b155a2bfc8bf6beffb514ecd14e30b4863e340b5fc4f496d82a3c562048088c1f3ff5b93b9b3b026cb9c3bfacfd535da10 + languageName: node + linkType: hard + +"axios@npm:1.6.1": + version: 1.6.1 + resolution: "axios@npm:1.6.1" + dependencies: + follow-redirects: ^1.15.0 + form-data: ^4.0.0 + proxy-from-env: ^1.1.0 + checksum: 573f03f59b7487d54551b16f5e155d1d130ad4864ed32d1da93d522b78a57123b34e3bde37f822a65ee297e79f1db840f9ad6514addff50d3cbf5caeed39e8dc + languageName: node + linkType: hard + +"axios@npm:^0.27.2": + version: 0.27.2 + resolution: "axios@npm:0.27.2" + dependencies: + follow-redirects: ^1.14.9 + form-data: ^4.0.0 + checksum: 38cb7540465fe8c4102850c4368053c21683af85c5fdf0ea619f9628abbcb59415d1e22ebc8a6390d2bbc9b58a9806c874f139767389c862ec9b772235f06854 + languageName: node + linkType: hard + +"axobject-query@npm:^3.1.1": + version: 3.1.1 + resolution: "axobject-query@npm:3.1.1" + dependencies: + deep-equal: ^2.0.5 + checksum: c12a5da10dc7bab75e1cda9b6a3b5fcf10eba426ddf1a17b71ef65a434ed707ede7d1c4f013ba1609e970bc8c0cddac01365080d376204314e9b294719acd8a5 + languageName: node + linkType: hard + +"babel-jest@npm:^27.4.2, babel-jest@npm:^27.5.1": + version: 27.5.1 + resolution: "babel-jest@npm:27.5.1" + dependencies: + "@jest/transform": ^27.5.1 + "@jest/types": ^27.5.1 + "@types/babel__core": ^7.1.14 + babel-plugin-istanbul: ^6.1.1 + babel-preset-jest: ^27.5.1 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + slash: ^3.0.0 + peerDependencies: + "@babel/core": ^7.8.0 + checksum: 4e93e6e9fb996cc5f1505e924eb8e8cc7b25c294ba9629762a2715390f48af6a4c14dbb84cd9730013ac0e03267a5a9aa2fb6318c544489cda7f50f4e506def4 + languageName: node + linkType: hard + +"babel-loader@npm:^8.2.3": + version: 8.3.0 + resolution: "babel-loader@npm:8.3.0" + dependencies: + find-cache-dir: ^3.3.1 + loader-utils: ^2.0.0 + make-dir: ^3.1.0 + schema-utils: ^2.6.5 + peerDependencies: + "@babel/core": ^7.0.0 + webpack: ">=2" + checksum: d48bcf9e030e598656ad3ff5fb85967db2eaaf38af5b4a4b99d25618a2057f9f100e6b231af2a46c1913206db506115ca7a8cbdf52c9c73d767070dae4352ab5 + languageName: node + linkType: hard + +"babel-plugin-istanbul@npm:^6.1.1": + version: 6.1.1 + resolution: "babel-plugin-istanbul@npm:6.1.1" + dependencies: + "@babel/helper-plugin-utils": ^7.0.0 + "@istanbuljs/load-nyc-config": ^1.0.0 + "@istanbuljs/schema": ^0.1.2 + istanbul-lib-instrument: ^5.0.4 + test-exclude: ^6.0.0 + checksum: cb4fd95738219f232f0aece1116628cccff16db891713c4ccb501cddbbf9272951a5df81f2f2658dfdf4b3e7b236a9d5cbcf04d5d8c07dd5077297339598061a + languageName: node + linkType: hard + +"babel-plugin-jest-hoist@npm:^27.5.1": + version: 27.5.1 + resolution: "babel-plugin-jest-hoist@npm:27.5.1" + dependencies: + "@babel/template": ^7.3.3 + "@babel/types": ^7.3.3 + "@types/babel__core": ^7.0.0 + "@types/babel__traverse": ^7.0.6 + checksum: 709c17727aa8fd3be755d256fb514bf945a5c2ea6017f037d80280fc44ae5fe7dfeebf63d8412df53796455c2c216119d628d8cc90b099434fd819005943d058 + languageName: node + linkType: hard + +"babel-plugin-macros@npm:^3.1.0": + version: 3.1.0 + resolution: "babel-plugin-macros@npm:3.1.0" + dependencies: + "@babel/runtime": ^7.12.5 + cosmiconfig: ^7.0.0 + resolve: ^1.19.0 + checksum: 765de4abebd3e4688ebdfbff8571ddc8cd8061f839bb6c3e550b0344a4027b04c60491f843296ce3f3379fb356cc873d57a9ee6694262547eb822c14a25be9a6 + languageName: node + linkType: hard + +"babel-plugin-named-asset-import@npm:^0.3.8": + version: 0.3.8 + resolution: "babel-plugin-named-asset-import@npm:0.3.8" + peerDependencies: + "@babel/core": ^7.1.0 + checksum: d1e58df8cb75d91d070feea31087bc989906d3465144bde7e9f3c3690b514a90a55d3aebf3e65e76c5d4c743ecedde5f640f09f43a21fa60f1a5d413cb3f7a67 + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs2@npm:^0.3.3": + version: 0.3.3 + resolution: "babel-plugin-polyfill-corejs2@npm:0.3.3" + dependencies: + "@babel/compat-data": ^7.17.7 + "@babel/helper-define-polyfill-provider": ^0.3.3 + semver: ^6.1.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7db3044993f3dddb3cc3d407bc82e640964a3bfe22de05d90e1f8f7a5cb71460011ab136d3c03c6c1ba428359ebf635688cd6205e28d0469bba221985f5c6179 + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs3@npm:^0.6.0": + version: 0.6.0 + resolution: "babel-plugin-polyfill-corejs3@npm:0.6.0" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.3.3 + core-js-compat: ^3.25.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 470bb8c59f7c0912bd77fe1b5a2e72f349b3f65bbdee1d60d6eb7e1f4a085c6f24b2dd5ab4ac6c2df6444a96b070ef6790eccc9edb6a2668c60d33133bfb62c6 + languageName: node + linkType: hard + +"babel-plugin-polyfill-regenerator@npm:^0.4.1": + version: 0.4.1 + resolution: "babel-plugin-polyfill-regenerator@npm:0.4.1" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.3.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ab0355efbad17d29492503230387679dfb780b63b25408990d2e4cf421012dae61d6199ddc309f4d2409ce4e9d3002d187702700dd8f4f8770ebbba651ed066c + languageName: node + linkType: hard + +"babel-plugin-transform-react-remove-prop-types@npm:^0.4.24": + version: 0.4.24 + resolution: "babel-plugin-transform-react-remove-prop-types@npm:0.4.24" + checksum: 54afe56d67f0d118c9da23996f39948e502a152b3f582eb6e8f163fcb76c2c1ea4e0cdd4f9fac5c0ef050eab4fe0a950b0b74aae6237bcc0d31d8fc4cc808d1a + languageName: node + linkType: hard + +"babel-preset-current-node-syntax@npm:^1.0.0": + version: 1.0.1 + resolution: "babel-preset-current-node-syntax@npm:1.0.1" + dependencies: + "@babel/plugin-syntax-async-generators": ^7.8.4 + "@babel/plugin-syntax-bigint": ^7.8.3 + "@babel/plugin-syntax-class-properties": ^7.8.3 + "@babel/plugin-syntax-import-meta": ^7.8.3 + "@babel/plugin-syntax-json-strings": ^7.8.3 + "@babel/plugin-syntax-logical-assignment-operators": ^7.8.3 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + "@babel/plugin-syntax-numeric-separator": ^7.8.3 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + "@babel/plugin-syntax-top-level-await": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: d118c2742498c5492c095bc8541f4076b253e705b5f1ad9a2e7d302d81a84866f0070346662355c8e25fc02caa28dc2da8d69bcd67794a0d60c4d6fab6913cc8 + languageName: node + linkType: hard + +"babel-preset-jest@npm:^27.5.1": + version: 27.5.1 + resolution: "babel-preset-jest@npm:27.5.1" + dependencies: + babel-plugin-jest-hoist: ^27.5.1 + babel-preset-current-node-syntax: ^1.0.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 251bcea11c18fd9672fec104eadb45b43f117ceeb326fa7345ced778d4c1feab29343cd7a87a1dcfae4997d6c851a8b386d7f7213792da6e23b74f4443a8976d + languageName: node + linkType: hard + +"babel-preset-react-app@npm:^10.0.1": + version: 10.0.1 + resolution: "babel-preset-react-app@npm:10.0.1" + dependencies: + "@babel/core": ^7.16.0 + "@babel/plugin-proposal-class-properties": ^7.16.0 + "@babel/plugin-proposal-decorators": ^7.16.4 + "@babel/plugin-proposal-nullish-coalescing-operator": ^7.16.0 + "@babel/plugin-proposal-numeric-separator": ^7.16.0 + "@babel/plugin-proposal-optional-chaining": ^7.16.0 + "@babel/plugin-proposal-private-methods": ^7.16.0 + "@babel/plugin-transform-flow-strip-types": ^7.16.0 + "@babel/plugin-transform-react-display-name": ^7.16.0 + "@babel/plugin-transform-runtime": ^7.16.4 + "@babel/preset-env": ^7.16.4 + "@babel/preset-react": ^7.16.0 + "@babel/preset-typescript": ^7.16.0 + "@babel/runtime": ^7.16.3 + babel-plugin-macros: ^3.1.0 + babel-plugin-transform-react-remove-prop-types: ^0.4.24 + checksum: ee66043484e67b8aef2541976388299691478ea00834f3bb14b6b3d5edcd316a5ac95351f6ec084b41ee555cad820d4194280ad38ce51884fedc7e8946a57b74 + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 + languageName: node + linkType: hard + +"base64-js@npm:^1.3.1": + version: 1.5.1 + resolution: "base64-js@npm:1.5.1" + checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005 + languageName: node + linkType: hard + +"batch@npm:0.6.1": + version: 0.6.1 + resolution: "batch@npm:0.6.1" + checksum: 61f9934c7378a51dce61b915586191078ef7f1c3eca707fdd58b96ff2ff56d9e0af2bdab66b1462301a73c73374239e6542d9821c0af787f3209a23365d07e7f + languageName: node + linkType: hard + +"bcrypt-pbkdf@npm:^1.0.0": + version: 1.0.2 + resolution: "bcrypt-pbkdf@npm:1.0.2" + dependencies: + tweetnacl: ^0.14.3 + checksum: 4edfc9fe7d07019609ccf797a2af28351736e9d012c8402a07120c4453a3b789a15f2ee1530dc49eee8f7eb9379331a8dd4b3766042b9e502f74a68e7f662291 + languageName: node + linkType: hard + +"bfj@npm:^7.0.2": + version: 7.0.2 + resolution: "bfj@npm:7.0.2" + dependencies: + bluebird: ^3.5.5 + check-types: ^11.1.1 + hoopy: ^0.1.4 + tryer: ^1.0.1 + checksum: 0ca673234170eb3dcf00fb1d867ba274729ab05779dd19b35628c49da7adc32472b5f0bca0554ffdca15b094f9b36f16f2a8992ba8884ebd1d351d7f27abee7b + languageName: node + linkType: hard + +"big-integer@npm:^1.6.16": + version: 1.6.51 + resolution: "big-integer@npm:1.6.51" + checksum: 3d444173d1b2e20747e2c175568bedeebd8315b0637ea95d75fd27830d3b8e8ba36c6af40374f36bdaea7b5de376dcada1b07587cb2a79a928fccdb6e6e3c518 + languageName: node + linkType: hard + +"big.js@npm:^5.2.2": + version: 5.2.2 + resolution: "big.js@npm:5.2.2" + checksum: b89b6e8419b097a8fb4ed2399a1931a68c612bce3cfd5ca8c214b2d017531191070f990598de2fc6f3f993d91c0f08aa82697717f6b3b8732c9731866d233c9e + languageName: node + linkType: hard + +"binary-extensions@npm:^2.0.0": + version: 2.2.0 + resolution: "binary-extensions@npm:2.2.0" + checksum: ccd267956c58d2315f5d3ea6757cf09863c5fc703e50fbeb13a7dc849b812ef76e3cf9ca8f35a0c48498776a7478d7b4a0418e1e2b8cb9cb9731f2922aaad7f8 + languageName: node + linkType: hard + +"blob-polyfill@npm:7.0.20220408": + version: 7.0.20220408 + resolution: "blob-polyfill@npm:7.0.20220408" + checksum: bbd062e904d851b0e0a733265150d0c189a575f80a98256515d265e265ada6f92a787d43fedaa791c00910c174131f9d7168e8c158e3334c965d045358c177da + languageName: node + linkType: hard + +"blob-util@npm:^2.0.2": + version: 2.0.2 + resolution: "blob-util@npm:2.0.2" + checksum: d543e6b92e4ca715ca33c78e89a07a2290d43e5b2bc897d7ec588c5c7bbf59df93e45225ac0c9258aa6ce4320358990f99c9288f1c48280f8ec5d7a2e088d19b + languageName: node + linkType: hard + +"bluebird@npm:3.7.2, bluebird@npm:^3.5.5, bluebird@npm:^3.7.2": + version: 3.7.2 + resolution: "bluebird@npm:3.7.2" + checksum: 869417503c722e7dc54ca46715f70e15f4d9c602a423a02c825570862d12935be59ed9c7ba34a9b31f186c017c23cac6b54e35446f8353059c101da73eac22ef + languageName: node + linkType: hard + +"body-parser@npm:1.20.1": + version: 1.20.1 + resolution: "body-parser@npm:1.20.1" + dependencies: + bytes: 3.1.2 + content-type: ~1.0.4 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.1 + type-is: ~1.6.18 + unpipe: 1.0.0 + checksum: f1050dbac3bede6a78f0b87947a8d548ce43f91ccc718a50dd774f3c81f2d8b04693e52acf62659fad23101827dd318da1fb1363444ff9a8482b886a3e4a5266 + languageName: node + linkType: hard + +"body-parser@npm:1.20.2": + version: 1.20.2 + resolution: "body-parser@npm:1.20.2" + dependencies: + bytes: 3.1.2 + content-type: ~1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.2 + type-is: ~1.6.18 + unpipe: 1.0.0 + checksum: 14d37ec638ab5c93f6099ecaed7f28f890d222c650c69306872e00b9efa081ff6c596cd9afb9930656aae4d6c4e1c17537bea12bb73c87a217cb3cfea8896737 + languageName: node + linkType: hard + +"bonjour-service@npm:^1.0.11": + version: 1.1.0 + resolution: "bonjour-service@npm:1.1.0" + dependencies: + array-flatten: ^2.1.2 + dns-equal: ^1.0.0 + fast-deep-equal: ^3.1.3 + multicast-dns: ^7.2.5 + checksum: c0cdf6f6438ef4873ffd17768a9e62300ca30ac2bc3437bcfb6c75a3efd70ad80418c38ec19af2f5fe3a9f1dee725b83ff8e0c4a473b1b9f1718a39033b34cbf + languageName: node + linkType: hard + +"boolbase@npm:^1.0.0, boolbase@npm:~1.0.0": + version: 1.0.0 + resolution: "boolbase@npm:1.0.0" + checksum: 3e25c80ef626c3a3487c73dbfc70ac322ec830666c9ad915d11b701142fab25ec1e63eff2c450c74347acfd2de854ccde865cd79ef4db1683f7c7b046ea43bb0 + languageName: node + linkType: hard + +"boxen@npm:7.0.0": + version: 7.0.0 + resolution: "boxen@npm:7.0.0" + dependencies: + ansi-align: ^3.0.1 + camelcase: ^7.0.0 + chalk: ^5.0.1 + cli-boxes: ^3.0.0 + string-width: ^5.1.2 + type-fest: ^2.13.0 + widest-line: ^4.0.1 + wrap-ansi: ^8.0.1 + checksum: b917cf7a168ef3149635a8c02d5c9717d66182348bd27038d85328ad12655151e3324db0f2815253846c33e5f0ddf28b6cd52d56a12b9f88617b7f8f722b946a + languageName: node + linkType: hard + +"brace-expansion@npm:^1.1.7": + version: 1.1.11 + resolution: "brace-expansion@npm:1.1.11" + dependencies: + balanced-match: ^1.0.0 + concat-map: 0.0.1 + checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1": + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" + dependencies: + balanced-match: ^1.0.0 + checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 + languageName: node + linkType: hard + +"braces@npm:^3.0.2, braces@npm:~3.0.2": + version: 3.0.3 + resolution: "braces@npm:3.0.3" + dependencies: + fill-range: ^7.1.1 + checksum: b95aa0b3bd909f6cd1720ffcf031aeaf46154dd88b4da01f9a1d3f7ea866a79eba76a6d01cbc3c422b2ee5cdc39a4f02491058d5df0d7bf6e6a162a832df1f69 + languageName: node + linkType: hard + +"broadcast-channel@npm:^3.4.1": + version: 3.7.0 + resolution: "broadcast-channel@npm:3.7.0" + dependencies: + "@babel/runtime": ^7.7.2 + detect-node: ^2.1.0 + js-sha3: 0.8.0 + microseconds: 0.2.0 + nano-time: 1.0.0 + oblivious-set: 1.0.0 + rimraf: 3.0.2 + unload: 2.2.0 + checksum: 803794c48dcce7f03aca69797430bd8b1c4cfd70b7de22079cd89567eeffaa126a1db98c7c2d86af8131d9bb41ed367c0fef96dfb446151c927b831572c621fc + languageName: node + linkType: hard + +"browser-process-hrtime@npm:^1.0.0": + version: 1.0.0 + resolution: "browser-process-hrtime@npm:1.0.0" + checksum: e30f868cdb770b1201afb714ad1575dd86366b6e861900884665fb627109b3cc757c40067d3bfee1ff2a29c835257ea30725a8018a9afd02ac1c24b408b1e45f + languageName: node + linkType: hard + +"browserslist-config-single-spa@npm:^1.0.1": + version: 1.0.1 + resolution: "browserslist-config-single-spa@npm:1.0.1" + checksum: 7857db70f4733237caeef2022a3662cf373ee83ab813904aaa0ae40626666b4c5c72488aedb833e92b622c54154c3f452647f5e70499950d05898d81dc0f7109 + languageName: node + linkType: hard + +"browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.16.6, browserslist@npm:^4.18.1, browserslist@npm:^4.21.3, browserslist@npm:^4.21.4": + version: 4.21.4 + resolution: "browserslist@npm:4.21.4" + dependencies: + caniuse-lite: ^1.0.30001400 + electron-to-chromium: ^1.4.251 + node-releases: ^2.0.6 + update-browserslist-db: ^1.0.9 + bin: + browserslist: cli.js + checksum: 4af3793704dbb4615bcd29059ab472344dc7961c8680aa6c4bb84f05340e14038d06a5aead58724eae69455b8fade8b8c69f1638016e87e5578969d74c078b79 + languageName: node + linkType: hard + +"bser@npm:2.1.1": + version: 2.1.1 + resolution: "bser@npm:2.1.1" + dependencies: + node-int64: ^0.4.0 + checksum: 9ba4dc58ce86300c862bffc3ae91f00b2a03b01ee07f3564beeeaf82aa243b8b03ba53f123b0b842c190d4399b94697970c8e7cf7b1ea44b61aa28c3526a4449 + languageName: node + linkType: hard + +"buffer-crc32@npm:~0.2.3": + version: 0.2.13 + resolution: "buffer-crc32@npm:0.2.13" + checksum: 06252347ae6daca3453b94e4b2f1d3754a3b146a111d81c68924c22d91889a40623264e95e67955b1cb4a68cbedf317abeabb5140a9766ed248973096db5ce1c + languageName: node + linkType: hard + +"buffer-from@npm:^1.0.0": + version: 1.1.2 + resolution: "buffer-from@npm:1.1.2" + checksum: 0448524a562b37d4d7ed9efd91685a5b77a50672c556ea254ac9a6d30e3403a517d8981f10e565db24e8339413b43c97ca2951f10e399c6125a0d8911f5679bb + languageName: node + linkType: hard + +"buffer@npm:^5.6.0": + version: 5.7.1 + resolution: "buffer@npm:5.7.1" + dependencies: + base64-js: ^1.3.1 + ieee754: ^1.1.13 + checksum: e2cf8429e1c4c7b8cbd30834ac09bd61da46ce35f5c22a78e6c2f04497d6d25541b16881e30a019c6fd3154150650ccee27a308eff3e26229d788bbdeb08ab84 + languageName: node + linkType: hard + +"builtin-modules@npm:^3.1.0": + version: 3.3.0 + resolution: "builtin-modules@npm:3.3.0" + checksum: db021755d7ed8be048f25668fe2117620861ef6703ea2c65ed2779c9e3636d5c3b82325bd912244293959ff3ae303afa3471f6a15bf5060c103e4cc3a839749d + languageName: node + linkType: hard + +"bytes@npm:3.0.0": + version: 3.0.0 + resolution: "bytes@npm:3.0.0" + checksum: a2b386dd8188849a5325f58eef69c3b73c51801c08ffc6963eddc9be244089ba32d19347caf6d145c86f315ae1b1fc7061a32b0c1aa6379e6a719090287ed101 + languageName: node + linkType: hard + +"bytes@npm:3.1.2": + version: 3.1.2 + resolution: "bytes@npm:3.1.2" + checksum: e4bcd3948d289c5127591fbedf10c0b639ccbf00243504e4e127374a15c3bc8eed0d28d4aaab08ff6f1cf2abc0cce6ba3085ed32f4f90e82a5683ce0014e1b6e + languageName: node + linkType: hard + +"cacache@npm:^16.1.0": + version: 16.1.3 + resolution: "cacache@npm:16.1.3" + dependencies: + "@npmcli/fs": ^2.1.0 + "@npmcli/move-file": ^2.0.0 + chownr: ^2.0.0 + fs-minipass: ^2.1.0 + glob: ^8.0.1 + infer-owner: ^1.0.4 + lru-cache: ^7.7.1 + minipass: ^3.1.6 + minipass-collect: ^1.0.2 + minipass-flush: ^1.0.5 + minipass-pipeline: ^1.2.4 + mkdirp: ^1.0.4 + p-map: ^4.0.0 + promise-inflight: ^1.0.1 + rimraf: ^3.0.2 + ssri: ^9.0.0 + tar: ^6.1.11 + unique-filename: ^2.0.0 + checksum: d91409e6e57d7d9a3a25e5dcc589c84e75b178ae8ea7de05cbf6b783f77a5fae938f6e8fda6f5257ed70000be27a681e1e44829251bfffe4c10216002f8f14e6 + languageName: node + linkType: hard + +"cachedir@npm:^2.3.0": + version: 2.3.0 + resolution: "cachedir@npm:2.3.0" + checksum: ec90cb0f2e6336e266aa748dbadf3da9e0b20e843e43f1591acab7a3f1451337dc2f26cb9dd833ae8cfefeffeeb43ef5b5ff62782a685f4e3c2305dd98482fcb + languageName: node + linkType: hard + +"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2": + version: 1.0.2 + resolution: "call-bind@npm:1.0.2" + dependencies: + function-bind: ^1.1.1 + get-intrinsic: ^1.0.2 + checksum: f8e31de9d19988a4b80f3e704788c4a2d6b6f3d17cfec4f57dc29ced450c53a49270dc66bf0fbd693329ee948dd33e6c90a329519aef17474a4d961e8d6426b0 + languageName: node + linkType: hard + +"callsites@npm:^3.0.0": + version: 3.1.0 + resolution: "callsites@npm:3.1.0" + checksum: 072d17b6abb459c2ba96598918b55868af677154bec7e73d222ef95a8fdb9bbf7dae96a8421085cdad8cd190d86653b5b6dc55a4484f2e5b2e27d5e0c3fc15b3 + languageName: node + linkType: hard + +"camel-case@npm:^4.1.2": + version: 4.1.2 + resolution: "camel-case@npm:4.1.2" + dependencies: + pascal-case: ^3.1.2 + tslib: ^2.0.3 + checksum: bcbd25cd253b3cbc69be3f535750137dbf2beb70f093bdc575f73f800acc8443d34fd52ab8f0a2413c34f1e8203139ffc88428d8863e4dfe530cfb257a379ad6 + languageName: node + linkType: hard + +"camelcase-css@npm:^2.0.1": + version: 2.0.1 + resolution: "camelcase-css@npm:2.0.1" + checksum: 1cec2b3b3dcb5026688a470b00299a8db7d904c4802845c353dbd12d9d248d3346949a814d83bfd988d4d2e5b9904c07efe76fecd195a1d4f05b543e7c0b56b1 + languageName: node + linkType: hard + +"camelcase@npm:^5.3.1": + version: 5.3.1 + resolution: "camelcase@npm:5.3.1" + checksum: e6effce26b9404e3c0f301498184f243811c30dfe6d0b9051863bd8e4034d09c8c2923794f280d6827e5aa055f6c434115ff97864a16a963366fb35fd673024b + languageName: node + linkType: hard + +"camelcase@npm:^6.2.0, camelcase@npm:^6.2.1": + version: 6.3.0 + resolution: "camelcase@npm:6.3.0" + checksum: 8c96818a9076434998511251dcb2761a94817ea17dbdc37f47ac080bd088fc62c7369429a19e2178b993497132c8cbcf5cc1f44ba963e76782ba469c0474938d + languageName: node + linkType: hard + +"camelcase@npm:^7.0.0": + version: 7.0.1 + resolution: "camelcase@npm:7.0.1" + checksum: 86ab8f3ebf08bcdbe605a211a242f00ed30d8bfb77dab4ebb744dd36efbc84432d1c4adb28975ba87a1b8be40a80fbd1e60e2f06565315918fa7350011a26d3d + languageName: node + linkType: hard + +"caniuse-api@npm:^3.0.0": + version: 3.0.0 + resolution: "caniuse-api@npm:3.0.0" + dependencies: + browserslist: ^4.0.0 + caniuse-lite: ^1.0.0 + lodash.memoize: ^4.1.2 + lodash.uniq: ^4.5.0 + checksum: db2a229383b20d0529b6b589dde99d7b6cb56ba371366f58cbbfa2929c9f42c01f873e2b6ef641d4eda9f0b4118de77dbb2805814670bdad4234bf08e720b0b4 + languageName: node + linkType: hard + +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001400, caniuse-lite@npm:^1.0.30001426": + version: 1.0.30001449 + resolution: "caniuse-lite@npm:1.0.30001449" + checksum: f1b395f0a5495c1931c53f58441e0db79b8b0f8ef72bb6d241d13c49b05827630efe6793d540610e0a014d8fdda330dd42f981c82951bd4bdcf635480e1a0102 + languageName: node + linkType: hard + +"case-sensitive-paths-webpack-plugin@npm:^2.4.0": + version: 2.4.0 + resolution: "case-sensitive-paths-webpack-plugin@npm:2.4.0" + checksum: bcf469446eeee9ac0046e30860074ebb9aa4803aab9140e6bb72b600b23b1d70635690754be4504ce35cd99cdf05226bee8d894ba362a3f5485d5f6310fc6d02 + languageName: node + linkType: hard + +"caseless@npm:~0.12.0": + version: 0.12.0 + resolution: "caseless@npm:0.12.0" + checksum: b43bd4c440aa1e8ee6baefee8063b4850fd0d7b378f6aabc796c9ec8cb26d27fb30b46885350777d9bd079c5256c0e1329ad0dc7c2817e0bb466810ebb353751 + languageName: node + linkType: hard + +"chalk-template@npm:0.4.0": + version: 0.4.0 + resolution: "chalk-template@npm:0.4.0" + dependencies: + chalk: ^4.1.2 + checksum: 6c706802a79a7963cbce18f022b046fe86e438a67843151868852f80ea7346e975a6a9749991601e7e5d3b6a6c4852a04c53dc966a9a3d04031bd0e0ed53c819 + languageName: node + linkType: hard + +"chalk@npm:5.0.1": + version: 5.0.1 + resolution: "chalk@npm:5.0.1" + checksum: 7b45300372b908f0471fbf7389ce2f5de8d85bb949026fd51a1b95b10d0ed32c7ed5aab36dd5e9d2bf3191867909b4404cef75c5f4d2d1daeeacd301dd280b76 + languageName: node + linkType: hard + +"chalk@npm:5.3.0, chalk@npm:^5.0.1": + version: 5.3.0 + resolution: "chalk@npm:5.3.0" + checksum: 623922e077b7d1e9dedaea6f8b9e9352921f8ae3afe739132e0e00c275971bdd331268183b2628cf4ab1727c45ea1f28d7e24ac23ce1db1eb653c414ca8a5a80 + languageName: node + linkType: hard + +"chalk@npm:^2.3.0, chalk@npm:^2.4.1, chalk@npm:^2.4.2": + version: 2.4.2 + resolution: "chalk@npm:2.4.2" + dependencies: + ansi-styles: ^3.2.1 + escape-string-regexp: ^1.0.5 + supports-color: ^5.3.0 + checksum: ec3661d38fe77f681200f878edbd9448821924e0f93a9cefc0e26a33b145f1027a2084bf19967160d11e1f03bfe4eaffcabf5493b89098b2782c3fe0b03d80c2 + languageName: node + linkType: hard + +"chalk@npm:^3.0.0": + version: 3.0.0 + resolution: "chalk@npm:3.0.0" + dependencies: + ansi-styles: ^4.1.0 + supports-color: ^7.1.0 + checksum: 8e3ddf3981c4da405ddbd7d9c8d91944ddf6e33d6837756979f7840a29272a69a5189ecae0ff84006750d6d1e92368d413335eab4db5476db6e6703a1d1e0505 + languageName: node + linkType: hard + +"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0, chalk@npm:^4.1.2": + version: 4.1.2 + resolution: "chalk@npm:4.1.2" + dependencies: + ansi-styles: ^4.1.0 + supports-color: ^7.1.0 + checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc + languageName: node + linkType: hard + +"char-regex@npm:^1.0.2": + version: 1.0.2 + resolution: "char-regex@npm:1.0.2" + checksum: b563e4b6039b15213114626621e7a3d12f31008bdce20f9c741d69987f62aeaace7ec30f6018890ad77b2e9b4d95324c9f5acfca58a9441e3b1dcdd1e2525d17 + languageName: node + linkType: hard + +"char-regex@npm:^2.0.0": + version: 2.0.1 + resolution: "char-regex@npm:2.0.1" + checksum: 8524c03fd7e58381dccf33babe885fe62731ae20755528b19c39945b8203479184f35247210dc9eeeef279cdbdd6511cd3182e0e1db8e4549bf2586470b7c204 + languageName: node + linkType: hard + +"check-more-types@npm:2.24.0, check-more-types@npm:^2.24.0": + version: 2.24.0 + resolution: "check-more-types@npm:2.24.0" + checksum: b09080ec3404d20a4b0ead828994b2e5913236ef44ed3033a27062af0004cf7d2091fbde4b396bf13b7ce02fb018bc9960b48305e6ab2304cd82d73ed7a51ef4 + languageName: node + linkType: hard + +"check-types@npm:^11.1.1": + version: 11.2.2 + resolution: "check-types@npm:11.2.2" + checksum: 61ed60d59e3397c8cf694f20edf73d0061cd6a905754efdec2ccdceafbd390cb09717bab855f9eba921d36278f84c86fe20f7e731a384e9803bc469c09153831 + languageName: node + linkType: hard + +"chokidar@npm:^3.4.2, chokidar@npm:^3.5.3": + version: 3.5.3 + resolution: "chokidar@npm:3.5.3" + dependencies: + 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 + dependenciesMeta: + fsevents: + optional: true + checksum: b49fcde40176ba007ff361b198a2d35df60d9bb2a5aab228279eb810feae9294a6b4649ab15981304447afe1e6ffbf4788ad5db77235dc770ab777c6e771980c + languageName: node + linkType: hard + +"chownr@npm:^2.0.0": + version: 2.0.0 + resolution: "chownr@npm:2.0.0" + checksum: c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f + languageName: node + linkType: hard + +"chrome-trace-event@npm:^1.0.2": + version: 1.0.3 + resolution: "chrome-trace-event@npm:1.0.3" + checksum: cb8b1fc7e881aaef973bd0c4a43cd353c2ad8323fb471a041e64f7c2dd849cde4aad15f8b753331a32dda45c973f032c8a03b8177fc85d60eaa75e91e08bfb97 + languageName: node + linkType: hard + +"ci-info@npm:^3.2.0": + version: 3.7.1 + resolution: "ci-info@npm:3.7.1" + checksum: 72d93d5101ea1c186511277fbd8d06ae8a6e028cc2fb94361e92bf735b39c5ebd192e8d15a66ff8c4e3ed569f87c2f844e96f90e141b2de5c649f77ec34ff601 + languageName: node + linkType: hard + +"cjs-module-lexer@npm:^1.0.0": + version: 1.2.2 + resolution: "cjs-module-lexer@npm:1.2.2" + checksum: 977f3f042bd4f08e368c890d91eecfbc4f91da0bc009a3c557bc4dfbf32022ad1141244ac1178d44de70fc9f3dea7add7cd9a658a34b9fae98a55d8f92331ce5 + languageName: node + linkType: hard + +"classnames@npm:^2.2.5": + version: 2.3.2 + resolution: "classnames@npm:2.3.2" + checksum: 2c62199789618d95545c872787137262e741f9db13328e216b093eea91c85ef2bfb152c1f9e63027204e2559a006a92eb74147d46c800a9f96297ae1d9f96f4e + languageName: node + linkType: hard + +"clean-css@npm:^5.2.2": + version: 5.3.2 + resolution: "clean-css@npm:5.3.2" + dependencies: + source-map: ~0.6.0 + checksum: 8787b281acc9878f309b5f835d410085deedfd4e126472666773040a6a8a72f472a1d24185947d23b87b1c419bf2c5ed429395d5c5ff8279c98b05d8011e9758 + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 + languageName: node + linkType: hard + +"cli-boxes@npm:^3.0.0": + version: 3.0.0 + resolution: "cli-boxes@npm:3.0.0" + checksum: 637d84419d293a9eac40a1c8c96a2859e7d98b24a1a317788e13c8f441be052fc899480c6acab3acc82eaf1bccda6b7542d7cdcf5c9c3cc39227175dc098d5b2 + languageName: node + linkType: hard + +"cli-cursor@npm:^3.1.0": + version: 3.1.0 + resolution: "cli-cursor@npm:3.1.0" + dependencies: + restore-cursor: ^3.1.0 + checksum: 2692784c6cd2fd85cfdbd11f53aea73a463a6d64a77c3e098b2b4697a20443f430c220629e1ca3b195ea5ac4a97a74c2ee411f3807abf6df2b66211fec0c0a29 + languageName: node + linkType: hard + +"cli-cursor@npm:^4.0.0": + version: 4.0.0 + resolution: "cli-cursor@npm:4.0.0" + dependencies: + restore-cursor: ^4.0.0 + checksum: ab3f3ea2076e2176a1da29f9d64f72ec3efad51c0960898b56c8a17671365c26e67b735920530eaf7328d61f8bd41c27f46b9cf6e4e10fe2fa44b5e8c0e392cc + languageName: node + linkType: hard + +"cli-table3@npm:~0.6.1": + version: 0.6.3 + resolution: "cli-table3@npm:0.6.3" + dependencies: + "@colors/colors": 1.5.0 + string-width: ^4.2.0 + dependenciesMeta: + "@colors/colors": + optional: true + checksum: 09897f68467973f827c04e7eaadf13b55f8aec49ecd6647cc276386ea660059322e2dd8020a8b6b84d422dbdd619597046fa89cbbbdc95b2cea149a2df7c096c + languageName: node + linkType: hard + +"cli-truncate@npm:^2.1.0": + version: 2.1.0 + resolution: "cli-truncate@npm:2.1.0" + dependencies: + slice-ansi: ^3.0.0 + string-width: ^4.2.0 + checksum: bf1e4e6195392dc718bf9cd71f317b6300dc4a9191d052f31046b8773230ece4fa09458813bf0e3455a5e68c0690d2ea2c197d14a8b85a7b5e01c97f4b5feb5d + languageName: node + linkType: hard + +"cli-truncate@npm:^3.1.0": + version: 3.1.0 + resolution: "cli-truncate@npm:3.1.0" + dependencies: + slice-ansi: ^5.0.0 + string-width: ^5.0.0 + checksum: c3243e41974445691c63f8b405df1d5a24049dc33d324fe448dc572e561a7b772ae982692900b1a5960901cc4fc7def25a629b9c69a4208ee89d12ab3332617a + languageName: node + linkType: hard + +"clipboardy@npm:3.0.0": + version: 3.0.0 + resolution: "clipboardy@npm:3.0.0" + dependencies: + arch: ^2.2.0 + execa: ^5.1.1 + is-wsl: ^2.2.0 + checksum: 2c292acb59705494cbe07d7df7c8becff4f01651514d32ebd80f4aec2d20946d8f3824aac67ecdf2d09ef21fdf0eb24b6a7f033c137ccdceedc4661c54455c94 + languageName: node + linkType: hard + +"cliui@npm:^7.0.2": + version: 7.0.4 + resolution: "cliui@npm:7.0.4" + dependencies: + string-width: ^4.2.0 + strip-ansi: ^6.0.0 + wrap-ansi: ^7.0.0 + checksum: ce2e8f578a4813806788ac399b9e866297740eecd4ad1823c27fd344d78b22c5f8597d548adbcc46f0573e43e21e751f39446c5a5e804a12aace402b7a315d7f + languageName: node + linkType: hard + +"clone-deep@npm:^4.0.1": + version: 4.0.1 + resolution: "clone-deep@npm:4.0.1" + dependencies: + is-plain-object: ^2.0.4 + kind-of: ^6.0.2 + shallow-clone: ^3.0.0 + checksum: 770f912fe4e6f21873c8e8fbb1e99134db3b93da32df271d00589ea4a29dbe83a9808a322c93f3bcaf8584b8b4fa6fc269fc8032efbaa6728e0c9886c74467d2 + languageName: node + linkType: hard + +"clsx@npm:^1.0.4, clsx@npm:^1.2.1": + version: 1.2.1 + resolution: "clsx@npm:1.2.1" + checksum: 30befca8019b2eb7dbad38cff6266cf543091dae2825c856a62a8ccf2c3ab9c2907c4d12b288b73101196767f66812365400a227581484a05f968b0307cfaf12 + languageName: node + linkType: hard + +"clsx@npm:^2.0.0": + version: 2.0.0 + resolution: "clsx@npm:2.0.0" + checksum: a2cfb2351b254611acf92faa0daf15220f4cd648bdf96ce369d729813b85336993871a4bf6978ddea2b81b5a130478339c20d9d0b5c6fc287e5147f0c059276e + languageName: node + linkType: hard + +"co@npm:^4.6.0": + version: 4.6.0 + resolution: "co@npm:4.6.0" + checksum: 5210d9223010eb95b29df06a91116f2cf7c8e0748a9013ed853b53f362ea0e822f1e5bb054fb3cefc645239a4cf966af1f6133a3b43f40d591f3b68ed6cf0510 + languageName: node + linkType: hard + +"coa@npm:^2.0.2": + version: 2.0.2 + resolution: "coa@npm:2.0.2" + dependencies: + "@types/q": ^1.5.1 + chalk: ^2.4.1 + q: ^1.1.2 + checksum: 44736914aac2160d3d840ed64432a90a3bb72285a0cd6a688eb5cabdf15d15a85eee0915b3f6f2a4659d5075817b1cb577340d3c9cbb47d636d59ab69f819552 + languageName: node + linkType: hard + +"collect-v8-coverage@npm:^1.0.0": + version: 1.0.1 + resolution: "collect-v8-coverage@npm:1.0.1" + checksum: 4efe0a1fccd517b65478a2364b33dadd0a43fc92a56f59aaece9b6186fe5177b2de471253587de7c91516f07c7268c2f6770b6cbcffc0e0ece353b766ec87e55 + languageName: node + linkType: hard + +"color-convert@npm:^1.9.0": + version: 1.9.3 + resolution: "color-convert@npm:1.9.3" + dependencies: + color-name: 1.1.3 + checksum: fd7a64a17cde98fb923b1dd05c5f2e6f7aefda1b60d67e8d449f9328b4e53b228a428fd38bfeaeb2db2ff6b6503a776a996150b80cdf224062af08a5c8a3a203 + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: ~1.1.4 + checksum: 79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336 + languageName: node + linkType: hard + +"color-name@npm:1.1.3": + version: 1.1.3 + resolution: "color-name@npm:1.1.3" + checksum: 09c5d3e33d2105850153b14466501f2bfb30324a2f76568a408763a3b7433b0e50e5b4ab1947868e65cb101bb7cb75029553f2c333b6d4b8138a73fcc133d69d + languageName: node + linkType: hard + +"color-name@npm:^1.1.4, color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 + languageName: node + linkType: hard + +"color-support@npm:^1.1.3": + version: 1.1.3 + resolution: "color-support@npm:1.1.3" + bin: + color-support: bin.js + checksum: 9b7356817670b9a13a26ca5af1c21615463b500783b739b7634a0c2047c16cef4b2865d7576875c31c3cddf9dd621fa19285e628f20198b233a5cfdda6d0793b + languageName: node + linkType: hard + +"colord@npm:^2.9.1": + version: 2.9.3 + resolution: "colord@npm:2.9.3" + checksum: 95d909bfbcfd8d5605cbb5af56f2d1ce2b323990258fd7c0d2eb0e6d3bb177254d7fb8213758db56bb4ede708964f78c6b992b326615f81a18a6aaf11d64c650 + languageName: node + linkType: hard + +"colorette@npm:^2.0.10, colorette@npm:^2.0.16, colorette@npm:^2.0.20": + version: 2.0.20 + resolution: "colorette@npm:2.0.20" + checksum: 0c016fea2b91b733eb9f4bcdb580018f52c0bc0979443dad930e5037a968237ac53d9beb98e218d2e9235834f8eebce7f8e080422d6194e957454255bde71d3d + languageName: node + linkType: hard + +"combined-stream@npm:^1.0.6, combined-stream@npm:^1.0.8, combined-stream@npm:~1.0.6": + version: 1.0.8 + resolution: "combined-stream@npm:1.0.8" + dependencies: + delayed-stream: ~1.0.0 + checksum: 49fa4aeb4916567e33ea81d088f6584749fc90c7abec76fd516bf1c5aa5c79f3584b5ba3de6b86d26ddd64bae5329c4c7479343250cfe71c75bb366eae53bb7c + languageName: node + linkType: hard + +"commander@npm:11.0.0": + version: 11.0.0 + resolution: "commander@npm:11.0.0" + checksum: 6621954e1e1d078b4991c1f5bbd9439ad37aa7768d6ab4842de1dbd4d222c8a27e1b8e62108b3a92988614af45031d5bb2a2aaa92951f4d0c934d1a1ac564bb4 + languageName: node + linkType: hard + +"commander@npm:^2.20.0": + version: 2.20.3 + resolution: "commander@npm:2.20.3" + checksum: ab8c07884e42c3a8dbc5dd9592c606176c7eb5c1ca5ff274bcf907039b2c41de3626f684ea75ccf4d361ba004bbaff1f577d5384c155f3871e456bdf27becf9e + languageName: node + linkType: hard + +"commander@npm:^6.2.1": + version: 6.2.1 + resolution: "commander@npm:6.2.1" + checksum: d7090410c0de6bc5c67d3ca41c41760d6d268f3c799e530aafb73b7437d1826bbf0d2a3edac33f8b57cc9887b4a986dce307fa5557e109be40eadb7c43b21742 + languageName: node + linkType: hard + +"commander@npm:^7.2.0": + version: 7.2.0 + resolution: "commander@npm:7.2.0" + checksum: 53501cbeee61d5157546c0bef0fedb6cdfc763a882136284bed9a07225f09a14b82d2a84e7637edfd1a679fb35ed9502fd58ef1d091e6287f60d790147f68ddc + languageName: node + linkType: hard + +"commander@npm:^8.3.0": + version: 8.3.0 + resolution: "commander@npm:8.3.0" + checksum: 0f82321821fc27b83bd409510bb9deeebcfa799ff0bf5d102128b500b7af22872c0c92cb6a0ebc5a4cf19c6b550fba9cedfa7329d18c6442a625f851377bacf0 + languageName: node + linkType: hard + +"common-path-prefix@npm:^3.0.0": + version: 3.0.0 + resolution: "common-path-prefix@npm:3.0.0" + checksum: fdb3c4f54e51e70d417ccd950c07f757582de800c0678ca388aedefefc84982039f346f9fd9a1252d08d2da9e9ef4019f580a1d1d3a10da031e4bb3c924c5818 + languageName: node + linkType: hard + +"common-tags@npm:^1.8.0": + version: 1.8.2 + resolution: "common-tags@npm:1.8.2" + checksum: 767a6255a84bbc47df49a60ab583053bb29a7d9687066a18500a516188a062c4e4cd52de341f22de0b07062e699b1b8fe3cfa1cb55b241cb9301aeb4f45b4dff + languageName: node + linkType: hard + +"commondir@npm:^1.0.1": + version: 1.0.1 + resolution: "commondir@npm:1.0.1" + checksum: 59715f2fc456a73f68826285718503340b9f0dd89bfffc42749906c5cf3d4277ef11ef1cca0350d0e79204f00f1f6d83851ececc9095dc88512a697ac0b9bdcb + languageName: node + linkType: hard + +"compressible@npm:~2.0.16": + version: 2.0.18 + resolution: "compressible@npm:2.0.18" + dependencies: + mime-db: ">= 1.43.0 < 2" + checksum: 58321a85b375d39230405654721353f709d0c1442129e9a17081771b816302a012471a9b8f4864c7dbe02eef7f2aaac3c614795197092262e94b409c9be108f0 + languageName: node + linkType: hard + +"compression@npm:1.7.4, compression@npm:^1.7.4": + version: 1.7.4 + resolution: "compression@npm:1.7.4" + 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 + checksum: 35c0f2eb1f28418978615dc1bc02075b34b1568f7f56c62d60f4214d4b7cc00d0f6d282b5f8a954f59872396bd770b6b15ffd8aa94c67d4bce9b8887b906999b + languageName: node + linkType: hard + +"concat-map@npm:0.0.1": + version: 0.0.1 + resolution: "concat-map@npm:0.0.1" + checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af + languageName: node + linkType: hard + +"confusing-browser-globals@npm:^1.0.11": + version: 1.0.11 + resolution: "confusing-browser-globals@npm:1.0.11" + checksum: 3afc635abd37e566477f610e7978b15753f0e84025c25d49236f1f14d480117185516bdd40d2a2167e6bed8048641a9854964b9c067e3dcdfa6b5d0ad3c3a5ef + languageName: node + linkType: hard + +"connect-history-api-fallback@npm:^2.0.0": + version: 2.0.0 + resolution: "connect-history-api-fallback@npm:2.0.0" + checksum: dc5368690f4a5c413889792f8df70d5941ca9da44523cde3f87af0745faee5ee16afb8195434550f0504726642734f2683d6c07f8b460f828a12c45fbd4c9a68 + languageName: node + linkType: hard + +"connected-react-router@npm:6.9.1": + version: 6.9.1 + resolution: "connected-react-router@npm:6.9.1" + dependencies: + immutable: ^3.8.1 || ^4.0.0-rc.1 + lodash.isequalwith: ^4.4.0 + prop-types: ^15.7.2 + seamless-immutable: ^7.1.3 + peerDependencies: + history: ^4.7.2 + react: ^16.4.0 || ^17.0.0 + react-redux: ^6.0.0 || ^7.1.0 + react-router: ^4.3.1 || ^5.0.0 + redux: ^3.6.0 || ^4.0.0 + dependenciesMeta: + immutable: + optional: true + seamless-immutable: + optional: true + checksum: 9657f76f7bbc660df8e668973898129a47e5d89d81619e2b0c1a210e84f14df6539cf36f3d4041b775dfc34fbede47289cee3e1ed2a718530c672314986e173e + languageName: node + linkType: hard + +"console-control-strings@npm:^1.1.0": + version: 1.1.0 + resolution: "console-control-strings@npm:1.1.0" + checksum: 8755d76787f94e6cf79ce4666f0c5519906d7f5b02d4b884cf41e11dcd759ed69c57da0670afd9236d229a46e0f9cf519db0cd829c6dca820bb5a5c3def584ed + languageName: node + linkType: hard + +"content-disposition@npm:0.5.2": + version: 0.5.2 + resolution: "content-disposition@npm:0.5.2" + checksum: 298d7da63255a38f7858ee19c7b6aae32b167e911293174b4c1349955e97e78e1d0b0d06c10e229405987275b417cf36ff65cbd4821a98bc9df4e41e9372cde7 + languageName: node + linkType: hard + +"content-disposition@npm:0.5.4": + version: 0.5.4 + resolution: "content-disposition@npm:0.5.4" + dependencies: + safe-buffer: 5.2.1 + checksum: afb9d545e296a5171d7574fcad634b2fdf698875f4006a9dd04a3e1333880c5c0c98d47b560d01216fb6505a54a2ba6a843ee3a02ec86d7e911e8315255f56c3 + languageName: node + linkType: hard + +"content-type@npm:~1.0.4, content-type@npm:~1.0.5": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 566271e0a251642254cde0f845f9dd4f9856e52d988f4eb0d0dcffbb7a1f8ec98de7a5215fc628f3bce30fe2fb6fd2bc064b562d721658c59b544e2d34ea2766 + languageName: node + linkType: hard + +"convert-source-map@npm:^1.4.0, convert-source-map@npm:^1.5.0, convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": + version: 1.9.0 + resolution: "convert-source-map@npm:1.9.0" + checksum: dc55a1f28ddd0e9485ef13565f8f756b342f9a46c4ae18b843fe3c30c675d058d6a4823eff86d472f187b176f0adf51ea7b69ea38be34be4a63cbbf91b0593c8 + languageName: node + linkType: hard + +"cookie-signature@npm:1.0.6": + version: 1.0.6 + resolution: "cookie-signature@npm:1.0.6" + checksum: f4e1b0a98a27a0e6e66fd7ea4e4e9d8e038f624058371bf4499cfcd8f3980be9a121486995202ba3fca74fbed93a407d6d54d43a43f96fd28d0bd7a06761591a + languageName: node + linkType: hard + +"cookie@npm:0.5.0": + version: 0.5.0 + resolution: "cookie@npm:0.5.0" + checksum: 1f4bd2ca5765f8c9689a7e8954183f5332139eb72b6ff783d8947032ec1fdf43109852c178e21a953a30c0dd42257828185be01b49d1eb1a67fd054ca588a180 + languageName: node + linkType: hard + +"cookie@npm:0.6.0": + version: 0.6.0 + resolution: "cookie@npm:0.6.0" + checksum: f56a7d32a07db5458e79c726b77e3c2eff655c36792f2b6c58d351fb5f61531e5b1ab7f46987150136e366c65213cbe31729e02a3eaed630c3bf7334635fb410 + languageName: node + linkType: hard + +"core-js-compat@npm:^3.25.1": + version: 3.27.2 + resolution: "core-js-compat@npm:3.27.2" + dependencies: + browserslist: ^4.21.4 + checksum: 4574d4507de8cba9a75e37401b3ca6e5908ab066ec717e3b34866d25f623e1aa614fb886e10973be64a6250f325dcba6809e4fae4ed43375cc3e4276c5514c13 + languageName: node + linkType: hard + +"core-js-pure@npm:^3.23.3": + version: 3.27.2 + resolution: "core-js-pure@npm:3.27.2" + checksum: 7cb24502a782a032ffa2af6e84abfcfeffa0c30e84c38f4d0a1d7567c8c86e2d36a7554a00ca47762606c84d2a86d99662a7158e9f4df989f3fe3c7e7c09fa45 + languageName: node + linkType: hard + +"core-js@npm:^3.19.2": + version: 3.27.2 + resolution: "core-js@npm:3.27.2" + checksum: 718debd426f55a6b97cf9b757c936be258afd6d4f7052f89d0f96c982d7013e9000b0b006df42831a0cf32adad298e34d6a19052dce9ae1c7ab87162c0c665e0 + languageName: node + linkType: hard + +"core-util-is@npm:1.0.2": + version: 1.0.2 + resolution: "core-util-is@npm:1.0.2" + checksum: 7a4c925b497a2c91421e25bf76d6d8190f0b2359a9200dbeed136e63b2931d6294d3b1893eda378883ed363cd950f44a12a401384c609839ea616befb7927dab + languageName: node + linkType: hard + +"core-util-is@npm:~1.0.0": + version: 1.0.3 + resolution: "core-util-is@npm:1.0.3" + checksum: 9de8597363a8e9b9952491ebe18167e3b36e7707569eed0ebf14f8bba773611376466ae34575bca8cfe3c767890c859c74056084738f09d4e4a6f902b2ad7d99 + languageName: node + linkType: hard + +"cosmiconfig-typescript-loader@npm:^1.0.0": + version: 1.0.9 + resolution: "cosmiconfig-typescript-loader@npm:1.0.9" + dependencies: + cosmiconfig: ^7 + ts-node: ^10.7.0 + peerDependencies: + "@types/node": "*" + cosmiconfig: ">=7" + typescript: ">=3" + checksum: 26a0198e03e81a9e7e1a6ce880d7309fdd056c7a3a23b587253e6d1d1224154d3f9edf727d9c0310628e89752353211b75de151b705298b4d0741fa1740c661e + languageName: node + linkType: hard + +"cosmiconfig@npm:^6.0.0": + version: 6.0.0 + resolution: "cosmiconfig@npm:6.0.0" + dependencies: + "@types/parse-json": ^4.0.0 + import-fresh: ^3.1.0 + parse-json: ^5.0.0 + path-type: ^4.0.0 + yaml: ^1.7.2 + checksum: 8eed7c854b91643ecb820767d0deb038b50780ecc3d53b0b19e03ed8aabed4ae77271198d1ae3d49c3b110867edf679f5faad924820a8d1774144a87cb6f98fc + languageName: node + linkType: hard + +"cosmiconfig@npm:^7, cosmiconfig@npm:^7.0.0, cosmiconfig@npm:^7.0.1": + version: 7.1.0 + resolution: "cosmiconfig@npm:7.1.0" + 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 + checksum: c53bf7befc1591b2651a22414a5e786cd5f2eeaa87f3678a3d49d6069835a9d8d1aef223728e98aa8fec9a95bf831120d245096db12abe019fecb51f5696c96f + languageName: node + linkType: hard + +"create-require@npm:^1.1.0": + version: 1.1.1 + resolution: "create-require@npm:1.1.1" + checksum: a9a1503d4390d8b59ad86f4607de7870b39cad43d929813599a23714831e81c520bddf61bcdd1f8e30f05fd3a2b71ae8538e946eb2786dc65c2bbc520f692eff + languageName: node + linkType: hard + +"cross-env@npm:7.0.3": + version: 7.0.3 + resolution: "cross-env@npm:7.0.3" + dependencies: + cross-spawn: ^7.0.1 + bin: + cross-env: src/bin/cross-env.js + cross-env-shell: src/bin/cross-env-shell.js + checksum: 26f2f3ea2ab32617f57effb70d329c2070d2f5630adc800985d8b30b56e8bf7f5f439dd3a0358b79cee6f930afc23cf8e23515f17ccfb30092c6b62c6b630a79 + languageName: node + linkType: hard + +"cross-fetch@npm:4.0.0": + version: 4.0.0 + resolution: "cross-fetch@npm:4.0.0" + dependencies: + node-fetch: ^2.6.12 + checksum: ecca4f37ffa0e8283e7a8a590926b66713a7ef7892757aa36c2d20ffa27b0ac5c60dcf453119c809abe5923fc0bae3702a4d896bfb406ef1077b0d0018213e24 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.1, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": + version: 7.0.3 + resolution: "cross-spawn@npm:7.0.3" + dependencies: + path-key: ^3.1.0 + shebang-command: ^2.0.0 + which: ^2.0.1 + checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52 + languageName: node + linkType: hard + +"crypto-random-string@npm:^2.0.0": + version: 2.0.0 + resolution: "crypto-random-string@npm:2.0.0" + checksum: 0283879f55e7c16fdceacc181f87a0a65c53bc16ffe1d58b9d19a6277adcd71900d02bb2c4843dd55e78c51e30e89b0fec618a7f170ebcc95b33182c28f05fd6 + languageName: node + linkType: hard + +"css-blank-pseudo@npm:^3.0.3": + version: 3.0.3 + resolution: "css-blank-pseudo@npm:3.0.3" + dependencies: + postcss-selector-parser: ^6.0.9 + peerDependencies: + postcss: ^8.4 + bin: + css-blank-pseudo: dist/cli.cjs + checksum: 9be0a13885a99d8ba9e1f45ea66e801d4da75b58c1c3c516a40772fa3a93ef9952b15dcac0418acbb6c89daaae0572819647701b8e553a02972826e33d4cd67f + languageName: node + linkType: hard + +"css-declaration-sorter@npm:^6.3.1": + version: 6.3.1 + resolution: "css-declaration-sorter@npm:6.3.1" + peerDependencies: + postcss: ^8.0.9 + checksum: ff0d9989ee21ec4c42430b9bb86c43f973ed5024d68f30edc1e3fb07a22828ce3c3e5b922019f2ccbff606722e43c407c5c76e3cddac523ac4afcb31e4b2601c + languageName: node + linkType: hard + +"css-has-pseudo@npm:^3.0.4": + version: 3.0.4 + resolution: "css-has-pseudo@npm:3.0.4" + dependencies: + postcss-selector-parser: ^6.0.9 + peerDependencies: + postcss: ^8.4 + bin: + css-has-pseudo: dist/cli.cjs + checksum: 8f165d68f6621891d9fa1d874794916a52ed8847dfbec591523ad68774650cc1eae062ba08f59514666e04aeba27be72c9b211892f3a187c5ba6e287bd4260e7 + languageName: node + linkType: hard + +"css-loader@npm:^6.5.1": + version: 6.7.3 + resolution: "css-loader@npm:6.7.3" + dependencies: + icss-utils: ^5.1.0 + postcss: ^8.4.19 + 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.2.0 + semver: ^7.3.8 + peerDependencies: + webpack: ^5.0.0 + checksum: 473cc32b6c837c2848e2051ad1ba331c1457449f47442e75a8c480d9891451434ada241f7e3de2347e57de17fcd84610b3bcfc4a9da41102cdaedd1e17902d31 + languageName: node + linkType: hard + +"css-minimizer-webpack-plugin@npm:^3.2.0": + version: 3.4.1 + resolution: "css-minimizer-webpack-plugin@npm:3.4.1" + dependencies: + cssnano: ^5.0.6 + jest-worker: ^27.0.2 + postcss: ^8.3.5 + schema-utils: ^4.0.0 + serialize-javascript: ^6.0.0 + source-map: ^0.6.1 + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + "@parcel/css": + optional: true + clean-css: + optional: true + csso: + optional: true + esbuild: + optional: true + checksum: 065c6c1eadb7c99267db5d04d6f3909e9968b73c4cb79ab9e4502a5fbf1a3d564cfe6f8e0bff8e4ab00d4ed233e9c3c76a4ebe0ee89150b3d9ecb064ddf1e5e9 + languageName: node + linkType: hard + +"css-prefers-color-scheme@npm:^6.0.3": + version: 6.0.3 + resolution: "css-prefers-color-scheme@npm:6.0.3" + peerDependencies: + postcss: ^8.4 + bin: + css-prefers-color-scheme: dist/cli.cjs + checksum: 3a2b02f0454adda68861cdcaf6a0d11f462eadf165301cba61c5ec7c5f229ac261c5baa54c377d9b811ec5f21b30d72a02bc032cdad2415b3a566f08a0c47b3a + languageName: node + linkType: hard + +"css-select-base-adapter@npm:^0.1.1": + version: 0.1.1 + resolution: "css-select-base-adapter@npm:0.1.1" + checksum: c107e9cfa53a23427e4537451a67358375e656baa3322345a982d3c2751fb3904002aae7e5d72386c59f766fe6b109d1ffb43eeab1c16f069f7a3828eb17851c + languageName: node + linkType: hard + +"css-select@npm:^2.0.0": + version: 2.1.0 + resolution: "css-select@npm:2.1.0" + dependencies: + boolbase: ^1.0.0 + css-what: ^3.2.1 + domutils: ^1.7.0 + nth-check: ^1.0.2 + checksum: 0c4099910f2411e2a9103cf92ea6a4ad738b57da75bcf73d39ef2c14a00ef36e5f16cb863211c901320618b24ace74da6333442d82995cafd5040077307de462 + languageName: node + linkType: hard + +"css-select@npm:^4.1.3": + version: 4.3.0 + resolution: "css-select@npm:4.3.0" + dependencies: + boolbase: ^1.0.0 + css-what: ^6.0.1 + domhandler: ^4.3.1 + domutils: ^2.8.0 + nth-check: ^2.0.1 + checksum: d6202736839194dd7f910320032e7cfc40372f025e4bf21ca5bf6eb0a33264f322f50ba9c0adc35dadd342d3d6fae5ca244779a4873afbfa76561e343f2058e0 + languageName: node + linkType: hard + +"css-tree@npm:1.0.0-alpha.37": + version: 1.0.0-alpha.37 + resolution: "css-tree@npm:1.0.0-alpha.37" + dependencies: + mdn-data: 2.0.4 + source-map: ^0.6.1 + checksum: 0e419a1388ec0fbbe92885fba4a557f9fb0e077a2a1fad629b7245bbf7b4ef5df49e6877401b952b09b9057ffe1a3dba74f6fdfbf7b2223a5a35bce27ff2307d + languageName: node + linkType: hard + +"css-tree@npm:^1.1.2, css-tree@npm:^1.1.3": + version: 1.1.3 + resolution: "css-tree@npm:1.1.3" + dependencies: + mdn-data: 2.0.14 + source-map: ^0.6.1 + checksum: 79f9b81803991b6977b7fcb1588799270438274d89066ce08f117f5cdb5e20019b446d766c61506dd772c839df84caa16042d6076f20c97187f5abe3b50e7d1f + languageName: node + linkType: hard + +"css-what@npm:^3.2.1": + version: 3.4.2 + resolution: "css-what@npm:3.4.2" + checksum: 26bb5ec3ae718393d418016365c849fa14bd0de408c735dea3ddf58146b6cc54f3b336fb4afd31d95c06ca79583acbcdfec7ee93d31ff5c1a697df135b38dfeb + languageName: node + linkType: hard + +"css-what@npm:^6.0.1": + version: 6.1.0 + resolution: "css-what@npm:6.1.0" + checksum: b975e547e1e90b79625918f84e67db5d33d896e6de846c9b584094e529f0c63e2ab85ee33b9daffd05bff3a146a1916bec664e18bb76dd5f66cbff9fc13b2bbe + languageName: node + linkType: hard + +"css.escape@npm:^1.5.1": + version: 1.5.1 + resolution: "css.escape@npm:1.5.1" + checksum: f6d38088d870a961794a2580b2b2af1027731bb43261cfdce14f19238a88664b351cc8978abc20f06cc6bbde725699dec8deb6fe9816b139fc3f2af28719e774 + languageName: node + linkType: hard + +"cssdb@npm:^7.1.0": + version: 7.4.1 + resolution: "cssdb@npm:7.4.1" + checksum: c58803ce3e0e60af8a5a1101f365a5ea0cf1a6a5eddcd5c6fb5d92aaf187e2c11c5620185fd7096cb920c3ce087f9edb2234348a33d06433e12c1ce7fcf93197 + languageName: node + linkType: hard + +"cssesc@npm:^3.0.0": + version: 3.0.0 + resolution: "cssesc@npm:3.0.0" + bin: + cssesc: bin/cssesc + checksum: f8c4ababffbc5e2ddf2fa9957dda1ee4af6048e22aeda1869d0d00843223c1b13ad3f5d88b51caa46c994225eacb636b764eb807a8883e2fb6f99b4f4e8c48b2 + languageName: node + linkType: hard + +"cssnano-preset-default@npm:^5.2.13": + version: 5.2.13 + resolution: "cssnano-preset-default@npm:5.2.13" + dependencies: + css-declaration-sorter: ^6.3.1 + cssnano-utils: ^3.1.0 + postcss-calc: ^8.2.3 + postcss-colormin: ^5.3.0 + postcss-convert-values: ^5.1.3 + postcss-discard-comments: ^5.1.2 + postcss-discard-duplicates: ^5.1.0 + postcss-discard-empty: ^5.1.1 + postcss-discard-overridden: ^5.1.0 + postcss-merge-longhand: ^5.1.7 + postcss-merge-rules: ^5.1.3 + postcss-minify-font-values: ^5.1.0 + postcss-minify-gradients: ^5.1.1 + postcss-minify-params: ^5.1.4 + postcss-minify-selectors: ^5.2.1 + postcss-normalize-charset: ^5.1.0 + postcss-normalize-display-values: ^5.1.0 + postcss-normalize-positions: ^5.1.1 + postcss-normalize-repeat-style: ^5.1.1 + postcss-normalize-string: ^5.1.0 + postcss-normalize-timing-functions: ^5.1.0 + postcss-normalize-unicode: ^5.1.1 + postcss-normalize-url: ^5.1.0 + postcss-normalize-whitespace: ^5.1.1 + postcss-ordered-values: ^5.1.3 + postcss-reduce-initial: ^5.1.1 + postcss-reduce-transforms: ^5.1.0 + postcss-svgo: ^5.1.0 + postcss-unique-selectors: ^5.1.1 + peerDependencies: + postcss: ^8.2.15 + checksum: f773de44f67f71e7301e1f4b4664b894c3a48bba4dadc16c559acd0b14ceafed228bdc76fe19d500b0ded9394732377069daadff2184465fa369f8dfd72d47e2 + languageName: node + linkType: hard + +"cssnano-utils@npm:^3.1.0": + version: 3.1.0 + resolution: "cssnano-utils@npm:3.1.0" + peerDependencies: + postcss: ^8.2.15 + checksum: 975c84ce9174cf23bb1da1e9faed8421954607e9ea76440cd3bb0c1bea7e17e490d800fca5ae2812d1d9e9d5524eef23ede0a3f52497d7ccc628e5d7321536f2 + languageName: node + linkType: hard + +"cssnano@npm:^5.0.6": + version: 5.1.14 + resolution: "cssnano@npm:5.1.14" + dependencies: + cssnano-preset-default: ^5.2.13 + lilconfig: ^2.0.3 + yaml: ^1.10.2 + peerDependencies: + postcss: ^8.2.15 + checksum: 73463c723c5e598b37b8b4d2f014145bd72133e6581349a1b154904e0830e58de17afb1e801ed3ea3b18e386883964ce4d0299e43d4dc37d339214a956c6697f + languageName: node + linkType: hard + +"csso@npm:^4.0.2, csso@npm:^4.2.0": + version: 4.2.0 + resolution: "csso@npm:4.2.0" + dependencies: + css-tree: ^1.1.2 + checksum: 380ba9663da3bcea58dee358a0d8c4468bb6539be3c439dc266ac41c047217f52fd698fb7e4b6b6ccdfb8cf53ef4ceed8cc8ceccb8dfca2aa628319826b5b998 + languageName: node + linkType: hard + +"cssom@npm:^0.4.4": + version: 0.4.4 + resolution: "cssom@npm:0.4.4" + checksum: e3bc1076e7ee4213d4fef05e7ae03bfa83dc05f32611d8edc341f4ecc3d9647b89c8245474c7dd2cdcdb797a27c462e99da7ad00a34399694559f763478ff53f + languageName: node + linkType: hard + +"cssom@npm:~0.3.6": + version: 0.3.8 + resolution: "cssom@npm:0.3.8" + checksum: 24beb3087c76c0d52dd458be9ee1fbc80ac771478a9baef35dd258cdeb527c68eb43204dd439692bb2b1ae5272fa5f2946d10946edab0d04f1078f85e06bc7f6 + languageName: node + linkType: hard + +"cssstyle@npm:^2.3.0": + version: 2.3.0 + resolution: "cssstyle@npm:2.3.0" + dependencies: + cssom: ~0.3.6 + checksum: 5f05e6fd2e3df0b44695c2f08b9ef38b011862b274e320665176467c0725e44a53e341bc4959a41176e83b66064ab786262e7380fd1cabeae6efee0d255bb4e3 + languageName: node + linkType: hard + +"csstype@npm:^3.0.2, csstype@npm:^3.1.1": + version: 3.1.1 + resolution: "csstype@npm:3.1.1" + checksum: 1f7b4f5fdd955b7444b18ebdddf3f5c699159f13e9cf8ac9027ae4a60ae226aef9bbb14a6e12ca7dba3358b007cee6354b116e720262867c398de6c955ea451d + languageName: node + linkType: hard + +"custom-event-polyfill@npm:1.0.7": + version: 1.0.7 + resolution: "custom-event-polyfill@npm:1.0.7" + checksum: f9ff2cf13e482a75b3cf83dce9e2c6e3063c5ac1b9c23ac440e4f27e875b0873445b11811237f3f30aeb1216e9ad20f9f9d30ccf5b1b658a4e50dd0b3e67b629 + languageName: node + linkType: hard + +"cypress-failed-log@npm:2.10.0": + version: 2.10.0 + resolution: "cypress-failed-log@npm:2.10.0" + dependencies: + debug: 4.3.4 + logdown: 3.3.1 + checksum: 05fb09ac19c5f3ee8b1883102efea3fa3f73e2710fe6254fb2a2cba9cd33d45bb9ee454ded31d18d008c84bd1cf00a1b65a0b581a408e1d2d2a311a62817f8ff + languageName: node + linkType: hard + +"cypress@npm:13.6.4": + version: 13.6.4 + resolution: "cypress@npm:13.6.4" + dependencies: + "@cypress/request": ^3.0.0 + "@cypress/xvfb": ^1.2.4 + "@types/sinonjs__fake-timers": 8.1.1 + "@types/sizzle": ^2.3.2 + arch: ^2.2.0 + blob-util: ^2.0.2 + bluebird: ^3.7.2 + buffer: ^5.6.0 + cachedir: ^2.3.0 + chalk: ^4.1.0 + check-more-types: ^2.24.0 + cli-cursor: ^3.1.0 + cli-table3: ~0.6.1 + commander: ^6.2.1 + common-tags: ^1.8.0 + dayjs: ^1.10.4 + debug: ^4.3.4 + enquirer: ^2.3.6 + eventemitter2: 6.4.7 + execa: 4.1.0 + executable: ^4.1.1 + extract-zip: 2.0.1 + figures: ^3.2.0 + fs-extra: ^9.1.0 + getos: ^3.2.1 + is-ci: ^3.0.0 + is-installed-globally: ~0.4.0 + lazy-ass: ^1.6.0 + listr2: ^3.8.3 + lodash: ^4.17.21 + log-symbols: ^4.0.0 + minimist: ^1.2.8 + ospath: ^1.2.2 + pretty-bytes: ^5.6.0 + process: ^0.11.10 + proxy-from-env: 1.0.0 + request-progress: ^3.0.0 + semver: ^7.5.3 + supports-color: ^8.1.1 + tmp: ~0.2.1 + untildify: ^4.0.0 + yauzl: ^2.10.0 + bin: + cypress: bin/cypress + checksum: 39daef291ccd18d7d724d7f8c1f5a2ed2b3d24c5c1eab1e00642c5db232fcc4dbd3fd30db3a2dce4e8b737d510355d135eb43034d800198d2867ecde4cdd696a + languageName: node + linkType: hard + +"damerau-levenshtein@npm:^1.0.8": + version: 1.0.8 + resolution: "damerau-levenshtein@npm:1.0.8" + checksum: d240b7757544460ae0586a341a53110ab0a61126570ef2d8c731e3eab3f0cb6e488e2609e6a69b46727635de49be20b071688698744417ff1b6c1d7ccd03e0de + languageName: node + linkType: hard + +"dashdash@npm:^1.12.0": + version: 1.14.1 + resolution: "dashdash@npm:1.14.1" + dependencies: + assert-plus: ^1.0.0 + checksum: 3634c249570f7f34e3d34f866c93f866c5b417f0dd616275decae08147dcdf8fccfaa5947380ccfb0473998ea3a8057c0b4cd90c875740ee685d0624b2983598 + languageName: node + linkType: hard + +"data-urls@npm:^2.0.0": + version: 2.0.0 + resolution: "data-urls@npm:2.0.0" + dependencies: + abab: ^2.0.3 + whatwg-mimetype: ^2.3.0 + whatwg-url: ^8.0.0 + checksum: 97caf828aac25e25e04ba6869db0f99c75e6859bb5b424ada28d3e7841941ebf08ddff3c1b1bb4585986bd507a5d54c2a716853ea6cb98af877400e637393e71 + languageName: node + linkType: hard + +"datagateway-common@^2.0.0, datagateway-common@workspace:packages/datagateway-common": + version: 0.0.0-use.local + resolution: "datagateway-common@workspace:packages/datagateway-common" + dependencies: + "@babel/eslint-parser": 7.23.3 + "@date-io/date-fns": 2.17.0 + "@emotion/react": 11.11.1 + "@emotion/styled": 11.11.0 + "@mui/icons-material": 5.11.0 + "@mui/material": 5.11.0 + "@mui/x-date-pickers": 6.11.2 + "@testing-library/jest-dom": 6.4.1 + "@testing-library/react": 12.1.3 + "@testing-library/react-hooks": 8.0.1 + "@testing-library/user-event": 14.5.2 + "@types/jest": 29.5.2 + "@types/lodash.debounce": 4.0.6 + "@types/node": 20.11.5 + "@types/react": 17.0.39 + "@types/react-router-dom": 5.3.3 + "@types/react-virtualized": 9.21.10 + "@typescript-eslint/eslint-plugin": 5.62.0 + "@typescript-eslint/parser": 5.62.0 + axios: 1.6.1 + connected-react-router: 6.9.1 + date-fns: 2.30.0 + eslint: 8.56.0 + eslint-config-prettier: 8.10.0 + eslint-config-react-app: 7.0.0 + eslint-plugin-cypress: 2.15.1 + eslint-plugin-prettier: 4.2.1 + hex-to-rgba: 2.0.1 + history: 4.10.1 + i18next: 22.0.3 + jest-fail-on-console: 3.1.1 + lint-staged: 13.3.0 + lodash.debounce: 4.0.8 + loglevel: 1.9.1 + prettier: 2.8.0 + react: 17.0.2 + react-dom: 17.0.2 + react-draggable: 4.4.3 + react-i18next: 12.3.1 + react-query: 3.39.2 + react-redux: 8.1.3 + react-router-dom: 5.3.0 + react-scripts: 5.0.0 + react-test-renderer: 17.0.2 + react-virtualized: 9.22.3 + redux: 4.2.0 + redux-mock-store: 1.5.4 + redux-thunk: 2.4.1 + resize-observer-polyfill: 1.5.1 + tslib: 2.6.0 + typescript: 5.3.3 + peerDependencies: + "@mui/icons-material": ">= 5.5.0 < 6" + "@mui/material": ">= 5.5.0 < 6" + react: ">= 17.0.2 < 18" + react-dom: ">= 17.0.2 < 18" + react-router-dom: ">= 5.2.0 < 6" + languageName: unknown + linkType: soft + +"datagateway-dataview@workspace:packages/datagateway-dataview": + version: 0.0.0-use.local + resolution: "datagateway-dataview@workspace:packages/datagateway-dataview" + dependencies: + "@babel/eslint-parser": 7.23.3 + "@craco/craco": 7.1.0 + "@emotion/react": 11.11.1 + "@emotion/styled": 11.11.0 + "@mui/icons-material": 5.11.0 + "@mui/material": 5.11.0 + "@testing-library/jest-dom": 6.4.1 + "@testing-library/react": 12.1.3 + "@testing-library/react-hooks": 8.0.1 + "@testing-library/user-event": 14.5.2 + "@types/history": 4.7.11 + "@types/jest": 29.5.2 + "@types/jsrsasign": 10.5.2 + "@types/lodash.debounce": 4.0.6 + "@types/lodash.memoize": 4.1.6 + "@types/node": 20.11.5 + "@types/react": 17.0.39 + "@types/react-dom": 17.0.11 + "@types/react-redux": 7.1.22 + "@types/react-router-dom": 5.3.3 + "@types/react-virtualized": 9.21.10 + "@types/redux-logger": 3.0.8 + "@types/redux-mock-store": 1.0.3 + "@typescript-eslint/eslint-plugin": 5.62.0 + "@typescript-eslint/parser": 5.62.0 + axios: 1.6.1 + blob-polyfill: 7.0.20220408 + connected-react-router: 6.9.1 + cross-env: 7.0.3 + custom-event-polyfill: 1.0.7 + cypress: 13.6.4 + cypress-failed-log: 2.10.0 + datagateway-common: ^2.0.0 + date-fns: 2.30.0 + eslint: 8.56.0 + eslint-config-prettier: 8.10.0 + eslint-config-react-app: 7.0.0 + eslint-plugin-cypress: 2.15.1 + eslint-plugin-prettier: 4.2.1 + express: 4.19.2 + history: 4.10.1 + i18next: 22.0.3 + i18next-browser-languagedetector: 7.2.0 + i18next-http-backend: 2.4.2 + jest-fail-on-console: 3.1.1 + jsrsasign: 11.0.0 + lint-staged: 13.3.0 + lodash.debounce: 4.0.8 + lodash.memoize: 4.1.2 + loglevel: 1.9.1 + prettier: 2.8.0 + react: 17.0.2 + react-app-polyfill: 3.0.0 + react-dom: 17.0.2 + react-i18next: 12.3.1 + react-query: 3.39.2 + react-redux: 8.1.3 + react-router-dom: 5.3.0 + react-scripts: 5.0.0 + react-virtualized: 9.22.3 + redux: 4.2.0 + redux-logger: 3.0.6 + redux-mock-store: 1.5.4 + redux-thunk: 2.4.1 + serve: 14.2.0 + single-spa-react: 4.6.1 + start-server-and-test: 2.0.0 + tslib: 2.6.0 + typescript: 5.3.3 + url-search-params-polyfill: 8.2.4 + languageName: unknown + linkType: soft + +"datagateway-download@workspace:packages/datagateway-download": + version: 0.0.0-use.local + resolution: "datagateway-download@workspace:packages/datagateway-download" + dependencies: + "@babel/eslint-parser": 7.23.3 + "@craco/craco": 7.1.0 + "@emotion/react": 11.11.1 + "@emotion/styled": 11.11.0 + "@mui/icons-material": 5.11.0 + "@mui/material": 5.11.0 + "@testing-library/jest-dom": 6.4.1 + "@testing-library/react": 12.1.3 + "@testing-library/react-hooks": 8.0.1 + "@testing-library/user-event": 14.5.2 + "@types/jest": 29.5.2 + "@types/jsrsasign": 10.5.2 + "@types/lodash.chunk": 4.2.6 + "@types/node": 20.11.5 + "@types/react": 17.0.39 + "@types/react-dom": 17.0.11 + "@types/react-router-dom": 5.3.3 + "@types/react-virtualized": 9.21.10 + "@typescript-eslint/eslint-plugin": 5.62.0 + "@typescript-eslint/parser": 5.62.0 + axios: 1.6.1 + cross-env: 7.0.3 + cypress: 13.6.4 + cypress-failed-log: 2.10.0 + datagateway-common: ^2.0.0 + date-fns: 2.30.0 + date-fns-tz: 2.0.0 + eslint: 8.56.0 + eslint-config-prettier: 8.10.0 + eslint-config-react-app: 7.0.0 + eslint-plugin-cypress: 2.15.1 + eslint-plugin-prettier: 4.2.1 + history: 4.10.1 + i18next: 22.0.3 + i18next-browser-languagedetector: 7.2.0 + i18next-http-backend: 2.4.2 + jest-fail-on-console: 3.1.1 + jsrsasign: 11.0.0 + lint-staged: 13.3.0 + lodash.chunk: 4.2.0 + loglevel: 1.9.1 + p-limit: 3.1.0 + prettier: 2.8.0 + react: 17.0.2 + react-dom: 17.0.2 + react-i18next: 12.3.1 + react-query: 3.39.2 + react-router-dom: 5.3.0 + react-scripts: 5.0.0 + react-virtualized: 9.22.3 + serve: 14.2.0 + single-spa-react: 4.6.1 + start-server-and-test: 2.0.0 + tslib: 2.6.0 + typescript: 5.3.3 + languageName: unknown + linkType: soft + +"datagateway-search@workspace:packages/datagateway-search": + version: 0.0.0-use.local + resolution: "datagateway-search@workspace:packages/datagateway-search" + dependencies: + "@babel/eslint-parser": 7.23.3 + "@craco/craco": 7.1.0 + "@date-io/date-fns": 2.17.0 + "@emotion/react": 11.11.1 + "@emotion/styled": 11.11.0 + "@mui/icons-material": 5.11.0 + "@mui/material": 5.11.0 + "@mui/x-date-pickers": 6.11.2 + "@testing-library/cypress": 8.0.7 + "@testing-library/jest-dom": 6.4.1 + "@testing-library/react": 12.1.3 + "@testing-library/react-hooks": 8.0.1 + "@testing-library/user-event": 14.5.2 + "@types/history": 4.7.11 + "@types/jest": 29.5.2 + "@types/jsrsasign": 10.5.2 + "@types/lodash.isequal": 4.5.8 + "@types/node": 20.11.5 + "@types/react": 17.0.39 + "@types/react-dom": 17.0.11 + "@types/react-redux": 7.1.22 + "@types/react-router-dom": 5.3.3 + "@types/react-virtualized": 9.21.10 + "@types/redux-logger": 3.0.8 + "@types/redux-mock-store": 1.0.3 + "@typescript-eslint/eslint-plugin": 5.62.0 + "@typescript-eslint/parser": 5.62.0 + axios: 1.6.1 + connected-react-router: 6.9.1 + cross-env: 7.0.3 + custom-event-polyfill: 1.0.7 + cypress: 13.6.4 + cypress-failed-log: 2.10.0 + datagateway-common: ^2.0.0 + date-fns: 2.30.0 + eslint: 8.56.0 + eslint-config-prettier: 8.10.0 + eslint-config-react-app: 7.0.0 + eslint-plugin-cypress: 2.15.1 + eslint-plugin-prettier: 4.2.1 + express: 4.19.2 + history: 4.10.1 + i18next: 22.0.3 + i18next-browser-languagedetector: 7.2.0 + i18next-http-backend: 2.4.2 + jest-fail-on-console: 3.1.1 + jsrsasign: 11.0.0 + lint-staged: 13.3.0 + lodash.isequal: 4.5.0 + loglevel: 1.9.1 + prettier: 2.8.0 + react: 17.0.2 + react-app-polyfill: 3.0.0 + react-dom: 17.0.2 + react-i18next: 12.3.1 + react-query: 3.39.2 + react-redux: 8.1.3 + react-router-dom: 5.3.0 + react-scripts: 5.0.0 + react-virtualized: 9.22.3 + redux: 4.2.0 + redux-logger: 3.0.6 + redux-mock-store: 1.5.4 + redux-thunk: 2.4.1 + resize-observer-polyfill: 1.5.1 + serve: 14.2.0 + single-spa-react: 4.6.1 + start-server-and-test: 2.0.0 + tslib: 2.6.0 + typescript: 5.3.3 + url-search-params-polyfill: 8.2.4 + languageName: unknown + linkType: soft + +"datagateway@workspace:.": + version: 0.0.0-use.local + resolution: "datagateway@workspace:." + dependencies: + husky: 8.0.1 + languageName: unknown + linkType: soft + +"date-fns-tz@npm:2.0.0": + version: 2.0.0 + resolution: "date-fns-tz@npm:2.0.0" + peerDependencies: + date-fns: ">=2.0.0" + checksum: a6553603a9d26dd9669326c99a58a2335ac550bc060c74b86a5ad9e1de73c9d4e3e5236f0f552f990e616e4e8dcc2b6a637913a04d2e04396e6a9f8ae83c73da + languageName: node + linkType: hard + +"date-fns@npm:2.30.0": + version: 2.30.0 + resolution: "date-fns@npm:2.30.0" + dependencies: + "@babel/runtime": ^7.21.0 + checksum: f7be01523282e9bb06c0cd2693d34f245247a29098527d4420628966a2d9aad154bd0e90a6b1cf66d37adcb769cd108cf8a7bd49d76db0fb119af5cdd13644f4 + languageName: node + linkType: hard + +"dayjs@npm:^1.10.4": + version: 1.11.7 + resolution: "dayjs@npm:1.11.7" + checksum: 5003a7c1dd9ed51385beb658231c3548700b82d3548c0cfbe549d85f2d08e90e972510282b7506941452c58d32136d6362f009c77ca55381a09c704e9f177ebb + languageName: node + linkType: hard + +"debug@npm:2.6.9, debug@npm:^2.6.0": + version: 2.6.9 + resolution: "debug@npm:2.6.9" + dependencies: + ms: 2.0.0 + checksum: d2f51589ca66df60bf36e1fa6e4386b318c3f1e06772280eea5b1ae9fd3d05e9c2b7fd8a7d862457d00853c75b00451aa2d7459b924629ee385287a650f58fe6 + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": + version: 4.3.4 + resolution: "debug@npm:4.3.4" + dependencies: + ms: 2.1.2 + peerDependenciesMeta: + supports-color: + optional: true + checksum: 3dbad3f94ea64f34431a9cbf0bafb61853eda57bff2880036153438f50fb5a84f27683ba0d8e5426bf41a8c6ff03879488120cf5b3a761e77953169c0600a708 + languageName: node + linkType: hard + +"debug@npm:^3.1.0, debug@npm:^3.2.7": + version: 3.2.7 + resolution: "debug@npm:3.2.7" + dependencies: + ms: ^2.1.1 + checksum: b3d8c5940799914d30314b7c3304a43305fd0715581a919dacb8b3176d024a782062368405b47491516d2091d6462d4d11f2f4974a405048094f8bfebfa3071c + languageName: node + linkType: hard + +"decimal.js@npm:^10.2.1": + version: 10.4.3 + resolution: "decimal.js@npm:10.4.3" + checksum: 796404dcfa9d1dbfdc48870229d57f788b48c21c603c3f6554a1c17c10195fc1024de338b0cf9e1efe0c7c167eeb18f04548979bcc5fdfabebb7cc0ae3287bae + languageName: node + linkType: hard + +"dedent@npm:^0.7.0": + version: 0.7.0 + resolution: "dedent@npm:0.7.0" + checksum: 87de191050d9a40dd70cad01159a0bcf05ecb59750951242070b6abf9569088684880d00ba92a955b4058804f16eeaf91d604f283929b4f614d181cd7ae633d2 + languageName: node + linkType: hard + +"deep-diff@npm:^0.3.5": + version: 0.3.8 + resolution: "deep-diff@npm:0.3.8" + checksum: 8a0fb6cbe468e50211836f8daa1c14798b2d7436bfbcb7d8eb0902e0d61bf1dfd48d5b9edd46a10596182b90ad25f87461b8e55111ff9257b6067ad0676f79c9 + languageName: node + linkType: hard + +"deep-equal@npm:^2.0.5": + version: 2.2.0 + resolution: "deep-equal@npm:2.2.0" + dependencies: + call-bind: ^1.0.2 + es-get-iterator: ^1.1.2 + get-intrinsic: ^1.1.3 + is-arguments: ^1.1.1 + is-array-buffer: ^3.0.1 + is-date-object: ^1.0.5 + is-regex: ^1.1.4 + is-shared-array-buffer: ^1.0.2 + isarray: ^2.0.5 + object-is: ^1.1.5 + object-keys: ^1.1.1 + object.assign: ^4.1.4 + regexp.prototype.flags: ^1.4.3 + side-channel: ^1.0.4 + which-boxed-primitive: ^1.0.2 + which-collection: ^1.0.1 + which-typed-array: ^1.1.9 + checksum: 46a34509d2766d6c6dc5aec4756089cf0cc137e46787e91f08f1ee0bb570d874f19f0493146907df0cf18aed4a7b4b50f6f62c899240a76c323f057528b122e3 + languageName: node + linkType: hard + +"deep-extend@npm:^0.6.0": + version: 0.6.0 + resolution: "deep-extend@npm:0.6.0" + checksum: 7be7e5a8d468d6b10e6a67c3de828f55001b6eb515d014f7aeb9066ce36bd5717161eb47d6a0f7bed8a9083935b465bc163ee2581c8b128d29bf61092fdf57a7 + languageName: node + linkType: hard + +"deep-is@npm:^0.1.3, deep-is@npm:~0.1.3": + version: 0.1.4 + resolution: "deep-is@npm:0.1.4" + checksum: edb65dd0d7d1b9c40b2f50219aef30e116cedd6fc79290e740972c132c09106d2e80aa0bc8826673dd5a00222d4179c84b36a790eef63a4c4bca75a37ef90804 + languageName: node + linkType: hard + +"deepmerge@npm:^4.2.2": + version: 4.3.0 + resolution: "deepmerge@npm:4.3.0" + checksum: c7980eb5c5be040b371f1df0d566473875cfabed9f672ccc177b81ba8eee5686ce2478de2f1d0076391621cbe729e5eacda397179a59ef0f68901849647db126 + languageName: node + linkType: hard + +"default-gateway@npm:^6.0.3": + version: 6.0.3 + resolution: "default-gateway@npm:6.0.3" + dependencies: + execa: ^5.0.0 + checksum: 126f8273ecac8ee9ff91ea778e8784f6cd732d77c3157e8c5bdd6ed03651b5291f71446d05bc02d04073b1e67583604db5394ea3cf992ede0088c70ea15b7378 + languageName: node + linkType: hard + +"define-lazy-prop@npm:^2.0.0": + version: 2.0.0 + resolution: "define-lazy-prop@npm:2.0.0" + checksum: 0115fdb065e0490918ba271d7339c42453d209d4cb619dfe635870d906731eff3e1ade8028bb461ea27ce8264ec5e22c6980612d332895977e89c1bbc80fcee2 + languageName: node + linkType: hard + +"define-properties@npm:^1.1.3, define-properties@npm:^1.1.4": + version: 1.1.4 + resolution: "define-properties@npm:1.1.4" + dependencies: + has-property-descriptors: ^1.0.0 + object-keys: ^1.1.1 + checksum: ce0aef3f9eb193562b5cfb79b2d2c86b6a109dfc9fdcb5f45d680631a1a908c06824ddcdb72b7573b54e26ace07f0a23420aaba0d5c627b34d2c1de8ef527e2b + languageName: node + linkType: hard + +"defined@npm:^1.0.0": + version: 1.0.1 + resolution: "defined@npm:1.0.1" + checksum: b1a852300bdb57f297289b55eafdd0c517afaa3ec8190e78fce91b9d8d0c0369d4505ecbdacfd3d98372e664f4a267d9bd793938d4a8c76209c9d9516fbe2101 + languageName: node + linkType: hard + +"delayed-stream@npm:~1.0.0": + version: 1.0.0 + resolution: "delayed-stream@npm:1.0.0" + checksum: 46fe6e83e2cb1d85ba50bd52803c68be9bd953282fa7096f51fc29edd5d67ff84ff753c51966061e5ba7cb5e47ef6d36a91924eddb7f3f3483b1c560f77a0020 + languageName: node + linkType: hard + +"delegates@npm:^1.0.0": + version: 1.0.0 + resolution: "delegates@npm:1.0.0" + checksum: a51744d9b53c164ba9c0492471a1a2ffa0b6727451bdc89e31627fdf4adda9d51277cfcbfb20f0a6f08ccb3c436f341df3e92631a3440226d93a8971724771fd + languageName: node + linkType: hard + +"depd@npm:2.0.0": + version: 2.0.0 + resolution: "depd@npm:2.0.0" + checksum: abbe19c768c97ee2eed6282d8ce3031126662252c58d711f646921c9623f9052e3e1906443066beec1095832f534e57c523b7333f8e7e0d93051ab6baef5ab3a + languageName: node + linkType: hard + +"depd@npm:^1.1.2, depd@npm:~1.1.2": + version: 1.1.2 + resolution: "depd@npm:1.1.2" + checksum: 6b406620d269619852885ce15965272b829df6f409724415e0002c8632ab6a8c0a08ec1f0bd2add05dc7bd7507606f7e2cc034fa24224ab829580040b835ecd9 + languageName: node + linkType: hard + +"destroy@npm:1.2.0": + version: 1.2.0 + resolution: "destroy@npm:1.2.0" + checksum: 0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38 + languageName: node + linkType: hard + +"detect-newline@npm:^3.0.0": + version: 3.1.0 + resolution: "detect-newline@npm:3.1.0" + checksum: ae6cd429c41ad01b164c59ea36f264a2c479598e61cba7c99da24175a7ab80ddf066420f2bec9a1c57a6bead411b4655ff15ad7d281c000a89791f48cbe939e7 + languageName: node + linkType: hard + +"detect-node@npm:^2.0.4, detect-node@npm:^2.1.0": + version: 2.1.0 + resolution: "detect-node@npm:2.1.0" + checksum: 832184ec458353e41533ac9c622f16c19f7c02d8b10c303dfd3a756f56be93e903616c0bb2d4226183c9351c15fc0b3dba41a17a2308262afabcfa3776e6ae6e + languageName: node + linkType: hard + +"detect-port-alt@npm:^1.1.6": + version: 1.1.6 + resolution: "detect-port-alt@npm:1.1.6" + dependencies: + address: ^1.0.1 + debug: ^2.6.0 + bin: + detect: ./bin/detect-port + detect-port: ./bin/detect-port + checksum: 9dc37b1fa4a9dd6d4889e1045849b8d841232b598d1ca888bf712f4035b07a17cf6d537465a0d7323250048d3a5a0540e3b7cf89457efc222f96f77e2c40d16a + languageName: node + linkType: hard + +"detective@npm:^5.2.1": + version: 5.2.1 + resolution: "detective@npm:5.2.1" + dependencies: + acorn-node: ^1.8.2 + defined: ^1.0.0 + minimist: ^1.2.6 + bin: + detective: bin/detective.js + checksum: dc4601bbc6be850edb3c2dab7a0eaf5a6169a15ad201679c66d40ea1986df816eeaecd590047f15b0780285f3eeea13b82dca0d4c52a47e744a571e326a72dc9 + languageName: node + linkType: hard + +"didyoumean@npm:^1.2.2": + version: 1.2.2 + resolution: "didyoumean@npm:1.2.2" + checksum: d5d98719d58b3c2fa59663c4c42ba9716f1fd01245c31d5fce31915bd3aa26e6aac149788e007358f778ebbd68a2256eb5973e8ca6f221df221ba060115acf2e + languageName: node + linkType: hard + +"diff-sequences@npm:^27.5.1": + version: 27.5.1 + resolution: "diff-sequences@npm:27.5.1" + checksum: a00db5554c9da7da225db2d2638d85f8e41124eccbd56cbaefb3b276dcbb1c1c2ad851c32defe2055a54a4806f030656cbf6638105fd6ce97bb87b90b32a33ca + languageName: node + linkType: hard + +"diff-sequences@npm:^29.3.1": + version: 29.3.1 + resolution: "diff-sequences@npm:29.3.1" + checksum: 8edab8c383355022e470779a099852d595dd856f9f5bd7af24f177e74138a668932268b4c4fd54096eed643861575c3652d4ecbbb1a9d710488286aed3ffa443 + languageName: node + linkType: hard + +"diff@npm:^4.0.1": + version: 4.0.2 + resolution: "diff@npm:4.0.2" + checksum: f2c09b0ce4e6b301c221addd83bf3f454c0bc00caa3dd837cf6c127d6edf7223aa2bbe3b688feea110b7f262adbfc845b757c44c8a9f8c0c5b15d8fa9ce9d20d + languageName: node + linkType: hard + +"dir-glob@npm:^3.0.1": + version: 3.0.1 + resolution: "dir-glob@npm:3.0.1" + dependencies: + path-type: ^4.0.0 + checksum: fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615 + languageName: node + linkType: hard + +"dlv@npm:^1.1.3": + version: 1.1.3 + resolution: "dlv@npm:1.1.3" + checksum: d7381bca22ed11933a1ccf376db7a94bee2c57aa61e490f680124fa2d1cd27e94eba641d9f45be57caab4f9a6579de0983466f620a2cd6230d7ec93312105ae7 + languageName: node + linkType: hard + +"dns-equal@npm:^1.0.0": + version: 1.0.0 + resolution: "dns-equal@npm:1.0.0" + checksum: a8471ac849c7c13824f053babea1bc26e2f359394dd5a460f8340d8abd13434be01e3327a5c59d212f8c8997817450efd3f3ac77bec709b21979cf0235644524 + languageName: node + linkType: hard + +"dns-packet@npm:^5.2.2": + version: 5.4.0 + resolution: "dns-packet@npm:5.4.0" + dependencies: + "@leichtgewicht/ip-codec": ^2.0.1 + checksum: a169963848e8539dfd8a19058562f9e1c15c0f82cbf76fa98942f11c46f3c74e7e7c82e3a8a5182d4c9e6ff19e21be738dbd098a876dde755d3aedd2cc730880 + languageName: node + linkType: hard + +"doctrine@npm:^2.1.0": + version: 2.1.0 + resolution: "doctrine@npm:2.1.0" + dependencies: + esutils: ^2.0.2 + checksum: a45e277f7feaed309fe658ace1ff286c6e2002ac515af0aaf37145b8baa96e49899638c7cd47dccf84c3d32abfc113246625b3ac8f552d1046072adee13b0dc8 + languageName: node + linkType: hard + +"doctrine@npm:^3.0.0": + version: 3.0.0 + resolution: "doctrine@npm:3.0.0" + dependencies: + esutils: ^2.0.2 + checksum: fd7673ca77fe26cd5cba38d816bc72d641f500f1f9b25b83e8ce28827fe2da7ad583a8da26ab6af85f834138cf8dae9f69b0cd6ab925f52ddab1754db44d99ce + languageName: node + linkType: hard + +"dom-accessibility-api@npm:^0.5.9": + version: 0.5.16 + resolution: "dom-accessibility-api@npm:0.5.16" + checksum: 005eb283caef57fc1adec4d5df4dd49189b628f2f575af45decb210e04d634459e3f1ee64f18b41e2dcf200c844bc1d9279d80807e686a30d69a4756151ad248 + languageName: node + linkType: hard + +"dom-accessibility-api@npm:^0.6.3": + version: 0.6.3 + resolution: "dom-accessibility-api@npm:0.6.3" + checksum: c325b5144bb406df23f4affecffc117dbaec9af03daad9ee6b510c5be647b14d28ef0a4ea5ca06d696d8ab40bb777e5fed98b985976fdef9d8790178fa1d573f + languageName: node + linkType: hard + +"dom-converter@npm:^0.2.0": + version: 0.2.0 + resolution: "dom-converter@npm:0.2.0" + dependencies: + utila: ~0.4 + checksum: ea52fe303f5392e48dea563abef0e6fb3a478b8dbe3c599e99bb5d53981c6c38fc4944e56bb92a8ead6bb989d10b7914722ae11febbd2fd0910e33b9fc4aaa77 + languageName: node + linkType: hard + +"dom-helpers@npm:^5.0.1, dom-helpers@npm:^5.1.3": + version: 5.2.1 + resolution: "dom-helpers@npm:5.2.1" + dependencies: + "@babel/runtime": ^7.8.7 + csstype: ^3.0.2 + checksum: 863ba9e086f7093df3376b43e74ce4422571d404fc9828bf2c56140963d5edf0e56160f9b2f3bb61b282c07f8fc8134f023c98fd684bddcb12daf7b0f14d951c + languageName: node + linkType: hard + +"dom-serializer@npm:0": + version: 0.2.2 + resolution: "dom-serializer@npm:0.2.2" + dependencies: + domelementtype: ^2.0.1 + entities: ^2.0.0 + checksum: 376344893e4feccab649a14ca1a46473e9961f40fe62479ea692d4fee4d9df1c00ca8654811a79c1ca7b020096987e1ca4fb4d7f8bae32c1db800a680a0e5d5e + languageName: node + linkType: hard + +"dom-serializer@npm:^1.0.1": + version: 1.4.1 + resolution: "dom-serializer@npm:1.4.1" + dependencies: + domelementtype: ^2.0.1 + domhandler: ^4.2.0 + entities: ^2.0.0 + checksum: fbb0b01f87a8a2d18e6e5a388ad0f7ec4a5c05c06d219377da1abc7bb0f674d804f4a8a94e3f71ff15f6cb7dcfc75704a54b261db672b9b3ab03da6b758b0b22 + languageName: node + linkType: hard + +"domelementtype@npm:1": + version: 1.3.1 + resolution: "domelementtype@npm:1.3.1" + checksum: 7893da40218ae2106ec6ffc146b17f203487a52f5228b032ea7aa470e41dfe03e1bd762d0ee0139e792195efda765434b04b43cddcf63207b098f6ae44b36ad6 + languageName: node + linkType: hard + +"domelementtype@npm:^2.0.1, domelementtype@npm:^2.2.0": + version: 2.3.0 + resolution: "domelementtype@npm:2.3.0" + checksum: ee837a318ff702622f383409d1f5b25dd1024b692ef64d3096ff702e26339f8e345820f29a68bcdcea8cfee3531776b3382651232fbeae95612d6f0a75efb4f6 + languageName: node + linkType: hard + +"domexception@npm:^2.0.1": + version: 2.0.1 + resolution: "domexception@npm:2.0.1" + dependencies: + webidl-conversions: ^5.0.0 + checksum: d638e9cb05c52999f1b2eb87c374b03311ea5b1d69c2f875bc92da73e17db60c12142b45c950228642ff7f845c536b65305483350d080df59003a653da80b691 + languageName: node + linkType: hard + +"domhandler@npm:^4.0.0, domhandler@npm:^4.2.0, domhandler@npm:^4.3.1": + version: 4.3.1 + resolution: "domhandler@npm:4.3.1" + dependencies: + domelementtype: ^2.2.0 + checksum: 4c665ceed016e1911bf7d1dadc09dc888090b64dee7851cccd2fcf5442747ec39c647bb1cb8c8919f8bbdd0f0c625a6bafeeed4b2d656bbecdbae893f43ffaaa + languageName: node + linkType: hard + +"domutils@npm:^1.7.0": + version: 1.7.0 + resolution: "domutils@npm:1.7.0" + dependencies: + dom-serializer: 0 + domelementtype: 1 + checksum: f60a725b1f73c1ae82f4894b691601ecc6ecb68320d87923ac3633137627c7865725af813ae5d188ad3954283853bcf46779eb50304ec5d5354044569fcefd2b + languageName: node + linkType: hard + +"domutils@npm:^2.5.2, domutils@npm:^2.8.0": + version: 2.8.0 + resolution: "domutils@npm:2.8.0" + dependencies: + dom-serializer: ^1.0.1 + domelementtype: ^2.2.0 + domhandler: ^4.2.0 + checksum: abf7434315283e9aadc2a24bac0e00eab07ae4313b40cc239f89d84d7315ebdfd2fb1b5bf750a96bc1b4403d7237c7b2ebf60459be394d625ead4ca89b934391 + languageName: node + linkType: hard + +"dot-case@npm:^3.0.4": + version: 3.0.4 + resolution: "dot-case@npm:3.0.4" + dependencies: + no-case: ^3.0.4 + tslib: ^2.0.3 + checksum: a65e3519414856df0228b9f645332f974f2bf5433370f544a681122eab59e66038fc3349b4be1cdc47152779dac71a5864f1ccda2f745e767c46e9c6543b1169 + languageName: node + linkType: hard + +"dotenv-expand@npm:^5.1.0": + version: 5.1.0 + resolution: "dotenv-expand@npm:5.1.0" + checksum: 8017675b7f254384915d55f9eb6388e577cf0a1231a28d54b0ca03b782be9501b0ac90ac57338636d395fa59051e6209e9b44b8ddf169ce6076dffb5dea227d3 + languageName: node + linkType: hard + +"dotenv@npm:^10.0.0": + version: 10.0.0 + resolution: "dotenv@npm:10.0.0" + checksum: f412c5fe8c24fbe313d302d2500e247ba8a1946492db405a4de4d30dd0eb186a88a43f13c958c5a7de303938949c4231c56994f97d05c4bc1f22478d631b4005 + languageName: node + linkType: hard + +"duplexer@npm:^0.1.2, duplexer@npm:~0.1.1": + version: 0.1.2 + resolution: "duplexer@npm:0.1.2" + checksum: 62ba61a830c56801db28ff6305c7d289b6dc9f859054e8c982abd8ee0b0a14d2e9a8e7d086ffee12e868d43e2bbe8a964be55ddbd8c8957714c87373c7a4f9b0 + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 7d00d7cd8e49b9afa762a813faac332dee781932d6f2c848dc348939c4253f1d4564341b7af1d041853bc3f32c2ef141b58e0a4d9862c17a7f08f68df1e0f1ed + languageName: node + linkType: hard + +"ecc-jsbn@npm:~0.1.1": + version: 0.1.2 + resolution: "ecc-jsbn@npm:0.1.2" + dependencies: + jsbn: ~0.1.0 + safer-buffer: ^2.1.0 + checksum: 22fef4b6203e5f31d425f5b711eb389e4c6c2723402e389af394f8411b76a488fa414d309d866e2b577ce3e8462d344205545c88a8143cc21752a5172818888a + languageName: node + linkType: hard + +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 1b4cac778d64ce3b582a7e26b218afe07e207a0f9bfe13cc7395a6d307849cfe361e65033c3251e00c27dd060cab43014c2d6b2647676135e18b77d2d05b3f4f + languageName: node + linkType: hard + +"ejs@npm:^3.1.6": + version: 3.1.10 + resolution: "ejs@npm:3.1.10" + dependencies: + jake: ^10.8.5 + bin: + ejs: bin/cli.js + checksum: ce90637e9c7538663ae023b8a7a380b2ef7cc4096de70be85abf5a3b9641912dde65353211d05e24d56b1f242d71185c6d00e02cb8860701d571786d92c71f05 + languageName: node + linkType: hard + +"electron-to-chromium@npm:^1.4.251": + version: 1.4.284 + resolution: "electron-to-chromium@npm:1.4.284" + checksum: be496e9dca6509dbdbb54dc32146fc99f8eb716d28a7ee8ccd3eba0066561df36fc51418d8bd7cf5a5891810bf56c0def3418e74248f51ea4a843d423603d10a + languageName: node + linkType: hard + +"emittery@npm:^0.10.2": + version: 0.10.2 + resolution: "emittery@npm:0.10.2" + checksum: ee3e21788b043b90885b18ea756ec3105c1cedc50b29709c92b01e239c7e55345d4bb6d3aef4ddbaf528eef448a40b3bb831bad9ee0fc9c25cbf1367ab1ab5ac + languageName: node + linkType: hard + +"emittery@npm:^0.8.1": + version: 0.8.1 + resolution: "emittery@npm:0.8.1" + checksum: 2457e8c7b0688bb006126f2c025b2655abe682f66b184954122a8a065b5277f9813d49d627896a10b076b81c513ec5f491fd9c14fbd42c04b95ca3c9f3c365ee + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 8487182da74aabd810ac6d6f1994111dfc0e331b01271ae01ec1eb0ad7b5ecc2bbbbd2f053c05cb55a1ac30449527d819bbfbf0e3de1023db308cbcb47f86601 + languageName: node + linkType: hard + +"emojis-list@npm:^3.0.0": + version: 3.0.0 + resolution: "emojis-list@npm:3.0.0" + checksum: ddaaa02542e1e9436c03970eeed445f4ed29a5337dfba0fe0c38dfdd2af5da2429c2a0821304e8a8d1cadf27fdd5b22ff793571fa803ae16852a6975c65e8e70 + languageName: node + linkType: hard + +"encodeurl@npm:~1.0.2": + version: 1.0.2 + resolution: "encodeurl@npm:1.0.2" + checksum: e50e3d508cdd9c4565ba72d2012e65038e5d71bdc9198cb125beb6237b5b1ade6c0d343998da9e170fb2eae52c1bed37d4d6d98a46ea423a0cddbed5ac3f780c + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: ^0.6.2 + checksum: bb98632f8ffa823996e508ce6a58ffcf5856330fde839ae42c9e1f436cc3b5cc651d4aeae72222916545428e54fd0f6aa8862fd8d25bdbcc4589f1e3f3715e7f + languageName: node + linkType: hard + +"end-of-stream@npm:^1.1.0": + version: 1.4.4 + resolution: "end-of-stream@npm:1.4.4" + dependencies: + once: ^1.4.0 + checksum: 530a5a5a1e517e962854a31693dbb5c0b2fc40b46dad2a56a2deec656ca040631124f4795823acc68238147805f8b021abbe221f4afed5ef3c8e8efc2024908b + languageName: node + linkType: hard + +"enhanced-resolve@npm:^5.10.0": + version: 5.12.0 + resolution: "enhanced-resolve@npm:5.12.0" + dependencies: + graceful-fs: ^4.2.4 + tapable: ^2.2.0 + checksum: bf3f787facaf4ce3439bef59d148646344e372bef5557f0d37ea8aa02c51f50a925cd1f07b8d338f18992c29f544ec235a8c64bcdb56030196c48832a5494174 + languageName: node + linkType: hard + +"enquirer@npm:^2.3.6": + version: 2.3.6 + resolution: "enquirer@npm:2.3.6" + dependencies: + ansi-colors: ^4.1.1 + checksum: 1c0911e14a6f8d26721c91e01db06092a5f7675159f0261d69c403396a385afd13dd76825e7678f66daffa930cfaa8d45f506fb35f818a2788463d022af1b884 + languageName: node + linkType: hard + +"entities@npm:^2.0.0": + version: 2.2.0 + resolution: "entities@npm:2.2.0" + checksum: 19010dacaf0912c895ea262b4f6128574f9ccf8d4b3b65c7e8334ad0079b3706376360e28d8843ff50a78aabcb8f08f0a32dbfacdc77e47ed77ca08b713669b3 + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 65b5df55a8bab92229ab2b40dad3b387fad24613263d103a97f91c9fe43ceb21965cd3392b1ccb5d77088021e525c4e0481adb309625d0cb94ade1d1fb8dc17e + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 8b7b1be20d2de12d2255c0bc2ca638b7af5171142693299416e6a9339bd7d88fc8d7707d913d78e0993176005405a236b066b45666b27b797252c771156ace54 + languageName: node + linkType: hard + +"error-ex@npm:^1.3.1": + version: 1.3.2 + resolution: "error-ex@npm:1.3.2" + dependencies: + is-arrayish: ^0.2.1 + checksum: c1c2b8b65f9c91b0f9d75f0debaa7ec5b35c266c2cac5de412c1a6de86d4cbae04ae44e510378cb14d032d0645a36925d0186f8bb7367bcc629db256b743a001 + languageName: node + linkType: hard + +"error-stack-parser@npm:^2.0.6": + version: 2.1.4 + resolution: "error-stack-parser@npm:2.1.4" + dependencies: + stackframe: ^1.3.4 + checksum: 3b916d2d14c6682f287c8bfa28e14672f47eafe832701080e420e7cdbaebb2c50293868256a95706ac2330fe078cf5664713158b49bc30d7a5f2ac229ded0e18 + languageName: node + linkType: hard + +"es-abstract@npm:^1.17.2, es-abstract@npm:^1.19.0, es-abstract@npm:^1.20.4": + version: 1.21.1 + resolution: "es-abstract@npm:1.21.1" + dependencies: + available-typed-arrays: ^1.0.5 + call-bind: ^1.0.2 + es-set-tostringtag: ^2.0.1 + es-to-primitive: ^1.2.1 + function-bind: ^1.1.1 + function.prototype.name: ^1.1.5 + get-intrinsic: ^1.1.3 + get-symbol-description: ^1.0.0 + globalthis: ^1.0.3 + gopd: ^1.0.1 + has: ^1.0.3 + has-property-descriptors: ^1.0.0 + has-proto: ^1.0.1 + has-symbols: ^1.0.3 + internal-slot: ^1.0.4 + is-array-buffer: ^3.0.1 + is-callable: ^1.2.7 + is-negative-zero: ^2.0.2 + is-regex: ^1.1.4 + is-shared-array-buffer: ^1.0.2 + is-string: ^1.0.7 + is-typed-array: ^1.1.10 + is-weakref: ^1.0.2 + object-inspect: ^1.12.2 + object-keys: ^1.1.1 + object.assign: ^4.1.4 + regexp.prototype.flags: ^1.4.3 + safe-regex-test: ^1.0.0 + string.prototype.trimend: ^1.0.6 + string.prototype.trimstart: ^1.0.6 + typed-array-length: ^1.0.4 + unbox-primitive: ^1.0.2 + which-typed-array: ^1.1.9 + checksum: 23ff60d42d17a55d150e7bcedbdb065d4077a8b98c436e0e2e1ef4dd532a6d78a56028673de0bd8ed464a43c46ba781c50d9af429b6a17e44dbd14c7d7fb7926 + languageName: node + linkType: hard + +"es-array-method-boxes-properly@npm:^1.0.0": + version: 1.0.0 + resolution: "es-array-method-boxes-properly@npm:1.0.0" + checksum: 2537fcd1cecf187083890bc6f5236d3a26bf39237433587e5bf63392e88faae929dbba78ff0120681a3f6f81c23fe3816122982c160d63b38c95c830b633b826 + languageName: node + linkType: hard + +"es-get-iterator@npm:^1.1.2": + version: 1.1.3 + resolution: "es-get-iterator@npm:1.1.3" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.1.3 + has-symbols: ^1.0.3 + is-arguments: ^1.1.1 + is-map: ^2.0.2 + is-set: ^2.0.2 + is-string: ^1.0.7 + isarray: ^2.0.5 + stop-iteration-iterator: ^1.0.0 + checksum: 8fa118da42667a01a7c7529f8a8cca514feeff243feec1ce0bb73baaa3514560bd09d2b3438873cf8a5aaec5d52da248131de153b28e2638a061b6e4df13267d + languageName: node + linkType: hard + +"es-module-lexer@npm:^0.9.0": + version: 0.9.3 + resolution: "es-module-lexer@npm:0.9.3" + checksum: 84bbab23c396281db2c906c766af58b1ae2a1a2599844a504df10b9e8dc77ec800b3211fdaa133ff700f5703d791198807bba25d9667392d27a5e9feda344da8 + languageName: node + linkType: hard + +"es-set-tostringtag@npm:^2.0.1": + version: 2.0.1 + resolution: "es-set-tostringtag@npm:2.0.1" + dependencies: + get-intrinsic: ^1.1.3 + has: ^1.0.3 + has-tostringtag: ^1.0.0 + checksum: ec416a12948cefb4b2a5932e62093a7cf36ddc3efd58d6c58ca7ae7064475ace556434b869b0bbeb0c365f1032a8ccd577211101234b69837ad83ad204fff884 + languageName: node + linkType: hard + +"es-shim-unscopables@npm:^1.0.0": + version: 1.0.0 + resolution: "es-shim-unscopables@npm:1.0.0" + dependencies: + has: ^1.0.3 + checksum: 83e95cadbb6ee44d3644dfad60dcad7929edbc42c85e66c3e99aefd68a3a5c5665f2686885cddb47dfeabfd77bd5ea5a7060f2092a955a729bbd8834f0d86fa1 + languageName: node + linkType: hard + +"es-to-primitive@npm:^1.2.1": + version: 1.2.1 + resolution: "es-to-primitive@npm:1.2.1" + dependencies: + is-callable: ^1.1.4 + is-date-object: ^1.0.1 + is-symbol: ^1.0.2 + checksum: 4ead6671a2c1402619bdd77f3503991232ca15e17e46222b0a41a5d81aebc8740a77822f5b3c965008e631153e9ef0580540007744521e72de8e33599fca2eed + languageName: node + linkType: hard + +"escalade@npm:^3.1.1": + version: 3.1.1 + resolution: "escalade@npm:3.1.1" + checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 + languageName: node + linkType: hard + +"escape-html@npm:~1.0.3": + version: 1.0.3 + resolution: "escape-html@npm:1.0.3" + checksum: 6213ca9ae00d0ab8bccb6d8d4e0a98e76237b2410302cf7df70aaa6591d509a2a37ce8998008cbecae8fc8ffaadf3fb0229535e6a145f3ce0b211d060decbb24 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^1.0.5": + version: 1.0.5 + resolution: "escape-string-regexp@npm:1.0.5" + checksum: 6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^2.0.0": + version: 2.0.0 + resolution: "escape-string-regexp@npm:2.0.0" + checksum: 9f8a2d5743677c16e85c810e3024d54f0c8dea6424fad3c79ef6666e81dd0846f7437f5e729dfcdac8981bc9e5294c39b4580814d114076b8d36318f46ae4395 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^4.0.0": + version: 4.0.0 + resolution: "escape-string-regexp@npm:4.0.0" + checksum: 98b48897d93060f2322108bf29db0feba7dd774be96cd069458d1453347b25ce8682ecc39859d4bca2203cc0ab19c237bcc71755eff49a0f8d90beadeeba5cc5 + languageName: node + linkType: hard + +"escodegen@npm:^2.0.0": + version: 2.0.0 + resolution: "escodegen@npm:2.0.0" + dependencies: + esprima: ^4.0.1 + estraverse: ^5.2.0 + esutils: ^2.0.2 + optionator: ^0.8.1 + source-map: ~0.6.1 + dependenciesMeta: + source-map: + optional: true + bin: + escodegen: bin/escodegen.js + esgenerate: bin/esgenerate.js + checksum: 5aa6b2966fafe0545e4e77936300cc94ad57cfe4dc4ebff9950492eaba83eef634503f12d7e3cbd644ecc1bab388ad0e92b06fd32222c9281a75d1cf02ec6cef + languageName: node + linkType: hard + +"eslint-config-prettier@npm:8.10.0": + version: 8.10.0 + resolution: "eslint-config-prettier@npm:8.10.0" + peerDependencies: + eslint: ">=7.0.0" + bin: + eslint-config-prettier: bin/cli.js + checksum: 153266badd477e49b0759816246b2132f1dbdb6c7f313ca60a9af5822fd1071c2bc5684a3720d78b725452bbac04bb130878b2513aea5e72b1b792de5a69fec8 + languageName: node + linkType: hard + +"eslint-config-react-app@npm:7.0.0": + version: 7.0.0 + resolution: "eslint-config-react-app@npm:7.0.0" + dependencies: + "@babel/core": ^7.16.0 + "@babel/eslint-parser": ^7.16.3 + "@rushstack/eslint-patch": ^1.1.0 + "@typescript-eslint/eslint-plugin": ^5.5.0 + "@typescript-eslint/parser": ^5.5.0 + babel-preset-react-app: ^10.0.1 + confusing-browser-globals: ^1.0.11 + eslint-plugin-flowtype: ^8.0.3 + eslint-plugin-import: ^2.25.3 + eslint-plugin-jest: ^25.3.0 + eslint-plugin-jsx-a11y: ^6.5.1 + eslint-plugin-react: ^7.27.1 + eslint-plugin-react-hooks: ^4.3.0 + eslint-plugin-testing-library: ^5.0.1 + peerDependencies: + eslint: ^8.0.0 + checksum: dac130cfcb9689596ce3495692fecb25d913ba81de0e0c3e4b078ae79f0f0d20a77751f30823c5b3c09d66981c1df7f2836aa193f5c6c542faeb17761cd62019 + languageName: node + linkType: hard + +"eslint-config-react-app@npm:^7.0.0": + version: 7.0.1 + resolution: "eslint-config-react-app@npm:7.0.1" + dependencies: + "@babel/core": ^7.16.0 + "@babel/eslint-parser": ^7.16.3 + "@rushstack/eslint-patch": ^1.1.0 + "@typescript-eslint/eslint-plugin": ^5.5.0 + "@typescript-eslint/parser": ^5.5.0 + babel-preset-react-app: ^10.0.1 + confusing-browser-globals: ^1.0.11 + eslint-plugin-flowtype: ^8.0.3 + eslint-plugin-import: ^2.25.3 + eslint-plugin-jest: ^25.3.0 + eslint-plugin-jsx-a11y: ^6.5.1 + eslint-plugin-react: ^7.27.1 + eslint-plugin-react-hooks: ^4.3.0 + eslint-plugin-testing-library: ^5.0.1 + peerDependencies: + eslint: ^8.0.0 + checksum: a67e0821809e62308d6e419753fa2acfc7cd353659fab08cf34735f59c6c66910c0b6fda0471c4ec0d712ce762d65efc6431b39569f8d575e2d9bdfc384e0824 + languageName: node + linkType: hard + +"eslint-import-resolver-node@npm:^0.3.7": + version: 0.3.7 + resolution: "eslint-import-resolver-node@npm:0.3.7" + dependencies: + debug: ^3.2.7 + is-core-module: ^2.11.0 + resolve: ^1.22.1 + checksum: 3379aacf1d2c6952c1b9666c6fa5982c3023df695430b0d391c0029f6403a7775414873d90f397e98ba6245372b6c8960e16e74d9e4a3b0c0a4582f3bdbe3d6e + languageName: node + linkType: hard + +"eslint-module-utils@npm:^2.7.4": + version: 2.7.4 + resolution: "eslint-module-utils@npm:2.7.4" + dependencies: + debug: ^3.2.7 + peerDependenciesMeta: + eslint: + optional: true + checksum: 5da13645daff145a5c922896b258f8bba560722c3767254e458d894ff5fbb505d6dfd945bffa932a5b0ae06714da2379bd41011c4c20d2d59cc83e23895360f7 + languageName: node + linkType: hard + +"eslint-plugin-cypress@npm:2.15.1": + version: 2.15.1 + resolution: "eslint-plugin-cypress@npm:2.15.1" + dependencies: + globals: ^13.20.0 + peerDependencies: + eslint: ">= 3.2.1" + checksum: 3e66fa9a943fff52eaf3758250a63c2a0f8ffd60c50572beaf3688b33a55fbf0060d18ef32bc26abb57aef070517db827c22fd3d607582861d464970f95e550e + languageName: node + linkType: hard + +"eslint-plugin-flowtype@npm:^8.0.3": + version: 8.0.3 + resolution: "eslint-plugin-flowtype@npm:8.0.3" + dependencies: + lodash: ^4.17.21 + string-natural-compare: ^3.0.1 + peerDependencies: + "@babel/plugin-syntax-flow": ^7.14.5 + "@babel/plugin-transform-react-jsx": ^7.14.9 + eslint: ^8.1.0 + checksum: 30e63c5357b0b5571f39afed51e59c140084f4aa53c106b1fd04f26da42b268908466daa6020b92943e71409bdaee1c67202515ed9012404d027cc92cb03cefa + languageName: node + linkType: hard + +"eslint-plugin-import@npm:^2.25.3": + version: 2.27.5 + resolution: "eslint-plugin-import@npm:2.27.5" + dependencies: + array-includes: ^3.1.6 + array.prototype.flat: ^1.3.1 + array.prototype.flatmap: ^1.3.1 + debug: ^3.2.7 + doctrine: ^2.1.0 + eslint-import-resolver-node: ^0.3.7 + eslint-module-utils: ^2.7.4 + has: ^1.0.3 + is-core-module: ^2.11.0 + is-glob: ^4.0.3 + minimatch: ^3.1.2 + object.values: ^1.1.6 + resolve: ^1.22.1 + semver: ^6.3.0 + tsconfig-paths: ^3.14.1 + peerDependencies: + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + checksum: f500571a380167e25d72a4d925ef9a7aae8899eada57653e5f3051ec3d3c16d08271fcefe41a30a9a2f4fefc232f066253673ee4ea77b30dba65ae173dade85d + languageName: node + linkType: hard + +"eslint-plugin-jest@npm:^25.3.0": + version: 25.7.0 + resolution: "eslint-plugin-jest@npm:25.7.0" + dependencies: + "@typescript-eslint/experimental-utils": ^5.0.0 + peerDependencies: + "@typescript-eslint/eslint-plugin": ^4.0.0 || ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + "@typescript-eslint/eslint-plugin": + optional: true + jest: + optional: true + checksum: fc6da96131f4cbf33d15ef911ec8e600ccd71deb97d73c0ca340427cef7b01ff41a797e2e7d1e351abf97321a46ed0c0acff5ee8eeedac94961dd6dad1f718a9 + languageName: node + linkType: hard + +"eslint-plugin-jsx-a11y@npm:^6.5.1": + version: 6.7.1 + resolution: "eslint-plugin-jsx-a11y@npm:6.7.1" + dependencies: + "@babel/runtime": ^7.20.7 + aria-query: ^5.1.3 + array-includes: ^3.1.6 + array.prototype.flatmap: ^1.3.1 + ast-types-flow: ^0.0.7 + axe-core: ^4.6.2 + axobject-query: ^3.1.1 + damerau-levenshtein: ^1.0.8 + emoji-regex: ^9.2.2 + has: ^1.0.3 + jsx-ast-utils: ^3.3.3 + language-tags: =1.0.5 + minimatch: ^3.1.2 + object.entries: ^1.1.6 + object.fromentries: ^2.0.6 + semver: ^6.3.0 + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + checksum: f166dd5fe7257c7b891c6692e6a3ede6f237a14043ae3d97581daf318fc5833ddc6b4871aa34ab7656187430170500f6d806895747ea17ecdf8231a666c3c2fd + languageName: node + linkType: hard + +"eslint-plugin-prettier@npm:4.2.1": + version: 4.2.1 + resolution: "eslint-plugin-prettier@npm:4.2.1" + dependencies: + prettier-linter-helpers: ^1.0.0 + peerDependencies: + eslint: ">=7.28.0" + prettier: ">=2.0.0" + peerDependenciesMeta: + eslint-config-prettier: + optional: true + checksum: b9e839d2334ad8ec7a5589c5cb0f219bded260839a857d7a486997f9870e95106aa59b8756ff3f37202085ebab658de382b0267cae44c3a7f0eb0bcc03a4f6d6 + languageName: node + linkType: hard + +"eslint-plugin-react-hooks@npm:^4.3.0": + version: 4.6.0 + resolution: "eslint-plugin-react-hooks@npm:4.6.0" + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + checksum: 23001801f14c1d16bf0a837ca7970d9dd94e7b560384b41db378b49b6e32dc43d6e2790de1bd737a652a86f81a08d6a91f402525061b47719328f586a57e86c3 + languageName: node + linkType: hard + +"eslint-plugin-react@npm:^7.27.1": + version: 7.32.2 + resolution: "eslint-plugin-react@npm:7.32.2" + dependencies: + array-includes: ^3.1.6 + array.prototype.flatmap: ^1.3.1 + array.prototype.tosorted: ^1.1.1 + doctrine: ^2.1.0 + estraverse: ^5.3.0 + jsx-ast-utils: ^2.4.1 || ^3.0.0 + minimatch: ^3.1.2 + object.entries: ^1.1.6 + object.fromentries: ^2.0.6 + object.hasown: ^1.1.2 + object.values: ^1.1.6 + prop-types: ^15.8.1 + resolve: ^2.0.0-next.4 + semver: ^6.3.0 + string.prototype.matchall: ^4.0.8 + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + checksum: 2232b3b8945aa50b7773919c15cd96892acf35d2f82503667a79e2f55def90f728ed4f0e496f0f157acbe1bd4397c5615b676ae7428fe84488a544ca53feb944 + languageName: node + linkType: hard + +"eslint-plugin-testing-library@npm:^5.0.1": + version: 5.10.0 + resolution: "eslint-plugin-testing-library@npm:5.10.0" + dependencies: + "@typescript-eslint/utils": ^5.43.0 + peerDependencies: + eslint: ^7.5.0 || ^8.0.0 + checksum: 3278fc4683a99d24ac2b6d2ed0359db1b0509674350e4b9a958a226f57b4b90e070c02e1f4c2806da885d8025c1e8c952cb9a5e9751e69baac3d12cfe6804000 + languageName: node + linkType: hard + +"eslint-scope@npm:5.1.1, eslint-scope@npm:^5.1.1": + version: 5.1.1 + resolution: "eslint-scope@npm:5.1.1" + dependencies: + esrecurse: ^4.3.0 + estraverse: ^4.1.1 + checksum: 47e4b6a3f0cc29c7feedee6c67b225a2da7e155802c6ea13bbef4ac6b9e10c66cd2dcb987867ef176292bf4e64eccc680a49e35e9e9c669f4a02bac17e86abdb + languageName: node + linkType: hard + +"eslint-scope@npm:^7.2.2": + version: 7.2.2 + resolution: "eslint-scope@npm:7.2.2" + dependencies: + esrecurse: ^4.3.0 + estraverse: ^5.2.0 + checksum: ec97dbf5fb04b94e8f4c5a91a7f0a6dd3c55e46bfc7bbcd0e3138c3a76977570e02ed89a1810c778dcd72072ff0e9621ba1379b4babe53921d71e2e4486fda3e + languageName: node + linkType: hard + +"eslint-utils@npm:^3.0.0": + version: 3.0.0 + resolution: "eslint-utils@npm:3.0.0" + dependencies: + eslint-visitor-keys: ^2.0.0 + peerDependencies: + eslint: ">=5" + checksum: 0668fe02f5adab2e5a367eee5089f4c39033af20499df88fe4e6aba2015c20720404d8c3d6349b6f716b08fdf91b9da4e5d5481f265049278099c4c836ccb619 + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^2.0.0, eslint-visitor-keys@npm:^2.1.0": + version: 2.1.0 + resolution: "eslint-visitor-keys@npm:2.1.0" + checksum: e3081d7dd2611a35f0388bbdc2f5da60b3a3c5b8b6e928daffff7391146b434d691577aa95064c8b7faad0b8a680266bcda0a42439c18c717b80e6718d7e267d + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": + version: 3.4.3 + resolution: "eslint-visitor-keys@npm:3.4.3" + checksum: 36e9ef87fca698b6fd7ca5ca35d7b2b6eeaaf106572e2f7fd31c12d3bfdaccdb587bba6d3621067e5aece31c8c3a348b93922ab8f7b2cbc6aaab5e1d89040c60 + languageName: node + linkType: hard + +"eslint-webpack-plugin@npm:^3.1.1": + version: 3.2.0 + resolution: "eslint-webpack-plugin@npm:3.2.0" + dependencies: + "@types/eslint": ^7.29.0 || ^8.4.1 + jest-worker: ^28.0.2 + micromatch: ^4.0.5 + normalize-path: ^3.0.0 + schema-utils: ^4.0.0 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + webpack: ^5.0.0 + checksum: 095034c35e773fdb21ec7e597ae1f8a6899679c290db29d8568ca94619e8c7f4971f0f9edccc8a965322ab8af9286c87205985a38f4fdcf17654aee7cd8bb7b5 + languageName: node + linkType: hard + +"eslint@npm:8.56.0, eslint@npm:^8.3.0": + version: 8.56.0 + resolution: "eslint@npm:8.56.0" + dependencies: + "@eslint-community/eslint-utils": ^4.2.0 + "@eslint-community/regexpp": ^4.6.1 + "@eslint/eslintrc": ^2.1.4 + "@eslint/js": 8.56.0 + "@humanwhocodes/config-array": ^0.11.13 + "@humanwhocodes/module-importer": ^1.0.1 + "@nodelib/fs.walk": ^1.2.8 + "@ungap/structured-clone": ^1.2.0 + ajv: ^6.12.4 + 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.2.2 + eslint-visitor-keys: ^3.4.3 + espree: ^9.6.1 + esquery: ^1.4.2 + esutils: ^2.0.2 + fast-deep-equal: ^3.1.3 + file-entry-cache: ^6.0.1 + find-up: ^5.0.0 + glob-parent: ^6.0.2 + globals: ^13.19.0 + graphemer: ^1.4.0 + ignore: ^5.2.0 + imurmurhash: ^0.1.4 + is-glob: ^4.0.0 + is-path-inside: ^3.0.3 + js-yaml: ^4.1.0 + json-stable-stringify-without-jsonify: ^1.0.1 + levn: ^0.4.1 + lodash.merge: ^4.6.2 + minimatch: ^3.1.2 + natural-compare: ^1.4.0 + optionator: ^0.9.3 + strip-ansi: ^6.0.1 + text-table: ^0.2.0 + bin: + eslint: bin/eslint.js + checksum: 883436d1e809b4a25d9eb03d42f584b84c408dbac28b0019f6ea07b5177940bf3cca86208f749a6a1e0039b63e085ee47aca1236c30721e91f0deef5cc5a5136 + languageName: node + linkType: hard + +"espree@npm:^9.6.0, espree@npm:^9.6.1": + version: 9.6.1 + resolution: "espree@npm:9.6.1" + dependencies: + acorn: ^8.9.0 + acorn-jsx: ^5.3.2 + eslint-visitor-keys: ^3.4.1 + checksum: eb8c149c7a2a77b3f33a5af80c10875c3abd65450f60b8af6db1bfcfa8f101e21c1e56a561c6dc13b848e18148d43469e7cd208506238554fb5395a9ea5a1ab9 + languageName: node + linkType: hard + +"esprima@npm:^4.0.0, esprima@npm:^4.0.1": + version: 4.0.1 + resolution: "esprima@npm:4.0.1" + bin: + esparse: ./bin/esparse.js + esvalidate: ./bin/esvalidate.js + checksum: b45bc805a613dbea2835278c306b91aff6173c8d034223fa81498c77dcbce3b2931bf6006db816f62eacd9fd4ea975dfd85a5b7f3c6402cfd050d4ca3c13a628 + languageName: node + linkType: hard + +"esquery@npm:^1.4.2": + version: 1.5.0 + resolution: "esquery@npm:1.5.0" + dependencies: + estraverse: ^5.1.0 + checksum: aefb0d2596c230118656cd4ec7532d447333a410a48834d80ea648b1e7b5c9bc9ed8b5e33a89cb04e487b60d622f44cf5713bf4abed7c97343edefdc84a35900 + languageName: node + linkType: hard + +"esrecurse@npm:^4.3.0": + version: 4.3.0 + resolution: "esrecurse@npm:4.3.0" + dependencies: + estraverse: ^5.2.0 + checksum: ebc17b1a33c51cef46fdc28b958994b1dc43cd2e86237515cbc3b4e5d2be6a811b2315d0a1a4d9d340b6d2308b15322f5c8291059521cc5f4802f65e7ec32837 + languageName: node + linkType: hard + +"estraverse@npm:^4.1.1": + version: 4.3.0 + resolution: "estraverse@npm:4.3.0" + checksum: a6299491f9940bb246124a8d44b7b7a413a8336f5436f9837aaa9330209bd9ee8af7e91a654a3545aee9c54b3308e78ee360cef1d777d37cfef77d2fa33b5827 + languageName: node + linkType: hard + +"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0, estraverse@npm:^5.3.0": + version: 5.3.0 + resolution: "estraverse@npm:5.3.0" + checksum: 072780882dc8416ad144f8fe199628d2b3e7bbc9989d9ed43795d2c90309a2047e6bc5979d7e2322a341163d22cfad9e21f4110597fe487519697389497e4e2b + languageName: node + linkType: hard + +"estree-walker@npm:^1.0.1": + version: 1.0.1 + resolution: "estree-walker@npm:1.0.1" + checksum: 7e70da539691f6db03a08e7ce94f394ce2eef4180e136d251af299d41f92fb2d28ebcd9a6e393e3728d7970aeb5358705ddf7209d52fbcb2dd4693f95dcf925f + languageName: node + linkType: hard + +"esutils@npm:^2.0.2": + version: 2.0.3 + resolution: "esutils@npm:2.0.3" + checksum: 22b5b08f74737379a840b8ed2036a5fb35826c709ab000683b092d9054e5c2a82c27818f12604bfc2a9a76b90b6834ef081edbc1c7ae30d1627012e067c6ec87 + languageName: node + linkType: hard + +"etag@npm:~1.8.1": + version: 1.8.1 + resolution: "etag@npm:1.8.1" + checksum: 571aeb3dbe0f2bbd4e4fadbdb44f325fc75335cd5f6f6b6a091e6a06a9f25ed5392f0863c5442acb0646787446e816f13cbfc6edce5b07658541dff573cab1ff + languageName: node + linkType: hard + +"event-stream@npm:=3.3.4": + version: 3.3.4 + resolution: "event-stream@npm:3.3.4" + dependencies: + duplexer: ~0.1.1 + from: ~0 + map-stream: ~0.1.0 + pause-stream: 0.0.11 + split: 0.3 + stream-combiner: ~0.0.4 + through: ~2.3.1 + checksum: 80b467820b6daf824d9fb4345d2daf115a056e5c104463f2e98534e92d196a27f2df5ea2aa085624db26f4c45698905499e881d13bc7c01f7a13eac85be72a22 + languageName: node + linkType: hard + +"eventemitter2@npm:6.4.7": + version: 6.4.7 + resolution: "eventemitter2@npm:6.4.7" + checksum: 1b36a77e139d6965ebf3a36c01fa00c089ae6b80faa1911e52888f40b3a7057b36a2cc45dcd1ad87cda3798fe7b97a0aabcbb8175a8b96092a23bb7d0f039e66 + languageName: node + linkType: hard + +"eventemitter3@npm:^4.0.0": + version: 4.0.7 + resolution: "eventemitter3@npm:4.0.7" + checksum: 1875311c42fcfe9c707b2712c32664a245629b42bb0a5a84439762dd0fd637fc54d078155ea83c2af9e0323c9ac13687e03cfba79b03af9f40c89b4960099374 + languageName: node + linkType: hard + +"eventemitter3@npm:^5.0.1": + version: 5.0.1 + resolution: "eventemitter3@npm:5.0.1" + checksum: 543d6c858ab699303c3c32e0f0f47fc64d360bf73c3daf0ac0b5079710e340d6fe9f15487f94e66c629f5f82cd1a8678d692f3dbb6f6fcd1190e1b97fcad36f8 + languageName: node + linkType: hard + +"events@npm:^3.2.0": + version: 3.3.0 + resolution: "events@npm:3.3.0" + checksum: f6f487ad2198aa41d878fa31452f1a3c00958f46e9019286ff4787c84aac329332ab45c9cdc8c445928fc6d7ded294b9e005a7fce9426488518017831b272780 + languageName: node + linkType: hard + +"execa@npm:4.1.0": + version: 4.1.0 + resolution: "execa@npm:4.1.0" + dependencies: + cross-spawn: ^7.0.0 + get-stream: ^5.0.0 + human-signals: ^1.1.1 + is-stream: ^2.0.0 + merge-stream: ^2.0.0 + npm-run-path: ^4.0.0 + onetime: ^5.1.0 + signal-exit: ^3.0.2 + strip-final-newline: ^2.0.0 + checksum: e30d298934d9c52f90f3847704fd8224e849a081ab2b517bbc02f5f7732c24e56a21f14cb96a08256deffeb2d12b2b7cb7e2b014a12fb36f8d3357e06417ed55 + languageName: node + linkType: hard + +"execa@npm:5.1.1, execa@npm:^5.0.0, execa@npm:^5.1.1": + version: 5.1.1 + resolution: "execa@npm:5.1.1" + 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 + checksum: fba9022c8c8c15ed862847e94c252b3d946036d7547af310e344a527e59021fd8b6bb0723883ea87044dc4f0201f949046993124a42ccb0855cae5bf8c786343 + languageName: node + linkType: hard + +"execa@npm:7.2.0": + version: 7.2.0 + resolution: "execa@npm:7.2.0" + dependencies: + cross-spawn: ^7.0.3 + get-stream: ^6.0.1 + human-signals: ^4.3.0 + is-stream: ^3.0.0 + merge-stream: ^2.0.0 + npm-run-path: ^5.1.0 + onetime: ^6.0.0 + signal-exit: ^3.0.7 + strip-final-newline: ^3.0.0 + checksum: 14fd17ba0ca8c87b277584d93b1d9fc24f2a65e5152b31d5eb159a3b814854283eaae5f51efa9525e304447e2f757c691877f7adff8fde5746aae67eb1edd1cc + languageName: node + linkType: hard + +"executable@npm:^4.1.1": + version: 4.1.1 + resolution: "executable@npm:4.1.1" + dependencies: + pify: ^2.2.0 + checksum: f01927ce59bccec804e171bf859a26e362c1f50aa9ebc69f7cafdcce3859d29d4b6267fd47237c18b0a1830614bd3f0ee14b7380d9bad18a4e7af9b5f0b6984f + languageName: node + linkType: hard + +"exit@npm:^0.1.2": + version: 0.1.2 + resolution: "exit@npm:0.1.2" + checksum: abc407f07a875c3961e4781dfcb743b58d6c93de9ab263f4f8c9d23bb6da5f9b7764fc773f86b43dd88030444d5ab8abcb611cb680fba8ca075362b77114bba3 + languageName: node + linkType: hard + +"expect@npm:^27.5.1": + version: 27.5.1 + resolution: "expect@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + jest-get-type: ^27.5.1 + jest-matcher-utils: ^27.5.1 + jest-message-util: ^27.5.1 + checksum: b2c66beb52de53ef1872165aace40224e722bca3c2274c54cfa74b6d617d55cf0ccdbf36783ccd64dbea501b280098ed33fd0b207d4f15bc03cd3c7a24364a6a + languageName: node + linkType: hard + +"expect@npm:^29.0.0": + version: 29.4.1 + resolution: "expect@npm:29.4.1" + dependencies: + "@jest/expect-utils": ^29.4.1 + jest-get-type: ^29.2.0 + jest-matcher-utils: ^29.4.1 + jest-message-util: ^29.4.1 + jest-util: ^29.4.1 + checksum: 5918f69371557bbceb01bc163cd0ac03e8cbbc5de761892a9c27ef17a1f9e94dc91edd8298b4eaca18b71ba4a9d521c74b072f0a46950b13d6b61123b0431836 + languageName: node + linkType: hard + +"express@npm:4.19.2": + version: 4.19.2 + resolution: "express@npm:4.19.2" + dependencies: + accepts: ~1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.2 + content-disposition: 0.5.4 + content-type: ~1.0.4 + cookie: 0.6.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + etag: ~1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: ~1.1.2 + on-finished: 2.4.1 + parseurl: ~1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: ~2.0.7 + qs: 6.11.0 + range-parser: ~1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: ~1.6.18 + utils-merge: 1.0.1 + vary: ~1.1.2 + checksum: 212dbd6c2c222a96a61bc927639c95970a53b06257080bb9e2838adb3bffdb966856551fdad1ab5dd654a217c35db94f987d0aa88d48fb04d306340f5f34dca5 + languageName: node + linkType: hard + +"express@npm:^4.17.3": + version: 4.18.2 + resolution: "express@npm:4.18.2" + dependencies: + accepts: ~1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.1 + content-disposition: 0.5.4 + content-type: ~1.0.4 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + etag: ~1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: ~1.1.2 + on-finished: 2.4.1 + parseurl: ~1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: ~2.0.7 + qs: 6.11.0 + range-parser: ~1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: ~1.6.18 + utils-merge: 1.0.1 + vary: ~1.1.2 + checksum: 3c4b9b076879442f6b968fe53d85d9f1eeacbb4f4c41e5f16cc36d77ce39a2b0d81b3f250514982110d815b2f7173f5561367f9110fcc541f9371948e8c8b037 + languageName: node + linkType: hard + +"extend@npm:~3.0.2": + version: 3.0.2 + resolution: "extend@npm:3.0.2" + checksum: a50a8309ca65ea5d426382ff09f33586527882cf532931cb08ca786ea3146c0553310bda688710ff61d7668eba9f96b923fe1420cdf56a2c3eaf30fcab87b515 + languageName: node + linkType: hard + +"extract-zip@npm:2.0.1": + version: 2.0.1 + resolution: "extract-zip@npm:2.0.1" + dependencies: + "@types/yauzl": ^2.9.1 + debug: ^4.1.1 + get-stream: ^5.1.0 + yauzl: ^2.10.0 + dependenciesMeta: + "@types/yauzl": + optional: true + bin: + extract-zip: cli.js + checksum: 8cbda9debdd6d6980819cc69734d874ddd71051c9fe5bde1ef307ebcedfe949ba57b004894b585f758b7c9eeeea0e3d87f2dda89b7d25320459c2c9643ebb635 + languageName: node + linkType: hard + +"extsprintf@npm:1.3.0": + version: 1.3.0 + resolution: "extsprintf@npm:1.3.0" + checksum: cee7a4a1e34cffeeec18559109de92c27517e5641991ec6bab849aa64e3081022903dd53084f2080d0d2530803aa5ee84f1e9de642c365452f9e67be8f958ce2 + languageName: node + linkType: hard + +"extsprintf@npm:^1.2.0": + version: 1.4.1 + resolution: "extsprintf@npm:1.4.1" + checksum: a2f29b241914a8d2bad64363de684821b6b1609d06ae68d5b539e4de6b28659715b5bea94a7265201603713b7027d35399d10b0548f09071c5513e65e8323d33 + languageName: node + linkType: hard + +"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": + version: 3.1.3 + resolution: "fast-deep-equal@npm:3.1.3" + checksum: e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d + languageName: node + linkType: hard + +"fast-diff@npm:^1.1.2": + version: 1.2.0 + resolution: "fast-diff@npm:1.2.0" + checksum: 1b5306eaa9e826564d9e5ffcd6ebd881eb5f770b3f977fcbf38f05c824e42172b53c79920e8429c54eb742ce15a0caf268b0fdd5b38f6de52234c4a8368131ae + languageName: node + linkType: hard + +"fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.9": + version: 3.2.12 + resolution: "fast-glob@npm:3.2.12" + dependencies: + "@nodelib/fs.stat": ^2.0.2 + "@nodelib/fs.walk": ^1.2.3 + glob-parent: ^5.1.2 + merge2: ^1.3.0 + micromatch: ^4.0.4 + checksum: 0b1990f6ce831c7e28c4d505edcdaad8e27e88ab9fa65eedadb730438cfc7cde4910d6c975d6b7b8dc8a73da4773702ebcfcd6e3518e73938bb1383badfe01c2 + languageName: node + linkType: hard + +"fast-json-stable-stringify@npm:^2.0.0, fast-json-stable-stringify@npm:^2.1.0": + version: 2.1.0 + resolution: "fast-json-stable-stringify@npm:2.1.0" + checksum: b191531e36c607977e5b1c47811158733c34ccb3bfde92c44798929e9b4154884378536d26ad90dfecd32e1ffc09c545d23535ad91b3161a27ddbb8ebe0cbecb + languageName: node + linkType: hard + +"fast-levenshtein@npm:^2.0.6, fast-levenshtein@npm:~2.0.6": + version: 2.0.6 + resolution: "fast-levenshtein@npm:2.0.6" + checksum: 92cfec0a8dfafd9c7a15fba8f2cc29cd0b62b85f056d99ce448bbcd9f708e18ab2764bda4dd5158364f4145a7c72788538994f0d1787b956ef0d1062b0f7c24c + languageName: node + linkType: hard + +"fast-url-parser@npm:1.1.3": + version: 1.1.3 + resolution: "fast-url-parser@npm:1.1.3" + dependencies: + punycode: ^1.3.2 + checksum: 5043d0c4a8d775ff58504d56c096563c11b113e4cb8a2668c6f824a1cd4fb3812e2fdf76537eb24a7ce4ae7def6bd9747da630c617cf2a4b6ce0c42514e4f21c + languageName: node + linkType: hard + +"fastq@npm:^1.6.0": + version: 1.15.0 + resolution: "fastq@npm:1.15.0" + dependencies: + reusify: ^1.0.4 + checksum: 0170e6bfcd5d57a70412440b8ef600da6de3b2a6c5966aeaf0a852d542daff506a0ee92d6de7679d1de82e644bce69d7a574a6c93f0b03964b5337eed75ada1a + languageName: node + linkType: hard + +"faye-websocket@npm:^0.11.3": + version: 0.11.4 + resolution: "faye-websocket@npm:0.11.4" + dependencies: + websocket-driver: ">=0.5.1" + checksum: d49a62caf027f871149fc2b3f3c7104dc6d62744277eb6f9f36e2d5714e847d846b9f7f0d0b7169b25a012e24a594cde11a93034b30732e4c683f20b8a5019fa + languageName: node + linkType: hard + +"fb-watchman@npm:^2.0.0": + version: 2.0.2 + resolution: "fb-watchman@npm:2.0.2" + dependencies: + bser: 2.1.1 + checksum: b15a124cef28916fe07b400eb87cbc73ca082c142abf7ca8e8de6af43eca79ca7bd13eb4d4d48240b3bd3136eaac40d16e42d6edf87a8e5d1dd8070626860c78 + languageName: node + linkType: hard + +"fd-slicer@npm:~1.1.0": + version: 1.1.0 + resolution: "fd-slicer@npm:1.1.0" + dependencies: + pend: ~1.2.0 + checksum: c8585fd5713f4476eb8261150900d2cb7f6ff2d87f8feb306ccc8a1122efd152f1783bdb2b8dc891395744583436bfd8081d8e63ece0ec8687eeefea394d4ff2 + languageName: node + linkType: hard + +"figures@npm:^3.2.0": + version: 3.2.0 + resolution: "figures@npm:3.2.0" + dependencies: + escape-string-regexp: ^1.0.5 + checksum: 85a6ad29e9aca80b49b817e7c89ecc4716ff14e3779d9835af554db91bac41c0f289c418923519392a1e582b4d10482ad282021330cd045bb7b80c84152f2a2b + languageName: node + linkType: hard + +"file-entry-cache@npm:^6.0.1": + version: 6.0.1 + resolution: "file-entry-cache@npm:6.0.1" + dependencies: + flat-cache: ^3.0.4 + checksum: f49701feaa6314c8127c3c2f6173cfefff17612f5ed2daaafc6da13b5c91fd43e3b2a58fd0d63f9f94478a501b167615931e7200e31485e320f74a33885a9c74 + languageName: node + linkType: hard + +"file-loader@npm:^6.2.0": + version: 6.2.0 + resolution: "file-loader@npm:6.2.0" + dependencies: + loader-utils: ^2.0.0 + schema-utils: ^3.0.0 + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + checksum: faf43eecf233f4897b0150aaa874eeeac214e4f9de49738a9e0ef734a30b5260059e85b7edadf852b98e415f875bd5f12587768a93fd52aaf2e479ecf95fab20 + languageName: node + linkType: hard + +"filelist@npm:^1.0.1": + version: 1.0.4 + resolution: "filelist@npm:1.0.4" + dependencies: + minimatch: ^5.0.1 + checksum: a303573b0821e17f2d5e9783688ab6fbfce5d52aaac842790ae85e704a6f5e4e3538660a63183d6453834dedf1e0f19a9dadcebfa3e926c72397694ea11f5160 + languageName: node + linkType: hard + +"filesize@npm:^8.0.6": + version: 8.0.7 + resolution: "filesize@npm:8.0.7" + checksum: 8603d27c5287b984cb100733640645e078f5f5ad65c6d913173e01fb99e09b0747828498fd86647685ccecb69be31f3587b9739ab1e50732116b2374aff4cbf9 + languageName: node + linkType: hard + +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" + dependencies: + to-regex-range: ^5.0.1 + checksum: b4abfbca3839a3d55e4ae5ec62e131e2e356bf4859ce8480c64c4876100f4df292a63e5bb1618e1d7460282ca2b305653064f01654474aa35c68000980f17798 + languageName: node + linkType: hard + +"finalhandler@npm:1.2.0": + version: 1.2.0 + resolution: "finalhandler@npm:1.2.0" + dependencies: + debug: 2.6.9 + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + on-finished: 2.4.1 + parseurl: ~1.3.3 + statuses: 2.0.1 + unpipe: ~1.0.0 + checksum: 92effbfd32e22a7dff2994acedbd9bcc3aa646a3e919ea6a53238090e87097f8ef07cced90aa2cc421abdf993aefbdd5b00104d55c7c5479a8d00ed105b45716 + languageName: node + linkType: hard + +"find-cache-dir@npm:^3.3.1": + version: 3.3.2 + resolution: "find-cache-dir@npm:3.3.2" + dependencies: + commondir: ^1.0.1 + make-dir: ^3.0.2 + pkg-dir: ^4.1.0 + checksum: 1e61c2e64f5c0b1c535bd85939ae73b0e5773142713273818cc0b393ee3555fb0fd44e1a5b161b8b6c3e03e98c2fcc9c227d784850a13a90a8ab576869576817 + languageName: node + linkType: hard + +"find-root@npm:^1.1.0": + version: 1.1.0 + resolution: "find-root@npm:1.1.0" + checksum: b2a59fe4b6c932eef36c45a048ae8f93c85640212ebe8363164814990ee20f154197505965f3f4f102efc33bfb1cbc26fd17c4a2fc739ebc51b886b137cbefaf + languageName: node + linkType: hard + +"find-up@npm:^3.0.0": + version: 3.0.0 + resolution: "find-up@npm:3.0.0" + dependencies: + locate-path: ^3.0.0 + checksum: 38eba3fe7a66e4bc7f0f5a1366dc25508b7cfc349f852640e3678d26ad9a6d7e2c43eff0a472287de4a9753ef58f066a0ea892a256fa3636ad51b3fe1e17fae9 + languageName: node + linkType: hard + +"find-up@npm:^4.0.0, find-up@npm:^4.1.0": + version: 4.1.0 + resolution: "find-up@npm:4.1.0" + dependencies: + locate-path: ^5.0.0 + path-exists: ^4.0.0 + checksum: 4c172680e8f8c1f78839486e14a43ef82e9decd0e74145f40707cc42e7420506d5ec92d9a11c22bd2c48fb0c384ea05dd30e10dd152fefeec6f2f75282a8b844 + languageName: node + linkType: hard + +"find-up@npm:^5.0.0": + version: 5.0.0 + resolution: "find-up@npm:5.0.0" + dependencies: + locate-path: ^6.0.0 + path-exists: ^4.0.0 + checksum: 07955e357348f34660bde7920783204ff5a26ac2cafcaa28bace494027158a97b9f56faaf2d89a6106211a8174db650dd9f503f9c0d526b1202d5554a00b9095 + languageName: node + linkType: hard + +"flat-cache@npm:^3.0.4": + version: 3.0.4 + resolution: "flat-cache@npm:3.0.4" + dependencies: + flatted: ^3.1.0 + rimraf: ^3.0.2 + checksum: 4fdd10ecbcbf7d520f9040dd1340eb5dfe951e6f0ecf2252edeec03ee68d989ec8b9a20f4434270e71bcfd57800dc09b3344fca3966b2eb8f613072c7d9a2365 + languageName: node + linkType: hard + +"flatted@npm:^3.1.0": + version: 3.2.7 + resolution: "flatted@npm:3.2.7" + checksum: 427633049d55bdb80201c68f7eb1cbd533e03eac541f97d3aecab8c5526f12a20ccecaeede08b57503e772c769e7f8680b37e8d482d1e5f8d7e2194687f9ea35 + languageName: node + linkType: hard + +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.0": + version: 1.15.6 + resolution: "follow-redirects@npm:1.15.6" + peerDependenciesMeta: + debug: + optional: true + checksum: a62c378dfc8c00f60b9c80cab158ba54e99ba0239a5dd7c81245e5a5b39d10f0c35e249c3379eae719ff0285fff88c365dd446fab19dee771f1d76252df1bbf5 + languageName: node + linkType: hard + +"for-each@npm:^0.3.3": + version: 0.3.3 + resolution: "for-each@npm:0.3.3" + dependencies: + is-callable: ^1.1.3 + checksum: 6c48ff2bc63362319c65e2edca4a8e1e3483a2fabc72fbe7feaf8c73db94fc7861bd53bc02c8a66a0c1dd709da6b04eec42e0abdd6b40ce47305ae92a25e5d28 + languageName: node + linkType: hard + +"forever-agent@npm:~0.6.1": + version: 0.6.1 + resolution: "forever-agent@npm:0.6.1" + checksum: 766ae6e220f5fe23676bb4c6a99387cec5b7b62ceb99e10923376e27bfea72f3c3aeec2ba5f45f3f7ba65d6616965aa7c20b15002b6860833bb6e394dea546a8 + languageName: node + linkType: hard + +"fork-ts-checker-webpack-plugin@npm:^6.5.0": + version: 6.5.3 + resolution: "fork-ts-checker-webpack-plugin@npm:6.5.3" + dependencies: + "@babel/code-frame": ^7.8.3 + "@types/json-schema": ^7.0.5 + chalk: ^4.1.0 + chokidar: ^3.4.2 + cosmiconfig: ^6.0.0 + deepmerge: ^4.2.2 + fs-extra: ^9.0.0 + glob: ^7.1.6 + memfs: ^3.1.2 + minimatch: ^3.0.4 + schema-utils: 2.7.0 + semver: ^7.3.2 + tapable: ^1.0.0 + peerDependencies: + eslint: ">= 6" + typescript: ">= 2.7" + vue-template-compiler: "*" + webpack: ">= 4" + peerDependenciesMeta: + eslint: + optional: true + vue-template-compiler: + optional: true + checksum: 9732a49bfeed8fc23e6e8a59795fa7c238edeba91040a9b520db54b4d316dda27f9f1893d360e296fd0ad8930627d364417d28a8c7007fba60cc730ebfce4956 + languageName: node + linkType: hard + +"form-data@npm:^3.0.0": + version: 3.0.1 + resolution: "form-data@npm:3.0.1" + dependencies: + asynckit: ^0.4.0 + combined-stream: ^1.0.8 + mime-types: ^2.1.12 + checksum: b019e8d35c8afc14a2bd8a7a92fa4f525a4726b6d5a9740e8d2623c30e308fbb58dc8469f90415a856698933c8479b01646a9dff33c87cc4e76d72aedbbf860d + languageName: node + linkType: hard + +"form-data@npm:^4.0.0": + version: 4.0.0 + resolution: "form-data@npm:4.0.0" + dependencies: + asynckit: ^0.4.0 + combined-stream: ^1.0.8 + mime-types: ^2.1.12 + checksum: 01135bf8675f9d5c61ff18e2e2932f719ca4de964e3be90ef4c36aacfc7b9cb2fceb5eca0b7e0190e3383fe51c5b37f4cb80b62ca06a99aaabfcfd6ac7c9328c + languageName: node + linkType: hard + +"form-data@npm:~2.3.2": + version: 2.3.3 + resolution: "form-data@npm:2.3.3" + dependencies: + asynckit: ^0.4.0 + combined-stream: ^1.0.6 + mime-types: ^2.1.12 + checksum: 10c1780fa13dbe1ff3100114c2ce1f9307f8be10b14bf16e103815356ff567b6be39d70fc4a40f8990b9660012dc24b0f5e1dde1b6426166eb23a445ba068ca3 + languageName: node + linkType: hard + +"forwarded@npm:0.2.0": + version: 0.2.0 + resolution: "forwarded@npm:0.2.0" + checksum: fd27e2394d8887ebd16a66ffc889dc983fbbd797d5d3f01087c020283c0f019a7d05ee85669383d8e0d216b116d720fc0cef2f6e9b7eb9f4c90c6e0bc7fd28e6 + languageName: node + linkType: hard + +"fraction.js@npm:^4.2.0": + version: 4.2.0 + resolution: "fraction.js@npm:4.2.0" + checksum: 8c76a6e21dedea87109d6171a0ac77afa14205794a565d71cb10d2925f629a3922da61bf45ea52dbc30bce4d8636dc0a27213a88cbd600eab047d82f9a3a94c5 + languageName: node + linkType: hard + +"fresh@npm:0.5.2": + version: 0.5.2 + resolution: "fresh@npm:0.5.2" + checksum: 13ea8b08f91e669a64e3ba3a20eb79d7ca5379a81f1ff7f4310d54e2320645503cc0c78daedc93dfb6191287295f6479544a649c64d8e41a1c0fb0c221552346 + languageName: node + linkType: hard + +"from@npm:~0": + version: 0.1.7 + resolution: "from@npm:0.1.7" + checksum: b85125b7890489656eb2e4f208f7654a93ec26e3aefaf3bbbcc0d496fc1941e4405834fcc9fe7333192aa2187905510ace70417bbf9ac6f6f4784a731d986939 + languageName: node + linkType: hard + +"fs-extra@npm:^10.0.0": + version: 10.1.0 + resolution: "fs-extra@npm:10.1.0" + dependencies: + graceful-fs: ^4.2.0 + jsonfile: ^6.0.1 + universalify: ^2.0.0 + checksum: dc94ab37096f813cc3ca12f0f1b5ad6744dfed9ed21e953d72530d103cea193c2f81584a39e9dee1bea36de5ee66805678c0dddc048e8af1427ac19c00fffc50 + languageName: node + linkType: hard + +"fs-extra@npm:^9.0.0, fs-extra@npm:^9.0.1, fs-extra@npm:^9.1.0": + version: 9.1.0 + resolution: "fs-extra@npm:9.1.0" + dependencies: + at-least-node: ^1.0.0 + graceful-fs: ^4.2.0 + jsonfile: ^6.0.1 + universalify: ^2.0.0 + checksum: ba71ba32e0faa74ab931b7a0031d1523c66a73e225de7426e275e238e312d07313d2da2d33e34a52aa406c8763ade5712eb3ec9ba4d9edce652bcacdc29e6b20 + languageName: node + linkType: hard + +"fs-minipass@npm:^2.0.0, fs-minipass@npm:^2.1.0": + version: 2.1.0 + resolution: "fs-minipass@npm:2.1.0" + dependencies: + minipass: ^3.0.0 + checksum: 1b8d128dae2ac6cc94230cc5ead341ba3e0efaef82dab46a33d171c044caaa6ca001364178d42069b2809c35a1c3c35079a32107c770e9ffab3901b59af8c8b1 + languageName: node + linkType: hard + +"fs-monkey@npm:^1.0.3": + version: 1.0.3 + resolution: "fs-monkey@npm:1.0.3" + checksum: cf50804833f9b88a476911ae911fe50f61a98d986df52f890bd97e7262796d023698cb2309fa9b74fdd8974f04315b648748a0a8ee059e7d5257b293bfc409c0 + languageName: node + linkType: hard + +"fs.realpath@npm:^1.0.0": + version: 1.0.0 + resolution: "fs.realpath@npm:1.0.0" + checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 + languageName: node + linkType: hard + +"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2": + version: 2.3.2 + resolution: "fsevents@npm:2.3.2" + dependencies: + node-gyp: latest + checksum: 97ade64e75091afee5265e6956cb72ba34db7819b4c3e94c431d4be2b19b8bb7a2d4116da417950c3425f17c8fe693d25e20212cac583ac1521ad066b77ae31f + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@^2.3.2#~builtin, fsevents@patch:fsevents@~2.3.2#~builtin": + version: 2.3.2 + resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1" + dependencies: + node-gyp: latest + conditions: os=darwin + languageName: node + linkType: hard + +"function-bind@npm:^1.1.1": + version: 1.1.1 + resolution: "function-bind@npm:1.1.1" + checksum: b32fbaebb3f8ec4969f033073b43f5c8befbb58f1a79e12f1d7490358150359ebd92f49e72ff0144f65f2c48ea2a605bff2d07965f548f6474fd8efd95bf361a + languageName: node + linkType: hard + +"function.prototype.name@npm:^1.1.5": + version: 1.1.5 + resolution: "function.prototype.name@npm:1.1.5" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.3 + es-abstract: ^1.19.0 + functions-have-names: ^1.2.2 + checksum: acd21d733a9b649c2c442f067567743214af5fa248dbeee69d8278ce7df3329ea5abac572be9f7470b4ec1cd4d8f1040e3c5caccf98ebf2bf861a0deab735c27 + languageName: node + linkType: hard + +"functions-have-names@npm:^1.2.2": + version: 1.2.3 + resolution: "functions-have-names@npm:1.2.3" + checksum: c3f1f5ba20f4e962efb71344ce0a40722163e85bee2101ce25f88214e78182d2d2476aa85ef37950c579eb6cf6ee811c17b3101bb84004bb75655f3e33f3fdb5 + languageName: node + linkType: hard + +"gauge@npm:^4.0.3": + version: 4.0.4 + resolution: "gauge@npm:4.0.4" + dependencies: + aproba: ^1.0.3 || ^2.0.0 + color-support: ^1.1.3 + console-control-strings: ^1.1.0 + has-unicode: ^2.0.1 + signal-exit: ^3.0.7 + string-width: ^4.2.3 + strip-ansi: ^6.0.1 + wide-align: ^1.1.5 + checksum: 788b6bfe52f1dd8e263cda800c26ac0ca2ff6de0b6eee2fe0d9e3abf15e149b651bd27bf5226be10e6e3edb5c4e5d5985a5a1a98137e7a892f75eff76467ad2d + languageName: node + linkType: hard + +"gensync@npm:^1.0.0-beta.2": + version: 1.0.0-beta.2 + resolution: "gensync@npm:1.0.0-beta.2" + checksum: a7437e58c6be12aa6c90f7730eac7fa9833dc78872b4ad2963d2031b00a3367a93f98aec75f9aaac7220848e4026d67a8655e870b24f20a543d103c0d65952ec + languageName: node + linkType: hard + +"get-caller-file@npm:^2.0.5": + version: 2.0.5 + resolution: "get-caller-file@npm:2.0.5" + checksum: b9769a836d2a98c3ee734a88ba712e62703f1df31b94b784762c433c27a386dd6029ff55c2a920c392e33657d80191edbf18c61487e198844844516f843496b9 + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3": + version: 1.2.0 + resolution: "get-intrinsic@npm:1.2.0" + dependencies: + function-bind: ^1.1.1 + has: ^1.0.3 + has-symbols: ^1.0.3 + checksum: 78fc0487b783f5c58cf2dccafc3ae656ee8d2d8062a8831ce4a95e7057af4587a1d4882246c033aca0a7b4965276f4802b45cc300338d1b77a73d3e3e3f4877d + languageName: node + linkType: hard + +"get-own-enumerable-property-symbols@npm:^3.0.0": + version: 3.0.2 + resolution: "get-own-enumerable-property-symbols@npm:3.0.2" + checksum: 8f0331f14159f939830884799f937343c8c0a2c330506094bc12cbee3665d88337fe97a4ea35c002cc2bdba0f5d9975ad7ec3abb925015cdf2a93e76d4759ede + languageName: node + linkType: hard + +"get-package-type@npm:^0.1.0": + version: 0.1.0 + resolution: "get-package-type@npm:0.1.0" + checksum: bba0811116d11e56d702682ddef7c73ba3481f114590e705fc549f4d868972263896af313c57a25c076e3c0d567e11d919a64ba1b30c879be985fc9d44f96148 + languageName: node + linkType: hard + +"get-stream@npm:^5.0.0, get-stream@npm:^5.1.0": + version: 5.2.0 + resolution: "get-stream@npm:5.2.0" + dependencies: + pump: ^3.0.0 + checksum: 8bc1a23174a06b2b4ce600df38d6c98d2ef6d84e020c1ddad632ad75bac4e092eeb40e4c09e0761c35fc2dbc5e7fff5dab5e763a383582c4a167dd69a905bd12 + languageName: node + linkType: hard + +"get-stream@npm:^6.0.0, get-stream@npm:^6.0.1": + version: 6.0.1 + resolution: "get-stream@npm:6.0.1" + checksum: e04ecece32c92eebf5b8c940f51468cd53554dcbb0ea725b2748be583c9523d00128137966afce410b9b051eb2ef16d657cd2b120ca8edafcf5a65e81af63cad + languageName: node + linkType: hard + +"get-symbol-description@npm:^1.0.0": + version: 1.0.0 + resolution: "get-symbol-description@npm:1.0.0" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.1.1 + checksum: 9ceff8fe968f9270a37a1f73bf3f1f7bda69ca80f4f80850670e0e7b9444ff99323f7ac52f96567f8b5f5fbe7ac717a0d81d3407c7313e82810c6199446a5247 + languageName: node + linkType: hard + +"getos@npm:^3.2.1": + version: 3.2.1 + resolution: "getos@npm:3.2.1" + dependencies: + async: ^3.2.0 + checksum: 42fd78a66d47cebd3e09de5566cc0044e034b08f4a000a310dbd89a77b02c65d8f4002554bfa495ea5bdc4fa9d515f5ac785a7cc474ba45383cc697f865eeaf1 + languageName: node + linkType: hard + +"getpass@npm:^0.1.1": + version: 0.1.7 + resolution: "getpass@npm:0.1.7" + dependencies: + assert-plus: ^1.0.0 + checksum: ab18d55661db264e3eac6012c2d3daeafaab7a501c035ae0ccb193c3c23e9849c6e29b6ac762b9c2adae460266f925d55a3a2a3a3c8b94be2f222df94d70c046 + languageName: node + linkType: hard + +"glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": + version: 5.1.2 + resolution: "glob-parent@npm:5.1.2" + dependencies: + is-glob: ^4.0.1 + checksum: f4f2bfe2425296e8a47e36864e4f42be38a996db40420fe434565e4480e3322f18eb37589617a98640c5dc8fdec1a387007ee18dbb1f3f5553409c34d17f425e + languageName: node + linkType: hard + +"glob-parent@npm:^6.0.2": + version: 6.0.2 + resolution: "glob-parent@npm:6.0.2" + dependencies: + is-glob: ^4.0.3 + checksum: c13ee97978bef4f55106b71e66428eb1512e71a7466ba49025fc2aec59a5bfb0954d5abd58fc5ee6c9b076eef4e1f6d3375c2e964b88466ca390da4419a786a8 + languageName: node + linkType: hard + +"glob-to-regexp@npm:^0.4.1": + version: 0.4.1 + resolution: "glob-to-regexp@npm:0.4.1" + checksum: e795f4e8f06d2a15e86f76e4d92751cf8bbfcf0157cea5c2f0f35678a8195a750b34096b1256e436f0cebc1883b5ff0888c47348443e69546a5a87f9e1eb1167 + languageName: node + linkType: hard + +"glob@npm:^7.1.1, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6": + version: 7.2.3 + resolution: "glob@npm:7.2.3" + dependencies: + fs.realpath: ^1.0.0 + inflight: ^1.0.4 + inherits: 2 + minimatch: ^3.1.1 + once: ^1.3.0 + path-is-absolute: ^1.0.0 + checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 + languageName: node + linkType: hard + +"glob@npm:^8.0.1": + version: 8.1.0 + resolution: "glob@npm:8.1.0" + dependencies: + fs.realpath: ^1.0.0 + inflight: ^1.0.4 + inherits: 2 + minimatch: ^5.0.1 + once: ^1.3.0 + checksum: 92fbea3221a7d12075f26f0227abac435de868dd0736a17170663783296d0dd8d3d532a5672b4488a439bf5d7fb85cdd07c11185d6cd39184f0385cbdfb86a47 + languageName: node + linkType: hard + +"global-dirs@npm:^3.0.0": + version: 3.0.1 + resolution: "global-dirs@npm:3.0.1" + dependencies: + ini: 2.0.0 + checksum: 70147b80261601fd40ac02a104581432325c1c47329706acd773f3a6ce99bb36d1d996038c85ccacd482ad22258ec233c586b6a91535b1a116b89663d49d6438 + languageName: node + linkType: hard + +"global-modules@npm:^2.0.0": + version: 2.0.0 + resolution: "global-modules@npm:2.0.0" + dependencies: + global-prefix: ^3.0.0 + checksum: d6197f25856c878c2fb5f038899f2dca7cbb2f7b7cf8999660c0104972d5cfa5c68b5a0a77fa8206bb536c3903a4615665acb9709b4d80846e1bb47eaef65430 + languageName: node + linkType: hard + +"global-prefix@npm:^3.0.0": + version: 3.0.0 + resolution: "global-prefix@npm:3.0.0" + dependencies: + ini: ^1.3.5 + kind-of: ^6.0.2 + which: ^1.3.1 + checksum: 8a82fc1d6f22c45484a4e34656cc91bf021a03e03213b0035098d605bfc612d7141f1e14a21097e8a0413b4884afd5b260df0b6a25605ce9d722e11f1df2881d + languageName: node + linkType: hard + +"globals@npm:^11.1.0": + version: 11.12.0 + resolution: "globals@npm:11.12.0" + checksum: 67051a45eca3db904aee189dfc7cd53c20c7d881679c93f6146ddd4c9f4ab2268e68a919df740d39c71f4445d2b38ee360fc234428baea1dbdfe68bbcb46979e + languageName: node + linkType: hard + +"globals@npm:^13.19.0, globals@npm:^13.20.0": + version: 13.24.0 + resolution: "globals@npm:13.24.0" + dependencies: + type-fest: ^0.20.2 + checksum: 56066ef058f6867c04ff203b8a44c15b038346a62efbc3060052a1016be9f56f4cf0b2cd45b74b22b81e521a889fc7786c73691b0549c2f3a6e825b3d394f43c + languageName: node + linkType: hard + +"globalthis@npm:^1.0.3": + version: 1.0.3 + resolution: "globalthis@npm:1.0.3" + dependencies: + define-properties: ^1.1.3 + checksum: fbd7d760dc464c886d0196166d92e5ffb4c84d0730846d6621a39fbbc068aeeb9c8d1421ad330e94b7bca4bb4ea092f5f21f3d36077812af5d098b4dc006c998 + languageName: node + linkType: hard + +"globby@npm:^11.0.4, globby@npm:^11.1.0": + version: 11.1.0 + resolution: "globby@npm:11.1.0" + dependencies: + array-union: ^2.1.0 + dir-glob: ^3.0.1 + fast-glob: ^3.2.9 + ignore: ^5.2.0 + merge2: ^1.4.1 + slash: ^3.0.0 + checksum: b4be8885e0cfa018fc783792942d53926c35c50b3aefd3fdcfb9d22c627639dc26bd2327a40a0b74b074100ce95bb7187bfeae2f236856aa3de183af7a02aea6 + languageName: node + linkType: hard + +"gopd@npm:^1.0.1": + version: 1.0.1 + resolution: "gopd@npm:1.0.1" + dependencies: + get-intrinsic: ^1.1.3 + checksum: a5ccfb8806e0917a94e0b3de2af2ea4979c1da920bc381667c260e00e7cafdbe844e2cb9c5bcfef4e5412e8bf73bab837285bc35c7ba73aaaf0134d4583393a6 + languageName: node + linkType: hard + +"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": + version: 4.2.10 + resolution: "graceful-fs@npm:4.2.10" + checksum: 3f109d70ae123951905d85032ebeae3c2a5a7a997430df00ea30df0e3a6c60cf6689b109654d6fdacd28810a053348c4d14642da1d075049e6be1ba5216218da + languageName: node + linkType: hard + +"graphemer@npm:^1.4.0": + version: 1.4.0 + resolution: "graphemer@npm:1.4.0" + checksum: bab8f0be9b568857c7bec9fda95a89f87b783546d02951c40c33f84d05bb7da3fd10f863a9beb901463669b6583173a8c8cc6d6b306ea2b9b9d5d3d943c3a673 + languageName: node + linkType: hard + +"gzip-size@npm:^6.0.0": + version: 6.0.0 + resolution: "gzip-size@npm:6.0.0" + dependencies: + duplexer: ^0.1.2 + checksum: 2df97f359696ad154fc171dcb55bc883fe6e833bca7a65e457b9358f3cb6312405ed70a8da24a77c1baac0639906cd52358dc0ce2ec1a937eaa631b934c94194 + languageName: node + linkType: hard + +"handle-thing@npm:^2.0.0": + version: 2.0.1 + resolution: "handle-thing@npm:2.0.1" + checksum: 68071f313062315cd9dce55710e9496873945f1dd425107007058fc1629f93002a7649fcc3e464281ce02c7e809a35f5925504ab8105d972cf649f1f47cb7d6c + languageName: node + linkType: hard + +"harmony-reflect@npm:^1.4.6": + version: 1.6.2 + resolution: "harmony-reflect@npm:1.6.2" + checksum: 2e5bae414cd2bfae5476147f9935dc69ee9b9a413206994dcb94c5b3208d4555da3d4313aff6fd14bd9991c1e3ef69cdda5c8fac1eb1d7afc064925839339b8c + languageName: node + linkType: hard + +"has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2": + version: 1.0.2 + resolution: "has-bigints@npm:1.0.2" + checksum: 390e31e7be7e5c6fe68b81babb73dfc35d413604d7ee5f56da101417027a4b4ce6a27e46eff97ad040c835b5d228676eae99a9b5c3bc0e23c8e81a49241ff45b + languageName: node + linkType: hard + +"has-flag@npm:^3.0.0": + version: 3.0.0 + resolution: "has-flag@npm:3.0.0" + checksum: 4a15638b454bf086c8148979aae044dd6e39d63904cd452d970374fa6a87623423da485dfb814e7be882e05c096a7ccf1ebd48e7e7501d0208d8384ff4dea73b + languageName: node + linkType: hard + +"has-flag@npm:^4.0.0": + version: 4.0.0 + resolution: "has-flag@npm:4.0.0" + checksum: 261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad + languageName: node + linkType: hard + +"has-property-descriptors@npm:^1.0.0": + version: 1.0.0 + resolution: "has-property-descriptors@npm:1.0.0" + dependencies: + get-intrinsic: ^1.1.1 + checksum: a6d3f0a266d0294d972e354782e872e2fe1b6495b321e6ef678c9b7a06a40408a6891817350c62e752adced73a94ac903c54734fee05bf65b1905ee1368194bb + languageName: node + linkType: hard + +"has-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "has-proto@npm:1.0.1" + checksum: febc5b5b531de8022806ad7407935e2135f1cc9e64636c3916c6842bd7995994ca3b29871ecd7954bd35f9e2986c17b3b227880484d22259e2f8e6ce63fd383e + languageName: node + linkType: hard + +"has-symbols@npm:^1.0.1, has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": + version: 1.0.3 + resolution: "has-symbols@npm:1.0.3" + checksum: a054c40c631c0d5741a8285010a0777ea0c068f99ed43e5d6eb12972da223f8af553a455132fdb0801bdcfa0e0f443c0c03a68d8555aa529b3144b446c3f2410 + languageName: node + linkType: hard + +"has-tostringtag@npm:^1.0.0": + version: 1.0.0 + resolution: "has-tostringtag@npm:1.0.0" + dependencies: + has-symbols: ^1.0.2 + checksum: cc12eb28cb6ae22369ebaad3a8ab0799ed61270991be88f208d508076a1e99abe4198c965935ce85ea90b60c94ddda73693b0920b58e7ead048b4a391b502c1c + languageName: node + linkType: hard + +"has-unicode@npm:^2.0.1": + version: 2.0.1 + resolution: "has-unicode@npm:2.0.1" + checksum: 1eab07a7436512db0be40a710b29b5dc21fa04880b7f63c9980b706683127e3c1b57cb80ea96d47991bdae2dfe479604f6a1ba410106ee1046a41d1bd0814400 + languageName: node + linkType: hard + +"has@npm:^1.0.3": + version: 1.0.3 + resolution: "has@npm:1.0.3" + dependencies: + function-bind: ^1.1.1 + checksum: b9ad53d53be4af90ce5d1c38331e712522417d017d5ef1ebd0507e07c2fbad8686fffb8e12ddecd4c39ca9b9b47431afbb975b8abf7f3c3b82c98e9aad052792 + languageName: node + linkType: hard + +"he@npm:^1.2.0": + version: 1.2.0 + resolution: "he@npm:1.2.0" + bin: + he: bin/he + checksum: 3d4d6babccccd79c5c5a3f929a68af33360d6445587d628087f39a965079d84f18ce9c3d3f917ee1e3978916fc833bb8b29377c3b403f919426f91bc6965e7a7 + languageName: node + linkType: hard + +"hex-to-rgba@npm:2.0.1": + version: 2.0.1 + resolution: "hex-to-rgba@npm:2.0.1" + checksum: adbb81babe9d06cf743b925e2104968bb32d9e10f0de328b71c9e20ff52da4028fadde4623261866eaed4d9a3b975fb325fa34f2422eb035e839ed71ec462431 + languageName: node + linkType: hard + +"history@npm:4.10.1, history@npm:^4.9.0": + version: 4.10.1 + resolution: "history@npm:4.10.1" + dependencies: + "@babel/runtime": ^7.1.2 + loose-envify: ^1.2.0 + resolve-pathname: ^3.0.0 + tiny-invariant: ^1.0.2 + tiny-warning: ^1.0.0 + value-equal: ^1.0.1 + checksum: addd84bc4683929bae4400419b5af132ff4e4e9b311a0d4e224579ea8e184a6b80d7f72c55927e4fa117f69076a9e47ce082d8d0b422f1a9ddac7991490ca1d0 + languageName: node + linkType: hard + +"hoist-non-react-statics@npm:^3.1.0, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.1, hoist-non-react-statics@npm:^3.3.2": + version: 3.3.2 + resolution: "hoist-non-react-statics@npm:3.3.2" + dependencies: + react-is: ^16.7.0 + checksum: b1538270429b13901ee586aa44f4cc3ecd8831c061d06cb8322e50ea17b3f5ce4d0e2e66394761e6c8e152cd8c34fb3b4b690116c6ce2bd45b18c746516cb9e8 + languageName: node + linkType: hard + +"hoopy@npm:^0.1.4": + version: 0.1.4 + resolution: "hoopy@npm:0.1.4" + checksum: cfa60c7684c5e1ee4efe26e167bc54b73f839ffb59d1d44a5c4bf891e26b4f5bcc666555219a98fec95508fea4eda3a79540c53c05cc79afc1f66f9a238f4d9e + languageName: node + linkType: hard + +"hpack.js@npm:^2.1.6": + version: 2.1.6 + resolution: "hpack.js@npm:2.1.6" + dependencies: + inherits: ^2.0.1 + obuf: ^1.0.0 + readable-stream: ^2.0.1 + wbuf: ^1.1.0 + checksum: 2de144115197967ad6eeee33faf41096c6ba87078703c5cb011632dcfbffeb45784569e0cf02c317bd79c48375597c8ec88c30fff5bb0b023e8f654fb6e9c06e + languageName: node + linkType: hard + +"html-encoding-sniffer@npm:^2.0.1": + version: 2.0.1 + resolution: "html-encoding-sniffer@npm:2.0.1" + dependencies: + whatwg-encoding: ^1.0.5 + checksum: bf30cce461015ed7e365736fcd6a3063c7bc016a91f74398ef6158886970a96333938f7c02417ab3c12aa82e3e53b40822145facccb9ddfbcdc15a879ae4d7ba + languageName: node + linkType: hard + +"html-entities@npm:^2.1.0, html-entities@npm:^2.3.2": + version: 2.3.3 + resolution: "html-entities@npm:2.3.3" + checksum: 92521501da8aa5f66fee27f0f022d6e9ceae62667dae93aa6a2f636afa71ad530b7fb24a18d4d6c124c9885970cac5f8a52dbf1731741161002816ae43f98196 + languageName: node + linkType: hard + +"html-escaper@npm:^2.0.0": + version: 2.0.2 + resolution: "html-escaper@npm:2.0.2" + checksum: d2df2da3ad40ca9ee3a39c5cc6475ef67c8f83c234475f24d8e9ce0dc80a2c82df8e1d6fa78ddd1e9022a586ea1bd247a615e80a5cd9273d90111ddda7d9e974 + languageName: node + linkType: hard + +"html-minifier-terser@npm:^6.0.2": + version: 6.1.0 + resolution: "html-minifier-terser@npm:6.1.0" + dependencies: + camel-case: ^4.1.2 + clean-css: ^5.2.2 + commander: ^8.3.0 + he: ^1.2.0 + param-case: ^3.0.4 + relateurl: ^0.2.7 + terser: ^5.10.0 + bin: + html-minifier-terser: cli.js + checksum: ac52c14006476f773204c198b64838477859dc2879490040efab8979c0207424da55d59df7348153f412efa45a0840a1ca3c757bf14767d23a15e3e389d37a93 + languageName: node + linkType: hard + +"html-parse-stringify@npm:^3.0.1": + version: 3.0.1 + resolution: "html-parse-stringify@npm:3.0.1" + dependencies: + void-elements: 3.1.0 + checksum: 334fdebd4b5c355dba8e95284cead6f62bf865a2359da2759b039db58c805646350016d2017875718bc3c4b9bf81a0d11be5ee0cf4774a3a5a7b97cde21cfd67 + languageName: node + linkType: hard + +"html-webpack-plugin@npm:^5.5.0": + version: 5.5.0 + resolution: "html-webpack-plugin@npm:5.5.0" + dependencies: + "@types/html-minifier-terser": ^6.0.0 + html-minifier-terser: ^6.0.2 + lodash: ^4.17.21 + pretty-error: ^4.0.0 + tapable: ^2.0.0 + peerDependencies: + webpack: ^5.20.0 + checksum: f3d84d0df71fe2f5bac533cc74dce41ab058558cdcc6ff767d166a2abf1cf6fb8491d54d60ddbb34e95c00394e379ba52e0468e0284d1d0cc6a42987056e8219 + languageName: node + linkType: hard + +"htmlparser2@npm:^6.1.0": + version: 6.1.0 + resolution: "htmlparser2@npm:6.1.0" + dependencies: + domelementtype: ^2.0.1 + domhandler: ^4.0.0 + domutils: ^2.5.2 + entities: ^2.0.0 + checksum: 81a7b3d9c3bb9acb568a02fc9b1b81ffbfa55eae7f1c41ae0bf840006d1dbf54cb3aa245b2553e2c94db674840a9f0fdad7027c9a9d01a062065314039058c4e + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.0": + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 + languageName: node + linkType: hard + +"http-deceiver@npm:^1.2.7": + version: 1.2.7 + resolution: "http-deceiver@npm:1.2.7" + checksum: 64d7d1ae3a6933eb0e9a94e6f27be4af45a53a96c3c34e84ff57113787105a89fff9d1c3df263ef63add823df019b0e8f52f7121e32393bb5ce9a713bf100b41 + languageName: node + linkType: hard + +"http-errors@npm:2.0.0": + version: 2.0.0 + resolution: "http-errors@npm:2.0.0" + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + checksum: 9b0a3782665c52ce9dc658a0d1560bcb0214ba5699e4ea15aefb2a496e2ca83db03ebc42e1cce4ac1f413e4e0d2d736a3fd755772c556a9a06853ba2a0b7d920 + languageName: node + linkType: hard + +"http-errors@npm:~1.6.2": + version: 1.6.3 + resolution: "http-errors@npm:1.6.3" + dependencies: + depd: ~1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.0 + statuses: ">= 1.4.0 < 2" + checksum: a9654ee027e3d5de305a56db1d1461f25709ac23267c6dc28cdab8323e3f96caa58a9a6a5e93ac15d7285cee0c2f019378c3ada9026e7fe19c872d695f27de7c + languageName: node + linkType: hard + +"http-parser-js@npm:>=0.5.1": + version: 0.5.8 + resolution: "http-parser-js@npm:0.5.8" + checksum: 6bbdf2429858e8cf13c62375b0bfb6dc3955ca0f32e58237488bc86cd2378f31d31785fd3ac4ce93f1c74e0189cf8823c91f5cb061696214fd368d2452dc871d + languageName: node + linkType: hard + +"http-proxy-agent@npm:^4.0.1": + version: 4.0.1 + resolution: "http-proxy-agent@npm:4.0.1" + dependencies: + "@tootallnate/once": 1 + agent-base: 6 + debug: 4 + checksum: c6a5da5a1929416b6bbdf77b1aca13888013fe7eb9d59fc292e25d18e041bb154a8dfada58e223fc7b76b9b2d155a87e92e608235201f77d34aa258707963a82 + languageName: node + linkType: hard + +"http-proxy-agent@npm:^5.0.0": + version: 5.0.0 + resolution: "http-proxy-agent@npm:5.0.0" + dependencies: + "@tootallnate/once": 2 + agent-base: 6 + debug: 4 + checksum: e2ee1ff1656a131953839b2a19cd1f3a52d97c25ba87bd2559af6ae87114abf60971e498021f9b73f9fd78aea8876d1fb0d4656aac8a03c6caa9fc175f22b786 + languageName: node + linkType: hard + +"http-proxy-middleware@npm:^2.0.3": + version: 2.0.6 + resolution: "http-proxy-middleware@npm:2.0.6" + 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 + peerDependencies: + "@types/express": ^4.17.13 + peerDependenciesMeta: + "@types/express": + optional: true + checksum: 2ee85bc878afa6cbf34491e972ece0f5be0a3e5c98a60850cf40d2a9a5356e1fc57aab6cff33c1fc37691b0121c3a42602d2b1956c52577e87a5b77b62ae1c3a + languageName: node + linkType: hard + +"http-proxy@npm:^1.18.1": + version: 1.18.1 + resolution: "http-proxy@npm:1.18.1" + dependencies: + eventemitter3: ^4.0.0 + follow-redirects: ^1.0.0 + requires-port: ^1.0.0 + checksum: f5bd96bf83e0b1e4226633dbb51f8b056c3e6321917df402deacec31dd7fe433914fc7a2c1831cf7ae21e69c90b3a669b8f434723e9e8b71fd68afe30737b6a5 + languageName: node + linkType: hard + +"http-signature@npm:~1.3.6": + version: 1.3.6 + resolution: "http-signature@npm:1.3.6" + dependencies: + assert-plus: ^1.0.0 + jsprim: ^2.0.2 + sshpk: ^1.14.1 + checksum: 10be2af4764e71fee0281392937050201ee576ac755c543f570d6d87134ce5e858663fe999a7adb3e4e368e1e356d0d7fec6b9542295b875726ff615188e7a0c + languageName: node + linkType: hard + +"https-proxy-agent@npm:^5.0.0": + version: 5.0.1 + resolution: "https-proxy-agent@npm:5.0.1" + dependencies: + agent-base: 6 + debug: 4 + checksum: 571fccdf38184f05943e12d37d6ce38197becdd69e58d03f43637f7fa1269cf303a7d228aa27e5b27bbd3af8f09fd938e1c91dcfefff2df7ba77c20ed8dfc765 + languageName: node + linkType: hard + +"human-signals@npm:^1.1.1": + version: 1.1.1 + resolution: "human-signals@npm:1.1.1" + checksum: d587647c9e8ec24e02821b6be7de5a0fc37f591f6c4e319b3054b43fd4c35a70a94c46fc74d8c1a43c47fde157d23acd7421f375e1c1365b09a16835b8300205 + languageName: node + linkType: hard + +"human-signals@npm:^2.1.0": + version: 2.1.0 + resolution: "human-signals@npm:2.1.0" + checksum: b87fd89fce72391625271454e70f67fe405277415b48bcc0117ca73d31fa23a4241787afdc8d67f5a116cf37258c052f59ea82daffa72364d61351423848e3b8 + languageName: node + linkType: hard + +"human-signals@npm:^4.3.0": + version: 4.3.1 + resolution: "human-signals@npm:4.3.1" + checksum: 6f12958df3f21b6fdaf02d90896c271df00636a31e2bbea05bddf817a35c66b38a6fdac5863e2df85bd52f34958997f1f50350ff97249e1dff8452865d5235d1 + languageName: node + linkType: hard + +"humanize-ms@npm:^1.2.1": + version: 1.2.1 + resolution: "humanize-ms@npm:1.2.1" + dependencies: + ms: ^2.0.0 + checksum: 9c7a74a2827f9294c009266c82031030eae811ca87b0da3dceb8d6071b9bde22c9f3daef0469c3c533cc67a97d8a167cd9fc0389350e5f415f61a79b171ded16 + languageName: node + linkType: hard + +"husky@npm:8.0.1": + version: 8.0.1 + resolution: "husky@npm:8.0.1" + bin: + husky: lib/bin.js + checksum: 943a73a13d0201318fd30e83d299bb81d866bd245b69e6277804c3b462638dc1921694cb94c2b8c920a4a187060f7d6058d3365152865406352e934c5fff70dc + languageName: node + linkType: hard + +"i18next-browser-languagedetector@npm:7.2.0": + version: 7.2.0 + resolution: "i18next-browser-languagedetector@npm:7.2.0" + dependencies: + "@babel/runtime": ^7.23.2 + checksum: 757845c7ae7dfc541f5150855c3a3e4f6d29bcee113796d44dc781594abc7f16f2750a2a70d786904c16d23ba952eba2741c0bcfeaa381016669522a6236998f + languageName: node + linkType: hard + +"i18next-http-backend@npm:2.4.2": + version: 2.4.2 + resolution: "i18next-http-backend@npm:2.4.2" + dependencies: + cross-fetch: 4.0.0 + checksum: 90b71a024691988ae98781cfa9a6e1c25ee63b0206027939df85c55f46b91c41faaacea6f8a9f868a484bea9ee85377e1aae21a889b2dd970af9ac825120579c + languageName: node + linkType: hard + +"i18next@npm:22.0.3": + version: 22.0.3 + resolution: "i18next@npm:22.0.3" + dependencies: + "@babel/runtime": ^7.17.2 + checksum: 0ae40923e81f366c6e30126fad070b9188ee567374eb8046dc43ca9dd8bf3c4a3751c2e4c3f60f8d5cfcdb1925b884580cbb6cabfffba684f37c22a019d7f2b2 + languageName: node + linkType: hard + +"iconv-lite@npm:0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: ">= 2.1.2 < 3" + checksum: bd9f120f5a5b306f0bc0b9ae1edeb1577161503f5f8252a20f1a9e56ef8775c9959fd01c55f2d3a39d9a8abaf3e30c1abeb1895f367dcbbe0a8fd1c9ca01c4f6 + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: ">= 2.1.2 < 3.0.0" + checksum: 3f60d47a5c8fc3313317edfd29a00a692cc87a19cac0159e2ce711d0ebc9019064108323b5e493625e25594f11c6236647d8e256fbe7a58f4a3b33b89e6d30bf + languageName: node + linkType: hard + +"icss-utils@npm:^5.0.0, icss-utils@npm:^5.1.0": + version: 5.1.0 + resolution: "icss-utils@npm:5.1.0" + peerDependencies: + postcss: ^8.1.0 + checksum: 5c324d283552b1269cfc13a503aaaa172a280f914e5b81544f3803bc6f06a3b585fb79f66f7c771a2c052db7982c18bf92d001e3b47282e3abbbb4c4cc488d68 + languageName: node + linkType: hard + +"idb@npm:^7.0.1": + version: 7.1.1 + resolution: "idb@npm:7.1.1" + checksum: 1973c28d53c784b177bdef9f527ec89ec239ec7cf5fcbd987dae75a16c03f5b7dfcc8c6d3285716fd0309dd57739805390bd9f98ce23b1b7d8849a3b52de8d56 + languageName: node + linkType: hard + +"identity-obj-proxy@npm:^3.0.0": + version: 3.0.0 + resolution: "identity-obj-proxy@npm:3.0.0" + dependencies: + harmony-reflect: ^1.4.6 + checksum: 97559f8ea2aeaa1a880d279d8c49550dce01148321e00a2102cda5ddf9ce622fa1d7f3efc7bed63458af78889de888fdaebaf31c816312298bb3fdd0ef8aaf2c + languageName: node + linkType: hard + +"ieee754@npm:^1.1.13": + version: 1.2.1 + resolution: "ieee754@npm:1.2.1" + checksum: 5144c0c9815e54ada181d80a0b810221a253562422e7c6c3a60b1901154184f49326ec239d618c416c1c5945a2e197107aee8d986a3dd836b53dffefd99b5e7e + languageName: node + linkType: hard + +"ignore@npm:^5.2.0": + version: 5.2.4 + resolution: "ignore@npm:5.2.4" + checksum: 3d4c309c6006e2621659311783eaea7ebcd41fe4ca1d78c91c473157ad6666a57a2df790fe0d07a12300d9aac2888204d7be8d59f9aaf665b1c7fcdb432517ef + languageName: node + linkType: hard + +"immer@npm:^9.0.7": + version: 9.0.19 + resolution: "immer@npm:9.0.19" + checksum: f02ee53989989c287cd548a3d817fccf0bfe56db919755ee94a72ea3ae78a00363fba93ee6c010fe54a664380c29c53d44ed4091c6a86cae60957ad2cfabc010 + languageName: node + linkType: hard + +"immutable@npm:^3.8.1 || ^4.0.0-rc.1": + version: 4.2.2 + resolution: "immutable@npm:4.2.2" + checksum: 4d6437ea9388fe8ceca7eed5c768cf438cda7fa14d2831b87b90aa00cc60d536964d107c255b8a2e5dbf4f44a0e1295afbb9d1f0a65fb4f57b936e71df601862 + languageName: node + linkType: hard + +"import-fresh@npm:^3.1.0, import-fresh@npm:^3.2.1": + version: 3.3.0 + resolution: "import-fresh@npm:3.3.0" + dependencies: + parent-module: ^1.0.0 + resolve-from: ^4.0.0 + checksum: 2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa + languageName: node + linkType: hard + +"import-local@npm:^3.0.2": + version: 3.1.0 + resolution: "import-local@npm:3.1.0" + dependencies: + pkg-dir: ^4.2.0 + resolve-cwd: ^3.0.0 + bin: + import-local-fixture: fixtures/cli.js + checksum: bfcdb63b5e3c0e245e347f3107564035b128a414c4da1172a20dc67db2504e05ede4ac2eee1252359f78b0bfd7b19ef180aec427c2fce6493ae782d73a04cddd + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 7cae75c8cd9a50f57dadd77482359f659eaebac0319dd9368bcd1714f55e65badd6929ca58569da2b6494ef13fdd5598cd700b1eba23f8b79c5f19d195a3ecf7 + languageName: node + linkType: hard + +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 824cfb9929d031dabf059bebfe08cf3137365e112019086ed3dcff6a0a7b698cb80cf67ccccde0e25b9e2d7527aa6cc1fed1ac490c752162496caba3e6699612 + languageName: node + linkType: hard + +"infer-owner@npm:^1.0.4": + version: 1.0.4 + resolution: "infer-owner@npm:1.0.4" + checksum: 181e732764e4a0611576466b4b87dac338972b839920b2a8cde43642e4ed6bd54dc1fb0b40874728f2a2df9a1b097b8ff83b56d5f8f8e3927f837fdcb47d8a89 + languageName: node + linkType: hard + +"inflight@npm:^1.0.4": + version: 1.0.6 + resolution: "inflight@npm:1.0.6" + dependencies: + once: ^1.3.0 + wrappy: 1 + checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd + languageName: node + linkType: hard + +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:~2.0.3": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 + languageName: node + linkType: hard + +"inherits@npm:2.0.3": + version: 2.0.3 + resolution: "inherits@npm:2.0.3" + checksum: 78cb8d7d850d20a5e9a7f3620db31483aa00ad5f722ce03a55b110e5a723539b3716a3b463e2b96ce3fe286f33afc7c131fa2f91407528ba80cea98a7545d4c0 + languageName: node + linkType: hard + +"ini@npm:2.0.0": + version: 2.0.0 + resolution: "ini@npm:2.0.0" + checksum: e7aadc5fb2e4aefc666d74ee2160c073995a4061556b1b5b4241ecb19ad609243b9cceafe91bae49c219519394bbd31512516cb22a3b1ca6e66d869e0447e84e + languageName: node + linkType: hard + +"ini@npm:^1.3.5, ini@npm:~1.3.0": + version: 1.3.8 + resolution: "ini@npm:1.3.8" + checksum: dfd98b0ca3a4fc1e323e38a6c8eb8936e31a97a918d3b377649ea15bdb15d481207a0dda1021efbd86b464cae29a0d33c1d7dcaf6c5672bee17fa849bc50a1b3 + languageName: node + linkType: hard + +"internal-slot@npm:^1.0.3, internal-slot@npm:^1.0.4": + version: 1.0.4 + resolution: "internal-slot@npm:1.0.4" + dependencies: + get-intrinsic: ^1.1.3 + has: ^1.0.3 + side-channel: ^1.0.4 + checksum: 8974588d06bab4f675573a3b52975370facf6486df51bc0567a982c7024fa29495f10b76c0d4dc742dd951d1b72024fdc1e31bb0bedf1678dc7aacacaf5a4f73 + languageName: node + linkType: hard + +"ip@npm:^2.0.0": + version: 2.0.1 + resolution: "ip@npm:2.0.1" + checksum: d765c9fd212b8a99023a4cde6a558a054c298d640fec1020567494d257afd78ca77e37126b1a3ef0e053646ced79a816bf50621d38d5e768cdde0431fa3b0d35 + languageName: node + linkType: hard + +"ipaddr.js@npm:1.9.1": + version: 1.9.1 + resolution: "ipaddr.js@npm:1.9.1" + checksum: f88d3825981486f5a1942414c8d77dd6674dd71c065adcfa46f578d677edcb99fda25af42675cb59db492fdf427b34a5abfcde3982da11a8fd83a500b41cfe77 + languageName: node + linkType: hard + +"ipaddr.js@npm:^2.0.1": + version: 2.0.1 + resolution: "ipaddr.js@npm:2.0.1" + checksum: dd194a394a843d470f88d17191b0948f383ed1c8e320813f850c336a0fcb5e9215d97ec26ca35ab4fbbd31392c8b3467f3e8344628029ed3710b2ff6b5d1034e + languageName: node + linkType: hard + +"is-arguments@npm:^1.1.1": + version: 1.1.1 + resolution: "is-arguments@npm:1.1.1" + dependencies: + call-bind: ^1.0.2 + has-tostringtag: ^1.0.0 + checksum: 7f02700ec2171b691ef3e4d0e3e6c0ba408e8434368504bb593d0d7c891c0dbfda6d19d30808b904a6cb1929bca648c061ba438c39f296c2a8ca083229c49f27 + languageName: node + linkType: hard + +"is-array-buffer@npm:^3.0.1": + version: 3.0.1 + resolution: "is-array-buffer@npm:3.0.1" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.1.3 + is-typed-array: ^1.1.10 + checksum: f26ab87448e698285daf707e52a533920449f7abf63714140ffab9d5571aa5a71ac2fa2677e8b793ad0d5d3e40078d4d2c8a0ab39c957e3cfc6513bb6c9dfdc9 + languageName: node + linkType: hard + +"is-arrayish@npm:^0.2.1": + version: 0.2.1 + resolution: "is-arrayish@npm:0.2.1" + checksum: eef4417e3c10e60e2c810b6084942b3ead455af16c4509959a27e490e7aee87cfb3f38e01bbde92220b528a0ee1a18d52b787e1458ee86174d8c7f0e58cd488f + languageName: node + linkType: hard + +"is-bigint@npm:^1.0.1": + version: 1.0.4 + resolution: "is-bigint@npm:1.0.4" + dependencies: + has-bigints: ^1.0.1 + checksum: c56edfe09b1154f8668e53ebe8252b6f185ee852a50f9b41e8d921cb2bed425652049fbe438723f6cb48a63ca1aa051e948e7e401e093477c99c84eba244f666 + languageName: node + linkType: hard + +"is-binary-path@npm:~2.1.0": + version: 2.1.0 + resolution: "is-binary-path@npm:2.1.0" + dependencies: + binary-extensions: ^2.0.0 + checksum: 84192eb88cff70d320426f35ecd63c3d6d495da9d805b19bc65b518984b7c0760280e57dbf119b7e9be6b161784a5a673ab2c6abe83abb5198a432232ad5b35c + languageName: node + linkType: hard + +"is-boolean-object@npm:^1.1.0": + version: 1.1.2 + resolution: "is-boolean-object@npm:1.1.2" + dependencies: + call-bind: ^1.0.2 + has-tostringtag: ^1.0.0 + checksum: c03b23dbaacadc18940defb12c1c0e3aaece7553ef58b162a0f6bba0c2a7e1551b59f365b91e00d2dbac0522392d576ef322628cb1d036a0fe51eb466db67222 + languageName: node + linkType: hard + +"is-callable@npm:^1.1.3, is-callable@npm:^1.1.4, is-callable@npm:^1.2.7": + version: 1.2.7 + resolution: "is-callable@npm:1.2.7" + checksum: 61fd57d03b0d984e2ed3720fb1c7a897827ea174bd44402878e059542ea8c4aeedee0ea0985998aa5cc2736b2fa6e271c08587addb5b3959ac52cf665173d1ac + languageName: node + linkType: hard + +"is-ci@npm:^3.0.0": + version: 3.0.1 + resolution: "is-ci@npm:3.0.1" + dependencies: + ci-info: ^3.2.0 + bin: + is-ci: bin.js + checksum: 192c66dc7826d58f803ecae624860dccf1899fc1f3ac5505284c0a5cf5f889046ffeb958fa651e5725d5705c5bcb14f055b79150ea5fcad7456a9569de60260e + languageName: node + linkType: hard + +"is-core-module@npm:^2.11.0, is-core-module@npm:^2.9.0": + version: 2.11.0 + resolution: "is-core-module@npm:2.11.0" + dependencies: + has: ^1.0.3 + checksum: f96fd490c6b48eb4f6d10ba815c6ef13f410b0ba6f7eb8577af51697de523e5f2cd9de1c441b51d27251bf0e4aebc936545e33a5d26d5d51f28d25698d4a8bab + languageName: node + linkType: hard + +"is-date-object@npm:^1.0.1, is-date-object@npm:^1.0.5": + version: 1.0.5 + resolution: "is-date-object@npm:1.0.5" + dependencies: + has-tostringtag: ^1.0.0 + checksum: baa9077cdf15eb7b58c79398604ca57379b2fc4cf9aa7a9b9e295278648f628c9b201400c01c5e0f7afae56507d741185730307cbe7cad3b9f90a77e5ee342fc + languageName: node + linkType: hard + +"is-docker@npm:^2.0.0, is-docker@npm:^2.1.1": + version: 2.2.1 + resolution: "is-docker@npm:2.2.1" + bin: + is-docker: cli.js + checksum: 3fef7ddbf0be25958e8991ad941901bf5922ab2753c46980b60b05c1bf9c9c2402d35e6dc32e4380b980ef5e1970a5d9d5e5aa2e02d77727c3b6b5e918474c56 + languageName: node + linkType: hard + +"is-extglob@npm:^2.1.1": + version: 2.1.1 + resolution: "is-extglob@npm:2.1.1" + checksum: df033653d06d0eb567461e58a7a8c9f940bd8c22274b94bf7671ab36df5719791aae15eef6d83bbb5e23283967f2f984b8914559d4449efda578c775c4be6f85 + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^4.0.0": + version: 4.0.0 + resolution: "is-fullwidth-code-point@npm:4.0.0" + checksum: 8ae89bf5057bdf4f57b346fb6c55e9c3dd2549983d54191d722d5c739397a903012cc41a04ee3403fd872e811243ef91a7c5196da7b5841dc6b6aae31a264a8d + languageName: node + linkType: hard + +"is-generator-fn@npm:^2.0.0": + version: 2.1.0 + resolution: "is-generator-fn@npm:2.1.0" + checksum: a6ad5492cf9d1746f73b6744e0c43c0020510b59d56ddcb78a91cbc173f09b5e6beff53d75c9c5a29feb618bfef2bf458e025ecf3a57ad2268e2fb2569f56215 + languageName: node + linkType: hard + +"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": + version: 4.0.3 + resolution: "is-glob@npm:4.0.3" + dependencies: + is-extglob: ^2.1.1 + checksum: d381c1319fcb69d341cc6e6c7cd588e17cd94722d9a32dbd60660b993c4fb7d0f19438674e68dfec686d09b7c73139c9166b47597f846af387450224a8101ab4 + languageName: node + linkType: hard + +"is-installed-globally@npm:~0.4.0": + version: 0.4.0 + resolution: "is-installed-globally@npm:0.4.0" + dependencies: + global-dirs: ^3.0.0 + is-path-inside: ^3.0.2 + checksum: 3359840d5982d22e9b350034237b2cda2a12bac1b48a721912e1ab8e0631dd07d45a2797a120b7b87552759a65ba03e819f1bd63f2d7ab8657ec0b44ee0bf399 + languageName: node + linkType: hard + +"is-lambda@npm:^1.0.1": + version: 1.0.1 + resolution: "is-lambda@npm:1.0.1" + checksum: 93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 + languageName: node + linkType: hard + +"is-map@npm:^2.0.1, is-map@npm:^2.0.2": + version: 2.0.2 + resolution: "is-map@npm:2.0.2" + checksum: ace3d0ecd667bbdefdb1852de601268f67f2db725624b1958f279316e13fecb8fa7df91fd60f690d7417b4ec180712f5a7ee967008e27c65cfd475cc84337728 + languageName: node + linkType: hard + +"is-module@npm:^1.0.0": + version: 1.0.0 + resolution: "is-module@npm:1.0.0" + checksum: 8cd5390730c7976fb4e8546dd0b38865ee6f7bacfa08dfbb2cc07219606755f0b01709d9361e01f13009bbbd8099fa2927a8ed665118a6105d66e40f1b838c3f + languageName: node + linkType: hard + +"is-negative-zero@npm:^2.0.2": + version: 2.0.2 + resolution: "is-negative-zero@npm:2.0.2" + checksum: f3232194c47a549da60c3d509c9a09be442507616b69454716692e37ae9f37c4dea264fb208ad0c9f3efd15a796a46b79df07c7e53c6227c32170608b809149a + languageName: node + linkType: hard + +"is-number-object@npm:^1.0.4": + version: 1.0.7 + resolution: "is-number-object@npm:1.0.7" + dependencies: + has-tostringtag: ^1.0.0 + checksum: d1e8d01bb0a7134c74649c4e62da0c6118a0bfc6771ea3c560914d52a627873e6920dd0fd0ebc0e12ad2ff4687eac4c308f7e80320b973b2c8a2c8f97a7524f7 + languageName: node + linkType: hard + +"is-number@npm:^7.0.0": + version: 7.0.0 + resolution: "is-number@npm:7.0.0" + checksum: 456ac6f8e0f3111ed34668a624e45315201dff921e5ac181f8ec24923b99e9f32ca1a194912dc79d539c97d33dba17dc635202ff0b2cf98326f608323276d27a + languageName: node + linkType: hard + +"is-obj@npm:^1.0.1": + version: 1.0.1 + resolution: "is-obj@npm:1.0.1" + checksum: 3ccf0efdea12951e0b9c784e2b00e77e87b2f8bd30b42a498548a8afcc11b3287342a2030c308e473e93a7a19c9ea7854c99a8832a476591c727df2a9c79796c + languageName: node + linkType: hard + +"is-path-inside@npm:^3.0.2, is-path-inside@npm:^3.0.3": + version: 3.0.3 + resolution: "is-path-inside@npm:3.0.3" + checksum: abd50f06186a052b349c15e55b182326f1936c89a78bf6c8f2b707412517c097ce04bc49a0ca221787bc44e1049f51f09a2ffb63d22899051988d3a618ba13e9 + languageName: node + linkType: hard + +"is-plain-obj@npm:^3.0.0": + version: 3.0.0 + resolution: "is-plain-obj@npm:3.0.0" + checksum: a6ebdf8e12ab73f33530641972a72a4b8aed6df04f762070d823808303e4f76d87d5ea5bd76f96a7bbe83d93f04ac7764429c29413bd9049853a69cb630fb21c + languageName: node + linkType: hard + +"is-plain-object@npm:^2.0.4": + version: 2.0.4 + resolution: "is-plain-object@npm:2.0.4" + dependencies: + isobject: ^3.0.1 + checksum: 2a401140cfd86cabe25214956ae2cfee6fbd8186809555cd0e84574f88de7b17abacb2e477a6a658fa54c6083ecbda1e6ae404c7720244cd198903848fca70ca + languageName: node + linkType: hard + +"is-port-reachable@npm:4.0.0": + version: 4.0.0 + resolution: "is-port-reachable@npm:4.0.0" + checksum: 47b7e10db8edcef27fbf9e50f0de85ad368d35688790ca64a13db67260111ac5f4b98989b11af06199fa93f25d810bd09a5b21b2c2646529668638f7c34d3c04 + languageName: node + linkType: hard + +"is-potential-custom-element-name@npm:^1.0.1": + version: 1.0.1 + resolution: "is-potential-custom-element-name@npm:1.0.1" + checksum: ced7bbbb6433a5b684af581872afe0e1767e2d1146b2207ca0068a648fb5cab9d898495d1ac0583524faaf24ca98176a7d9876363097c2d14fee6dd324f3a1ab + languageName: node + linkType: hard + +"is-regex@npm:^1.1.4": + version: 1.1.4 + resolution: "is-regex@npm:1.1.4" + dependencies: + call-bind: ^1.0.2 + has-tostringtag: ^1.0.0 + checksum: 362399b33535bc8f386d96c45c9feb04cf7f8b41c182f54174c1a45c9abbbe5e31290bbad09a458583ff6bf3b2048672cdb1881b13289569a7c548370856a652 + languageName: node + linkType: hard + +"is-regexp@npm:^1.0.0": + version: 1.0.0 + resolution: "is-regexp@npm:1.0.0" + checksum: be692828e24cba479ec33644326fa98959ec68ba77965e0291088c1a741feaea4919d79f8031708f85fd25e39de002b4520622b55460660b9c369e6f7187faef + languageName: node + linkType: hard + +"is-root@npm:^2.1.0": + version: 2.1.0 + resolution: "is-root@npm:2.1.0" + checksum: 37eea0822a2a9123feb58a9d101558ba276771a6d830f87005683349a9acff15958a9ca590a44e778c6b335660b83e85c744789080d734f6081a935a4880aee2 + languageName: node + linkType: hard + +"is-set@npm:^2.0.1, is-set@npm:^2.0.2": + version: 2.0.2 + resolution: "is-set@npm:2.0.2" + checksum: b64343faf45e9387b97a6fd32be632ee7b269bd8183701f3b3f5b71a7cf00d04450ed8669d0bd08753e08b968beda96fca73a10fd0ff56a32603f64deba55a57 + languageName: node + linkType: hard + +"is-shared-array-buffer@npm:^1.0.2": + version: 1.0.2 + resolution: "is-shared-array-buffer@npm:1.0.2" + dependencies: + call-bind: ^1.0.2 + checksum: 9508929cf14fdc1afc9d61d723c6e8d34f5e117f0bffda4d97e7a5d88c3a8681f633a74f8e3ad1fe92d5113f9b921dc5ca44356492079612f9a247efbce7032a + languageName: node + linkType: hard + +"is-stream@npm:^2.0.0": + version: 2.0.1 + resolution: "is-stream@npm:2.0.1" + checksum: b8e05ccdf96ac330ea83c12450304d4a591f9958c11fd17bed240af8d5ffe08aedafa4c0f4cfccd4d28dc9d4d129daca1023633d5c11601a6cbc77521f6fae66 + languageName: node + linkType: hard + +"is-stream@npm:^3.0.0": + version: 3.0.0 + resolution: "is-stream@npm:3.0.0" + checksum: 172093fe99119ffd07611ab6d1bcccfe8bc4aa80d864b15f43e63e54b7abc71e779acd69afdb854c4e2a67fdc16ae710e370eda40088d1cfc956a50ed82d8f16 + languageName: node + linkType: hard + +"is-string@npm:^1.0.5, is-string@npm:^1.0.7": + version: 1.0.7 + resolution: "is-string@npm:1.0.7" + dependencies: + has-tostringtag: ^1.0.0 + checksum: 323b3d04622f78d45077cf89aab783b2f49d24dc641aa89b5ad1a72114cfeff2585efc8c12ef42466dff32bde93d839ad321b26884cf75e5a7892a938b089989 + languageName: node + linkType: hard + +"is-symbol@npm:^1.0.2, is-symbol@npm:^1.0.3": + version: 1.0.4 + resolution: "is-symbol@npm:1.0.4" + dependencies: + has-symbols: ^1.0.2 + checksum: 92805812ef590738d9de49d677cd17dfd486794773fb6fa0032d16452af46e9b91bb43ffe82c983570f015b37136f4b53b28b8523bfb10b0ece7a66c31a54510 + languageName: node + linkType: hard + +"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.9": + version: 1.1.10 + resolution: "is-typed-array@npm:1.1.10" + dependencies: + available-typed-arrays: ^1.0.5 + call-bind: ^1.0.2 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-tostringtag: ^1.0.0 + checksum: aac6ecb59d4c56a1cdeb69b1f129154ef462bbffe434cb8a8235ca89b42f258b7ae94073c41b3cb7bce37f6a1733ad4499f07882d5d5093a7ba84dfc4ebb8017 + languageName: node + linkType: hard + +"is-typedarray@npm:^1.0.0, is-typedarray@npm:~1.0.0": + version: 1.0.0 + resolution: "is-typedarray@npm:1.0.0" + checksum: 3508c6cd0a9ee2e0df2fa2e9baabcdc89e911c7bd5cf64604586697212feec525aa21050e48affb5ffc3df20f0f5d2e2cf79b08caa64e1ccc9578e251763aef7 + languageName: node + linkType: hard + +"is-unicode-supported@npm:^0.1.0": + version: 0.1.0 + resolution: "is-unicode-supported@npm:0.1.0" + checksum: a2aab86ee7712f5c2f999180daaba5f361bdad1efadc9610ff5b8ab5495b86e4f627839d085c6530363c6d6d4ecbde340fb8e54bdb83da4ba8e0865ed5513c52 + languageName: node + linkType: hard + +"is-weakmap@npm:^2.0.1": + version: 2.0.1 + resolution: "is-weakmap@npm:2.0.1" + checksum: 1222bb7e90c32bdb949226e66d26cb7bce12e1e28e3e1b40bfa6b390ba3e08192a8664a703dff2a00a84825f4e022f9cd58c4599ff9981ab72b1d69479f4f7f6 + languageName: node + linkType: hard + +"is-weakref@npm:^1.0.2": + version: 1.0.2 + resolution: "is-weakref@npm:1.0.2" + dependencies: + call-bind: ^1.0.2 + checksum: 95bd9a57cdcb58c63b1c401c60a474b0f45b94719c30f548c891860f051bc2231575c290a6b420c6bc6e7ed99459d424c652bd5bf9a1d5259505dc35b4bf83de + languageName: node + linkType: hard + +"is-weakset@npm:^2.0.1": + version: 2.0.2 + resolution: "is-weakset@npm:2.0.2" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.1.1 + checksum: 5d8698d1fa599a0635d7ca85be9c26d547b317ed8fd83fc75f03efbe75d50001b5eececb1e9971de85fcde84f69ae6f8346bc92d20d55d46201d328e4c74a367 + languageName: node + linkType: hard + +"is-wsl@npm:^2.2.0": + version: 2.2.0 + resolution: "is-wsl@npm:2.2.0" + dependencies: + is-docker: ^2.0.0 + checksum: 20849846ae414997d290b75e16868e5261e86ff5047f104027026fd61d8b5a9b0b3ade16239f35e1a067b3c7cc02f70183cb661010ed16f4b6c7c93dad1b19d8 + languageName: node + linkType: hard + +"isarray@npm:0.0.1": + version: 0.0.1 + resolution: "isarray@npm:0.0.1" + checksum: 49191f1425681df4a18c2f0f93db3adb85573bcdd6a4482539d98eac9e705d8961317b01175627e860516a2fc45f8f9302db26e5a380a97a520e272e2a40a8d4 + languageName: node + linkType: hard + +"isarray@npm:^2.0.5": + version: 2.0.5 + resolution: "isarray@npm:2.0.5" + checksum: bd5bbe4104438c4196ba58a54650116007fa0262eccef13a4c55b2e09a5b36b59f1e75b9fcc49883dd9d4953892e6fc007eef9e9155648ceea036e184b0f930a + languageName: node + linkType: hard + +"isarray@npm:~1.0.0": + version: 1.0.0 + resolution: "isarray@npm:1.0.0" + checksum: f032df8e02dce8ec565cf2eb605ea939bdccea528dbcf565cdf92bfa2da9110461159d86a537388ef1acef8815a330642d7885b29010e8f7eac967c9993b65ab + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 26bf6c5480dda5161c820c5b5c751ae1e766c587b1f951ea3fcfc973bafb7831ae5b54a31a69bd670220e42e99ec154475025a468eae58ea262f813fdc8d1c62 + languageName: node + linkType: hard + +"isobject@npm:^3.0.1": + version: 3.0.1 + resolution: "isobject@npm:3.0.1" + checksum: db85c4c970ce30693676487cca0e61da2ca34e8d4967c2e1309143ff910c207133a969f9e4ddb2dc6aba670aabce4e0e307146c310350b298e74a31f7d464703 + languageName: node + linkType: hard + +"isstream@npm:~0.1.2": + version: 0.1.2 + resolution: "isstream@npm:0.1.2" + checksum: 1eb2fe63a729f7bdd8a559ab552c69055f4f48eb5c2f03724430587c6f450783c8f1cd936c1c952d0a927925180fcc892ebd5b174236cf1065d4bd5bdb37e963 + languageName: node + linkType: hard + +"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0": + version: 3.2.0 + resolution: "istanbul-lib-coverage@npm:3.2.0" + checksum: a2a545033b9d56da04a8571ed05c8120bf10e9bce01cf8633a3a2b0d1d83dff4ac4fe78d6d5673c27fc29b7f21a41d75f83a36be09f82a61c367b56aa73c1ff9 + languageName: node + linkType: hard + +"istanbul-lib-instrument@npm:^5.0.4, istanbul-lib-instrument@npm:^5.1.0": + version: 5.2.1 + resolution: "istanbul-lib-instrument@npm:5.2.1" + dependencies: + "@babel/core": ^7.12.3 + "@babel/parser": ^7.14.7 + "@istanbuljs/schema": ^0.1.2 + istanbul-lib-coverage: ^3.2.0 + semver: ^6.3.0 + checksum: bf16f1803ba5e51b28bbd49ed955a736488381e09375d830e42ddeb403855b2006f850711d95ad726f2ba3f1ae8e7366de7e51d2b9ac67dc4d80191ef7ddf272 + languageName: node + linkType: hard + +"istanbul-lib-report@npm:^3.0.0": + version: 3.0.0 + resolution: "istanbul-lib-report@npm:3.0.0" + dependencies: + istanbul-lib-coverage: ^3.0.0 + make-dir: ^3.0.0 + supports-color: ^7.1.0 + checksum: 3f29eb3f53c59b987386e07fe772d24c7f58c6897f34c9d7a296f4000de7ae3de9eb95c3de3df91dc65b134c84dee35c54eee572a56243e8907c48064e34ff1b + languageName: node + linkType: hard + +"istanbul-lib-source-maps@npm:^4.0.0": + version: 4.0.1 + resolution: "istanbul-lib-source-maps@npm:4.0.1" + dependencies: + debug: ^4.1.1 + istanbul-lib-coverage: ^3.0.0 + source-map: ^0.6.1 + checksum: 21ad3df45db4b81852b662b8d4161f6446cd250c1ddc70ef96a585e2e85c26ed7cd9c2a396a71533cfb981d1a645508bc9618cae431e55d01a0628e7dec62ef2 + languageName: node + linkType: hard + +"istanbul-reports@npm:^3.1.3": + version: 3.1.5 + resolution: "istanbul-reports@npm:3.1.5" + dependencies: + html-escaper: ^2.0.0 + istanbul-lib-report: ^3.0.0 + checksum: 7867228f83ed39477b188ea07e7ccb9b4f5320b6f73d1db93a0981b7414fa4ef72d3f80c4692c442f90fc250d9406e71d8d7ab65bb615cb334e6292b73192b89 + languageName: node + linkType: hard + +"jake@npm:^10.8.5": + version: 10.8.5 + resolution: "jake@npm:10.8.5" + dependencies: + async: ^3.2.3 + chalk: ^4.0.2 + filelist: ^1.0.1 + minimatch: ^3.0.4 + bin: + jake: ./bin/cli.js + checksum: 56c913ecf5a8d74325d0af9bc17a233bad50977438d44864d925bb6c45c946e0fee8c4c1f5fe2225471ef40df5222e943047982717ebff0d624770564d3c46ba + languageName: node + linkType: hard + +"jest-changed-files@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-changed-files@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + execa: ^5.0.0 + throat: ^6.0.1 + checksum: 95e9dc74c3ca688ef85cfeab270f43f8902721a6c8ade6ac2459459a77890c85977f537d6fb809056deaa6d9c3f075fa7d2699ff5f3bf7d3fda17c3760b79b15 + languageName: node + linkType: hard + +"jest-circus@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-circus@npm:27.5.1" + dependencies: + "@jest/environment": ^27.5.1 + "@jest/test-result": ^27.5.1 + "@jest/types": ^27.5.1 + "@types/node": "*" + chalk: ^4.0.0 + co: ^4.6.0 + dedent: ^0.7.0 + expect: ^27.5.1 + is-generator-fn: ^2.0.0 + jest-each: ^27.5.1 + jest-matcher-utils: ^27.5.1 + jest-message-util: ^27.5.1 + jest-runtime: ^27.5.1 + jest-snapshot: ^27.5.1 + jest-util: ^27.5.1 + pretty-format: ^27.5.1 + slash: ^3.0.0 + stack-utils: ^2.0.3 + throat: ^6.0.1 + checksum: 6192dccbccb3a6acfa361cbb97bdbabe94864ccf3d885932cfd41f19534329d40698078cf9be1489415e8234255d6ea9f9aff5396b79ad842a6fca6e6fc08fd0 + languageName: node + linkType: hard + +"jest-cli@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-cli@npm:27.5.1" + dependencies: + "@jest/core": ^27.5.1 + "@jest/test-result": ^27.5.1 + "@jest/types": ^27.5.1 + chalk: ^4.0.0 + exit: ^0.1.2 + graceful-fs: ^4.2.9 + import-local: ^3.0.2 + jest-config: ^27.5.1 + jest-util: ^27.5.1 + jest-validate: ^27.5.1 + prompts: ^2.0.1 + yargs: ^16.2.0 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 6c0a69fb48e500241409e09ff743ed72bc6578d7769e2c994724e7ef1e5587f6c1f85dc429e93b98ae38a365222993ee70f0acc2199358992120900984f349e5 + languageName: node + linkType: hard + +"jest-config@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-config@npm:27.5.1" + dependencies: + "@babel/core": ^7.8.0 + "@jest/test-sequencer": ^27.5.1 + "@jest/types": ^27.5.1 + babel-jest: ^27.5.1 + chalk: ^4.0.0 + ci-info: ^3.2.0 + deepmerge: ^4.2.2 + glob: ^7.1.1 + graceful-fs: ^4.2.9 + jest-circus: ^27.5.1 + jest-environment-jsdom: ^27.5.1 + jest-environment-node: ^27.5.1 + jest-get-type: ^27.5.1 + jest-jasmine2: ^27.5.1 + jest-regex-util: ^27.5.1 + jest-resolve: ^27.5.1 + jest-runner: ^27.5.1 + jest-util: ^27.5.1 + jest-validate: ^27.5.1 + micromatch: ^4.0.4 + parse-json: ^5.2.0 + pretty-format: ^27.5.1 + slash: ^3.0.0 + strip-json-comments: ^3.1.1 + peerDependencies: + ts-node: ">=9.0.0" + peerDependenciesMeta: + ts-node: + optional: true + checksum: 1188fd46c0ed78cbe3175eb9ad6712ccf74a74be33d9f0d748e147c107f0889f8b701fbff1567f31836ae18597dacdc43d6a8fc30dd34ade6c9229cc6c7cb82d + languageName: node + linkType: hard + +"jest-diff@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-diff@npm:27.5.1" + dependencies: + chalk: ^4.0.0 + diff-sequences: ^27.5.1 + jest-get-type: ^27.5.1 + pretty-format: ^27.5.1 + checksum: 8be27c1e1ee57b2bb2bef9c0b233c19621b4c43d53a3c26e2c00a4e805eb4ea11fe1694a06a9fb0e80ffdcfdc0d2b1cb0b85920b3f5c892327ecd1e7bd96b865 + languageName: node + linkType: hard + +"jest-diff@npm:^29.4.1": + version: 29.4.1 + resolution: "jest-diff@npm:29.4.1" + dependencies: + chalk: ^4.0.0 + diff-sequences: ^29.3.1 + jest-get-type: ^29.2.0 + pretty-format: ^29.4.1 + checksum: 359af2d11a75bbb3c91e3def8cfd0ede00afc6fb5d69d9495f2af5f6e18f692adb940d8338a186159f75afe48088d82bce14e2cc272cad9a5c2148bf0bc7f6bf + languageName: node + linkType: hard + +"jest-docblock@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-docblock@npm:27.5.1" + dependencies: + detect-newline: ^3.0.0 + checksum: c0fed6d55b229d8bffdd8d03f121dd1a3be77c88f50552d374f9e1ea3bde57bf6bea017a0add04628d98abcb1bfb48b456438eeca8a74ef0053f4dae3b95d29c + languageName: node + linkType: hard + +"jest-each@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-each@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + chalk: ^4.0.0 + jest-get-type: ^27.5.1 + jest-util: ^27.5.1 + pretty-format: ^27.5.1 + checksum: b5a6d8730fd938982569c9e0b42bdf3c242f97b957ed8155a6473b5f7b540970f8685524e7f53963dc1805319f4b6602abfc56605590ca19d55bd7a87e467e63 + languageName: node + linkType: hard + +"jest-environment-jsdom@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-environment-jsdom@npm:27.5.1" + dependencies: + "@jest/environment": ^27.5.1 + "@jest/fake-timers": ^27.5.1 + "@jest/types": ^27.5.1 + "@types/node": "*" + jest-mock: ^27.5.1 + jest-util: ^27.5.1 + jsdom: ^16.6.0 + checksum: bc104aef7d7530d0740402aa84ac812138b6d1e51fe58adecce679f82b99340ddab73e5ec68fa079f33f50c9ddec9728fc9f0ddcca2ad6f0b351eed2762cc555 + languageName: node + linkType: hard + +"jest-environment-node@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-environment-node@npm:27.5.1" + dependencies: + "@jest/environment": ^27.5.1 + "@jest/fake-timers": ^27.5.1 + "@jest/types": ^27.5.1 + "@types/node": "*" + jest-mock: ^27.5.1 + jest-util: ^27.5.1 + checksum: 0f988330c4f3eec092e3fb37ea753b0c6f702e83cd8f4d770af9c2bf964a70bc45fbd34ec6fdb6d71ce98a778d9f54afd673e63f222e4667fff289e8069dba39 + languageName: node + linkType: hard + +"jest-fail-on-console@npm:3.1.1": + version: 3.1.1 + resolution: "jest-fail-on-console@npm:3.1.1" + dependencies: + chalk: ^4.1.0 + checksum: dbc244766fb78525b2d4a7e879678b91032acefa04694e17edb5917e325abf8ee356bdf728bc1c89058d67b9c8b3da4cd45515232eb9ab1b973a6b4f57bfb7af + languageName: node + linkType: hard + +"jest-get-type@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-get-type@npm:27.5.1" + checksum: 63064ab70195c21007d897c1157bf88ff94a790824a10f8c890392e7d17eda9c3900513cb291ca1c8d5722cad79169764e9a1279f7c8a9c4cd6e9109ff04bbc0 + languageName: node + linkType: hard + +"jest-get-type@npm:^29.2.0": + version: 29.2.0 + resolution: "jest-get-type@npm:29.2.0" + checksum: e396fd880a30d08940ed8a8e43cd4595db1b8ff09649018eb358ca701811137556bae82626af73459e3c0f8c5e972ed1e57fd3b1537b13a260893dac60a90942 + languageName: node + linkType: hard + +"jest-haste-map@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-haste-map@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + "@types/graceful-fs": ^4.1.2 + "@types/node": "*" + anymatch: ^3.0.3 + fb-watchman: ^2.0.0 + fsevents: ^2.3.2 + graceful-fs: ^4.2.9 + jest-regex-util: ^27.5.1 + jest-serializer: ^27.5.1 + jest-util: ^27.5.1 + jest-worker: ^27.5.1 + micromatch: ^4.0.4 + walker: ^1.0.7 + dependenciesMeta: + fsevents: + optional: true + checksum: e092a1412829a9254b4725531ee72926de530f77fda7b0d9ea18008fb7623c16f72e772d8e93be71cac9e591b2c6843a669610887dd2c89bd9eb528856e3ab47 + languageName: node + linkType: hard + +"jest-jasmine2@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-jasmine2@npm:27.5.1" + dependencies: + "@jest/environment": ^27.5.1 + "@jest/source-map": ^27.5.1 + "@jest/test-result": ^27.5.1 + "@jest/types": ^27.5.1 + "@types/node": "*" + chalk: ^4.0.0 + co: ^4.6.0 + expect: ^27.5.1 + is-generator-fn: ^2.0.0 + jest-each: ^27.5.1 + jest-matcher-utils: ^27.5.1 + jest-message-util: ^27.5.1 + jest-runtime: ^27.5.1 + jest-snapshot: ^27.5.1 + jest-util: ^27.5.1 + pretty-format: ^27.5.1 + throat: ^6.0.1 + checksum: b716adf253ceb73db661936153394ab90d7f3a8ba56d6189b7cd4df8e4e2a4153b4e63ebb5d36e29ceb0f4c211d5a6f36ab7048c6abbd881c8646567e2ab8e6d + languageName: node + linkType: hard + +"jest-leak-detector@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-leak-detector@npm:27.5.1" + dependencies: + jest-get-type: ^27.5.1 + pretty-format: ^27.5.1 + checksum: 5c9689060960567ddaf16c570d87afa760a461885765d2c71ef4f4857bbc3af1482c34e3cce88e50beefde1bf35e33530b020480752057a7e3dbb1ca0bae359f + languageName: node + linkType: hard + +"jest-matcher-utils@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-matcher-utils@npm:27.5.1" + dependencies: + chalk: ^4.0.0 + jest-diff: ^27.5.1 + jest-get-type: ^27.5.1 + pretty-format: ^27.5.1 + checksum: bb2135fc48889ff3fe73888f6cc7168ddab9de28b51b3148f820c89fdfd2effdcad005f18be67d0b9be80eda208ad47290f62f03d0a33f848db2dd0273c8217a + languageName: node + linkType: hard + +"jest-matcher-utils@npm:^29.4.1": + version: 29.4.1 + resolution: "jest-matcher-utils@npm:29.4.1" + dependencies: + chalk: ^4.0.0 + jest-diff: ^29.4.1 + jest-get-type: ^29.2.0 + pretty-format: ^29.4.1 + checksum: ea84dbcae82241cb28e94ff586660aeec51196d9245413dc516ce3aa78140b3ea728b1168b242281b59ad513b0148b9f12d674729bd043a894a3ba9d6ec164f4 + languageName: node + linkType: hard + +"jest-message-util@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-message-util@npm:27.5.1" + dependencies: + "@babel/code-frame": ^7.12.13 + "@jest/types": ^27.5.1 + "@types/stack-utils": ^2.0.0 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + micromatch: ^4.0.4 + pretty-format: ^27.5.1 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: eb6d637d1411c71646de578c49826b6da8e33dd293e501967011de9d1916d53d845afbfb52a5b661ff1c495be7c13f751c48c7f30781fd94fbd64842e8195796 + languageName: node + linkType: hard + +"jest-message-util@npm:^28.1.3": + version: 28.1.3 + resolution: "jest-message-util@npm:28.1.3" + dependencies: + "@babel/code-frame": ^7.12.13 + "@jest/types": ^28.1.3 + "@types/stack-utils": ^2.0.0 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + micromatch: ^4.0.4 + pretty-format: ^28.1.3 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: 1f266854166dcc6900d75a88b54a25225a2f3710d463063ff1c99021569045c35c7d58557b25447a17eb3a65ce763b2f9b25550248b468a9d4657db365f39e96 + languageName: node + linkType: hard + +"jest-message-util@npm:^29.4.1": + version: 29.4.1 + resolution: "jest-message-util@npm:29.4.1" + dependencies: + "@babel/code-frame": ^7.12.13 + "@jest/types": ^29.4.1 + "@types/stack-utils": ^2.0.0 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + micromatch: ^4.0.4 + pretty-format: ^29.4.1 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: 7d49823401b6d42f0d2d63dd9c0f11d2f64783416f82a68634190abee46e600e25bb0b380c746726acc56e854687bb03a76e26e617fcdda78e8c6316423b694f + languageName: node + linkType: hard + +"jest-mock@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-mock@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + "@types/node": "*" + checksum: f5b5904bb1741b4a1687a5f492535b7b1758dc26534c72a5423305f8711292e96a601dec966df81bb313269fb52d47227e29f9c2e08324d79529172f67311be0 + languageName: node + linkType: hard + +"jest-pnp-resolver@npm:^1.2.2": + version: 1.2.3 + resolution: "jest-pnp-resolver@npm:1.2.3" + peerDependencies: + jest-resolve: "*" + peerDependenciesMeta: + jest-resolve: + optional: true + checksum: db1a8ab2cb97ca19c01b1cfa9a9c8c69a143fde833c14df1fab0766f411b1148ff0df878adea09007ac6a2085ec116ba9a996a6ad104b1e58c20adbf88eed9b2 + languageName: node + linkType: hard + +"jest-regex-util@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-regex-util@npm:27.5.1" + checksum: d45ca7a9543616a34f7f3079337439cf07566e677a096472baa2810e274b9808b76767c97b0a4029b8a5b82b9d256dee28ef9ad4138b2b9e5933f6fac106c418 + languageName: node + linkType: hard + +"jest-regex-util@npm:^28.0.0": + version: 28.0.2 + resolution: "jest-regex-util@npm:28.0.2" + checksum: 0ea8c5c82ec88bc85e273c0ec82e0c0f35f7a1e2d055070e50f0cc2a2177f848eec55f73e37ae0d045c3db5014c42b2f90ac62c1ab3fdb354d2abd66a9e08add + languageName: node + linkType: hard + +"jest-resolve-dependencies@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-resolve-dependencies@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + jest-regex-util: ^27.5.1 + jest-snapshot: ^27.5.1 + checksum: c67af97afad1da88f5530317c732bbd1262d1225f6cd7f4e4740a5db48f90ab0bd8564738ac70d1a43934894f9aef62205c1b8f8ee89e5c7a737e6a121ee4c25 + languageName: node + linkType: hard + +"jest-resolve@npm:^27.4.2, jest-resolve@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-resolve@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + jest-haste-map: ^27.5.1 + jest-pnp-resolver: ^1.2.2 + jest-util: ^27.5.1 + jest-validate: ^27.5.1 + resolve: ^1.20.0 + resolve.exports: ^1.1.0 + slash: ^3.0.0 + checksum: 735830e7265b20a348029738680bb2f6e37f80ecea86cda869a4c318ba3a45d39c7a3a873a22f7f746d86258c50ead6e7f501de043e201c095d7ba628a1c440f + languageName: node + linkType: hard + +"jest-runner@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-runner@npm:27.5.1" + dependencies: + "@jest/console": ^27.5.1 + "@jest/environment": ^27.5.1 + "@jest/test-result": ^27.5.1 + "@jest/transform": ^27.5.1 + "@jest/types": ^27.5.1 + "@types/node": "*" + chalk: ^4.0.0 + emittery: ^0.8.1 + graceful-fs: ^4.2.9 + jest-docblock: ^27.5.1 + jest-environment-jsdom: ^27.5.1 + jest-environment-node: ^27.5.1 + jest-haste-map: ^27.5.1 + jest-leak-detector: ^27.5.1 + jest-message-util: ^27.5.1 + jest-resolve: ^27.5.1 + jest-runtime: ^27.5.1 + jest-util: ^27.5.1 + jest-worker: ^27.5.1 + source-map-support: ^0.5.6 + throat: ^6.0.1 + checksum: 5bbe6cf847dd322b3332ec9d6977b54f91bd5f72ff620bc1a0192f0f129deda8aa7ca74c98922187a7aa87d8e0ce4f6c50e99a7ccb2a310bf4d94be2e0c3ce8e + languageName: node + linkType: hard + +"jest-runtime@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-runtime@npm:27.5.1" + dependencies: + "@jest/environment": ^27.5.1 + "@jest/fake-timers": ^27.5.1 + "@jest/globals": ^27.5.1 + "@jest/source-map": ^27.5.1 + "@jest/test-result": ^27.5.1 + "@jest/transform": ^27.5.1 + "@jest/types": ^27.5.1 + chalk: ^4.0.0 + cjs-module-lexer: ^1.0.0 + collect-v8-coverage: ^1.0.0 + execa: ^5.0.0 + glob: ^7.1.3 + graceful-fs: ^4.2.9 + jest-haste-map: ^27.5.1 + jest-message-util: ^27.5.1 + jest-mock: ^27.5.1 + jest-regex-util: ^27.5.1 + jest-resolve: ^27.5.1 + jest-snapshot: ^27.5.1 + jest-util: ^27.5.1 + slash: ^3.0.0 + strip-bom: ^4.0.0 + checksum: 929e3df0c53dab43f831f2af4e2996b22aa8cb2d6d483919d6b0426cbc100098fd5b777b998c6568b77f8c4d860b2e83127514292ff61416064f5ef926492386 + languageName: node + linkType: hard + +"jest-serializer@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-serializer@npm:27.5.1" + dependencies: + "@types/node": "*" + graceful-fs: ^4.2.9 + checksum: 803e03a552278610edc6753c0dd9fa5bb5cd3ca47414a7b2918106efb62b79fd5e9ae785d0a21f12a299fa599fea8acc1fa6dd41283328cee43962cf7df9bb44 + languageName: node + linkType: hard + +"jest-snapshot@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-snapshot@npm:27.5.1" + dependencies: + "@babel/core": ^7.7.2 + "@babel/generator": ^7.7.2 + "@babel/plugin-syntax-typescript": ^7.7.2 + "@babel/traverse": ^7.7.2 + "@babel/types": ^7.0.0 + "@jest/transform": ^27.5.1 + "@jest/types": ^27.5.1 + "@types/babel__traverse": ^7.0.4 + "@types/prettier": ^2.1.5 + babel-preset-current-node-syntax: ^1.0.0 + chalk: ^4.0.0 + expect: ^27.5.1 + graceful-fs: ^4.2.9 + jest-diff: ^27.5.1 + jest-get-type: ^27.5.1 + jest-haste-map: ^27.5.1 + jest-matcher-utils: ^27.5.1 + jest-message-util: ^27.5.1 + jest-util: ^27.5.1 + natural-compare: ^1.4.0 + pretty-format: ^27.5.1 + semver: ^7.3.2 + checksum: a5cfadf0d21cd76063925d1434bc076443ed6d87847d0e248f0b245f11db3d98ff13e45cc03b15404027dabecd712d925f47b6eae4f64986f688640a7d362514 + languageName: node + linkType: hard + +"jest-util@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-util@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + "@types/node": "*" + chalk: ^4.0.0 + ci-info: ^3.2.0 + graceful-fs: ^4.2.9 + picomatch: ^2.2.3 + checksum: ac8d122f6daf7a035dcea156641fd3701aeba245417c40836a77e35b3341b9c02ddc5d904cfcd4ddbaa00ab854da76d3b911870cafdcdbaff90ea471de26c7d7 + languageName: node + linkType: hard + +"jest-util@npm:^28.1.3": + version: 28.1.3 + resolution: "jest-util@npm:28.1.3" + dependencies: + "@jest/types": ^28.1.3 + "@types/node": "*" + chalk: ^4.0.0 + ci-info: ^3.2.0 + graceful-fs: ^4.2.9 + picomatch: ^2.2.3 + checksum: fd6459742c941f070223f25e38a2ac0719aad92561591e9fb2a50d602a5d19d754750b79b4074327a42b00055662b95da3b006542ceb8b54309da44d4a62e721 + languageName: node + linkType: hard + +"jest-util@npm:^29.4.1": + version: 29.4.1 + resolution: "jest-util@npm:29.4.1" + dependencies: + "@jest/types": ^29.4.1 + "@types/node": "*" + chalk: ^4.0.0 + ci-info: ^3.2.0 + graceful-fs: ^4.2.9 + picomatch: ^2.2.3 + checksum: 10a0e6c448ace1386f728ee3b7669f67878bb0c2e668a902d11140cc3f75c89a18f4142a37a24ccb587ede20dad86d497b3e8df4f26848a9be50a44779d92bc9 + languageName: node + linkType: hard + +"jest-validate@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-validate@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + camelcase: ^6.2.0 + chalk: ^4.0.0 + jest-get-type: ^27.5.1 + leven: ^3.1.0 + pretty-format: ^27.5.1 + checksum: 82e870f8ee7e4fb949652711b1567f05ae31c54be346b0899e8353e5c20fad7692b511905b37966945e90af8dc0383eb41a74f3ffefb16140ea4f9164d841412 + languageName: node + linkType: hard + +"jest-watch-typeahead@npm:^1.0.0": + version: 1.1.0 + resolution: "jest-watch-typeahead@npm:1.1.0" + dependencies: + ansi-escapes: ^4.3.1 + chalk: ^4.0.0 + jest-regex-util: ^28.0.0 + jest-watcher: ^28.0.0 + slash: ^4.0.0 + string-length: ^5.0.1 + strip-ansi: ^7.0.1 + peerDependencies: + jest: ^27.0.0 || ^28.0.0 + checksum: 59b0a494ac01e3801c9ec586de3209153eedb024b981e25443111c5703711d23b67ebc71b072986c1758307e0bfb5bf1c92bd323f73f58602d6f4f609dce6a0c + languageName: node + linkType: hard + +"jest-watcher@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-watcher@npm:27.5.1" + dependencies: + "@jest/test-result": ^27.5.1 + "@jest/types": ^27.5.1 + "@types/node": "*" + ansi-escapes: ^4.2.1 + chalk: ^4.0.0 + jest-util: ^27.5.1 + string-length: ^4.0.1 + checksum: 191c4e9c278c0902ade1a8a80883ac244963ba3e6e78607a3d5f729ccca9c6e71fb3b316f87883658132641c5d818aa84202585c76752e03c539e6cbecb820bd + languageName: node + linkType: hard + +"jest-watcher@npm:^28.0.0": + version: 28.1.3 + resolution: "jest-watcher@npm:28.1.3" + dependencies: + "@jest/test-result": ^28.1.3 + "@jest/types": ^28.1.3 + "@types/node": "*" + ansi-escapes: ^4.2.1 + chalk: ^4.0.0 + emittery: ^0.10.2 + jest-util: ^28.1.3 + string-length: ^4.0.1 + checksum: 8f6d674a4865e7df251f71544f1b51f06fd36b5a3a61f2ac81aeb81fa2a196be354fba51d0f97911c88f67cd254583b3a22ee124bf2c5b6ee2fadec27356c207 + languageName: node + linkType: hard + +"jest-worker@npm:^26.2.1": + version: 26.6.2 + resolution: "jest-worker@npm:26.6.2" + dependencies: + "@types/node": "*" + merge-stream: ^2.0.0 + supports-color: ^7.0.0 + checksum: f9afa3b88e3f12027901e4964ba3ff048285b5783b5225cab28fac25b4058cea8ad54001e9a1577ee2bed125fac3ccf5c80dc507b120300cc1bbcb368796533e + languageName: node + linkType: hard + +"jest-worker@npm:^27.0.2, jest-worker@npm:^27.4.5, jest-worker@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-worker@npm:27.5.1" + dependencies: + "@types/node": "*" + merge-stream: ^2.0.0 + supports-color: ^8.0.0 + checksum: 98cd68b696781caed61c983a3ee30bf880b5bd021c01d98f47b143d4362b85d0737f8523761e2713d45e18b4f9a2b98af1eaee77afade4111bb65c77d6f7c980 + languageName: node + linkType: hard + +"jest-worker@npm:^28.0.2": + version: 28.1.3 + resolution: "jest-worker@npm:28.1.3" + dependencies: + "@types/node": "*" + merge-stream: ^2.0.0 + supports-color: ^8.0.0 + checksum: e921c9a1b8f0909da9ea07dbf3592f95b653aef3a8bb0cbcd20fc7f9a795a1304adecac31eecb308992c167e8d7e75c522061fec38a5928ace0f9571c90169ca + languageName: node + linkType: hard + +"jest@npm:^27.4.3": + version: 27.5.1 + resolution: "jest@npm:27.5.1" + dependencies: + "@jest/core": ^27.5.1 + import-local: ^3.0.2 + jest-cli: ^27.5.1 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 96f1d69042b3c6dfc695f2a4e4b0db38af6fb78582ad1a02beaa57cfcd77cbd31567d7d865c1c85709b7c3e176eefa3b2035ffecd646005f15d8ef528eccf205 + languageName: node + linkType: hard + +"joi@npm:^17.7.0": + version: 17.9.2 + resolution: "joi@npm:17.9.2" + dependencies: + "@hapi/hoek": ^9.0.0 + "@hapi/topo": ^5.0.0 + "@sideway/address": ^4.1.3 + "@sideway/formula": ^3.0.1 + "@sideway/pinpoint": ^2.0.0 + checksum: 8c3709849293411c524e5a679dba7b42598a29a663478941767b8d5b06288611dece58803c468a2c7320cc2429a3e71e3d94337fe47aefcf6c22174dbd90b601 + languageName: node + linkType: hard + +"js-sha3@npm:0.8.0": + version: 0.8.0 + resolution: "js-sha3@npm:0.8.0" + checksum: 75df77c1fc266973f06cce8309ce010e9e9f07ec35ab12022ed29b7f0d9c8757f5a73e1b35aa24840dced0dea7059085aa143d817aea9e188e2a80d569d9adce + languageName: node + linkType: hard + +"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": + version: 4.0.0 + resolution: "js-tokens@npm:4.0.0" + checksum: 8a95213a5a77deb6cbe94d86340e8d9ace2b93bc367790b260101d2f36a2eaf4e4e22d9fa9cf459b38af3a32fb4190e638024cf82ec95ef708680e405ea7cc78 + languageName: node + linkType: hard + +"js-yaml@npm:^3.13.1": + version: 3.14.1 + resolution: "js-yaml@npm:3.14.1" + dependencies: + argparse: ^1.0.7 + esprima: ^4.0.0 + bin: + js-yaml: bin/js-yaml.js + checksum: bef146085f472d44dee30ec34e5cf36bf89164f5d585435a3d3da89e52622dff0b188a580e4ad091c3341889e14cb88cac6e4deb16dc5b1e9623bb0601fc255c + languageName: node + linkType: hard + +"js-yaml@npm:^4.1.0": + version: 4.1.0 + resolution: "js-yaml@npm:4.1.0" + dependencies: + argparse: ^2.0.1 + bin: + js-yaml: bin/js-yaml.js + checksum: c7830dfd456c3ef2c6e355cc5a92e6700ceafa1d14bba54497b34a99f0376cecbb3e9ac14d3e5849b426d5a5140709a66237a8c991c675431271c4ce5504151a + languageName: node + linkType: hard + +"jsbn@npm:~0.1.0": + version: 0.1.1 + resolution: "jsbn@npm:0.1.1" + checksum: e5ff29c1b8d965017ef3f9c219dacd6e40ad355c664e277d31246c90545a02e6047018c16c60a00f36d561b3647215c41894f5d869ada6908a2e0ce4200c88f2 + languageName: node + linkType: hard + +"jsdom@npm:^16.6.0": + version: 16.7.0 + resolution: "jsdom@npm:16.7.0" + dependencies: + abab: ^2.0.5 + acorn: ^8.2.4 + acorn-globals: ^6.0.0 + cssom: ^0.4.4 + cssstyle: ^2.3.0 + data-urls: ^2.0.0 + decimal.js: ^10.2.1 + domexception: ^2.0.1 + escodegen: ^2.0.0 + form-data: ^3.0.0 + html-encoding-sniffer: ^2.0.1 + http-proxy-agent: ^4.0.1 + https-proxy-agent: ^5.0.0 + is-potential-custom-element-name: ^1.0.1 + nwsapi: ^2.2.0 + parse5: 6.0.1 + saxes: ^5.0.1 + symbol-tree: ^3.2.4 + tough-cookie: ^4.0.0 + w3c-hr-time: ^1.0.2 + w3c-xmlserializer: ^2.0.0 + webidl-conversions: ^6.1.0 + whatwg-encoding: ^1.0.5 + whatwg-mimetype: ^2.3.0 + whatwg-url: ^8.5.0 + ws: ^7.4.6 + xml-name-validator: ^3.0.0 + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + checksum: 454b83371857000763ed31130a049acd1b113e3b927e6dcd75c67ddc30cdd242d7ebcac5c2294b7a1a6428155cb1398709c573b3c6d809218692ea68edd93370 + languageName: node + linkType: hard + +"jsesc@npm:^2.5.1": + version: 2.5.2 + resolution: "jsesc@npm:2.5.2" + bin: + jsesc: bin/jsesc + checksum: 4dc190771129e12023f729ce20e1e0bfceac84d73a85bc3119f7f938843fe25a4aeccb54b6494dce26fcf263d815f5f31acdefac7cc9329efb8422a4f4d9fa9d + languageName: node + linkType: hard + +"jsesc@npm:~0.5.0": + version: 0.5.0 + resolution: "jsesc@npm:0.5.0" + bin: + jsesc: bin/jsesc + checksum: b8b44cbfc92f198ad972fba706ee6a1dfa7485321ee8c0b25f5cedd538dcb20cde3197de16a7265430fce8277a12db066219369e3d51055038946039f6e20e17 + languageName: node + linkType: hard + +"json-parse-even-better-errors@npm:^2.3.0, json-parse-even-better-errors@npm:^2.3.1": + version: 2.3.1 + resolution: "json-parse-even-better-errors@npm:2.3.1" + checksum: 798ed4cf3354a2d9ccd78e86d2169515a0097a5c133337807cdf7f1fc32e1391d207ccfc276518cc1d7d8d4db93288b8a50ba4293d212ad1336e52a8ec0a941f + languageName: node + linkType: hard + +"json-schema-traverse@npm:^0.4.1": + version: 0.4.1 + resolution: "json-schema-traverse@npm:0.4.1" + checksum: 7486074d3ba247769fda17d5181b345c9fb7d12e0da98b22d1d71a5db9698d8b4bd900a3ec1a4ffdd60846fc2556274a5c894d0c48795f14cb03aeae7b55260b + languageName: node + linkType: hard + +"json-schema-traverse@npm:^1.0.0": + version: 1.0.0 + resolution: "json-schema-traverse@npm:1.0.0" + checksum: 02f2f466cdb0362558b2f1fd5e15cce82ef55d60cd7f8fa828cf35ba74330f8d767fcae5c5c2adb7851fa811766c694b9405810879bc4e1ddd78a7c0e03658ad + languageName: node + linkType: hard + +"json-schema@npm:0.4.0, json-schema@npm:^0.4.0": + version: 0.4.0 + resolution: "json-schema@npm:0.4.0" + checksum: 66389434c3469e698da0df2e7ac5a3281bcff75e797a5c127db7c5b56270e01ae13d9afa3c03344f76e32e81678337a8c912bdbb75101c62e487dc3778461d72 + languageName: node + linkType: hard + +"json-stable-stringify-without-jsonify@npm:^1.0.1": + version: 1.0.1 + resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" + checksum: cff44156ddce9c67c44386ad5cddf91925fe06b1d217f2da9c4910d01f358c6e3989c4d5a02683c7a5667f9727ff05831f7aa8ae66c8ff691c556f0884d49215 + languageName: node + linkType: hard + +"json-stringify-safe@npm:~5.0.1": + version: 5.0.1 + resolution: "json-stringify-safe@npm:5.0.1" + checksum: 48ec0adad5280b8a96bb93f4563aa1667fd7a36334f79149abd42446d0989f2ddc58274b479f4819f1f00617957e6344c886c55d05a4e15ebb4ab931e4a6a8ee + languageName: node + linkType: hard + +"json5@npm:^1.0.1": + version: 1.0.2 + resolution: "json5@npm:1.0.2" + dependencies: + minimist: ^1.2.0 + bin: + json5: lib/cli.js + checksum: 866458a8c58a95a49bef3adba929c625e82532bcff1fe93f01d29cb02cac7c3fe1f4b79951b7792c2da9de0b32871a8401a6e3c5b36778ad852bf5b8a61165d7 + languageName: node + linkType: hard + +"json5@npm:^2.1.2, json5@npm:^2.2.0, json5@npm:^2.2.2": + version: 2.2.3 + resolution: "json5@npm:2.2.3" + bin: + json5: lib/cli.js + checksum: 2a7436a93393830bce797d4626275152e37e877b265e94ca69c99e3d20c2b9dab021279146a39cdb700e71b2dd32a4cebd1514cd57cee102b1af906ce5040349 + languageName: node + linkType: hard + +"jsonfile@npm:^6.0.1": + version: 6.1.0 + resolution: "jsonfile@npm:6.1.0" + dependencies: + graceful-fs: ^4.1.6 + universalify: ^2.0.0 + dependenciesMeta: + graceful-fs: + optional: true + checksum: 7af3b8e1ac8fe7f1eccc6263c6ca14e1966fcbc74b618d3c78a0a2075579487547b94f72b7a1114e844a1e15bb00d440e5d1720bfc4612d790a6f285d5ea8354 + languageName: node + linkType: hard + +"jsonpointer@npm:^5.0.0": + version: 5.0.1 + resolution: "jsonpointer@npm:5.0.1" + checksum: 0b40f712900ad0c846681ea2db23b6684b9d5eedf55807b4708c656f5894b63507d0e28ae10aa1bddbea551241035afe62b6df0800fc94c2e2806a7f3adecd7c + languageName: node + linkType: hard + +"jsprim@npm:^2.0.2": + version: 2.0.2 + resolution: "jsprim@npm:2.0.2" + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + checksum: d175f6b1991e160cb0aa39bc857da780e035611986b5492f32395411879fdaf4e513d98677f08f7352dac93a16b66b8361c674b86a3fa406e2e7af6b26321838 + languageName: node + linkType: hard + +"jsrsasign@npm:11.0.0": + version: 11.0.0 + resolution: "jsrsasign@npm:11.0.0" + checksum: 9bbcbb9d2609e279fb015eec259490053be0afd9a6a98743ce0bf42f825e8415b377bfb1aef1d988d3d9ece0bce34bec5bc64f71e99406d0743c37cbbb2f89a5 + languageName: node + linkType: hard + +"jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.3": + version: 3.3.3 + resolution: "jsx-ast-utils@npm:3.3.3" + dependencies: + array-includes: ^3.1.5 + object.assign: ^4.1.3 + checksum: a2ed78cac49a0f0c4be8b1eafe3c5257a1411341d8e7f1ac740debae003de04e5f6372bfcfbd9d082e954ffd99aac85bcda85b7c6bc11609992483f4cdc0f745 + languageName: node + linkType: hard + +"kind-of@npm:^6.0.2": + version: 6.0.3 + resolution: "kind-of@npm:6.0.3" + checksum: 3ab01e7b1d440b22fe4c31f23d8d38b4d9b91d9f291df683476576493d5dfd2e03848a8b05813dd0c3f0e835bc63f433007ddeceb71f05cb25c45ae1b19c6d3b + languageName: node + linkType: hard + +"kleur@npm:^3.0.3": + version: 3.0.3 + resolution: "kleur@npm:3.0.3" + checksum: df82cd1e172f957bae9c536286265a5cdbd5eeca487cb0a3b2a7b41ef959fc61f8e7c0e9aeea9c114ccf2c166b6a8dd45a46fd619c1c569d210ecd2765ad5169 + languageName: node + linkType: hard + +"klona@npm:^2.0.4, klona@npm:^2.0.5": + version: 2.0.6 + resolution: "klona@npm:2.0.6" + checksum: ac9ee3732e42b96feb67faae4d27cf49494e8a3bf3fa7115ce242fe04786788e0aff4741a07a45a2462e2079aa983d73d38519c85d65b70ef11447bbc3c58ce7 + languageName: node + linkType: hard + +"language-subtag-registry@npm:~0.3.2": + version: 0.3.22 + resolution: "language-subtag-registry@npm:0.3.22" + checksum: 8ab70a7e0e055fe977ac16ea4c261faec7205ac43db5e806f72e5b59606939a3b972c4bd1e10e323b35d6ffa97c3e1c4c99f6553069dad2dfdd22020fa3eb56a + languageName: node + linkType: hard + +"language-tags@npm:=1.0.5": + version: 1.0.5 + resolution: "language-tags@npm:1.0.5" + dependencies: + language-subtag-registry: ~0.3.2 + checksum: c81b5d8b9f5f9cfd06ee71ada6ddfe1cf83044dd5eeefcd1e420ad491944da8957688db4a0a9bc562df4afdc2783425cbbdfd152c01d93179cf86888903123cf + languageName: node + linkType: hard + +"lazy-ass@npm:1.6.0, lazy-ass@npm:^1.6.0": + version: 1.6.0 + resolution: "lazy-ass@npm:1.6.0" + checksum: 5a3ebb17915b03452320804466345382a6c25ac782ec4874fecdb2385793896cd459be2f187dc7def8899180c32ee0ab9a1aa7fe52193ac3ff3fe29bb0591729 + languageName: node + linkType: hard + +"leven@npm:^3.1.0": + version: 3.1.0 + resolution: "leven@npm:3.1.0" + checksum: 638401d534585261b6003db9d99afd244dfe82d75ddb6db5c0df412842d5ab30b2ef18de471aaec70fe69a46f17b4ae3c7f01d8a4e6580ef7adb9f4273ad1e55 + languageName: node + linkType: hard + +"levn@npm:^0.4.1": + version: 0.4.1 + resolution: "levn@npm:0.4.1" + dependencies: + prelude-ls: ^1.2.1 + type-check: ~0.4.0 + checksum: 12c5021c859bd0f5248561bf139121f0358285ec545ebf48bb3d346820d5c61a4309535c7f387ed7d84361cf821e124ce346c6b7cef8ee09a67c1473b46d0fc4 + languageName: node + linkType: hard + +"levn@npm:~0.3.0": + version: 0.3.0 + resolution: "levn@npm:0.3.0" + dependencies: + prelude-ls: ~1.1.2 + type-check: ~0.3.2 + checksum: 0d084a524231a8246bb10fec48cdbb35282099f6954838604f3c7fc66f2e16fa66fd9cc2f3f20a541a113c4dafdf181e822c887c8a319c9195444e6c64ac395e + languageName: node + linkType: hard + +"lilconfig@npm:2.1.0, lilconfig@npm:^2.0.3, lilconfig@npm:^2.0.5, lilconfig@npm:^2.0.6": + version: 2.1.0 + resolution: "lilconfig@npm:2.1.0" + checksum: 8549bb352b8192375fed4a74694cd61ad293904eee33f9d4866c2192865c44c4eb35d10782966242634e0cbc1e91fe62b1247f148dc5514918e3a966da7ea117 + languageName: node + linkType: hard + +"lines-and-columns@npm:^1.1.6": + version: 1.2.4 + resolution: "lines-and-columns@npm:1.2.4" + checksum: 0c37f9f7fa212b38912b7145e1cd16a5f3cd34d782441c3e6ca653485d326f58b3caccda66efce1c5812bde4961bbde3374fae4b0d11bf1226152337f3894aa5 + languageName: node + linkType: hard + +"lint-staged@npm:13.3.0": + version: 13.3.0 + resolution: "lint-staged@npm:13.3.0" + dependencies: + chalk: 5.3.0 + commander: 11.0.0 + debug: 4.3.4 + execa: 7.2.0 + lilconfig: 2.1.0 + listr2: 6.6.1 + micromatch: 4.0.5 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.3.1 + bin: + lint-staged: bin/lint-staged.js + checksum: f7c146cc2849c9ce4f1d2808d990fcbdef5e0bb79e6e79cc895f53c91f5ac4dcefdb8c3465156b38a015dcb051f2795c6bda4f20a1e2f2fa654c7ba521b2d2e0 + languageName: node + linkType: hard + +"listr2@npm:6.6.1": + version: 6.6.1 + resolution: "listr2@npm:6.6.1" + dependencies: + cli-truncate: ^3.1.0 + colorette: ^2.0.20 + eventemitter3: ^5.0.1 + log-update: ^5.0.1 + rfdc: ^1.3.0 + wrap-ansi: ^8.1.0 + peerDependencies: + enquirer: ">= 2.3.0 < 3" + peerDependenciesMeta: + enquirer: + optional: true + checksum: 99600e8a51f838f7208bce7e16d6b3d91d361f13881e6aa91d0b561a9a093ddcf63b7bc2a7b47aec7fdbff9d0e8c9f68cb66e6dfe2d857e5b1df8ab045c26ce8 + languageName: node + linkType: hard + +"listr2@npm:^3.8.3": + version: 3.14.0 + resolution: "listr2@npm:3.14.0" + dependencies: + cli-truncate: ^2.1.0 + colorette: ^2.0.16 + log-update: ^4.0.0 + p-map: ^4.0.0 + rfdc: ^1.3.0 + rxjs: ^7.5.1 + through: ^2.3.8 + wrap-ansi: ^7.0.0 + peerDependencies: + enquirer: ">= 2.3.0 < 3" + peerDependenciesMeta: + enquirer: + optional: true + checksum: fdb8b2d6bdf5df9371ebd5082bee46c6d0ca3d1e5f2b11fbb5a127839855d5f3da9d4968fce94f0a5ec67cac2459766abbb1faeef621065ebb1829b11ef9476d + languageName: node + linkType: hard + +"loader-runner@npm:^4.2.0": + version: 4.3.0 + resolution: "loader-runner@npm:4.3.0" + checksum: a90e00dee9a16be118ea43fec3192d0b491fe03a32ed48a4132eb61d498f5536a03a1315531c19d284392a8726a4ecad71d82044c28d7f22ef62e029bf761569 + languageName: node + linkType: hard + +"loader-utils@npm:^2.0.0, loader-utils@npm:^2.0.4": + version: 2.0.4 + resolution: "loader-utils@npm:2.0.4" + dependencies: + big.js: ^5.2.2 + emojis-list: ^3.0.0 + json5: ^2.1.2 + checksum: a5281f5fff1eaa310ad5e1164095689443630f3411e927f95031ab4fb83b4a98f388185bb1fe949e8ab8d4247004336a625e9255c22122b815bb9a4c5d8fc3b7 + languageName: node + linkType: hard + +"loader-utils@npm:^3.2.0": + version: 3.2.1 + resolution: "loader-utils@npm:3.2.1" + checksum: 4e3ea054cdc8be1ab1f1238f49f42fdf0483039eff920fb1d442039f3f0ad4ebd11fb8e584ccdf2cb7e3c56b3d40c1832416e6408a55651b843da288960cc792 + languageName: node + linkType: hard + +"locate-path@npm:^3.0.0": + version: 3.0.0 + resolution: "locate-path@npm:3.0.0" + dependencies: + p-locate: ^3.0.0 + path-exists: ^3.0.0 + checksum: 53db3996672f21f8b0bf2a2c645ae2c13ffdae1eeecfcd399a583bce8516c0b88dcb4222ca6efbbbeb6949df7e46860895be2c02e8d3219abd373ace3bfb4e11 + languageName: node + linkType: hard + +"locate-path@npm:^5.0.0": + version: 5.0.0 + resolution: "locate-path@npm:5.0.0" + dependencies: + p-locate: ^4.1.0 + checksum: 83e51725e67517287d73e1ded92b28602e3ae5580b301fe54bfb76c0c723e3f285b19252e375712316774cf52006cb236aed5704692c32db0d5d089b69696e30 + languageName: node + linkType: hard + +"locate-path@npm:^6.0.0": + version: 6.0.0 + resolution: "locate-path@npm:6.0.0" + dependencies: + p-locate: ^5.0.0 + checksum: 72eb661788a0368c099a184c59d2fee760b3831c9c1c33955e8a19ae4a21b4116e53fa736dc086cdeb9fce9f7cc508f2f92d2d3aae516f133e16a2bb59a39f5a + languageName: node + linkType: hard + +"lodash.chunk@npm:4.2.0": + version: 4.2.0 + resolution: "lodash.chunk@npm:4.2.0" + checksum: 6286c6d06814fbeda502164015c42ef53a9194e6ebaac52ec2b41e83344aefe7bc3d94fdfec525adcd2c66cefdf05dc333b6a1128e4de739797342315c17cbc7 + languageName: node + linkType: hard + +"lodash.debounce@npm:4.0.8, lodash.debounce@npm:^4.0.8": + version: 4.0.8 + resolution: "lodash.debounce@npm:4.0.8" + checksum: a3f527d22c548f43ae31c861ada88b2637eb48ac6aa3eb56e82d44917971b8aa96fbb37aa60efea674dc4ee8c42074f90f7b1f772e9db375435f6c83a19b3bc6 + languageName: node + linkType: hard + +"lodash.isequal@npm:4.5.0": + version: 4.5.0 + resolution: "lodash.isequal@npm:4.5.0" + checksum: da27515dc5230eb1140ba65ff8de3613649620e8656b19a6270afe4866b7bd461d9ba2ac8a48dcc57f7adac4ee80e1de9f965d89d4d81a0ad52bb3eec2609644 + languageName: node + linkType: hard + +"lodash.isequalwith@npm:^4.4.0": + version: 4.4.0 + resolution: "lodash.isequalwith@npm:4.4.0" + checksum: 428ba7a57c47ec05e2dd18c03a4b4c45dac524a46af7ce3f412594bfc7be6a5acaa51acf9ea113d0002598e9aafc6e19ee8d20bc28363145fcb4d21808c9039f + languageName: node + linkType: hard + +"lodash.isplainobject@npm:^4.0.6": + version: 4.0.6 + resolution: "lodash.isplainobject@npm:4.0.6" + checksum: 29c6351f281e0d9a1d58f1a4c8f4400924b4c79f18dfc4613624d7d54784df07efaff97c1ff2659f3e085ecf4fff493300adc4837553104cef2634110b0d5337 + languageName: node + linkType: hard + +"lodash.memoize@npm:4.1.2, lodash.memoize@npm:^4.1.2": + version: 4.1.2 + resolution: "lodash.memoize@npm:4.1.2" + checksum: 9ff3942feeccffa4f1fafa88d32f0d24fdc62fd15ded5a74a5f950ff5f0c6f61916157246744c620173dddf38d37095a92327d5fd3861e2063e736a5c207d089 + languageName: node + linkType: hard + +"lodash.merge@npm:^4.6.2": + version: 4.6.2 + resolution: "lodash.merge@npm:4.6.2" + checksum: ad580b4bdbb7ca1f7abf7e1bce63a9a0b98e370cf40194b03380a46b4ed799c9573029599caebc1b14e3f24b111aef72b96674a56cfa105e0f5ac70546cdc005 + languageName: node + linkType: hard + +"lodash.once@npm:^4.1.1": + version: 4.1.1 + resolution: "lodash.once@npm:4.1.1" + checksum: d768fa9f9b4e1dc6453be99b753906f58990e0c45e7b2ca5a3b40a33111e5d17f6edf2f768786e2716af90a8e78f8f91431ab8435f761fef00f9b0c256f6d245 + languageName: node + linkType: hard + +"lodash.sortby@npm:^4.7.0": + version: 4.7.0 + resolution: "lodash.sortby@npm:4.7.0" + checksum: db170c9396d29d11fe9a9f25668c4993e0c1331bcb941ddbd48fb76f492e732add7f2a47cfdf8e9d740fa59ac41bbfaf931d268bc72aab3ab49e9f89354d718c + languageName: node + linkType: hard + +"lodash.uniq@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.uniq@npm:4.5.0" + checksum: a4779b57a8d0f3c441af13d9afe7ecff22dd1b8ce1129849f71d9bbc8e8ee4e46dfb4b7c28f7ad3d67481edd6e51126e4e2a6ee276e25906d10f7140187c392d + languageName: node + linkType: hard + +"lodash@npm:^4.17.15, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.7.0": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 + languageName: node + linkType: hard + +"log-symbols@npm:^4.0.0": + version: 4.1.0 + resolution: "log-symbols@npm:4.1.0" + dependencies: + chalk: ^4.1.0 + is-unicode-supported: ^0.1.0 + checksum: fce1497b3135a0198803f9f07464165e9eb83ed02ceb2273930a6f8a508951178d8cf4f0378e9d28300a2ed2bc49050995d2bd5f53ab716bb15ac84d58c6ef74 + languageName: node + linkType: hard + +"log-update@npm:^4.0.0": + version: 4.0.0 + resolution: "log-update@npm:4.0.0" + dependencies: + ansi-escapes: ^4.3.0 + cli-cursor: ^3.1.0 + slice-ansi: ^4.0.0 + wrap-ansi: ^6.2.0 + checksum: ae2f85bbabc1906034154fb7d4c4477c79b3e703d22d78adee8b3862fa913942772e7fa11713e3d96fb46de4e3cabefbf5d0a544344f03b58d3c4bff52aa9eb2 + languageName: node + linkType: hard + +"log-update@npm:^5.0.1": + version: 5.0.1 + resolution: "log-update@npm:5.0.1" + dependencies: + ansi-escapes: ^5.0.0 + cli-cursor: ^4.0.0 + slice-ansi: ^5.0.0 + strip-ansi: ^7.0.1 + wrap-ansi: ^8.0.1 + checksum: 2c6b47dcce6f9233df6d232a37d9834cb3657a0749ef6398f1706118de74c55f158587d4128c225297ea66803f35c5ac3db4f3f617046d817233c45eedc32ef1 + languageName: node + linkType: hard + +"logdown@npm:3.3.1": + version: 3.3.1 + resolution: "logdown@npm:3.3.1" + dependencies: + chalk: ^2.3.0 + checksum: 381e7be208f168fd6664ddfe6980ed4ff16ef73e1b9828795df22154e18b47f16737fec1c38f035dd12d10af947a9aded2d753f1b0ade190800e3a28e868a619 + languageName: node + linkType: hard + +"loglevel@npm:1.9.1": + version: 1.9.1 + resolution: "loglevel@npm:1.9.1" + checksum: e1c8586108c4d566122e91f8a79c8df728920e3a714875affa5120566761a24077ec8ec9e5fc388b022e39fc411ec6e090cde1b5775871241b045139771eeb06 + languageName: node + linkType: hard + +"loose-envify@npm:^1.1.0, loose-envify@npm:^1.2.0, loose-envify@npm:^1.3.1, loose-envify@npm:^1.4.0": + version: 1.4.0 + resolution: "loose-envify@npm:1.4.0" + dependencies: + js-tokens: ^3.0.0 || ^4.0.0 + bin: + loose-envify: cli.js + checksum: 6517e24e0cad87ec9888f500c5b5947032cdfe6ef65e1c1936a0c48a524b81e65542c9c3edc91c97d5bddc806ee2a985dbc79be89215d613b1de5db6d1cfe6f4 + languageName: node + linkType: hard + +"lower-case@npm:^2.0.2": + version: 2.0.2 + resolution: "lower-case@npm:2.0.2" + dependencies: + tslib: ^2.0.3 + checksum: 83a0a5f159ad7614bee8bf976b96275f3954335a84fad2696927f609ddae902802c4f3312d86668722e668bef41400254807e1d3a7f2e8c3eede79691aa1f010 + languageName: node + linkType: hard + +"lru-cache@npm:^5.1.1": + version: 5.1.1 + resolution: "lru-cache@npm:5.1.1" + dependencies: + yallist: ^3.0.2 + checksum: c154ae1cbb0c2206d1501a0e94df349653c92c8cbb25236d7e85190bcaf4567a03ac6eb43166fabfa36fd35623694da7233e88d9601fbf411a9a481d85dbd2cb + languageName: node + linkType: hard + +"lru-cache@npm:^6.0.0": + version: 6.0.0 + resolution: "lru-cache@npm:6.0.0" + dependencies: + yallist: ^4.0.0 + checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297 + languageName: node + linkType: hard + +"lru-cache@npm:^7.7.1": + version: 7.14.1 + resolution: "lru-cache@npm:7.14.1" + checksum: d72c6713c6a6d86836a7a6523b3f1ac6764768cca47ec99341c3e76db06aacd4764620e5e2cda719a36848785a52a70e531822dc2b33fb071fa709683746c104 + languageName: node + linkType: hard + +"lz-string@npm:^1.4.4": + version: 1.4.4 + resolution: "lz-string@npm:1.4.4" + bin: + lz-string: bin/bin.js + checksum: 54e31238a61a84d8f664d9860a9fba7310c5b97a52c444f80543069bc084815eff40b8d4474ae1d93992fdf6c252dca37cf27f6adbeb4dbc3df2f3ac773d0e61 + languageName: node + linkType: hard + +"lz-string@npm:^1.5.0": + version: 1.5.0 + resolution: "lz-string@npm:1.5.0" + bin: + lz-string: bin/bin.js + checksum: 1ee98b4580246fd90dd54da6e346fb1caefcf05f677c686d9af237a157fdea3fd7c83a4bc58f858cd5b10a34d27afe0fdcbd0505a47e0590726a873dc8b8f65d + languageName: node + linkType: hard + +"magic-string@npm:^0.25.0, magic-string@npm:^0.25.7": + version: 0.25.9 + resolution: "magic-string@npm:0.25.9" + dependencies: + sourcemap-codec: ^1.4.8 + checksum: 9a0e55a15c7303fc360f9572a71cffba1f61451bc92c5602b1206c9d17f492403bf96f946dfce7483e66822d6b74607262e24392e87b0ac27b786e69a40e9b1a + languageName: node + linkType: hard + +"make-dir@npm:^3.0.0, make-dir@npm:^3.0.2, make-dir@npm:^3.1.0": + version: 3.1.0 + resolution: "make-dir@npm:3.1.0" + dependencies: + semver: ^6.0.0 + checksum: 484200020ab5a1fdf12f393fe5f385fc8e4378824c940fba1729dcd198ae4ff24867bc7a5646331e50cead8abff5d9270c456314386e629acec6dff4b8016b78 + languageName: node + linkType: hard + +"make-error@npm:^1.1.1": + version: 1.3.6 + resolution: "make-error@npm:1.3.6" + checksum: b86e5e0e25f7f777b77fabd8e2cbf15737972869d852a22b7e73c17623928fccb826d8e46b9951501d3f20e51ad74ba8c59ed584f610526a48f8ccf88aaec402 + languageName: node + linkType: hard + +"make-fetch-happen@npm:^10.0.3": + version: 10.2.1 + resolution: "make-fetch-happen@npm:10.2.1" + dependencies: + agentkeepalive: ^4.2.1 + cacache: ^16.1.0 + http-cache-semantics: ^4.1.0 + http-proxy-agent: ^5.0.0 + https-proxy-agent: ^5.0.0 + is-lambda: ^1.0.1 + lru-cache: ^7.7.1 + minipass: ^3.1.6 + minipass-collect: ^1.0.2 + minipass-fetch: ^2.0.3 + minipass-flush: ^1.0.5 + minipass-pipeline: ^1.2.4 + negotiator: ^0.6.3 + promise-retry: ^2.0.1 + socks-proxy-agent: ^7.0.0 + ssri: ^9.0.0 + checksum: 2332eb9a8ec96f1ffeeea56ccefabcb4193693597b132cd110734d50f2928842e22b84cfa1508e921b8385cdfd06dda9ad68645fed62b50fff629a580f5fb72c + languageName: node + linkType: hard + +"makeerror@npm:1.0.12": + version: 1.0.12 + resolution: "makeerror@npm:1.0.12" + dependencies: + tmpl: 1.0.5 + checksum: b38a025a12c8146d6eeea5a7f2bf27d51d8ad6064da8ca9405fcf7bf9b54acd43e3b30ddd7abb9b1bfa4ddb266019133313482570ddb207de568f71ecfcf6060 + languageName: node + linkType: hard + +"map-stream@npm:~0.1.0": + version: 0.1.0 + resolution: "map-stream@npm:0.1.0" + checksum: 38abbe4eb883888031e6b2fc0630bc583c99396be16b8ace5794b937b682a8a081f03e8b15bfd4914d1bc88318f0e9ac73ba3512ae65955cd449f63256ddb31d + languageName: node + linkType: hard + +"match-sorter@npm:^6.0.2": + version: 6.3.1 + resolution: "match-sorter@npm:6.3.1" + dependencies: + "@babel/runtime": ^7.12.5 + remove-accents: 0.4.2 + checksum: a4b02b676ac4ce64a89a091539ee4a70a802684713bcf06f2b70787927f510fe8a2adc849f9288857a90906083ad303467e530e8723b4a9756df9994fc164550 + languageName: node + linkType: hard + +"mdn-data@npm:2.0.14": + version: 2.0.14 + resolution: "mdn-data@npm:2.0.14" + checksum: 9d0128ed425a89f4cba8f787dca27ad9408b5cb1b220af2d938e2a0629d17d879a34d2cb19318bdb26c3f14c77dd5dfbae67211f5caaf07b61b1f2c5c8c7dc16 + languageName: node + linkType: hard + +"mdn-data@npm:2.0.4": + version: 2.0.4 + resolution: "mdn-data@npm:2.0.4" + checksum: add3c95e6d03d301b8a8bcfee3de33f4d07e4c5eee5b79f18d6d737de717e22472deadf67c1a8563983c0b603e10d7df40aa8e5fddf18884dfe118ccec7ae329 + languageName: node + linkType: hard + +"media-typer@npm:0.3.0": + version: 0.3.0 + resolution: "media-typer@npm:0.3.0" + checksum: af1b38516c28ec95d6b0826f6c8f276c58aec391f76be42aa07646b4e39d317723e869700933ca6995b056db4b09a78c92d5440dc23657e6764be5d28874bba1 + languageName: node + linkType: hard + +"memfs@npm:^3.1.2, memfs@npm:^3.4.3": + version: 3.4.13 + resolution: "memfs@npm:3.4.13" + dependencies: + fs-monkey: ^1.0.3 + checksum: 3f9717d6f060919d53f211acb6096a0ea2f566a8cbcc4ef7e1f2561e31e33dc456053fdf951c90a49c8ec55402de7f01b006b81683ab7bd4bdbbd8c9b9cdae5f + languageName: node + linkType: hard + +"merge-descriptors@npm:1.0.1": + version: 1.0.1 + resolution: "merge-descriptors@npm:1.0.1" + checksum: 5abc259d2ae25bb06d19ce2b94a21632583c74e2a9109ee1ba7fd147aa7362b380d971e0251069f8b3eb7d48c21ac839e21fa177b335e82c76ec172e30c31a26 + languageName: node + linkType: hard + +"merge-stream@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-stream@npm:2.0.0" + checksum: 6fa4dcc8d86629705cea944a4b88ef4cb0e07656ebf223fa287443256414283dd25d91c1cd84c77987f2aec5927af1a9db6085757cb43d90eb170ebf4b47f4f4 + languageName: node + linkType: hard + +"merge2@npm:^1.3.0, merge2@npm:^1.4.1": + version: 1.4.1 + resolution: "merge2@npm:1.4.1" + checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 + languageName: node + linkType: hard + +"methods@npm:~1.1.2": + version: 1.1.2 + resolution: "methods@npm:1.1.2" + checksum: 0917ff4041fa8e2f2fda5425a955fe16ca411591fbd123c0d722fcf02b73971ed6f764d85f0a6f547ce49ee0221ce2c19a5fa692157931cecb422984f1dcd13a + languageName: node + linkType: hard + +"micromatch@npm:4.0.5, micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": + version: 4.0.5 + resolution: "micromatch@npm:4.0.5" + dependencies: + braces: ^3.0.2 + picomatch: ^2.3.1 + checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc + languageName: node + linkType: hard + +"microseconds@npm:0.2.0": + version: 0.2.0 + resolution: "microseconds@npm:0.2.0" + checksum: 22bfa8553f92c7d95afff6de0aeb2aecf750680d41b8c72b02098ccc5bbbb0a384380ff539292dbd3788f5dfc298682f9d38a2b4c101f5ee2c9471d53934c5fa + languageName: node + linkType: hard + +"mime-db@npm:1.52.0, mime-db@npm:>= 1.43.0 < 2": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 0d99a03585f8b39d68182803b12ac601d9c01abfa28ec56204fa330bc9f3d1c5e14beb049bafadb3dbdf646dfb94b87e24d4ec7b31b7279ef906a8ea9b6a513f + languageName: node + linkType: hard + +"mime-db@npm:~1.33.0": + version: 1.33.0 + resolution: "mime-db@npm:1.33.0" + checksum: 281a0772187c9b8f6096976cb193ac639c6007ac85acdbb8dc1617ed7b0f4777fa001d1b4f1b634532815e60717c84b2f280201d55677fb850c9d45015b50084 + languageName: node + linkType: hard + +"mime-types@npm:2.1.18": + version: 2.1.18 + resolution: "mime-types@npm:2.1.18" + dependencies: + mime-db: ~1.33.0 + checksum: 729265eff1e5a0e87cb7f869da742a610679585167d2f2ec997a7387fc6aedf8e5cad078e99b0164a927bdf3ace34fca27430d6487456ad090cba5594441ba43 + languageName: node + linkType: hard + +"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:^2.1.31, mime-types@npm:~2.1.17, mime-types@npm:~2.1.19, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: 1.52.0 + checksum: 89a5b7f1def9f3af5dad6496c5ed50191ae4331cc5389d7c521c8ad28d5fdad2d06fd81baf38fed813dc4e46bb55c8145bb0ff406330818c9cf712fb2e9b3836 + languageName: node + linkType: hard + +"mime@npm:1.6.0": + version: 1.6.0 + resolution: "mime@npm:1.6.0" + bin: + mime: cli.js + checksum: fef25e39263e6d207580bdc629f8872a3f9772c923c7f8c7e793175cee22777bbe8bba95e5d509a40aaa292d8974514ce634ae35769faa45f22d17edda5e8557 + languageName: node + linkType: hard + +"mimic-fn@npm:^2.1.0": + version: 2.1.0 + resolution: "mimic-fn@npm:2.1.0" + checksum: d2421a3444848ce7f84bd49115ddacff29c15745db73f54041edc906c14b131a38d05298dae3081667627a59b2eb1ca4b436ff2e1b80f69679522410418b478a + languageName: node + linkType: hard + +"mimic-fn@npm:^4.0.0": + version: 4.0.0 + resolution: "mimic-fn@npm:4.0.0" + checksum: 995dcece15ee29aa16e188de6633d43a3db4611bcf93620e7e62109ec41c79c0f34277165b8ce5e361205049766e371851264c21ac64ca35499acb5421c2ba56 + languageName: node + linkType: hard + +"min-indent@npm:^1.0.0": + version: 1.0.1 + resolution: "min-indent@npm:1.0.1" + checksum: bfc6dd03c5eaf623a4963ebd94d087f6f4bbbfd8c41329a7f09706b0cb66969c4ddd336abeb587bc44bc6f08e13bf90f0b374f9d71f9f01e04adc2cd6f083ef1 + languageName: node + linkType: hard + +"mini-create-react-context@npm:^0.4.0": + version: 0.4.1 + resolution: "mini-create-react-context@npm:0.4.1" + dependencies: + "@babel/runtime": ^7.12.1 + tiny-warning: ^1.0.3 + peerDependencies: + prop-types: ^15.0.0 + react: ^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: f8cb2c7738aac355fe9ce7e8425f371b7fa90daddd5133edda4ccfdc18c49043b2ec04be6f3abf09b60a0f52549d54f158d5bfd81cdfb1a658531e5b9fe7bc6a + languageName: node + linkType: hard + +"mini-css-extract-plugin@npm:^2.4.5": + version: 2.7.2 + resolution: "mini-css-extract-plugin@npm:2.7.2" + dependencies: + schema-utils: ^4.0.0 + peerDependencies: + webpack: ^5.0.0 + checksum: cd65611d6dc452f230c6ebba8a47bc5f5146b813b13b0b402c6f4a69f6451242eeea781152bebd31cad8ca7c7e95dac91e7e464087f18fb65b2d1097b58cf4ae + languageName: node + linkType: hard + +"minimalistic-assert@npm:^1.0.0": + version: 1.0.1 + resolution: "minimalistic-assert@npm:1.0.1" + checksum: cc7974a9268fbf130fb055aff76700d7e2d8be5f761fb5c60318d0ed010d839ab3661a533ad29a5d37653133385204c503bfac995aaa4236f4e847461ea32ba7 + languageName: node + linkType: hard + +"minimatch@npm:3.1.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": + version: 3.1.2 + resolution: "minimatch@npm:3.1.2" + dependencies: + brace-expansion: ^1.1.7 + checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a + languageName: node + linkType: hard + +"minimatch@npm:^5.0.1": + version: 5.1.6 + resolution: "minimatch@npm:5.1.6" + dependencies: + brace-expansion: ^2.0.1 + checksum: 7564208ef81d7065a370f788d337cd80a689e981042cb9a1d0e6580b6c6a8c9279eba80010516e258835a988363f99f54a6f711a315089b8b42694f5da9d0d77 + languageName: node + linkType: hard + +"minimist@npm:^1.2.0, minimist@npm:^1.2.6, minimist@npm:^1.2.7, minimist@npm:^1.2.8": + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 + languageName: node + linkType: hard + +"minipass-collect@npm:^1.0.2": + version: 1.0.2 + resolution: "minipass-collect@npm:1.0.2" + dependencies: + minipass: ^3.0.0 + checksum: 14df761028f3e47293aee72888f2657695ec66bd7d09cae7ad558da30415fdc4752bbfee66287dcc6fd5e6a2fa3466d6c484dc1cbd986525d9393b9523d97f10 + languageName: node + linkType: hard + +"minipass-fetch@npm:^2.0.3": + version: 2.1.2 + resolution: "minipass-fetch@npm:2.1.2" + dependencies: + encoding: ^0.1.13 + minipass: ^3.1.6 + minipass-sized: ^1.0.3 + minizlib: ^2.1.2 + dependenciesMeta: + encoding: + optional: true + checksum: 3f216be79164e915fc91210cea1850e488793c740534985da017a4cbc7a5ff50506956d0f73bb0cb60e4fe91be08b6b61ef35101706d3ef5da2c8709b5f08f91 + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: ^3.0.0 + checksum: 56269a0b22bad756a08a94b1ffc36b7c9c5de0735a4dd1ab2b06c066d795cfd1f0ac44a0fcae13eece5589b908ecddc867f04c745c7009be0b566421ea0944cf + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: ^3.0.0 + checksum: b14240dac0d29823c3d5911c286069e36d0b81173d7bdf07a7e4a91ecdef92cdff4baaf31ea3746f1c61e0957f652e641223970870e2353593f382112257971b + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: ^3.0.0 + checksum: 79076749fcacf21b5d16dd596d32c3b6bf4d6e62abb43868fac21674078505c8b15eaca4e47ed844985a4514854f917d78f588fcd029693709417d8f98b2bd60 + languageName: node + linkType: hard + +"minipass@npm:^3.0.0, minipass@npm:^3.1.1, minipass@npm:^3.1.6": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: ^4.0.0 + checksum: a30d083c8054cee83cdcdc97f97e4641a3f58ae743970457b1489ce38ee1167b3aaf7d815cd39ec7a99b9c40397fd4f686e83750e73e652b21cb516f6d845e48 + languageName: node + linkType: hard + +"minipass@npm:^5.0.0": + version: 5.0.0 + resolution: "minipass@npm:5.0.0" + checksum: 425dab288738853fded43da3314a0b5c035844d6f3097a8e3b5b29b328da8f3c1af6fc70618b32c29ff906284cf6406b6841376f21caaadd0793c1d5a6a620ea + languageName: node + linkType: hard + +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": + version: 2.1.2 + resolution: "minizlib@npm:2.1.2" + dependencies: + minipass: ^3.0.0 + yallist: ^4.0.0 + checksum: f1fdeac0b07cf8f30fcf12f4b586795b97be856edea22b5e9072707be51fc95d41487faec3f265b42973a304fe3a64acd91a44a3826a963e37b37bafde0212c3 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: a96865108c6c3b1b8e1d5e9f11843de1e077e57737602de1b82030815f311be11f96f09cce59bd5b903d0b29834733e5313f9301e3ed6d6f6fba2eae0df4298f + languageName: node + linkType: hard + +"mkdirp@npm:~0.5.1": + version: 0.5.6 + resolution: "mkdirp@npm:0.5.6" + dependencies: + minimist: ^1.2.6 + bin: + mkdirp: bin/cmd.js + checksum: 0c91b721bb12c3f9af4b77ebf73604baf350e64d80df91754dc509491ae93bf238581e59c7188360cec7cb62fc4100959245a42cfe01834efedc5e9d068376c2 + languageName: node + linkType: hard + +"ms@npm:2.0.0": + version: 2.0.0 + resolution: "ms@npm:2.0.0" + checksum: 0e6a22b8b746d2e0b65a430519934fefd41b6db0682e3477c10f60c76e947c4c0ad06f63ffdf1d78d335f83edee8c0aa928aa66a36c7cd95b69b26f468d527f4 + languageName: node + linkType: hard + +"ms@npm:2.1.2": + version: 2.1.2 + resolution: "ms@npm:2.1.2" + checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f + languageName: node + linkType: hard + +"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d + languageName: node + linkType: hard + +"multicast-dns@npm:^7.2.5": + version: 7.2.5 + resolution: "multicast-dns@npm:7.2.5" + dependencies: + dns-packet: ^5.2.2 + thunky: ^1.0.2 + bin: + multicast-dns: cli.js + checksum: 00b8a57df152d4cd0297946320a94b7c3cdf75a46a2247f32f958a8927dea42958177f9b7fdae69fab2e4e033fb3416881af1f5e9055a3e1542888767139e2fb + languageName: node + linkType: hard + +"nano-time@npm:1.0.0": + version: 1.0.0 + resolution: "nano-time@npm:1.0.0" + dependencies: + big-integer: ^1.6.16 + checksum: eef8548546cc1020625f8e44751a7263e9eddf0412a6a1a6c80a8d2be2ea7973622804a977cdfe796807b85b20ff6c8ba340e8dd20effcc7078193ed5edbb5d4 + languageName: node + linkType: hard + +"nanoid@npm:^3.3.4": + version: 3.3.4 + resolution: "nanoid@npm:3.3.4" + bin: + nanoid: bin/nanoid.cjs + checksum: 2fddd6dee994b7676f008d3ffa4ab16035a754f4bb586c61df5a22cf8c8c94017aadd360368f47d653829e0569a92b129979152ff97af23a558331e47e37cd9c + languageName: node + linkType: hard + +"natural-compare-lite@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare-lite@npm:1.4.0" + checksum: 5222ac3986a2b78dd6069ac62cbb52a7bf8ffc90d972ab76dfe7b01892485d229530ed20d0c62e79a6b363a663b273db3bde195a1358ce9e5f779d4453887225 + languageName: node + linkType: hard + +"natural-compare@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare@npm:1.4.0" + checksum: 23ad088b08f898fc9b53011d7bb78ec48e79de7627e01ab5518e806033861bef68d5b0cd0e2205c2f36690ac9571ff6bcb05eb777ced2eeda8d4ac5b44592c3d + languageName: node + linkType: hard + +"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 + languageName: node + linkType: hard + +"neo-async@npm:^2.6.2": + version: 2.6.2 + resolution: "neo-async@npm:2.6.2" + checksum: deac9f8d00eda7b2e5cd1b2549e26e10a0faa70adaa6fdadca701cc55f49ee9018e427f424bac0c790b7c7e2d3068db97f3093f1093975f2acb8f8818b936ed9 + languageName: node + linkType: hard + +"no-case@npm:^3.0.4": + version: 3.0.4 + resolution: "no-case@npm:3.0.4" + dependencies: + lower-case: ^2.0.2 + tslib: ^2.0.3 + checksum: 0b2ebc113dfcf737d48dde49cfebf3ad2d82a8c3188e7100c6f375e30eafbef9e9124aadc3becef237b042fd5eb0aad2fd78669c20972d045bbe7fea8ba0be5c + languageName: node + linkType: hard + +"node-fetch@npm:^2.6.12": + version: 2.7.0 + resolution: "node-fetch@npm:2.7.0" + dependencies: + whatwg-url: ^5.0.0 + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: d76d2f5edb451a3f05b15115ec89fc6be39de37c6089f1b6368df03b91e1633fd379a7e01b7ab05089a25034b2023d959b47e59759cb38d88341b2459e89d6e5 + languageName: node + linkType: hard + +"node-forge@npm:^1": + version: 1.3.1 + resolution: "node-forge@npm:1.3.1" + checksum: 08fb072d3d670599c89a1704b3e9c649ff1b998256737f0e06fbd1a5bf41cae4457ccaee32d95052d80bbafd9ffe01284e078c8071f0267dc9744e51c5ed42a9 + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 9.3.1 + resolution: "node-gyp@npm:9.3.1" + dependencies: + env-paths: ^2.2.0 + glob: ^7.1.4 + graceful-fs: ^4.2.6 + make-fetch-happen: ^10.0.3 + nopt: ^6.0.0 + npmlog: ^6.0.0 + rimraf: ^3.0.2 + semver: ^7.3.5 + tar: ^6.1.2 + which: ^2.0.2 + bin: + node-gyp: bin/node-gyp.js + checksum: b860e9976fa645ca0789c69e25387401b4396b93c8375489b5151a6c55cf2640a3b6183c212b38625ef7c508994930b72198338e3d09b9d7ade5acc4aaf51ea7 + languageName: node + linkType: hard + +"node-int64@npm:^0.4.0": + version: 0.4.0 + resolution: "node-int64@npm:0.4.0" + checksum: d0b30b1ee6d961851c60d5eaa745d30b5c95d94bc0e74b81e5292f7c42a49e3af87f1eb9e89f59456f80645d679202537de751b7d72e9e40ceea40c5e449057e + languageName: node + linkType: hard + +"node-releases@npm:^2.0.6": + version: 2.0.8 + resolution: "node-releases@npm:2.0.8" + checksum: b1ab02c0d5d8e081bf9537232777a7a787dc8fef07f70feabe70a344599b220fe16462f746ac30f3eed5a58549445ad69368964d12a1f8b3b764f6caab7ba34a + languageName: node + linkType: hard + +"nopt@npm:^6.0.0": + version: 6.0.0 + resolution: "nopt@npm:6.0.0" + dependencies: + abbrev: ^1.0.0 + bin: + nopt: bin/nopt.js + checksum: 82149371f8be0c4b9ec2f863cc6509a7fd0fa729929c009f3a58e4eb0c9e4cae9920e8f1f8eb46e7d032fec8fb01bede7f0f41a67eb3553b7b8e14fa53de1dac + languageName: node + linkType: hard + +"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": + version: 3.0.0 + resolution: "normalize-path@npm:3.0.0" + checksum: 88eeb4da891e10b1318c4b2476b6e2ecbeb5ff97d946815ffea7794c31a89017c70d7f34b3c2ebf23ef4e9fc9fb99f7dffe36da22011b5b5c6ffa34f4873ec20 + languageName: node + linkType: hard + +"normalize-range@npm:^0.1.2": + version: 0.1.2 + resolution: "normalize-range@npm:0.1.2" + checksum: 9b2f14f093593f367a7a0834267c24f3cb3e887a2d9809c77d8a7e5fd08738bcd15af46f0ab01cc3a3d660386f015816b5c922cea8bf2ee79777f40874063184 + languageName: node + linkType: hard + +"normalize-url@npm:^6.0.1": + version: 6.1.0 + resolution: "normalize-url@npm:6.1.0" + checksum: 4a4944631173e7d521d6b80e4c85ccaeceb2870f315584fa30121f505a6dfd86439c5e3fdd8cd9e0e291290c41d0c3599f0cb12ab356722ed242584c30348e50 + languageName: node + linkType: hard + +"npm-run-path@npm:^4.0.0, npm-run-path@npm:^4.0.1": + version: 4.0.1 + resolution: "npm-run-path@npm:4.0.1" + dependencies: + path-key: ^3.0.0 + checksum: 5374c0cea4b0bbfdfae62da7bbdf1e1558d338335f4cacf2515c282ff358ff27b2ecb91ffa5330a8b14390ac66a1e146e10700440c1ab868208430f56b5f4d23 + languageName: node + linkType: hard + +"npm-run-path@npm:^5.1.0": + version: 5.1.0 + resolution: "npm-run-path@npm:5.1.0" + dependencies: + path-key: ^4.0.0 + checksum: dc184eb5ec239d6a2b990b43236845332ef12f4e0beaa9701de724aa797fe40b6bbd0157fb7639d24d3ab13f5d5cf22d223a19c6300846b8126f335f788bee66 + languageName: node + linkType: hard + +"npmlog@npm:^6.0.0": + version: 6.0.2 + resolution: "npmlog@npm:6.0.2" + dependencies: + are-we-there-yet: ^3.0.0 + console-control-strings: ^1.1.0 + gauge: ^4.0.3 + set-blocking: ^2.0.0 + checksum: ae238cd264a1c3f22091cdd9e2b106f684297d3c184f1146984ecbe18aaa86343953f26b9520dedd1b1372bc0316905b736c1932d778dbeb1fcf5a1001390e2a + languageName: node + linkType: hard + +"nth-check@npm:^1.0.2": + version: 1.0.2 + resolution: "nth-check@npm:1.0.2" + dependencies: + boolbase: ~1.0.0 + checksum: 59e115fdd75b971d0030f42ada3aac23898d4c03aa13371fa8b3339d23461d1badf3fde5aad251fb956aaa75c0a3b9bfcd07c08a34a83b4f9dadfdce1d19337c + languageName: node + linkType: hard + +"nth-check@npm:^2.0.1": + version: 2.1.1 + resolution: "nth-check@npm:2.1.1" + dependencies: + boolbase: ^1.0.0 + checksum: 5afc3dafcd1573b08877ca8e6148c52abd565f1d06b1eb08caf982e3fa289a82f2cae697ffb55b5021e146d60443f1590a5d6b944844e944714a5b549675bcd3 + languageName: node + linkType: hard + +"nwsapi@npm:^2.2.0": + version: 2.2.2 + resolution: "nwsapi@npm:2.2.2" + checksum: 43769106292bc95f776756ca2f3513dab7b4d506a97c67baec32406447841a35f65f29c1f95ab5d42785210fd41668beed33ca16fa058780be43b101ad73e205 + languageName: node + linkType: hard + +"object-assign@npm:^4.1.1": + version: 4.1.1 + resolution: "object-assign@npm:4.1.1" + checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f + languageName: node + linkType: hard + +"object-hash@npm:^3.0.0": + version: 3.0.0 + resolution: "object-hash@npm:3.0.0" + checksum: 80b4904bb3857c52cc1bfd0b52c0352532ca12ed3b8a6ff06a90cd209dfda1b95cee059a7625eb9da29537027f68ac4619363491eedb2f5d3dddbba97494fd6c + languageName: node + linkType: hard + +"object-inspect@npm:^1.12.2, object-inspect@npm:^1.9.0": + version: 1.12.3 + resolution: "object-inspect@npm:1.12.3" + checksum: dabfd824d97a5f407e6d5d24810d888859f6be394d8b733a77442b277e0808860555176719c5905e765e3743a7cada6b8b0a3b85e5331c530fd418cc8ae991db + languageName: node + linkType: hard + +"object-is@npm:^1.1.5": + version: 1.1.5 + resolution: "object-is@npm:1.1.5" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.3 + checksum: 989b18c4cba258a6b74dc1d74a41805c1a1425bce29f6cabb50dcb1a6a651ea9104a1b07046739a49a5bb1bc49727bcb00efd5c55f932f6ea04ec8927a7901fe + languageName: node + linkType: hard + +"object-keys@npm:^1.1.1": + version: 1.1.1 + resolution: "object-keys@npm:1.1.1" + checksum: b363c5e7644b1e1b04aa507e88dcb8e3a2f52b6ffd0ea801e4c7a62d5aa559affe21c55a07fd4b1fd55fc03a33c610d73426664b20032405d7b92a1414c34d6a + languageName: node + linkType: hard + +"object.assign@npm:^4.1.3, object.assign@npm:^4.1.4": + version: 4.1.4 + resolution: "object.assign@npm:4.1.4" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + has-symbols: ^1.0.3 + object-keys: ^1.1.1 + checksum: 76cab513a5999acbfe0ff355f15a6a125e71805fcf53de4e9d4e082e1989bdb81d1e329291e1e4e0ae7719f0e4ef80e88fb2d367ae60500d79d25a6224ac8864 + languageName: node + linkType: hard + +"object.entries@npm:^1.1.6": + version: 1.1.6 + resolution: "object.entries@npm:1.1.6" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + checksum: 0f8c47517e6a9a980241eafe3b73de11e59511883173c2b93d67424a008e47e11b77c80e431ad1d8a806f6108b225a1cab9223e53e555776c612a24297117d28 + languageName: node + linkType: hard + +"object.fromentries@npm:^2.0.6": + version: 2.0.6 + resolution: "object.fromentries@npm:2.0.6" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + checksum: 453c6d694180c0c30df451b60eaf27a5b9bca3fb43c37908fd2b78af895803dc631242bcf05582173afa40d8d0e9c96e16e8874b39471aa53f3ac1f98a085d85 + languageName: node + linkType: hard + +"object.getownpropertydescriptors@npm:^2.1.0": + version: 2.1.5 + resolution: "object.getownpropertydescriptors@npm:2.1.5" + dependencies: + array.prototype.reduce: ^1.0.5 + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + checksum: 7883e1aac1f9cd4cd85e2bb8c7aab6a60940a7cfe07b788356f301844d4967482fc81058e7bda24e1b3909cbb4879387ea9407329b78704f8937bc0b97dec58b + languageName: node + linkType: hard + +"object.hasown@npm:^1.1.2": + version: 1.1.2 + resolution: "object.hasown@npm:1.1.2" + dependencies: + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + checksum: b936572536db0cdf38eb30afd2f1026a8b6f2cc5d2c4497c9d9bbb01eaf3e980dead4fd07580cfdd098e6383e5a9db8212d3ea0c6bdd2b5e68c60aa7e3b45566 + languageName: node + linkType: hard + +"object.values@npm:^1.1.0, object.values@npm:^1.1.6": + version: 1.1.6 + resolution: "object.values@npm:1.1.6" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + checksum: f6fff9fd817c24cfd8107f50fb33061d81cd11bacc4e3dbb3852e9ff7692fde4dbce823d4333ea27cd9637ef1b6690df5fbb61f1ed314fa2959598dc3ae23d8e + languageName: node + linkType: hard + +"oblivious-set@npm:1.0.0": + version: 1.0.0 + resolution: "oblivious-set@npm:1.0.0" + checksum: f31740ea9c3a8242ad2324e4ebb9a35359fbc2e6e7131731a0fc1c8b7b1238eb07e4c8c631a38535243a7b8e3042b7e89f7dc2a95d2989afd6f80bd5793b0aab + languageName: node + linkType: hard + +"obuf@npm:^1.0.0, obuf@npm:^1.1.2": + version: 1.1.2 + resolution: "obuf@npm:1.1.2" + checksum: 41a2ba310e7b6f6c3b905af82c275bf8854896e2e4c5752966d64cbcd2f599cfffd5932006bcf3b8b419dfdacebb3a3912d5d94e10f1d0acab59876c8757f27f + languageName: node + linkType: hard + +"on-finished@npm:2.4.1": + version: 2.4.1 + resolution: "on-finished@npm:2.4.1" + dependencies: + ee-first: 1.1.1 + checksum: d20929a25e7f0bb62f937a425b5edeb4e4cde0540d77ba146ec9357f00b0d497cdb3b9b05b9c8e46222407d1548d08166bff69cc56dfa55ba0e4469228920ff0 + languageName: node + linkType: hard + +"on-headers@npm:~1.0.2": + version: 1.0.2 + resolution: "on-headers@npm:1.0.2" + checksum: 2bf13467215d1e540a62a75021e8b318a6cfc5d4fc53af8e8f84ad98dbcea02d506c6d24180cd62e1d769c44721ba542f3154effc1f7579a8288c9f7873ed8e5 + languageName: node + linkType: hard + +"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: 1 + checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 + languageName: node + linkType: hard + +"onetime@npm:^5.1.0, onetime@npm:^5.1.2": + version: 5.1.2 + resolution: "onetime@npm:5.1.2" + dependencies: + mimic-fn: ^2.1.0 + checksum: 2478859ef817fc5d4e9c2f9e5728512ddd1dbc9fb7829ad263765bb6d3b91ce699d6e2332eef6b7dff183c2f490bd3349f1666427eaba4469fba0ac38dfd0d34 + languageName: node + linkType: hard + +"onetime@npm:^6.0.0": + version: 6.0.0 + resolution: "onetime@npm:6.0.0" + dependencies: + mimic-fn: ^4.0.0 + checksum: 0846ce78e440841335d4e9182ef69d5762e9f38aa7499b19f42ea1c4cd40f0b4446094c455c713f9adac3f4ae86f613bb5e30c99e52652764d06a89f709b3788 + languageName: node + linkType: hard + +"open@npm:^8.0.9, open@npm:^8.4.0": + version: 8.4.0 + resolution: "open@npm:8.4.0" + dependencies: + define-lazy-prop: ^2.0.0 + is-docker: ^2.1.1 + is-wsl: ^2.2.0 + checksum: e9545bec64cdbf30a0c35c1bdc310344adf8428a117f7d8df3c0af0a0a24c513b304916a6d9b11db0190ff7225c2d578885080b761ed46a3d5f6f1eebb98b63c + languageName: node + linkType: hard + +"optionator@npm:^0.8.1": + version: 0.8.3 + resolution: "optionator@npm:0.8.3" + dependencies: + deep-is: ~0.1.3 + fast-levenshtein: ~2.0.6 + levn: ~0.3.0 + prelude-ls: ~1.1.2 + type-check: ~0.3.2 + word-wrap: ~1.2.3 + checksum: b8695ddf3d593203e25ab0900e265d860038486c943ff8b774f596a310f8ceebdb30c6832407a8198ba3ec9debe1abe1f51d4aad94843612db3b76d690c61d34 + languageName: node + linkType: hard + +"optionator@npm:^0.9.3": + version: 0.9.3 + resolution: "optionator@npm:0.9.3" + dependencies: + "@aashutoshrathi/word-wrap": ^1.2.3 + deep-is: ^0.1.3 + fast-levenshtein: ^2.0.6 + levn: ^0.4.1 + prelude-ls: ^1.2.1 + type-check: ^0.4.0 + checksum: 09281999441f2fe9c33a5eeab76700795365a061563d66b098923eb719251a42bdbe432790d35064d0816ead9296dbeb1ad51a733edf4167c96bd5d0882e428a + languageName: node + linkType: hard + +"ospath@npm:^1.2.2": + version: 1.2.2 + resolution: "ospath@npm:1.2.2" + checksum: 505f48a4f4f1c557d6c656ec985707726e3714721680139be037613e903aa8c8fa4ddd8d1342006f9b2dc0065e6e20f8b7bea2ee05354f31257044790367b347 + languageName: node + linkType: hard + +"p-limit@npm:3.1.0, p-limit@npm:^3.0.2": + version: 3.1.0 + resolution: "p-limit@npm:3.1.0" + dependencies: + yocto-queue: ^0.1.0 + checksum: 7c3690c4dbf62ef625671e20b7bdf1cbc9534e83352a2780f165b0d3ceba21907e77ad63401708145ca4e25bfc51636588d89a8c0aeb715e6c37d1c066430360 + languageName: node + linkType: hard + +"p-limit@npm:^2.0.0, p-limit@npm:^2.2.0": + version: 2.3.0 + resolution: "p-limit@npm:2.3.0" + dependencies: + p-try: ^2.0.0 + checksum: 84ff17f1a38126c3314e91ecfe56aecbf36430940e2873dadaa773ffe072dc23b7af8e46d4b6485d302a11673fe94c6b67ca2cfbb60c989848b02100d0594ac1 + languageName: node + linkType: hard + +"p-locate@npm:^3.0.0": + version: 3.0.0 + resolution: "p-locate@npm:3.0.0" + dependencies: + p-limit: ^2.0.0 + checksum: 83991734a9854a05fe9dbb29f707ea8a0599391f52daac32b86f08e21415e857ffa60f0e120bfe7ce0cc4faf9274a50239c7895fc0d0579d08411e513b83a4ae + languageName: node + linkType: hard + +"p-locate@npm:^4.1.0": + version: 4.1.0 + resolution: "p-locate@npm:4.1.0" + dependencies: + p-limit: ^2.2.0 + checksum: 513bd14a455f5da4ebfcb819ef706c54adb09097703de6aeaa5d26fe5ea16df92b48d1ac45e01e3944ce1e6aa2a66f7f8894742b8c9d6e276e16cd2049a2b870 + languageName: node + linkType: hard + +"p-locate@npm:^5.0.0": + version: 5.0.0 + resolution: "p-locate@npm:5.0.0" + dependencies: + p-limit: ^3.0.2 + checksum: 1623088f36cf1cbca58e9b61c4e62bf0c60a07af5ae1ca99a720837356b5b6c5ba3eb1b2127e47a06865fee59dd0453cad7cc844cda9d5a62ac1a5a51b7c86d3 + languageName: node + linkType: hard + +"p-map@npm:^4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: ^3.0.0 + checksum: cb0ab21ec0f32ddffd31dfc250e3afa61e103ef43d957cc45497afe37513634589316de4eb88abdfd969fe6410c22c0b93ab24328833b8eb1ccc087fc0442a1c + languageName: node + linkType: hard + +"p-retry@npm:^4.5.0": + version: 4.6.2 + resolution: "p-retry@npm:4.6.2" + dependencies: + "@types/retry": 0.12.0 + retry: ^0.13.1 + checksum: 45c270bfddaffb4a895cea16cb760dcc72bdecb6cb45fef1971fa6ea2e91ddeafddefe01e444ac73e33b1b3d5d29fb0dd18a7effb294262437221ddc03ce0f2e + languageName: node + linkType: hard + +"p-try@npm:^2.0.0": + version: 2.2.0 + resolution: "p-try@npm:2.2.0" + checksum: f8a8e9a7693659383f06aec604ad5ead237c7a261c18048a6e1b5b85a5f8a067e469aa24f5bc009b991ea3b058a87f5065ef4176793a200d4917349881216cae + languageName: node + linkType: hard + +"param-case@npm:^3.0.4": + version: 3.0.4 + resolution: "param-case@npm:3.0.4" + dependencies: + dot-case: ^3.0.4 + tslib: ^2.0.3 + checksum: b34227fd0f794e078776eb3aa6247442056cb47761e9cd2c4c881c86d84c64205f6a56ef0d70b41ee7d77da02c3f4ed2f88e3896a8fefe08bdfb4deca037c687 + languageName: node + linkType: hard + +"parent-module@npm:^1.0.0": + version: 1.0.1 + resolution: "parent-module@npm:1.0.1" + dependencies: + callsites: ^3.0.0 + checksum: 6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff + languageName: node + linkType: hard + +"parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": + version: 5.2.0 + resolution: "parse-json@npm:5.2.0" + 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 + checksum: 62085b17d64da57f40f6afc2ac1f4d95def18c4323577e1eced571db75d9ab59b297d1d10582920f84b15985cbfc6b6d450ccbf317644cfa176f3ed982ad87e2 + languageName: node + linkType: hard + +"parse5@npm:6.0.1": + version: 6.0.1 + resolution: "parse5@npm:6.0.1" + checksum: 7d569a176c5460897f7c8f3377eff640d54132b9be51ae8a8fa4979af940830b2b0c296ce75e5bd8f4041520aadde13170dbdec44889975f906098ea0002f4bd + languageName: node + linkType: hard + +"parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2 + languageName: node + linkType: hard + +"pascal-case@npm:^3.1.2": + version: 3.1.2 + resolution: "pascal-case@npm:3.1.2" + dependencies: + no-case: ^3.0.4 + tslib: ^2.0.3 + checksum: ba98bfd595fc91ef3d30f4243b1aee2f6ec41c53b4546bfa3039487c367abaa182471dcfc830a1f9e1a0df00c14a370514fa2b3a1aacc68b15a460c31116873e + languageName: node + linkType: hard + +"path-exists@npm:^3.0.0": + version: 3.0.0 + resolution: "path-exists@npm:3.0.0" + checksum: 96e92643aa34b4b28d0de1cd2eba52a1c5313a90c6542d03f62750d82480e20bfa62bc865d5cfc6165f5fcd5aeb0851043c40a39be5989646f223300021bae0a + languageName: node + linkType: hard + +"path-exists@npm:^4.0.0": + version: 4.0.0 + resolution: "path-exists@npm:4.0.0" + checksum: 505807199dfb7c50737b057dd8d351b82c033029ab94cb10a657609e00c1bc53b951cfdbccab8de04c5584d5eff31128ce6afd3db79281874a5ef2adbba55ed1 + languageName: node + linkType: hard + +"path-is-absolute@npm:^1.0.0": + version: 1.0.1 + resolution: "path-is-absolute@npm:1.0.1" + checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 + languageName: node + linkType: hard + +"path-is-inside@npm:1.0.2": + version: 1.0.2 + resolution: "path-is-inside@npm:1.0.2" + checksum: 0b5b6c92d3018b82afb1f74fe6de6338c4c654de4a96123cb343f2b747d5606590ac0c890f956ed38220a4ab59baddfd7b713d78a62d240b20b14ab801fa02cb + languageName: node + linkType: hard + +"path-key@npm:^3.0.0, path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 + languageName: node + linkType: hard + +"path-key@npm:^4.0.0": + version: 4.0.0 + resolution: "path-key@npm:4.0.0" + checksum: 8e6c314ae6d16b83e93032c61020129f6f4484590a777eed709c4a01b50e498822b00f76ceaf94bc64dbd90b327df56ceadce27da3d83393790f1219e07721d7 + languageName: node + linkType: hard + +"path-parse@npm:^1.0.7": + version: 1.0.7 + resolution: "path-parse@npm:1.0.7" + checksum: 49abf3d81115642938a8700ec580da6e830dde670be21893c62f4e10bd7dd4c3742ddc603fe24f898cba7eb0c6bc1777f8d9ac14185d34540c6d4d80cd9cae8a + languageName: node + linkType: hard + +"path-to-regexp@npm:0.1.7": + version: 0.1.7 + resolution: "path-to-regexp@npm:0.1.7" + checksum: 69a14ea24db543e8b0f4353305c5eac6907917031340e5a8b37df688e52accd09e3cebfe1660b70d76b6bd89152f52183f28c74813dbf454ba1a01c82a38abce + languageName: node + linkType: hard + +"path-to-regexp@npm:2.2.1": + version: 2.2.1 + resolution: "path-to-regexp@npm:2.2.1" + checksum: b921a74e7576e25b06ad1635abf7e8125a29220d2efc2b71d74b9591f24a27e6f09078fa9a1b27516a097ea0637b7cab79d19b83d7f36a8ef3ef5422770e89d9 + languageName: node + linkType: hard + +"path-to-regexp@npm:^1.7.0": + version: 1.8.0 + resolution: "path-to-regexp@npm:1.8.0" + dependencies: + isarray: 0.0.1 + checksum: 709f6f083c0552514ef4780cb2e7e4cf49b0cc89a97439f2b7cc69a608982b7690fb5d1720a7473a59806508fc2dae0be751ba49f495ecf89fd8fbc62abccbcd + languageName: node + linkType: hard + +"path-type@npm:^4.0.0": + version: 4.0.0 + resolution: "path-type@npm:4.0.0" + checksum: 5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45 + languageName: node + linkType: hard + +"pause-stream@npm:0.0.11": + version: 0.0.11 + resolution: "pause-stream@npm:0.0.11" + dependencies: + through: ~2.3 + checksum: 3c4a14052a638b92e0c96eb00c0d7977df7f79ea28395250c525d197f1fc02d34ce1165d5362e2e6ebbb251524b94a76f3f0d4abc39ab8b016d97449fe15583c + languageName: node + linkType: hard + +"pend@npm:~1.2.0": + version: 1.2.0 + resolution: "pend@npm:1.2.0" + checksum: 6c72f5243303d9c60bd98e6446ba7d30ae29e3d56fdb6fae8767e8ba6386f33ee284c97efe3230a0d0217e2b1723b8ab490b1bbf34fcbb2180dbc8a9de47850d + languageName: node + linkType: hard + +"performance-now@npm:^2.1.0": + version: 2.1.0 + resolution: "performance-now@npm:2.1.0" + checksum: 534e641aa8f7cba160f0afec0599b6cecefbb516a2e837b512be0adbe6c1da5550e89c78059c7fabc5c9ffdf6627edabe23eb7c518c4500067a898fa65c2b550 + languageName: node + linkType: hard + +"picocolors@npm:^0.2.1": + version: 0.2.1 + resolution: "picocolors@npm:0.2.1" + checksum: 3b0f441f0062def0c0f39e87b898ae7461c3a16ffc9f974f320b44c799418cabff17780ee647fda42b856a1dc45897e2c62047e1b546d94d6d5c6962f45427b2 + languageName: node + linkType: hard + +"picocolors@npm:^1.0.0": + version: 1.0.0 + resolution: "picocolors@npm:1.0.0" + checksum: a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 + languageName: node + linkType: hard + +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.2, picomatch@npm:^2.2.3, picomatch@npm:^2.3.1": + version: 2.3.1 + resolution: "picomatch@npm:2.3.1" + checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf + languageName: node + linkType: hard + +"pidtree@npm:0.6.0": + version: 0.6.0 + resolution: "pidtree@npm:0.6.0" + bin: + pidtree: bin/pidtree.js + checksum: 8fbc073ede9209dd15e80d616e65eb674986c93be49f42d9ddde8dbbd141bb53d628a7ca4e58ab5c370bb00383f67d75df59a9a226dede8fa801267a7030c27a + languageName: node + linkType: hard + +"pify@npm:^2.2.0, pify@npm:^2.3.0": + version: 2.3.0 + resolution: "pify@npm:2.3.0" + checksum: 9503aaeaf4577acc58642ad1d25c45c6d90288596238fb68f82811c08104c800e5a7870398e9f015d82b44ecbcbef3dc3d4251a1cbb582f6e5959fe09884b2ba + languageName: node + linkType: hard + +"pirates@npm:^4.0.4": + version: 4.0.5 + resolution: "pirates@npm:4.0.5" + checksum: c9994e61b85260bec6c4fc0307016340d9b0c4f4b6550a957afaaff0c9b1ad58fbbea5cfcf083860a25cb27a375442e2b0edf52e2e1e40e69934e08dcc52d227 + languageName: node + linkType: hard + +"pkg-dir@npm:^4.1.0, pkg-dir@npm:^4.2.0": + version: 4.2.0 + resolution: "pkg-dir@npm:4.2.0" + dependencies: + find-up: ^4.0.0 + checksum: 9863e3f35132bf99ae1636d31ff1e1e3501251d480336edb1c211133c8d58906bed80f154a1d723652df1fda91e01c7442c2eeaf9dc83157c7ae89087e43c8d6 + languageName: node + linkType: hard + +"pkg-up@npm:^3.1.0": + version: 3.1.0 + resolution: "pkg-up@npm:3.1.0" + dependencies: + find-up: ^3.0.0 + checksum: 5bac346b7c7c903613c057ae3ab722f320716199d753f4a7d053d38f2b5955460f3e6ab73b4762c62fd3e947f58e04f1343e92089e7bb6091c90877406fcd8c8 + languageName: node + linkType: hard + +"postcss-attribute-case-insensitive@npm:^5.0.2": + version: 5.0.2 + resolution: "postcss-attribute-case-insensitive@npm:5.0.2" + dependencies: + postcss-selector-parser: ^6.0.10 + peerDependencies: + postcss: ^8.2 + checksum: c0b8139f37e68dba372724cba03a53c30716224f0085f98485cada99489beb7c3da9d598ffc1d81519b59d9899291712c9041c250205e6ec0b034bb2c144dcf9 + languageName: node + linkType: hard + +"postcss-browser-comments@npm:^4": + version: 4.0.0 + resolution: "postcss-browser-comments@npm:4.0.0" + peerDependencies: + browserslist: ">=4" + postcss: ">=8" + checksum: 9b8e7094838c2d7bd1ab3ca9cb8d0a78a9a6c8e22f43133ba02db8862fb6c141630e9f590e46f7125cfa4723cacd27b74fa00c05a9907b364dc1f6f17cf13f6f + languageName: node + linkType: hard + +"postcss-calc@npm:^8.2.3": + version: 8.2.4 + resolution: "postcss-calc@npm:8.2.4" + dependencies: + postcss-selector-parser: ^6.0.9 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.2 + checksum: 314b4cebb0c4ed0cf8356b4bce71eca78f5a7842e6a3942a3bba49db168d5296b2bd93c3f735ae1c616f2651d94719ade33becc03c73d2d79c7394fb7f73eabb + languageName: node + linkType: hard + +"postcss-clamp@npm:^4.1.0": + version: 4.1.0 + resolution: "postcss-clamp@npm:4.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.6 + checksum: 118eec936b3b035dc8d75c89973408f15c5a3de3d1ee210a2b3511e3e431d9c56e6f354b509a90540241e2225ffe3caaa2fdf25919c63348ce4583a28ada642c + languageName: node + linkType: hard + +"postcss-color-functional-notation@npm:^4.2.4": + version: 4.2.4 + resolution: "postcss-color-functional-notation@npm:4.2.4" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: b763e164fe3577a1de96f75e4bf451585c4f80b8ce60799763a51582cc9402d76faed57324a5d5e5556d90ca7ea0ebde565acb820c95e04bee6f36a91b019831 + languageName: node + linkType: hard + +"postcss-color-hex-alpha@npm:^8.0.4": + version: 8.0.4 + resolution: "postcss-color-hex-alpha@npm:8.0.4" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4 + checksum: a2f3173a60176cf0aea3b7ebbc799b2cb08229127f0fff708fa31efa14e4ded47ca49aff549d8ed92e74ffe24adee32d5b9d557dbde0524fde5fe389bc520b4e + languageName: node + linkType: hard + +"postcss-color-rebeccapurple@npm:^7.1.1": + version: 7.1.1 + resolution: "postcss-color-rebeccapurple@npm:7.1.1" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: 03482f9b8170da0fa014c41a5d88bce7b987471fb73fc456d397222a2455c89ac7f974dd6ddf40fd31907e768aad158057164b7c5f62cee63a6ecf29d47d7467 + languageName: node + linkType: hard + +"postcss-colormin@npm:^5.3.0": + version: 5.3.0 + resolution: "postcss-colormin@npm:5.3.0" + dependencies: + browserslist: ^4.16.6 + caniuse-api: ^3.0.0 + colord: ^2.9.1 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 3d3e3cc25071407fb73d68541ca1039ebd154fceb649041461a8a3cab0400cc89b42dbb34a4eeaf573be4ba2370ce23af5e01aff5e03a8d72275f40605577212 + languageName: node + linkType: hard + +"postcss-convert-values@npm:^5.1.3": + version: 5.1.3 + resolution: "postcss-convert-values@npm:5.1.3" + dependencies: + browserslist: ^4.21.4 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: df48cdaffabf9737f9cfdc58a3dc2841cf282506a7a944f6c70236cff295d3a69f63de6e0935eeb8a9d3f504324e5b4e240abc29e21df9e35a02585d3060aeb5 + languageName: node + linkType: hard + +"postcss-custom-media@npm:^8.0.2": + version: 8.0.2 + resolution: "postcss-custom-media@npm:8.0.2" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.3 + checksum: 887bbbacf6f8fab688123796e5dc1e8283b99f21e4c674235bd929dc8018c50df8634ea08932033ec93baaca32670ef2b87e6632863e0b4d84847375dbde9366 + languageName: node + linkType: hard + +"postcss-custom-properties@npm:^12.1.10": + version: 12.1.11 + resolution: "postcss-custom-properties@npm:12.1.11" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: 421f9d8d6b9c9066919f39251859232efc4dc5dd406c01e62e08734319a6ccda6d03dd6b46063ba0971053ac6ad3f7abade56d67650b3e370851b2291e8e45e6 + languageName: node + linkType: hard + +"postcss-custom-selectors@npm:^6.0.3": + version: 6.0.3 + resolution: "postcss-custom-selectors@npm:6.0.3" + dependencies: + postcss-selector-parser: ^6.0.4 + peerDependencies: + postcss: ^8.3 + checksum: 18080d60a8a77a76d8ddff185104d65418fffd02bbf9824499f807ced7941509ba63828ab8fe3ec1d6b0d6c72a482bb90a79d79cdef58e5f4b30113cca16e69b + languageName: node + linkType: hard + +"postcss-dir-pseudo-class@npm:^6.0.5": + version: 6.0.5 + resolution: "postcss-dir-pseudo-class@npm:6.0.5" + dependencies: + postcss-selector-parser: ^6.0.10 + peerDependencies: + postcss: ^8.2 + checksum: 7810c439d8d1a9072c00f8ab39261a1492873ad170425745bd2819c59767db2f352f906588fc2a7d814e91117900563d7e569ecd640367c7332b26b9829927ef + languageName: node + linkType: hard + +"postcss-discard-comments@npm:^5.1.2": + version: 5.1.2 + resolution: "postcss-discard-comments@npm:5.1.2" + peerDependencies: + postcss: ^8.2.15 + checksum: abfd064ebc27aeaf5037643dd51ffaff74d1fa4db56b0523d073ace4248cbb64ffd9787bd6924b0983a9d0bd0e9bf9f10d73b120e50391dc236e0d26c812fa2a + languageName: node + linkType: hard + +"postcss-discard-duplicates@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-discard-duplicates@npm:5.1.0" + peerDependencies: + postcss: ^8.2.15 + checksum: 88d6964201b1f4ed6bf7a32cefe68e86258bb6e42316ca01d9b32bdb18e7887d02594f89f4a2711d01b51ea6e3fcca8c54be18a59770fe5f4521c61d3eb6ca35 + languageName: node + linkType: hard + +"postcss-discard-empty@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-discard-empty@npm:5.1.1" + peerDependencies: + postcss: ^8.2.15 + checksum: 970adb12fae5c214c0768236ad9a821552626e77dedbf24a8213d19cc2c4a531a757cd3b8cdd3fc22fb1742471b8692a1db5efe436a71236dec12b1318ee8ff4 + languageName: node + linkType: hard + +"postcss-discard-overridden@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-discard-overridden@npm:5.1.0" + peerDependencies: + postcss: ^8.2.15 + checksum: d64d4a545aa2c81b22542895cfcddc787d24119f294d35d29b0599a1c818b3cc51f4ee80b80f5a0a09db282453dd5ac49f104c2117cc09112d0ac9b40b499a41 + languageName: node + linkType: hard + +"postcss-double-position-gradients@npm:^3.1.2": + version: 3.1.2 + resolution: "postcss-double-position-gradients@npm:3.1.2" + dependencies: + "@csstools/postcss-progressive-custom-properties": ^1.1.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: ca09bf2aefddc180f1c1413f379eef30d492b8147543413f7251216f23f413c394b2ed10b7cd255e87b18e0c8efe36087ea8b9bfb26a09813f9607a0b8e538b6 + languageName: node + linkType: hard + +"postcss-env-function@npm:^4.0.6": + version: 4.0.6 + resolution: "postcss-env-function@npm:4.0.6" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4 + checksum: 645b2363cfa21be9dcce7fe4a0f172f0af70c00d6a4c1eb3d7ff7e9cfe26d569e291ec2533114d77b12d610023cd168a92d62c38f2fc969fa333b5ae2bff5ffe + languageName: node + linkType: hard + +"postcss-flexbugs-fixes@npm:^5.0.2": + version: 5.0.2 + resolution: "postcss-flexbugs-fixes@npm:5.0.2" + peerDependencies: + postcss: ^8.1.4 + checksum: 022ddbcca8987303b9be75ff259e9de81b98643adac87a5fc6b52a0fcbbf95e1ac9fd508c4ed67cad76ac5d039b7123de8a0832329481b3c626f5d63f7a28f47 + languageName: node + linkType: hard + +"postcss-focus-visible@npm:^6.0.4": + version: 6.0.4 + resolution: "postcss-focus-visible@npm:6.0.4" + dependencies: + postcss-selector-parser: ^6.0.9 + peerDependencies: + postcss: ^8.4 + checksum: acd010b9ddef9b86ffb5fa604c13515ba83e18bc5118dad0a1281150f412aa0ece056c2c5ac56b55e2599f53ab0f740f5ebfdc51e1f5cfe43b8130bac0096fcc + languageName: node + linkType: hard + +"postcss-focus-within@npm:^5.0.4": + version: 5.0.4 + resolution: "postcss-focus-within@npm:5.0.4" + dependencies: + postcss-selector-parser: ^6.0.9 + peerDependencies: + postcss: ^8.4 + checksum: f23d8ab757345a6deaa807d76e10c88caf4b771c38b60e1593b24aee161c503b5823620e89302226a6ae5e7afdb6ac31809241291912e4176eb594a7ddcc9521 + languageName: node + linkType: hard + +"postcss-font-variant@npm:^5.0.0": + version: 5.0.0 + resolution: "postcss-font-variant@npm:5.0.0" + peerDependencies: + postcss: ^8.1.0 + checksum: a19286589261c2bc3e20470486e1ee3b4daf34271c5020167f30856c9b30c26f23264307cb97a184d503814e1b8c5d8a1f9f64a14fd4fd9551c173dca9424695 + languageName: node + linkType: hard + +"postcss-gap-properties@npm:^3.0.5": + version: 3.0.5 + resolution: "postcss-gap-properties@npm:3.0.5" + peerDependencies: + postcss: ^8.2 + checksum: aed559d6d375203a08a006c9ae8cf5ae90d9edaec5cadd20fe65c1b8ce63c2bc8dfe752d4331880a6e24a300541cde61058be790b7bd9b5d04d470c250fbcd39 + languageName: node + linkType: hard + +"postcss-image-set-function@npm:^4.0.7": + version: 4.0.7 + resolution: "postcss-image-set-function@npm:4.0.7" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: 7e509330986de14250ead1a557e8da8baaf66ebe8a40354a5dff60ab40d99a483d92aa57d52713251ca1adbf0055ef476c5702b0d0ba5f85a4f407367cdabac0 + languageName: node + linkType: hard + +"postcss-import@npm:^14.1.0": + version: 14.1.0 + resolution: "postcss-import@npm:14.1.0" + dependencies: + postcss-value-parser: ^4.0.0 + read-cache: ^1.0.0 + resolve: ^1.1.7 + peerDependencies: + postcss: ^8.0.0 + checksum: cd45d406e90f67cdab9524352e573cc6b4462b790934a05954e929a6653ebd31288ceebc8ce3c3ed7117ae672d9ebbec57df0bceec0a56e9b259c2e71d47ca86 + languageName: node + linkType: hard + +"postcss-initial@npm:^4.0.1": + version: 4.0.1 + resolution: "postcss-initial@npm:4.0.1" + peerDependencies: + postcss: ^8.0.0 + checksum: 6956953853865de79c39d11533a2860e9f38b770bb284d0010d98a00b9469e22de344e4e5fd8208614d797030487e8918dd2f2c37d9e24d4dd59d565d4fc3e12 + languageName: node + linkType: hard + +"postcss-js@npm:^4.0.0": + version: 4.0.0 + resolution: "postcss-js@npm:4.0.0" + dependencies: + camelcase-css: ^2.0.1 + peerDependencies: + postcss: ^8.3.3 + checksum: 14be8a58670b4c5d037d40f179240a4f736d53530db727e2635638fa296bc4bff18149ca860928398aace422e55d07c9f5729eeccd395340944985199cdc82a5 + languageName: node + linkType: hard + +"postcss-lab-function@npm:^4.2.1": + version: 4.2.1 + resolution: "postcss-lab-function@npm:4.2.1" + dependencies: + "@csstools/postcss-progressive-custom-properties": ^1.1.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: 26ac74b430011271b5581beba69b2cd788f56375fcb64c90f6ec1577379af85f6022dc38c410ff471dac520c7ddc289160a6a16cca3c7ff76f5af7e90d31eaa3 + languageName: node + linkType: hard + +"postcss-load-config@npm:^3.1.4": + version: 3.1.4 + resolution: "postcss-load-config@npm:3.1.4" + dependencies: + lilconfig: ^2.0.5 + yaml: ^1.10.2 + peerDependencies: + postcss: ">=8.0.9" + ts-node: ">=9.0.0" + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + checksum: 1c589504c2d90b1568aecae8238ab993c17dba2c44f848a8f13619ba556d26a1c09644d5e6361b5784e721e94af37b604992f9f3dc0483e687a0cc1cc5029a34 + languageName: node + linkType: hard + +"postcss-loader@npm:^6.2.1": + version: 6.2.1 + resolution: "postcss-loader@npm:6.2.1" + dependencies: + cosmiconfig: ^7.0.0 + klona: ^2.0.5 + semver: ^7.3.5 + peerDependencies: + postcss: ^7.0.0 || ^8.0.1 + webpack: ^5.0.0 + checksum: e40ae79c3e39df37014677a817b001bd115d8b10dedf53a07b97513d93b1533cd702d7a48831bdd77b9a9484b1ec84a5d4a723f80e83fb28682c75b5e65e8a90 + languageName: node + linkType: hard + +"postcss-logical@npm:^5.0.4": + version: 5.0.4 + resolution: "postcss-logical@npm:5.0.4" + peerDependencies: + postcss: ^8.4 + checksum: 17c71291ed6a03883a5aa54b9923b874c32710707d041a0f0752e6febdb09dee5d2abf4ef271978d932e4a4c948f349bb23edf633c03e3427ba15e71bfc66ac7 + languageName: node + linkType: hard + +"postcss-media-minmax@npm:^5.0.0": + version: 5.0.0 + resolution: "postcss-media-minmax@npm:5.0.0" + peerDependencies: + postcss: ^8.1.0 + checksum: 2cd7283e07a1ac1acdcc3ecbaa0e9932f8d1e7647e7aeb14d91845fcb890d60d7257ec70c825cae8d48ae80a08cc77ebc4021a0dfa32360e0cd991e2bc021607 + languageName: node + linkType: hard + +"postcss-merge-longhand@npm:^5.1.7": + version: 5.1.7 + resolution: "postcss-merge-longhand@npm:5.1.7" + dependencies: + postcss-value-parser: ^4.2.0 + stylehacks: ^5.1.1 + peerDependencies: + postcss: ^8.2.15 + checksum: 81c3fc809f001b9b71a940148e242bdd6e2d77713d1bfffa15eb25c1f06f6648d5e57cb21645746d020a2a55ff31e1740d2b27900442913a9d53d8a01fb37e1b + languageName: node + linkType: hard + +"postcss-merge-rules@npm:^5.1.3": + version: 5.1.3 + resolution: "postcss-merge-rules@npm:5.1.3" + dependencies: + browserslist: ^4.21.4 + caniuse-api: ^3.0.0 + cssnano-utils: ^3.1.0 + postcss-selector-parser: ^6.0.5 + peerDependencies: + postcss: ^8.2.15 + checksum: 0ddaddff98cd7f3fac2b0e716c641f529a61a8668be6d5b48d60770d0a1246126088e1d606f309b9748ff598a3794f3fd6dd5b8c3d79112f84744cab5375d4d9 + languageName: node + linkType: hard + +"postcss-minify-font-values@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-minify-font-values@npm:5.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 35e858fa41efa05acdeb28f1c76579c409fdc7eabb1744c3bd76e895bb9fea341a016746362a67609688ab2471f587202b9a3e14ea28ad677754d663a2777ece + languageName: node + linkType: hard + +"postcss-minify-gradients@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-minify-gradients@npm:5.1.1" + dependencies: + colord: ^2.9.1 + cssnano-utils: ^3.1.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 27354072a07c5e6dab36731103b94ca2354d4ed3c5bc6aacfdf2ede5a55fa324679d8fee5450800bc50888dbb5e9ed67569c0012040c2be128143d0cebb36d67 + languageName: node + linkType: hard + +"postcss-minify-params@npm:^5.1.4": + version: 5.1.4 + resolution: "postcss-minify-params@npm:5.1.4" + dependencies: + browserslist: ^4.21.4 + cssnano-utils: ^3.1.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: bd63e2cc89edcf357bb5c2a16035f6d02ef676b8cede4213b2bddd42626b3d428403849188f95576fc9f03e43ebd73a29bf61d33a581be9a510b13b7f7f100d5 + languageName: node + linkType: hard + +"postcss-minify-selectors@npm:^5.2.1": + version: 5.2.1 + resolution: "postcss-minify-selectors@npm:5.2.1" + dependencies: + postcss-selector-parser: ^6.0.5 + peerDependencies: + postcss: ^8.2.15 + checksum: 6fdbc84f99a60d56b43df8930707da397775e4c36062a106aea2fd2ac81b5e24e584a1892f4baa4469fa495cb87d1422560eaa8f6c9d500f9f0b691a5f95bab5 + languageName: node + linkType: hard + +"postcss-modules-extract-imports@npm:^3.0.0": + version: 3.0.0 + resolution: "postcss-modules-extract-imports@npm:3.0.0" + peerDependencies: + postcss: ^8.1.0 + checksum: 4b65f2f1382d89c4bc3c0a1bdc5942f52f3cb19c110c57bd591ffab3a5fee03fcf831604168205b0c1b631a3dce2255c70b61aaae3ef39d69cd7eb450c2552d2 + languageName: node + linkType: hard + +"postcss-modules-local-by-default@npm:^4.0.0": + version: 4.0.0 + resolution: "postcss-modules-local-by-default@npm:4.0.0" + dependencies: + icss-utils: ^5.0.0 + postcss-selector-parser: ^6.0.2 + postcss-value-parser: ^4.1.0 + peerDependencies: + postcss: ^8.1.0 + checksum: 6cf570badc7bc26c265e073f3ff9596b69bb954bc6ac9c5c1b8cba2995b80834226b60e0a3cbb87d5f399dbb52e6466bba8aa1d244f6218f99d834aec431a69d + languageName: node + linkType: hard + +"postcss-modules-scope@npm:^3.0.0": + version: 3.0.0 + resolution: "postcss-modules-scope@npm:3.0.0" + dependencies: + postcss-selector-parser: ^6.0.4 + peerDependencies: + postcss: ^8.1.0 + checksum: 330b9398dbd44c992c92b0dc612c0626135e2cc840fee41841eb61247a6cfed95af2bd6f67ead9dd9d0bb41f5b0367129d93c6e434fa3e9c58ade391d9a5a138 + languageName: node + linkType: hard + +"postcss-modules-values@npm:^4.0.0": + version: 4.0.0 + resolution: "postcss-modules-values@npm:4.0.0" + dependencies: + icss-utils: ^5.0.0 + peerDependencies: + postcss: ^8.1.0 + checksum: f7f2cdf14a575b60e919ad5ea52fed48da46fe80db2733318d71d523fc87db66c835814940d7d05b5746b0426e44661c707f09bdb83592c16aea06e859409db6 + languageName: node + linkType: hard + +"postcss-nested@npm:6.0.0": + version: 6.0.0 + resolution: "postcss-nested@npm:6.0.0" + dependencies: + postcss-selector-parser: ^6.0.10 + peerDependencies: + postcss: ^8.2.14 + checksum: 2105dc52cd19747058f1a46862c9e454b5a365ac2e7135fc1015d67a8fe98ada2a8d9ee578e90f7a093bd55d3994dd913ba5ff1d5e945b4ed9a8a2992ecc8f10 + languageName: node + linkType: hard + +"postcss-nesting@npm:^10.2.0": + version: 10.2.0 + resolution: "postcss-nesting@npm:10.2.0" + dependencies: + "@csstools/selector-specificity": ^2.0.0 + postcss-selector-parser: ^6.0.10 + peerDependencies: + postcss: ^8.2 + checksum: 25e6e66186bd7f18bc4628cf0f43e02189268f28a449aa4a63b33b8f2c33745af99acfcd4ce2ac69319dc850e83b28dbaabcf517e3977dfe20e37fed0e032c7d + languageName: node + linkType: hard + +"postcss-normalize-charset@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-normalize-charset@npm:5.1.0" + peerDependencies: + postcss: ^8.2.15 + checksum: e79d92971fc05b8b3c9b72f3535a574e077d13c69bef68156a0965f397fdf157de670da72b797f57b0e3bac8f38155b5dd1735ecab143b9cc4032d72138193b4 + languageName: node + linkType: hard + +"postcss-normalize-display-values@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-normalize-display-values@npm:5.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: b6eb7b9b02c3bdd62bbc54e01e2b59733d73a1c156905d238e178762962efe0c6f5104544da39f32cade8a4fb40f10ff54b63a8ebfbdff51e8780afb9fbdcf86 + languageName: node + linkType: hard + +"postcss-normalize-positions@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-normalize-positions@npm:5.1.1" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: d9afc233729c496463c7b1cdd06732469f401deb387484c3a2422125b46ec10b4af794c101f8c023af56f01970b72b535e88373b9058ecccbbf88db81662b3c4 + languageName: node + linkType: hard + +"postcss-normalize-repeat-style@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-normalize-repeat-style@npm:5.1.1" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 2c6ad2b0ae10a1fda156b948c34f78c8f1e185513593de4d7e2480973586675520edfec427645fa168c337b0a6b3ceca26f92b96149741ca98a9806dad30d534 + languageName: node + linkType: hard + +"postcss-normalize-string@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-normalize-string@npm:5.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 6e549c6e5b2831e34c7bdd46d8419e2278f6af1d5eef6d26884a37c162844e60339340c57e5e06058cdbe32f27fc6258eef233e811ed2f71168ef2229c236ada + languageName: node + linkType: hard + +"postcss-normalize-timing-functions@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-normalize-timing-functions@npm:5.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: da550f50e90b0b23e17b67449a7d1efd1aa68288e66d4aa7614ca6f5cc012896be1972b7168eee673d27da36504faccf7b9f835c0f7e81243f966a42c8c030aa + languageName: node + linkType: hard + +"postcss-normalize-unicode@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-normalize-unicode@npm:5.1.1" + dependencies: + browserslist: ^4.21.4 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 4c24d26cc9f4b19a9397db4e71dd600dab690f1de8e14a3809e2aa1452dbc3791c208c38a6316bbc142f29e934fdf02858e68c94038c06174d78a4937e0f273c + languageName: node + linkType: hard + +"postcss-normalize-url@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-normalize-url@npm:5.1.0" + dependencies: + normalize-url: ^6.0.1 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 3bd4b3246d6600230bc827d1760b24cb3101827ec97570e3016cbe04dc0dd28f4dbe763245d1b9d476e182c843008fbea80823061f1d2219b96f0d5c724a24c0 + languageName: node + linkType: hard + +"postcss-normalize-whitespace@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-normalize-whitespace@npm:5.1.1" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 12d8fb6d1c1cba208cc08c1830959b7d7ad447c3f5581873f7e185f99a9a4230c43d3af21ca12c818e4690a5085a95b01635b762ad4a7bef69d642609b4c0e19 + languageName: node + linkType: hard + +"postcss-normalize@npm:^10.0.1": + version: 10.0.1 + resolution: "postcss-normalize@npm:10.0.1" + dependencies: + "@csstools/normalize.css": "*" + postcss-browser-comments: ^4 + sanitize.css: "*" + peerDependencies: + browserslist: ">= 4" + postcss: ">= 8" + checksum: af67ade84e5d65de0cf84cde479840da96ffb2037fe6bf86737788216f67e414622e718e7d84182885ad65fa948150e4a0c3e454ca63e619dd5c7b4eb4224c39 + languageName: node + linkType: hard + +"postcss-opacity-percentage@npm:^1.1.2": + version: 1.1.3 + resolution: "postcss-opacity-percentage@npm:1.1.3" + peerDependencies: + postcss: ^8.2 + checksum: 54d1b8ca68035bc1a5788aaabdbc3b66ffee34b5a2412cecf073627dad7e3f2bae07c01fac3bc7f46bbac5da3291ac9ddcf74bfee26dfd86f9f96c847a0afc13 + languageName: node + linkType: hard + +"postcss-ordered-values@npm:^5.1.3": + version: 5.1.3 + resolution: "postcss-ordered-values@npm:5.1.3" + dependencies: + cssnano-utils: ^3.1.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 6f3ca85b6ceffc68aadaf319d9ee4c5ac16d93195bf8cba2d1559b631555ad61941461cda6d3909faab86e52389846b2b36345cff8f0c3f4eb345b1b8efadcf9 + languageName: node + linkType: hard + +"postcss-overflow-shorthand@npm:^3.0.4": + version: 3.0.4 + resolution: "postcss-overflow-shorthand@npm:3.0.4" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: 74009022491e3901263f8f5811630393480323e51f5d23ef17f3fdc7e03bf9c2502a632f3ba8fe6a468b57590f13b2fa3b17a68ef19653589e76277607696743 + languageName: node + linkType: hard + +"postcss-page-break@npm:^3.0.4": + version: 3.0.4 + resolution: "postcss-page-break@npm:3.0.4" + peerDependencies: + postcss: ^8 + checksum: a7d08c945fc691f62c77ac701e64722218b14ec5c8fc1972b8af9c21553492d40808cf95e61b9697b1dacaf7e6180636876d7fee314f079e6c9e39ac1b1edc6f + languageName: node + linkType: hard + +"postcss-place@npm:^7.0.5": + version: 7.0.5 + resolution: "postcss-place@npm:7.0.5" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: 903fec0c313bb7ec20f2c8f0a125866fb7804aa3186b5b2c7c2d58cb9039ff301461677a060e9db643d1aaffaf80a0ff71e900a6da16705dad6b49c804cb3c73 + languageName: node + linkType: hard + +"postcss-preset-env@npm:^7.0.1": + version: 7.8.3 + resolution: "postcss-preset-env@npm:7.8.3" + dependencies: + "@csstools/postcss-cascade-layers": ^1.1.1 + "@csstools/postcss-color-function": ^1.1.1 + "@csstools/postcss-font-format-keywords": ^1.0.1 + "@csstools/postcss-hwb-function": ^1.0.2 + "@csstools/postcss-ic-unit": ^1.0.1 + "@csstools/postcss-is-pseudo-class": ^2.0.7 + "@csstools/postcss-nested-calc": ^1.0.0 + "@csstools/postcss-normalize-display-values": ^1.0.1 + "@csstools/postcss-oklab-function": ^1.1.1 + "@csstools/postcss-progressive-custom-properties": ^1.3.0 + "@csstools/postcss-stepped-value-functions": ^1.0.1 + "@csstools/postcss-text-decoration-shorthand": ^1.0.0 + "@csstools/postcss-trigonometric-functions": ^1.0.2 + "@csstools/postcss-unset-value": ^1.0.2 + autoprefixer: ^10.4.13 + browserslist: ^4.21.4 + css-blank-pseudo: ^3.0.3 + css-has-pseudo: ^3.0.4 + css-prefers-color-scheme: ^6.0.3 + cssdb: ^7.1.0 + postcss-attribute-case-insensitive: ^5.0.2 + postcss-clamp: ^4.1.0 + postcss-color-functional-notation: ^4.2.4 + postcss-color-hex-alpha: ^8.0.4 + postcss-color-rebeccapurple: ^7.1.1 + postcss-custom-media: ^8.0.2 + postcss-custom-properties: ^12.1.10 + postcss-custom-selectors: ^6.0.3 + postcss-dir-pseudo-class: ^6.0.5 + postcss-double-position-gradients: ^3.1.2 + postcss-env-function: ^4.0.6 + postcss-focus-visible: ^6.0.4 + postcss-focus-within: ^5.0.4 + postcss-font-variant: ^5.0.0 + postcss-gap-properties: ^3.0.5 + postcss-image-set-function: ^4.0.7 + postcss-initial: ^4.0.1 + postcss-lab-function: ^4.2.1 + postcss-logical: ^5.0.4 + postcss-media-minmax: ^5.0.0 + postcss-nesting: ^10.2.0 + postcss-opacity-percentage: ^1.1.2 + postcss-overflow-shorthand: ^3.0.4 + postcss-page-break: ^3.0.4 + postcss-place: ^7.0.5 + postcss-pseudo-class-any-link: ^7.1.6 + postcss-replace-overflow-wrap: ^4.0.0 + postcss-selector-not: ^6.0.1 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2 + checksum: 71bfb697ffc55e27895b2bf3a579dd9b4c1321872816091935e33d6f659cab60795a03bb022dc8a4cab48fd5680a419fe9ae5d61a3a3d8c785ec9308f323e787 + languageName: node + linkType: hard + +"postcss-pseudo-class-any-link@npm:^7.1.6": + version: 7.1.6 + resolution: "postcss-pseudo-class-any-link@npm:7.1.6" + dependencies: + postcss-selector-parser: ^6.0.10 + peerDependencies: + postcss: ^8.2 + checksum: 43aa18ea1ef1b168f61310856dd92f46ceb3dc60b6cf820e079ca1a849df5cc0f12a1511bdc1811a23f03d60ddcc959200c80c3f9a7b57feebe32bab226afb39 + languageName: node + linkType: hard + +"postcss-reduce-initial@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-reduce-initial@npm:5.1.1" + dependencies: + browserslist: ^4.21.4 + caniuse-api: ^3.0.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 1b704aba8c38103cbb5a75c6201dbf58ec2f3a978013c7f7e8957fd3bf3282f992050dec5a01bc050d031bad836e187dd6622b922ca78ab92bcd0afd21fb0b98 + languageName: node + linkType: hard + +"postcss-reduce-transforms@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-reduce-transforms@npm:5.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 0c6af2cba20e3ff63eb9ad045e634ddfb9c3e5c0e614c020db2a02f3aa20632318c4ede9e0c995f9225d9a101e673de91c0a6e10bb2fa5da6d6c75d15a55882f + languageName: node + linkType: hard + +"postcss-replace-overflow-wrap@npm:^4.0.0": + version: 4.0.0 + resolution: "postcss-replace-overflow-wrap@npm:4.0.0" + peerDependencies: + postcss: ^8.0.3 + checksum: 3ffe20b300a4c377a11c588b142740d8557e03c707474c45234c934190ac374750ddc92c7906c373471d273a20504a429c2062c21fdcaff830fb28e0a81ac1dc + languageName: node + linkType: hard + +"postcss-selector-not@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-selector-not@npm:6.0.1" + dependencies: + postcss-selector-parser: ^6.0.10 + peerDependencies: + postcss: ^8.2 + checksum: fe523a0219e4bd34f04498534bb9e8aec3193f3585eafe4c388d086955b41201cae71fd20980ca465acade7f182029b43dbd5ca7e9d50bf34bbcaf1d19fe3ee6 + languageName: node + linkType: hard + +"postcss-selector-parser@npm:^6.0.10, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.0.5, postcss-selector-parser@npm:^6.0.9": + version: 6.0.11 + resolution: "postcss-selector-parser@npm:6.0.11" + dependencies: + cssesc: ^3.0.0 + util-deprecate: ^1.0.2 + checksum: 0b01aa9c2d2c8dbeb51e9b204796b678284be9823abc8d6d40a8b16d4149514e922c264a8ed4deb4d6dbced564b9be390f5942c058582d8656351516d6c49cde + languageName: node + linkType: hard + +"postcss-svgo@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-svgo@npm:5.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + svgo: ^2.7.0 + peerDependencies: + postcss: ^8.2.15 + checksum: d86eb5213d9f700cf5efe3073799b485fb7cacae0c731db3d7749c9c2b1c9bc85e95e0baeca439d699ff32ea24815fc916c4071b08f67ed8219df229ce1129bd + languageName: node + linkType: hard + +"postcss-unique-selectors@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-unique-selectors@npm:5.1.1" + dependencies: + postcss-selector-parser: ^6.0.5 + peerDependencies: + postcss: ^8.2.15 + checksum: 637e7b786e8558265775c30400c54b6b3b24d4748923f4a39f16a65fd0e394f564ccc9f0a1d3c0e770618a7637a7502ea1d0d79f731d429cb202255253c23278 + languageName: node + linkType: hard + +"postcss-value-parser@npm:^4.0.0, postcss-value-parser@npm:^4.1.0, postcss-value-parser@npm:^4.2.0": + version: 4.2.0 + resolution: "postcss-value-parser@npm:4.2.0" + checksum: 819ffab0c9d51cf0acbabf8996dffbfafbafa57afc0e4c98db88b67f2094cb44488758f06e5da95d7036f19556a4a732525e84289a425f4f6fd8e412a9d7442f + languageName: node + linkType: hard + +"postcss@npm:^7.0.35": + version: 7.0.39 + resolution: "postcss@npm:7.0.39" + dependencies: + picocolors: ^0.2.1 + source-map: ^0.6.1 + checksum: 4ac793f506c23259189064bdc921260d869a115a82b5e713973c5af8e94fbb5721a5cc3e1e26840500d7e1f1fa42a209747c5b1a151918a9bc11f0d7ed9048e3 + languageName: node + linkType: hard + +"postcss@npm:^8.3.5, postcss@npm:^8.4.18, postcss@npm:^8.4.19, postcss@npm:^8.4.4": + version: 8.4.21 + resolution: "postcss@npm:8.4.21" + dependencies: + nanoid: ^3.3.4 + picocolors: ^1.0.0 + source-map-js: ^1.0.2 + checksum: e39ac60ccd1542d4f9d93d894048aac0d686b3bb38e927d8386005718e6793dbbb46930f0a523fe382f1bbd843c6d980aaea791252bf5e176180e5a4336d9679 + languageName: node + linkType: hard + +"prelude-ls@npm:^1.2.1": + version: 1.2.1 + resolution: "prelude-ls@npm:1.2.1" + checksum: cd192ec0d0a8e4c6da3bb80e4f62afe336df3f76271ac6deb0e6a36187133b6073a19e9727a1ff108cd8b9982e4768850d413baa71214dd80c7979617dca827a + languageName: node + linkType: hard + +"prelude-ls@npm:~1.1.2": + version: 1.1.2 + resolution: "prelude-ls@npm:1.1.2" + checksum: c4867c87488e4a0c233e158e4d0d5565b609b105d75e4c05dc760840475f06b731332eb93cc8c9cecb840aa8ec323ca3c9a56ad7820ad2e63f0261dadcb154e4 + languageName: node + linkType: hard + +"prettier-linter-helpers@npm:^1.0.0": + version: 1.0.0 + resolution: "prettier-linter-helpers@npm:1.0.0" + dependencies: + fast-diff: ^1.1.2 + checksum: 00ce8011cf6430158d27f9c92cfea0a7699405633f7f1d4a45f07e21bf78e99895911cbcdc3853db3a824201a7c745bd49bfea8abd5fb9883e765a90f74f8392 + languageName: node + linkType: hard + +"prettier@npm:2.8.0": + version: 2.8.0 + resolution: "prettier@npm:2.8.0" + bin: + prettier: bin-prettier.js + checksum: 72004ce0cc9bb097daf3e3833f62495768724392c1d5b178dd47372337616e9e50ecbb0804f236596223f7b5eb1bbe69cefc8957dca21112c5777e77ef73a564 + languageName: node + linkType: hard + +"pretty-bytes@npm:^5.3.0, pretty-bytes@npm:^5.4.1, pretty-bytes@npm:^5.6.0": + version: 5.6.0 + resolution: "pretty-bytes@npm:5.6.0" + checksum: 9c082500d1e93434b5b291bd651662936b8bd6204ec9fa17d563116a192d6d86b98f6d328526b4e8d783c07d5499e2614a807520249692da9ec81564b2f439cd + languageName: node + linkType: hard + +"pretty-error@npm:^4.0.0": + version: 4.0.0 + resolution: "pretty-error@npm:4.0.0" + dependencies: + lodash: ^4.17.20 + renderkid: ^3.0.0 + checksum: a5b9137365690104ded6947dca2e33360bf55e62a4acd91b1b0d7baa3970e43754c628cc9e16eafbdd4e8f8bcb260a5865475d4fc17c3106ff2d61db4e72cdf3 + languageName: node + linkType: hard + +"pretty-format@npm:^27.0.2, pretty-format@npm:^27.5.1": + version: 27.5.1 + resolution: "pretty-format@npm:27.5.1" + dependencies: + ansi-regex: ^5.0.1 + ansi-styles: ^5.0.0 + react-is: ^17.0.1 + checksum: cf610cffcb793885d16f184a62162f2dd0df31642d9a18edf4ca298e909a8fe80bdbf556d5c9573992c102ce8bf948691da91bf9739bee0ffb6e79c8a8a6e088 + languageName: node + linkType: hard + +"pretty-format@npm:^28.1.3": + version: 28.1.3 + resolution: "pretty-format@npm:28.1.3" + dependencies: + "@jest/schemas": ^28.1.3 + ansi-regex: ^5.0.1 + ansi-styles: ^5.0.0 + react-is: ^18.0.0 + checksum: e69f857358a3e03d271252d7524bec758c35e44680287f36c1cb905187fbc82da9981a6eb07edfd8a03bc3cbeebfa6f5234c13a3d5b59f2bbdf9b4c4053e0a7f + languageName: node + linkType: hard + +"pretty-format@npm:^29.0.0, pretty-format@npm:^29.4.1": + version: 29.4.1 + resolution: "pretty-format@npm:29.4.1" + dependencies: + "@jest/schemas": ^29.4.0 + ansi-styles: ^5.0.0 + react-is: ^18.0.0 + checksum: bcc8e86bcf8e7f5106c96e2ea7905912bd17ae2aac76e4e0745d2a50df4b340638ed95090ee455a1c0f78189efa05077bd655ca08bf66292e83ebd7035fc46fd + languageName: node + linkType: hard + +"process-nextick-args@npm:~2.0.0": + version: 2.0.1 + resolution: "process-nextick-args@npm:2.0.1" + checksum: 1d38588e520dab7cea67cbbe2efdd86a10cc7a074c09657635e34f035277b59fbb57d09d8638346bf7090f8e8ebc070c96fa5fd183b777fff4f5edff5e9466cf + languageName: node + linkType: hard + +"process@npm:^0.11.10": + version: 0.11.10 + resolution: "process@npm:0.11.10" + checksum: bfcce49814f7d172a6e6a14d5fa3ac92cc3d0c3b9feb1279774708a719e19acd673995226351a082a9ae99978254e320ccda4240ddc474ba31a76c79491ca7c3 + languageName: node + linkType: hard + +"promise-inflight@npm:^1.0.1": + version: 1.0.1 + resolution: "promise-inflight@npm:1.0.1" + checksum: 22749483091d2c594261517f4f80e05226d4d5ecc1fc917e1886929da56e22b5718b7f2a75f3807e7a7d471bc3be2907fe92e6e8f373ddf5c64bae35b5af3981 + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: ^2.0.2 + retry: ^0.12.0 + checksum: f96a3f6d90b92b568a26f71e966cbbc0f63ab85ea6ff6c81284dc869b41510e6cdef99b6b65f9030f0db422bf7c96652a3fff9f2e8fb4a0f069d8f4430359429 + languageName: node + linkType: hard + +"promise@npm:^8.1.0": + version: 8.3.0 + resolution: "promise@npm:8.3.0" + dependencies: + asap: ~2.0.6 + checksum: a69f0ddbddf78ffc529cffee7ad950d307347615970564b17988ce43fbe767af5c738a9439660b24a9a8cbea106c0dcbb6c2b20e23b7e96a8e89e5c2679e94d5 + languageName: node + linkType: hard + +"prompts@npm:^2.0.1, prompts@npm:^2.4.2": + version: 2.4.2 + resolution: "prompts@npm:2.4.2" + dependencies: + kleur: ^3.0.3 + sisteransi: ^1.0.5 + checksum: d8fd1fe63820be2412c13bfc5d0a01909acc1f0367e32396962e737cb2fc52d004f3302475d5ce7d18a1e8a79985f93ff04ee03007d091029c3f9104bffc007d + languageName: node + linkType: hard + +"prop-types@npm:^15.6.0, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": + version: 15.8.1 + resolution: "prop-types@npm:15.8.1" + dependencies: + loose-envify: ^1.4.0 + object-assign: ^4.1.1 + react-is: ^16.13.1 + checksum: c056d3f1c057cb7ff8344c645450e14f088a915d078dcda795041765047fa080d38e5d626560ccaac94a4e16e3aa15f3557c1a9a8d1174530955e992c675e459 + languageName: node + linkType: hard + +"proxy-addr@npm:~2.0.7": + version: 2.0.7 + resolution: "proxy-addr@npm:2.0.7" + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + checksum: 29c6990ce9364648255454842f06f8c46fcd124d3e6d7c5066df44662de63cdc0bad032e9bf5a3d653ff72141cc7b6019873d685708ac8210c30458ad99f2b74 + languageName: node + linkType: hard + +"proxy-from-env@npm:1.0.0": + version: 1.0.0 + resolution: "proxy-from-env@npm:1.0.0" + checksum: 292e28d1de0c315958d71d8315eb546dd3cd8c8cbc2dab7c54eeb9f5c17f421771964ad0b5e1f77011bab2305bdae42e1757ce33bdb1ccc3e87732322a8efcf1 + languageName: node + linkType: hard + +"proxy-from-env@npm:^1.1.0": + version: 1.1.0 + resolution: "proxy-from-env@npm:1.1.0" + checksum: ed7fcc2ba0a33404958e34d95d18638249a68c430e30fcb6c478497d72739ba64ce9810a24f53a7d921d0c065e5b78e3822759800698167256b04659366ca4d4 + languageName: node + linkType: hard + +"ps-tree@npm:1.2.0": + version: 1.2.0 + resolution: "ps-tree@npm:1.2.0" + dependencies: + event-stream: =3.3.4 + bin: + ps-tree: ./bin/ps-tree.js + checksum: e635dd00f53d30d31696cf5f95b3a8dbdf9b1aeb36d4391578ce8e8cd22949b7c5536c73b0dc18c78615ea3ddd4be96101166be59ca2e3e3cb1e2f79ba3c7f98 + languageName: node + linkType: hard + +"psl@npm:^1.1.33": + version: 1.9.0 + resolution: "psl@npm:1.9.0" + checksum: 20c4277f640c93d393130673f392618e9a8044c6c7bf61c53917a0fddb4952790f5f362c6c730a9c32b124813e173733f9895add8d26f566ed0ea0654b2e711d + languageName: node + linkType: hard + +"pump@npm:^3.0.0": + version: 3.0.0 + resolution: "pump@npm:3.0.0" + dependencies: + end-of-stream: ^1.1.0 + once: ^1.3.1 + checksum: e42e9229fba14732593a718b04cb5e1cfef8254544870997e0ecd9732b189a48e1256e4e5478148ecb47c8511dca2b09eae56b4d0aad8009e6fac8072923cfc9 + languageName: node + linkType: hard + +"punycode@npm:^1.3.2": + version: 1.4.1 + resolution: "punycode@npm:1.4.1" + checksum: fa6e698cb53db45e4628559e557ddaf554103d2a96a1d62892c8f4032cd3bc8871796cae9eabc1bc700e2b6677611521ce5bb1d9a27700086039965d0cf34518 + languageName: node + linkType: hard + +"punycode@npm:^2.1.0, punycode@npm:^2.1.1": + version: 2.3.0 + resolution: "punycode@npm:2.3.0" + checksum: 39f760e09a2a3bbfe8f5287cf733ecdad69d6af2fe6f97ca95f24b8921858b91e9ea3c9eeec6e08cede96181b3bb33f95c6ffd8c77e63986508aa2e8159fa200 + languageName: node + linkType: hard + +"q@npm:^1.1.2": + version: 1.5.1 + resolution: "q@npm:1.5.1" + checksum: 147baa93c805bc1200ed698bdf9c72e9e42c05f96d007e33a558b5fdfd63e5ea130e99313f28efc1783e90e6bdb4e48b67a36fcc026b7b09202437ae88a1fb12 + languageName: node + linkType: hard + +"qs@npm:6.10.4": + version: 6.10.4 + resolution: "qs@npm:6.10.4" + dependencies: + side-channel: ^1.0.4 + checksum: 31e4fedd759d01eae52dde6692abab175f9af3e639993c5caaa513a2a3607b34d8058d3ae52ceeccf37c3025f22ed5e90e9ddd6c2537e19c0562ddd10dc5b1eb + languageName: node + linkType: hard + +"qs@npm:6.11.0": + version: 6.11.0 + resolution: "qs@npm:6.11.0" + dependencies: + side-channel: ^1.0.4 + checksum: 6e1f29dd5385f7488ec74ac7b6c92f4d09a90408882d0c208414a34dd33badc1a621019d4c799a3df15ab9b1d0292f97c1dd71dc7c045e69f81a8064e5af7297 + languageName: node + linkType: hard + +"querystringify@npm:^2.1.1": + version: 2.2.0 + resolution: "querystringify@npm:2.2.0" + checksum: 5641ea231bad7ef6d64d9998faca95611ed4b11c2591a8cae741e178a974f6a8e0ebde008475259abe1621cb15e692404e6b6626e927f7b849d5c09392604b15 + languageName: node + linkType: hard + +"queue-microtask@npm:^1.2.2": + version: 1.2.3 + resolution: "queue-microtask@npm:1.2.3" + checksum: b676f8c040cdc5b12723ad2f91414d267605b26419d5c821ff03befa817ddd10e238d22b25d604920340fd73efd8ba795465a0377c4adf45a4a41e4234e42dc4 + languageName: node + linkType: hard + +"quick-lru@npm:^5.1.1": + version: 5.1.1 + resolution: "quick-lru@npm:5.1.1" + checksum: a516faa25574be7947969883e6068dbe4aa19e8ef8e8e0fd96cddd6d36485e9106d85c0041a27153286b0770b381328f4072aa40d3b18a19f5f7d2b78b94b5ed + languageName: node + linkType: hard + +"raf@npm:^3.4.1": + version: 3.4.1 + resolution: "raf@npm:3.4.1" + dependencies: + performance-now: ^2.1.0 + checksum: 50ba284e481c8185dbcf45fc4618ba3aec580bb50c9121385d5698cb6012fe516d2015b1df6dd407a7b7c58d44be8086108236affbce1861edd6b44637c8cd52 + languageName: node + linkType: hard + +"randombytes@npm:^2.1.0": + version: 2.1.0 + resolution: "randombytes@npm:2.1.0" + dependencies: + safe-buffer: ^5.1.0 + checksum: d779499376bd4cbb435ef3ab9a957006c8682f343f14089ed5f27764e4645114196e75b7f6abf1cbd84fd247c0cb0651698444df8c9bf30e62120fbbc52269d6 + languageName: node + linkType: hard + +"range-parser@npm:1.2.0": + version: 1.2.0 + resolution: "range-parser@npm:1.2.0" + checksum: bdf397f43fedc15c559d3be69c01dedf38444ca7a1610f5bf5955e3f3da6057a892f34691e7ebdd8c7e1698ce18ef6c4d4811f70e658dda3ff230ef741f8423a + languageName: node + linkType: hard + +"range-parser@npm:^1.2.1, range-parser@npm:~1.2.1": + version: 1.2.1 + resolution: "range-parser@npm:1.2.1" + checksum: 0a268d4fea508661cf5743dfe3d5f47ce214fd6b7dec1de0da4d669dd4ef3d2144468ebe4179049eff253d9d27e719c88dae55be64f954e80135a0cada804ec9 + languageName: node + linkType: hard + +"raw-body@npm:2.5.1": + version: 2.5.1 + resolution: "raw-body@npm:2.5.1" + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + checksum: 5362adff1575d691bb3f75998803a0ffed8c64eabeaa06e54b4ada25a0cd1b2ae7f4f5ec46565d1bec337e08b5ac90c76eaa0758de6f72a633f025d754dec29e + languageName: node + linkType: hard + +"raw-body@npm:2.5.2": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + checksum: ba1583c8d8a48e8fbb7a873fdbb2df66ea4ff83775421bfe21ee120140949ab048200668c47d9ae3880012f6e217052690628cf679ddfbd82c9fc9358d574676 + languageName: node + linkType: hard + +"rc@npm:^1.0.1, rc@npm:^1.1.6": + version: 1.2.8 + resolution: "rc@npm:1.2.8" + dependencies: + deep-extend: ^0.6.0 + ini: ~1.3.0 + minimist: ^1.2.0 + strip-json-comments: ~2.0.1 + bin: + rc: ./cli.js + checksum: 2e26e052f8be2abd64e6d1dabfbd7be03f80ec18ccbc49562d31f617d0015fbdbcf0f9eed30346ea6ab789e0fdfe4337f033f8016efdbee0df5354751842080e + languageName: node + linkType: hard + +"react-app-polyfill@npm:3.0.0, react-app-polyfill@npm:^3.0.0": + version: 3.0.0 + resolution: "react-app-polyfill@npm:3.0.0" + dependencies: + core-js: ^3.19.2 + object-assign: ^4.1.1 + promise: ^8.1.0 + raf: ^3.4.1 + regenerator-runtime: ^0.13.9 + whatwg-fetch: ^3.6.2 + checksum: 1bb031080af15397d6eb9c69a0c2e93799991f7197a086e4409ba719398f1256b542a3d6c9a34673d516c684eef3e8226c99b335982593851f58f65f6e43571b + languageName: node + linkType: hard + +"react-dev-utils@npm:^12.0.0": + version: 12.0.1 + resolution: "react-dev-utils@npm:12.0.1" + dependencies: + "@babel/code-frame": ^7.16.0 + address: ^1.1.2 + browserslist: ^4.18.1 + chalk: ^4.1.2 + cross-spawn: ^7.0.3 + detect-port-alt: ^1.1.6 + escape-string-regexp: ^4.0.0 + filesize: ^8.0.6 + find-up: ^5.0.0 + fork-ts-checker-webpack-plugin: ^6.5.0 + global-modules: ^2.0.0 + globby: ^11.0.4 + gzip-size: ^6.0.0 + immer: ^9.0.7 + is-root: ^2.1.0 + loader-utils: ^3.2.0 + open: ^8.4.0 + pkg-up: ^3.1.0 + prompts: ^2.4.2 + react-error-overlay: ^6.0.11 + recursive-readdir: ^2.2.2 + shell-quote: ^1.7.3 + strip-ansi: ^6.0.1 + text-table: ^0.2.0 + checksum: 2c6917e47f03d9595044770b0f883a61c6b660fcaa97b8ba459a1d57c9cca9aa374cd51296b22d461ff5e432105dbe6f04732dab128e52729c79239e1c23ab56 + languageName: node + linkType: hard + +"react-dom@npm:17.0.2": + version: 17.0.2 + resolution: "react-dom@npm:17.0.2" + dependencies: + loose-envify: ^1.1.0 + object-assign: ^4.1.1 + scheduler: ^0.20.2 + peerDependencies: + react: 17.0.2 + checksum: 1c1eaa3bca7c7228d24b70932e3d7c99e70d1d04e13bb0843bbf321582bc25d7961d6b8a6978a58a598af2af496d1cedcfb1bf65f6b0960a0a8161cb8dab743c + languageName: node + linkType: hard + +"react-draggable@npm:4.4.3": + version: 4.4.3 + resolution: "react-draggable@npm:4.4.3" + dependencies: + classnames: ^2.2.5 + prop-types: ^15.6.0 + checksum: 94d3d5f0e7fd5920894915f069e393d55b46de114570a613ca56bd1f46bb5fc8dc9dbd1a254d8e09153e8261589122d1c725f722b37d454da883d0ffcc1a68bf + languageName: node + linkType: hard + +"react-error-boundary@npm:^3.1.0": + version: 3.1.4 + resolution: "react-error-boundary@npm:3.1.4" + dependencies: + "@babel/runtime": ^7.12.5 + peerDependencies: + react: ">=16.13.1" + checksum: f36270a5d775a25c8920f854c0d91649ceea417b15b5bc51e270a959b0476647bb79abb4da3be7dd9a4597b029214e8fe43ea914a7f16fa7543c91f784977f1b + languageName: node + linkType: hard + +"react-error-overlay@npm:^6.0.11": + version: 6.0.11 + resolution: "react-error-overlay@npm:6.0.11" + checksum: ce7b44c38fadba9cedd7c095cf39192e632daeccf1d0747292ed524f17dcb056d16bc197ddee5723f9dd888f0b9b19c3b486c430319e30504289b9296f2d2c42 + languageName: node + linkType: hard + +"react-i18next@npm:12.3.1": + version: 12.3.1 + resolution: "react-i18next@npm:12.3.1" + dependencies: + "@babel/runtime": ^7.20.6 + html-parse-stringify: ^3.0.1 + peerDependencies: + i18next: ">= 19.0.0" + react: ">= 16.8.0" + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + checksum: fe3f360e5184bc63861734e94bf625a09b9ec0d28fab41779a68758af258fd1737dde25ff7a88ddb66c1571a3e3de5b3403825a91b4949bf9832a00615acb87a + languageName: node + linkType: hard + +"react-is@npm:^16.12.0 || ^17.0.0 || ^18.0.0, react-is@npm:^18.0.0, react-is@npm:^18.2.0": + version: 18.2.0 + resolution: "react-is@npm:18.2.0" + checksum: e72d0ba81b5922759e4aff17e0252bd29988f9642ed817f56b25a3e217e13eea8a7f2322af99a06edb779da12d5d636e9fda473d620df9a3da0df2a74141d53e + languageName: node + linkType: hard + +"react-is@npm:^16.13.1, react-is@npm:^16.6.0, react-is@npm:^16.7.0": + version: 16.13.1 + resolution: "react-is@npm:16.13.1" + checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f + languageName: node + linkType: hard + +"react-is@npm:^17.0.1, react-is@npm:^17.0.2": + version: 17.0.2 + resolution: "react-is@npm:17.0.2" + checksum: 9d6d111d8990dc98bc5402c1266a808b0459b5d54830bbea24c12d908b536df7883f268a7868cfaedde3dd9d4e0d574db456f84d2e6df9c4526f99bb4b5344d8 + languageName: node + linkType: hard + +"react-lifecycles-compat@npm:^3.0.4": + version: 3.0.4 + resolution: "react-lifecycles-compat@npm:3.0.4" + checksum: a904b0fc0a8eeb15a148c9feb7bc17cec7ef96e71188280061fc340043fd6d8ee3ff233381f0e8f95c1cf926210b2c4a31f38182c8f35ac55057e453d6df204f + languageName: node + linkType: hard + +"react-query@npm:3.39.2": + version: 3.39.2 + resolution: "react-query@npm:3.39.2" + dependencies: + "@babel/runtime": ^7.5.5 + broadcast-channel: ^3.4.1 + match-sorter: ^6.0.2 + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + checksum: 83b199e66af28ab67ec4d22e51da42f02447186623db926b75d27a1c09a3383da6ddc9e5b83d82578fac7abdba7e6f265aecbffdb91db61981950d3d59409346 + languageName: node + linkType: hard + +"react-redux@npm:8.1.3": + version: 8.1.3 + resolution: "react-redux@npm:8.1.3" + dependencies: + "@babel/runtime": ^7.12.1 + "@types/hoist-non-react-statics": ^3.3.1 + "@types/use-sync-external-store": ^0.0.3 + hoist-non-react-statics: ^3.3.2 + react-is: ^18.0.0 + use-sync-external-store: ^1.0.0 + peerDependencies: + "@types/react": ^16.8 || ^17.0 || ^18.0 + "@types/react-dom": ^16.8 || ^17.0 || ^18.0 + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + react-native: ">=0.59" + redux: ^4 || ^5.0.0-beta.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + react-dom: + optional: true + react-native: + optional: true + redux: + optional: true + checksum: 192ea6f6053148ec80a4148ec607bc259403b937e515f616a1104ca5ab357e97e98b8245ed505a17afee67a72341d4a559eaca9607968b4a422aa9b44ba7eb89 + languageName: node + linkType: hard + +"react-refresh@npm:^0.11.0": + version: 0.11.0 + resolution: "react-refresh@npm:0.11.0" + checksum: 112178a05b1e0ffeaf5d9fb4e56b4410a34a73adeb04dbf13abdc50d9ac9df2ada83e81485156cca0b3fa296aa3612751b3d6cd13be4464642a43679b819cbc7 + languageName: node + linkType: hard + +"react-router-dom@npm:5.3.0": + version: 5.3.0 + resolution: "react-router-dom@npm:5.3.0" + dependencies: + "@babel/runtime": ^7.12.13 + history: ^4.9.0 + loose-envify: ^1.3.1 + prop-types: ^15.6.2 + react-router: 5.2.1 + tiny-invariant: ^1.0.2 + tiny-warning: ^1.0.0 + peerDependencies: + react: ">=15" + checksum: 47584fd629ecca52398d7888cab193b8a74057cc99a7ef44410c405d4082f618c3c0399db5325bc3524f9c511404086169570013b61a94dfa6acdfdc850d7a1f + languageName: node + linkType: hard + +"react-router@npm:5.2.1": + version: 5.2.1 + resolution: "react-router@npm:5.2.1" + dependencies: + "@babel/runtime": ^7.12.13 + history: ^4.9.0 + hoist-non-react-statics: ^3.1.0 + loose-envify: ^1.3.1 + mini-create-react-context: ^0.4.0 + path-to-regexp: ^1.7.0 + prop-types: ^15.6.2 + react-is: ^16.6.0 + tiny-invariant: ^1.0.2 + tiny-warning: ^1.0.0 + peerDependencies: + react: ">=15" + checksum: 7daae084bf64531eb619cc5f4cc40ce5ae0a541b64f71d74ec71a38cbf6130ebdbb7cf38f157303fad5846deec259401f96c4d6c7386466dcc989719e01f9aaa + languageName: node + linkType: hard + +"react-scripts@npm:5.0.0": + version: 5.0.0 + resolution: "react-scripts@npm:5.0.0" + dependencies: + "@babel/core": ^7.16.0 + "@pmmmwh/react-refresh-webpack-plugin": ^0.5.3 + "@svgr/webpack": ^5.5.0 + babel-jest: ^27.4.2 + babel-loader: ^8.2.3 + babel-plugin-named-asset-import: ^0.3.8 + babel-preset-react-app: ^10.0.1 + bfj: ^7.0.2 + browserslist: ^4.18.1 + camelcase: ^6.2.1 + case-sensitive-paths-webpack-plugin: ^2.4.0 + css-loader: ^6.5.1 + css-minimizer-webpack-plugin: ^3.2.0 + dotenv: ^10.0.0 + dotenv-expand: ^5.1.0 + eslint: ^8.3.0 + eslint-config-react-app: ^7.0.0 + eslint-webpack-plugin: ^3.1.1 + file-loader: ^6.2.0 + fs-extra: ^10.0.0 + fsevents: ^2.3.2 + html-webpack-plugin: ^5.5.0 + identity-obj-proxy: ^3.0.0 + jest: ^27.4.3 + jest-resolve: ^27.4.2 + jest-watch-typeahead: ^1.0.0 + mini-css-extract-plugin: ^2.4.5 + postcss: ^8.4.4 + postcss-flexbugs-fixes: ^5.0.2 + postcss-loader: ^6.2.1 + postcss-normalize: ^10.0.1 + postcss-preset-env: ^7.0.1 + prompts: ^2.4.2 + react-app-polyfill: ^3.0.0 + react-dev-utils: ^12.0.0 + react-refresh: ^0.11.0 + resolve: ^1.20.0 + resolve-url-loader: ^4.0.0 + sass-loader: ^12.3.0 + semver: ^7.3.5 + source-map-loader: ^3.0.0 + style-loader: ^3.3.1 + tailwindcss: ^3.0.2 + terser-webpack-plugin: ^5.2.5 + webpack: ^5.64.4 + webpack-dev-server: ^4.6.0 + webpack-manifest-plugin: ^4.0.2 + workbox-webpack-plugin: ^6.4.1 + peerDependencies: + react: ">= 16" + typescript: ^3.2.1 || ^4 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + typescript: + optional: true + bin: + react-scripts: bin/react-scripts.js + checksum: 55ffad0d68ee6345326f5803c1925ae44b46cc33cb1cad9bcb68fd1784acfb3876bc12118b3079bc4d934834ae0197a9776baa0a06df0263831acc91ac42df29 + languageName: node + linkType: hard + +"react-shallow-renderer@npm:^16.13.1": + version: 16.15.0 + resolution: "react-shallow-renderer@npm:16.15.0" + dependencies: + object-assign: ^4.1.1 + react-is: ^16.12.0 || ^17.0.0 || ^18.0.0 + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 + checksum: 6052c7e3e9627485120ebd8257f128aad8f56386fe8d42374b7743eac1be457c33506d153c7886b4e32923c0c352d402ab805ef9ca02dbcd8393b2bdeb6e5af8 + languageName: node + linkType: hard + +"react-test-renderer@npm:17.0.2": + version: 17.0.2 + resolution: "react-test-renderer@npm:17.0.2" + dependencies: + object-assign: ^4.1.1 + react-is: ^17.0.2 + react-shallow-renderer: ^16.13.1 + scheduler: ^0.20.2 + peerDependencies: + react: 17.0.2 + checksum: e6b5c6ed2a0bde2c34f1ab9523ff9bc4c141a271daf730d6b852374e83acc0155d58ab71a318251e953ebfa65b8bebb9c5dce3eba1ccfcbef7cc4e1e8261c401 + languageName: node + linkType: hard + +"react-transition-group@npm:^4.4.5": + version: 4.4.5 + resolution: "react-transition-group@npm:4.4.5" + dependencies: + "@babel/runtime": ^7.5.5 + dom-helpers: ^5.0.1 + loose-envify: ^1.4.0 + prop-types: ^15.6.2 + peerDependencies: + react: ">=16.6.0" + react-dom: ">=16.6.0" + checksum: 75602840106aa9c6545149d6d7ae1502fb7b7abadcce70a6954c4b64a438ff1cd16fc77a0a1e5197cdd72da398f39eb929ea06f9005c45b132ed34e056ebdeb1 + languageName: node + linkType: hard + +"react-virtualized@npm:9.22.3": + version: 9.22.3 + resolution: "react-virtualized@npm:9.22.3" + dependencies: + "@babel/runtime": ^7.7.2 + clsx: ^1.0.4 + dom-helpers: ^5.1.3 + loose-envify: ^1.4.0 + prop-types: ^15.7.2 + react-lifecycles-compat: ^3.0.4 + peerDependencies: + react: ^15.3.0 || ^16.0.0-alpha + react-dom: ^15.3.0 || ^16.0.0-alpha + checksum: 5e3b566592293bc0057bc6be4f6ee29c58c8931421d2882a3ef45ca9b24c6f3ea78bbc5a182c2916af6520845e5a90f569b3a63c9b5e89428720913e6d6239cc + languageName: node + linkType: hard + +"react@npm:17.0.2": + version: 17.0.2 + resolution: "react@npm:17.0.2" + dependencies: + loose-envify: ^1.1.0 + object-assign: ^4.1.1 + checksum: b254cc17ce3011788330f7bbf383ab653c6848902d7936a87b09d835d091e3f295f7e9dd1597c6daac5dc80f90e778c8230218ba8ad599f74adcc11e33b9d61b + languageName: node + linkType: hard + +"read-cache@npm:^1.0.0": + version: 1.0.0 + resolution: "read-cache@npm:1.0.0" + dependencies: + pify: ^2.3.0 + checksum: cffc728b9ede1e0667399903f9ecaf3789888b041c46ca53382fa3a06303e5132774dc0a96d0c16aa702dbac1ea0833d5a868d414f5ab2af1e1438e19e6657c6 + languageName: node + linkType: hard + +"readable-stream@npm:^2.0.1": + version: 2.3.7 + resolution: "readable-stream@npm:2.3.7" + 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 + checksum: e4920cf7549a60f8aaf694d483a0e61b2a878b969d224f89b3bc788b8d920075132c4b55a7494ee944c7b6a9a0eada28a7f6220d80b0312ece70bbf08eeca755 + languageName: node + linkType: hard + +"readable-stream@npm:^3.0.6, readable-stream@npm:^3.6.0": + version: 3.6.0 + resolution: "readable-stream@npm:3.6.0" + dependencies: + inherits: ^2.0.3 + string_decoder: ^1.1.1 + util-deprecate: ^1.0.1 + checksum: d4ea81502d3799439bb955a3a5d1d808592cf3133350ed352aeaa499647858b27b1c4013984900238b0873ec8d0d8defce72469fb7a83e61d53f5ad61cb80dc8 + languageName: node + linkType: hard + +"readdirp@npm:~3.6.0": + version: 3.6.0 + resolution: "readdirp@npm:3.6.0" + dependencies: + picomatch: ^2.2.1 + checksum: 1ced032e6e45670b6d7352d71d21ce7edf7b9b928494dcaba6f11fba63180d9da6cd7061ebc34175ffda6ff529f481818c962952004d273178acd70f7059b320 + languageName: node + linkType: hard + +"recursive-readdir@npm:^2.2.2": + version: 2.2.3 + resolution: "recursive-readdir@npm:2.2.3" + dependencies: + minimatch: ^3.0.5 + checksum: 88ec96e276237290607edc0872b4f9842837b95cfde0cdbb1e00ba9623dfdf3514d44cdd14496ab60a0c2dd180a6ef8a3f1c34599e6cf2273afac9b72a6fb2b5 + languageName: node + linkType: hard + +"redent@npm:^3.0.0": + version: 3.0.0 + resolution: "redent@npm:3.0.0" + dependencies: + indent-string: ^4.0.0 + strip-indent: ^3.0.0 + checksum: fa1ef20404a2d399235e83cc80bd55a956642e37dd197b4b612ba7327bf87fa32745aeb4a1634b2bab25467164ab4ed9c15be2c307923dd08b0fe7c52431ae6b + languageName: node + linkType: hard + +"redux-logger@npm:3.0.6": + version: 3.0.6 + resolution: "redux-logger@npm:3.0.6" + dependencies: + deep-diff: ^0.3.5 + checksum: c40f63c44c6475cf6374ae0eaa810d913f142614cb80692a0beacaf135c5dc3eb3e2cdd4296f01446ba48cb69b82e81363b84d829f1f6659382c991022a814ac + languageName: node + linkType: hard + +"redux-mock-store@npm:1.5.4": + version: 1.5.4 + resolution: "redux-mock-store@npm:1.5.4" + dependencies: + lodash.isplainobject: ^4.0.6 + checksum: 571eab2cca3e46321969025af865ddd780804c811be9db277fddf772d86e3ea67b4ef1b19ea3866417d41eb1b73605103020321f68cf68f379a52679a6823d12 + languageName: node + linkType: hard + +"redux-thunk@npm:2.4.1": + version: 2.4.1 + resolution: "redux-thunk@npm:2.4.1" + peerDependencies: + redux: ^4 + checksum: af5abb425fb9dccda02e5f387d6f3003997f62d906542a3d35fc9420088f550dc1a018bdc246c7d23ee852b4d4ab8b5c64c5be426e45a328d791c4586a3c6b6e + languageName: node + linkType: hard + +"redux@npm:4.2.0": + version: 4.2.0 + resolution: "redux@npm:4.2.0" + dependencies: + "@babel/runtime": ^7.9.2 + checksum: 75f3955c89b3f18edf5411e5fb482aa2e4f41a416183e8802a6bf6472c4fc3d47675b8b321d147f8af8e0f616436ac507bf5a25f1c4d6180e797b549c7db2c1d + languageName: node + linkType: hard + +"redux@npm:^4.0.0, redux@npm:^4.0.5": + version: 4.2.1 + resolution: "redux@npm:4.2.1" + dependencies: + "@babel/runtime": ^7.9.2 + checksum: f63b9060c3a1d930ae775252bb6e579b42415aee7a23c4114e21a0b4ba7ec12f0ec76936c00f546893f06e139819f0e2855e0d55ebfce34ca9c026241a6950dd + languageName: node + linkType: hard + +"regenerate-unicode-properties@npm:^10.1.0": + version: 10.1.0 + resolution: "regenerate-unicode-properties@npm:10.1.0" + dependencies: + regenerate: ^1.4.2 + checksum: b1a8929588433ab8b9dc1a34cf3665b3b472f79f2af6ceae00d905fc496b332b9af09c6718fb28c730918f19a00dc1d7310adbaa9b72a2ec7ad2f435da8ace17 + languageName: node + linkType: hard + +"regenerate@npm:^1.4.2": + version: 1.4.2 + resolution: "regenerate@npm:1.4.2" + checksum: 3317a09b2f802da8db09aa276e469b57a6c0dd818347e05b8862959c6193408242f150db5de83c12c3fa99091ad95fb42a6db2c3329bfaa12a0ea4cbbeb30cb0 + languageName: node + linkType: hard + +"regenerator-runtime@npm:^0.13.11, regenerator-runtime@npm:^0.13.9": + version: 0.13.11 + resolution: "regenerator-runtime@npm:0.13.11" + checksum: 27481628d22a1c4e3ff551096a683b424242a216fee44685467307f14d58020af1e19660bf2e26064de946bad7eff28950eae9f8209d55723e2d9351e632bbb4 + languageName: node + linkType: hard + +"regenerator-runtime@npm:^0.14.0": + version: 0.14.0 + resolution: "regenerator-runtime@npm:0.14.0" + checksum: 1c977ad82a82a4412e4f639d65d22be376d3ebdd30da2c003eeafdaaacd03fc00c2320f18120007ee700900979284fc78a9f00da7fb593f6e6eeebc673fba9a3 + languageName: node + linkType: hard + +"regenerator-transform@npm:^0.15.1": + version: 0.15.1 + resolution: "regenerator-transform@npm:0.15.1" + dependencies: + "@babel/runtime": ^7.8.4 + checksum: 2d15bdeadbbfb1d12c93f5775493d85874dbe1d405bec323da5c61ec6e701bc9eea36167483e1a5e752de9b2df59ab9a2dfff6bf3784f2b28af2279a673d29a4 + languageName: node + linkType: hard + +"regex-parser@npm:^2.2.11": + version: 2.2.11 + resolution: "regex-parser@npm:2.2.11" + checksum: 78200331ec0cc372302d287a4946c38681eb5fe435453fca572cb53cac0ba579e5eb3b9e25eac24c0c80a555fb3ea7a637814a35da1e9bc88e8819110ae5de24 + languageName: node + linkType: hard + +"regexp.prototype.flags@npm:^1.4.3": + version: 1.4.3 + resolution: "regexp.prototype.flags@npm:1.4.3" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.3 + functions-have-names: ^1.2.2 + checksum: 51228bae732592adb3ededd5e15426be25f289e9c4ef15212f4da73f4ec3919b6140806374b8894036a86020d054a8d2657d3fee6bb9b4d35d8939c20030b7a6 + languageName: node + linkType: hard + +"regexpu-core@npm:^5.2.1": + version: 5.2.2 + resolution: "regexpu-core@npm:5.2.2" + dependencies: + regenerate: ^1.4.2 + regenerate-unicode-properties: ^10.1.0 + regjsgen: ^0.7.1 + regjsparser: ^0.9.1 + unicode-match-property-ecmascript: ^2.0.0 + unicode-match-property-value-ecmascript: ^2.1.0 + checksum: 87c56815e20d213848d38f6b047ba52f0d632f36e791b777f59327e8d350c0743b27cc25feab64c0eadc9fe9959dde6b1261af71108a9371b72c8c26beda05ef + languageName: node + linkType: hard + +"registry-auth-token@npm:3.3.2": + version: 3.3.2 + resolution: "registry-auth-token@npm:3.3.2" + dependencies: + rc: ^1.1.6 + safe-buffer: ^5.0.1 + checksum: c9d7ae160a738f1fa825556e3669e6c771d2c0239ce37679f7e8646157a97d0a76464738be075002a1f754ef9bfb913b689f4bbfd5296d28f136fbf98c8c2217 + languageName: node + linkType: hard + +"registry-url@npm:3.1.0": + version: 3.1.0 + resolution: "registry-url@npm:3.1.0" + dependencies: + rc: ^1.0.1 + checksum: 6d223da41b04e1824f5faa63905c6f2e43b216589d72794111573f017352b790aef42cd1f826463062f89d804abb2027e3d9665d2a9a0426a11eedd04d470af3 + languageName: node + linkType: hard + +"regjsgen@npm:^0.7.1": + version: 0.7.1 + resolution: "regjsgen@npm:0.7.1" + checksum: 7cac399921c58db8e16454869283ff66871531180218064fa938ac05c11c2976792a00706c3c78bbc625e1d793ca373065ea90564e06189a751a7b4ae33acadc + languageName: node + linkType: hard + +"regjsparser@npm:^0.9.1": + version: 0.9.1 + resolution: "regjsparser@npm:0.9.1" + dependencies: + jsesc: ~0.5.0 + bin: + regjsparser: bin/parser + checksum: 5e1b76afe8f1d03c3beaf9e0d935dd467589c3625f6d65fb8ffa14f224d783a0fed4bf49c2c1b8211043ef92b6117313419edf055a098ed8342e340586741afc + languageName: node + linkType: hard + +"relateurl@npm:^0.2.7": + version: 0.2.7 + resolution: "relateurl@npm:0.2.7" + checksum: 5891e792eae1dfc3da91c6fda76d6c3de0333a60aa5ad848982ebb6dccaa06e86385fb1235a1582c680a3d445d31be01c6bfc0804ebbcab5aaf53fa856fde6b6 + languageName: node + linkType: hard + +"remove-accents@npm:0.4.2": + version: 0.4.2 + resolution: "remove-accents@npm:0.4.2" + checksum: 84a6988555dea24115e2d1954db99509588d43fe55a1590f0b5894802776f7b488b3151c37ceb9e4f4b646f26b80b7325dcea2fae58bc3865df146e1fa606711 + languageName: node + linkType: hard + +"renderkid@npm:^3.0.0": + version: 3.0.0 + resolution: "renderkid@npm:3.0.0" + dependencies: + css-select: ^4.1.3 + dom-converter: ^0.2.0 + htmlparser2: ^6.1.0 + lodash: ^4.17.21 + strip-ansi: ^6.0.1 + checksum: 77162b62d6f33ab81f337c39efce0439ff0d1f6d441e29c35183151f83041c7850774fb904da163d6c844264d440d10557714e6daa0b19e4561a5cd4ef305d41 + languageName: node + linkType: hard + +"request-progress@npm:^3.0.0": + version: 3.0.0 + resolution: "request-progress@npm:3.0.0" + dependencies: + throttleit: ^1.0.0 + checksum: 6ea1761dcc8a8b7b5894afd478c0286aa31bd69438d7050294bd4fd0d0b3e09b5cde417d38deef9c49809039c337d8744e4bb49d8632b0c3e4ffa5e8a687e0fd + languageName: node + linkType: hard + +"require-directory@npm:^2.1.1": + version: 2.1.1 + resolution: "require-directory@npm:2.1.1" + checksum: fb47e70bf0001fdeabdc0429d431863e9475e7e43ea5f94ad86503d918423c1543361cc5166d713eaa7029dd7a3d34775af04764bebff99ef413111a5af18c80 + languageName: node + linkType: hard + +"require-from-string@npm:^2.0.2": + version: 2.0.2 + resolution: "require-from-string@npm:2.0.2" + checksum: a03ef6895445f33a4015300c426699bc66b2b044ba7b670aa238610381b56d3f07c686251740d575e22f4c87531ba662d06937508f0f3c0f1ddc04db3130560b + languageName: node + linkType: hard + +"requires-port@npm:^1.0.0": + version: 1.0.0 + resolution: "requires-port@npm:1.0.0" + checksum: eee0e303adffb69be55d1a214e415cf42b7441ae858c76dfc5353148644f6fd6e698926fc4643f510d5c126d12a705e7c8ed7e38061113bdf37547ab356797ff + languageName: node + linkType: hard + +"resize-observer-polyfill@npm:1.5.1": + version: 1.5.1 + resolution: "resize-observer-polyfill@npm:1.5.1" + checksum: 57e7f79489867b00ba43c9c051524a5c8f162a61d5547e99333549afc23e15c44fd43f2f318ea0261ea98c0eb3158cca261e6f48d66e1ed1cd1f340a43977094 + languageName: node + linkType: hard + +"resolve-cwd@npm:^3.0.0": + version: 3.0.0 + resolution: "resolve-cwd@npm:3.0.0" + dependencies: + resolve-from: ^5.0.0 + checksum: 546e0816012d65778e580ad62b29e975a642989108d9a3c5beabfb2304192fa3c9f9146fbdfe213563c6ff51975ae41bac1d3c6e047dd9572c94863a057b4d81 + languageName: node + linkType: hard + +"resolve-from@npm:^4.0.0": + version: 4.0.0 + resolution: "resolve-from@npm:4.0.0" + checksum: f4ba0b8494846a5066328ad33ef8ac173801a51739eb4d63408c847da9a2e1c1de1e6cbbf72699211f3d13f8fc1325648b169bd15eb7da35688e30a5fb0e4a7f + languageName: node + linkType: hard + +"resolve-from@npm:^5.0.0": + version: 5.0.0 + resolution: "resolve-from@npm:5.0.0" + checksum: 4ceeb9113e1b1372d0cd969f3468fa042daa1dd9527b1b6bb88acb6ab55d8b9cd65dbf18819f9f9ddf0db804990901dcdaade80a215e7b2c23daae38e64f5bdf + languageName: node + linkType: hard + +"resolve-pathname@npm:^3.0.0": + version: 3.0.0 + resolution: "resolve-pathname@npm:3.0.0" + checksum: 6147241ba42c423dbe83cb067a2b4af4f60908c3af57e1ea567729cc71416c089737fe2a73e9e79e7a60f00f66c91e4b45ad0d37cd4be2d43fec44963ef14368 + languageName: node + linkType: hard + +"resolve-url-loader@npm:^4.0.0": + version: 4.0.0 + resolution: "resolve-url-loader@npm:4.0.0" + 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 + peerDependencies: + rework: 1.0.1 + rework-visit: 1.0.0 + peerDependenciesMeta: + rework: + optional: true + rework-visit: + optional: true + checksum: 8e5bcf97867a5e128b6b86988d445b7fbd1214f7c5c0214332f835e8607438e153d9b3899799a03ddd03540254bb591e572feb330981a4478be934f6f045c925 + languageName: node + linkType: hard + +"resolve.exports@npm:^1.1.0": + version: 1.1.1 + resolution: "resolve.exports@npm:1.1.1" + checksum: 485aa10082eb388a569d696e17ad7b16f4186efc97dd34eadd029d95b811f21ffee13b1b733198bb4584dbb3cb296aa6f141835221fb7613b9606b84f1386655 + languageName: node + linkType: hard + +"resolve@npm:^1.1.7, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1": + version: 1.22.1 + resolution: "resolve@npm:1.22.1" + dependencies: + is-core-module: ^2.9.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: 07af5fc1e81aa1d866cbc9e9460fbb67318a10fa3c4deadc35c3ad8a898ee9a71a86a65e4755ac3195e0ea0cfbe201eb323ebe655ce90526fd61917313a34e4e + languageName: node + linkType: hard + +"resolve@npm:^2.0.0-next.4": + version: 2.0.0-next.4 + resolution: "resolve@npm:2.0.0-next.4" + dependencies: + is-core-module: ^2.9.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: c438ac9a650f2030fd074219d7f12ceb983b475da2d89ad3d6dd05fbf6b7a0a8cd37d4d10b43cb1f632bc19f22246ab7f36ebda54d84a29bfb2910a0680906d3 + languageName: node + linkType: hard + +"resolve@patch:resolve@^1.1.7#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.1#~builtin": + version: 1.22.1 + resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin::version=1.22.1&hash=c3c19d" + dependencies: + is-core-module: ^2.9.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: 5656f4d0bedcf8eb52685c1abdf8fbe73a1603bb1160a24d716e27a57f6cecbe2432ff9c89c2bd57542c3a7b9d14b1882b73bfe2e9d7849c9a4c0b8b39f02b8b + languageName: node + linkType: hard + +"resolve@patch:resolve@^2.0.0-next.4#~builtin": + version: 2.0.0-next.4 + resolution: "resolve@patch:resolve@npm%3A2.0.0-next.4#~builtin::version=2.0.0-next.4&hash=c3c19d" + dependencies: + is-core-module: ^2.9.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: 4bf9f4f8a458607af90518ff73c67a4bc1a38b5a23fef2bb0ccbd45e8be89820a1639b637b0ba377eb2be9eedfb1739a84cde24fe4cd670c8207d8fea922b011 + languageName: node + linkType: hard + +"restore-cursor@npm:^3.1.0": + version: 3.1.0 + resolution: "restore-cursor@npm:3.1.0" + dependencies: + onetime: ^5.1.0 + signal-exit: ^3.0.2 + checksum: f877dd8741796b909f2a82454ec111afb84eb45890eb49ac947d87991379406b3b83ff9673a46012fca0d7844bb989f45cc5b788254cf1a39b6b5a9659de0630 + languageName: node + linkType: hard + +"restore-cursor@npm:^4.0.0": + version: 4.0.0 + resolution: "restore-cursor@npm:4.0.0" + dependencies: + onetime: ^5.1.0 + signal-exit: ^3.0.2 + checksum: 5b675c5a59763bf26e604289eab35711525f11388d77f409453904e1e69c0d37ae5889295706b2c81d23bd780165084d040f9b68fffc32cc921519031c4fa4af + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 623bd7d2e5119467ba66202d733ec3c2e2e26568074923bc0585b6b99db14f357e79bdedb63cab56cec47491c4a0da7e6021a7465ca6dc4f481d3898fdd3158c + languageName: node + linkType: hard + +"retry@npm:^0.13.1": + version: 0.13.1 + resolution: "retry@npm:0.13.1" + checksum: 47c4d5be674f7c13eee4cfe927345023972197dbbdfba5d3af7e461d13b44de1bfd663bfc80d2f601f8ef3fc8164c16dd99655a221921954a65d044a2fc1233b + languageName: node + linkType: hard + +"reusify@npm:^1.0.4": + version: 1.0.4 + resolution: "reusify@npm:1.0.4" + checksum: c3076ebcc22a6bc252cb0b9c77561795256c22b757f40c0d8110b1300723f15ec0fc8685e8d4ea6d7666f36c79ccc793b1939c748bf36f18f542744a4e379fcc + languageName: node + linkType: hard + +"rfdc@npm:^1.3.0": + version: 1.3.0 + resolution: "rfdc@npm:1.3.0" + checksum: fb2ba8512e43519983b4c61bd3fa77c0f410eff6bae68b08614437bc3f35f91362215f7b4a73cbda6f67330b5746ce07db5dd9850ad3edc91271ad6deea0df32 + languageName: node + linkType: hard + +"rimraf@npm:3.0.2, rimraf@npm:^3.0.0, rimraf@npm:^3.0.2": + version: 3.0.2 + resolution: "rimraf@npm:3.0.2" + dependencies: + glob: ^7.1.3 + bin: + rimraf: bin.js + checksum: 87f4164e396f0171b0a3386cc1877a817f572148ee13a7e113b238e48e8a9f2f31d009a92ec38a591ff1567d9662c6b67fd8818a2dbbaed74bc26a87a2a4a9a0 + languageName: node + linkType: hard + +"rollup-plugin-terser@npm:^7.0.0": + version: 7.0.2 + resolution: "rollup-plugin-terser@npm:7.0.2" + dependencies: + "@babel/code-frame": ^7.10.4 + jest-worker: ^26.2.1 + serialize-javascript: ^4.0.0 + terser: ^5.0.0 + peerDependencies: + rollup: ^2.0.0 + checksum: af84bb7a7a894cd00852b6486528dfb8653cf94df4c126f95f389a346f401d054b08c46bee519a2ab6a22b33804d1d6ac6d8c90b1b2bf8fffb097eed73fc3c72 + languageName: node + linkType: hard + +"rollup@npm:^2.43.1": + version: 2.79.1 + resolution: "rollup@npm:2.79.1" + dependencies: + fsevents: ~2.3.2 + dependenciesMeta: + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 6a2bf167b3587d4df709b37d149ad0300692cc5deb510f89ac7bdc77c8738c9546ae3de9322b0968e1ed2b0e984571f5f55aae28fa7de4cfcb1bc5402a4e2be6 + languageName: node + linkType: hard + +"run-parallel@npm:^1.1.9": + version: 1.2.0 + resolution: "run-parallel@npm:1.2.0" + dependencies: + queue-microtask: ^1.2.2 + checksum: cb4f97ad25a75ebc11a8ef4e33bb962f8af8516bb2001082ceabd8902e15b98f4b84b4f8a9b222e5d57fc3bd1379c483886ed4619367a7680dad65316993021d + languageName: node + linkType: hard + +"rxjs@npm:^7.5.1, rxjs@npm:^7.8.0": + version: 7.8.0 + resolution: "rxjs@npm:7.8.0" + dependencies: + tslib: ^2.1.0 + checksum: 61b4d4fd323c1043d8d6ceb91f24183b28bcf5def4f01ca111511d5c6b66755bc5578587fe714ef5d67cf4c9f2e26f4490d4e1d8cabf9bd5967687835e9866a2 + languageName: node + linkType: hard + +"safe-buffer@npm:5.1.2, safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c + languageName: node + linkType: hard + +"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.2, safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 + languageName: node + linkType: hard + +"safe-regex-test@npm:^1.0.0": + version: 1.0.0 + resolution: "safe-regex-test@npm:1.0.0" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.1.3 + is-regex: ^1.1.4 + checksum: bc566d8beb8b43c01b94e67de3f070fd2781685e835959bbbaaec91cc53381145ca91f69bd837ce6ec244817afa0a5e974fc4e40a2957f0aca68ac3add1ddd34 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.0.2, safer-buffer@npm:^2.1.0, safer-buffer@npm:~2.1.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 + languageName: node + linkType: hard + +"sanitize.css@npm:*": + version: 13.0.0 + resolution: "sanitize.css@npm:13.0.0" + checksum: a99ca77c4d135800a4a93c3555e5aa4a2eb040a833df716dbe9132e1f2086fbf9acdb8021a579f40dcf77166d2d50f3358b4b6121a247d26fed5a0e6f5af3bb7 + languageName: node + linkType: hard + +"sass-loader@npm:^12.3.0": + version: 12.6.0 + resolution: "sass-loader@npm:12.6.0" + dependencies: + klona: ^2.0.4 + neo-async: ^2.6.2 + peerDependencies: + fibers: ">= 3.1.0" + node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + sass: ^1.3.0 + sass-embedded: "*" + webpack: ^5.0.0 + peerDependenciesMeta: + fibers: + optional: true + node-sass: + optional: true + sass: + optional: true + sass-embedded: + optional: true + checksum: 5d73a428588150f704016aa27397941bb9246cecd2ee083b573e95d969fc080ac6a16f2fe1cc64aca08f6e70da6f3c586ee68f0efc9f527fecc360e5f1c299ec + languageName: node + linkType: hard + +"sax@npm:~1.2.4": + version: 1.2.4 + resolution: "sax@npm:1.2.4" + checksum: d3df7d32b897a2c2f28e941f732c71ba90e27c24f62ee918bd4d9a8cfb3553f2f81e5493c7f0be94a11c1911b643a9108f231dd6f60df3fa9586b5d2e3e9e1fe + languageName: node + linkType: hard + +"saxes@npm:^5.0.1": + version: 5.0.1 + resolution: "saxes@npm:5.0.1" + dependencies: + xmlchars: ^2.2.0 + checksum: 5636b55cf15f7cf0baa73f2797bf992bdcf75d1b39d82c0aa4608555c774368f6ac321cb641fd5f3d3ceb87805122cd47540da6a7b5960fe0dbdb8f8c263f000 + languageName: node + linkType: hard + +"scheduler@npm:^0.20.2": + version: 0.20.2 + resolution: "scheduler@npm:0.20.2" + dependencies: + loose-envify: ^1.1.0 + object-assign: ^4.1.1 + checksum: c4b35cf967c8f0d3e65753252d0f260271f81a81e427241295c5a7b783abf4ea9e905f22f815ab66676f5313be0a25f47be582254db8f9241b259213e999b8fc + languageName: node + linkType: hard + +"schema-utils@npm:2.7.0": + version: 2.7.0 + resolution: "schema-utils@npm:2.7.0" + dependencies: + "@types/json-schema": ^7.0.4 + ajv: ^6.12.2 + ajv-keywords: ^3.4.1 + checksum: 8889325b0ee1ae6a8f5d6aaa855c71e136ebbb7fd731b01a9d3ec8225dcb245f644c47c50104db4c741983b528cdff8558570021257d4d397ec6aaecd9172a8e + languageName: node + linkType: hard + +"schema-utils@npm:^2.6.5": + version: 2.7.1 + resolution: "schema-utils@npm:2.7.1" + dependencies: + "@types/json-schema": ^7.0.5 + ajv: ^6.12.4 + ajv-keywords: ^3.5.2 + checksum: 32c62fc9e28edd101e1bd83453a4216eb9bd875cc4d3775e4452b541908fa8f61a7bbac8ffde57484f01d7096279d3ba0337078e85a918ecbeb72872fb09fb2b + languageName: node + linkType: hard + +"schema-utils@npm:^3.0.0, schema-utils@npm:^3.1.0, schema-utils@npm:^3.1.1": + version: 3.1.1 + resolution: "schema-utils@npm:3.1.1" + dependencies: + "@types/json-schema": ^7.0.8 + ajv: ^6.12.5 + ajv-keywords: ^3.5.2 + checksum: fb73f3d759d43ba033c877628fe9751620a26879f6301d3dbeeb48cf2a65baec5cdf99da65d1bf3b4ff5444b2e59cbe4f81c2456b5e0d2ba7d7fd4aed5da29ce + languageName: node + linkType: hard + +"schema-utils@npm:^4.0.0": + version: 4.0.0 + resolution: "schema-utils@npm:4.0.0" + dependencies: + "@types/json-schema": ^7.0.9 + ajv: ^8.8.0 + ajv-formats: ^2.1.1 + ajv-keywords: ^5.0.0 + checksum: c843e92fdd1a5c145dbb6ffdae33e501867f9703afac67bdf35a685e49f85b1dcc10ea250033175a64bd9d31f0555bc6785b8359da0c90bcea30cf6dfbb55a8f + languageName: node + linkType: hard + +"seamless-immutable@npm:^7.1.3": + version: 7.1.4 + resolution: "seamless-immutable@npm:7.1.4" + checksum: f65c1dc12e460265ccc4b164085b807570f9fb8a619cd3c216fc7ed933fb09c57a24a7df1b638dc9bd6367d8d69c2f00b5370b0c0996b4046242539096d2d0c6 + languageName: node + linkType: hard + +"select-hose@npm:^2.0.0": + version: 2.0.0 + resolution: "select-hose@npm:2.0.0" + checksum: d7e5fcc695a4804209d232a1b18624a5134be334d4e1114b0721f7a5e72bd73da483dcf41528c1af4f4f4892ad7cfd6a1e55c8ffb83f9c9fe723b738db609dbb + languageName: node + linkType: hard + +"selfsigned@npm:^2.1.1": + version: 2.1.1 + resolution: "selfsigned@npm:2.1.1" + dependencies: + node-forge: ^1 + checksum: aa9ce2150a54838978d5c0aee54d7ebe77649a32e4e690eb91775f71fdff773874a4fbafd0ac73d8ec3b702ff8a395c604df4f8e8868528f36fd6c15076fb43a + languageName: node + linkType: hard + +"semver@npm:^6.0.0, semver@npm:^6.1.1, semver@npm:^6.1.2, semver@npm:^6.3.0, semver@npm:^6.3.1": + version: 6.3.1 + resolution: "semver@npm:6.3.1" + bin: + semver: bin/semver.js + checksum: ae47d06de28836adb9d3e25f22a92943477371292d9b665fb023fae278d345d508ca1958232af086d85e0155aee22e313e100971898bbb8d5d89b8b1d4054ca2 + languageName: node + linkType: hard + +"semver@npm:^7.3.2, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3": + version: 7.6.0 + resolution: "semver@npm:7.6.0" + dependencies: + lru-cache: ^6.0.0 + bin: + semver: bin/semver.js + checksum: 7427f05b70786c696640edc29fdd4bc33b2acf3bbe1740b955029044f80575fc664e1a512e4113c3af21e767154a94b4aa214bf6cd6e42a1f6dba5914e0b208c + languageName: node + linkType: hard + +"send@npm:0.18.0": + version: 0.18.0 + resolution: "send@npm:0.18.0" + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + etag: ~1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: ~1.2.1 + statuses: 2.0.1 + checksum: 74fc07ebb58566b87b078ec63e5a3e41ecd987e4272ba67b7467e86c6ad51bc6b0b0154133b6d8b08a2ddda360464f71382f7ef864700f34844a76c8027817a8 + languageName: node + linkType: hard + +"serialize-javascript@npm:^4.0.0": + version: 4.0.0 + resolution: "serialize-javascript@npm:4.0.0" + dependencies: + randombytes: ^2.1.0 + checksum: 3273b3394b951671fcf388726e9577021870dfbf85e742a1183fb2e91273e6101bdccea81ff230724f6659a7ee4cef924b0ff9baca32b79d9384ec37caf07302 + languageName: node + linkType: hard + +"serialize-javascript@npm:^6.0.0": + version: 6.0.1 + resolution: "serialize-javascript@npm:6.0.1" + dependencies: + randombytes: ^2.1.0 + checksum: 3c4f4cb61d0893b988415bdb67243637333f3f574e9e9cc9a006a2ced0b390b0b3b44aef8d51c951272a9002ec50885eefdc0298891bc27eb2fe7510ea87dc4f + languageName: node + linkType: hard + +"serve-handler@npm:6.1.5": + version: 6.1.5 + resolution: "serve-handler@npm:6.1.5" + dependencies: + bytes: 3.0.0 + content-disposition: 0.5.2 + fast-url-parser: 1.1.3 + mime-types: 2.1.18 + minimatch: 3.1.2 + path-is-inside: 1.0.2 + path-to-regexp: 2.2.1 + range-parser: 1.2.0 + checksum: 7a98ca9cbf8692583b6cde4deb3941cff900fa38bf16adbfccccd8430209bab781e21d9a1f61c9c03e226f9f67689893bbce25941368f3ddaf985fc3858b49dc + languageName: node + linkType: hard + +"serve-index@npm:^1.9.1": + version: 1.9.1 + resolution: "serve-index@npm:1.9.1" + 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 + checksum: e2647ce13379485b98a53ba2ea3fbad4d44b57540d00663b02b976e426e6194d62ac465c0d862cb7057f65e0de8ab8a684aa095427a4b8612412eca0d300d22f + languageName: node + linkType: hard + +"serve-static@npm:1.15.0": + version: 1.15.0 + resolution: "serve-static@npm:1.15.0" + dependencies: + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + parseurl: ~1.3.3 + send: 0.18.0 + checksum: af57fc13be40d90a12562e98c0b7855cf6e8bd4c107fe9a45c212bf023058d54a1871b1c89511c3958f70626fff47faeb795f5d83f8cf88514dbaeb2b724464d + languageName: node + linkType: hard + +"serve@npm:14.2.0": + version: 14.2.0 + resolution: "serve@npm:14.2.0" + dependencies: + "@zeit/schemas": 2.29.0 + ajv: 8.11.0 + arg: 5.0.2 + boxen: 7.0.0 + chalk: 5.0.1 + chalk-template: 0.4.0 + clipboardy: 3.0.0 + compression: 1.7.4 + is-port-reachable: 4.0.0 + serve-handler: 6.1.5 + update-check: 1.5.4 + bin: + serve: build/main.js + checksum: a1c26e6c3dd0c482589b39a105e2f09bebf20ee8a0358accd5d64b313952ad3e1a56b8af2bdfef269f9fd37140b4f6c940d12395c851e4a46dfdace8f97616e4 + languageName: node + linkType: hard + +"set-blocking@npm:^2.0.0": + version: 2.0.0 + resolution: "set-blocking@npm:2.0.0" + checksum: 6e65a05f7cf7ebdf8b7c75b101e18c0b7e3dff4940d480efed8aad3a36a4005140b660fa1d804cb8bce911cac290441dc728084a30504d3516ac2ff7ad607b02 + languageName: node + linkType: hard + +"setprototypeof@npm:1.1.0": + version: 1.1.0 + resolution: "setprototypeof@npm:1.1.0" + checksum: 27cb44304d6c9e1a23bc6c706af4acaae1a7aa1054d4ec13c05f01a99fd4887109a83a8042b67ad90dbfcd100d43efc171ee036eb080667172079213242ca36e + languageName: node + linkType: hard + +"setprototypeof@npm:1.2.0": + version: 1.2.0 + resolution: "setprototypeof@npm:1.2.0" + checksum: be18cbbf70e7d8097c97f713a2e76edf84e87299b40d085c6bf8b65314e994cc15e2e317727342fa6996e38e1f52c59720b53fe621e2eb593a6847bf0356db89 + languageName: node + linkType: hard + +"shallow-clone@npm:^3.0.0": + version: 3.0.1 + resolution: "shallow-clone@npm:3.0.1" + dependencies: + kind-of: ^6.0.2 + checksum: 39b3dd9630a774aba288a680e7d2901f5c0eae7b8387fc5c8ea559918b29b3da144b7bdb990d7ccd9e11be05508ac9e459ce51d01fd65e583282f6ffafcba2e7 + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: ^3.0.0 + checksum: 6b52fe87271c12968f6a054e60f6bde5f0f3d2db483a1e5c3e12d657c488a15474121a1d55cd958f6df026a54374ec38a4a963988c213b7570e1d51575cea7fa + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 1a2bcae50de99034fcd92ad4212d8e01eedf52c7ec7830eedcf886622804fe36884278f2be8be0ea5fde3fd1c23911643a4e0f726c8685b61871c8908af01222 + languageName: node + linkType: hard + +"shell-quote@npm:^1.7.3": + version: 1.7.4 + resolution: "shell-quote@npm:1.7.4" + checksum: 2874ea9c1a7c3ebfc9ec5734a897e16533d0d06f2e4cddc22ba3d1cab5cdc07d0f825364c1b1e39abe61236f44d8e60e933c7ad7349ce44de4f5dddc7b4354e9 + languageName: node + linkType: hard + +"side-channel@npm:^1.0.4": + version: 1.0.4 + resolution: "side-channel@npm:1.0.4" + dependencies: + call-bind: ^1.0.0 + get-intrinsic: ^1.0.2 + object-inspect: ^1.9.0 + checksum: 351e41b947079c10bd0858364f32bb3a7379514c399edb64ab3dce683933483fc63fb5e4efe0a15a2e8a7e3c436b6a91736ddb8d8c6591b0460a24bb4a1ee245 + languageName: node + linkType: hard + +"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": + version: 3.0.7 + resolution: "signal-exit@npm:3.0.7" + checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 + languageName: node + linkType: hard + +"single-spa-react@npm:4.6.1": + version: 4.6.1 + resolution: "single-spa-react@npm:4.6.1" + dependencies: + browserslist-config-single-spa: ^1.0.1 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: "*" + checksum: 12383d3b1dfc328efb7386f1094cbd255cf7e4785685416cd854ff3e1ba5da7828a2edaada94859593c8bc0405c5982c9655d1f51b5b67a2a94a6c1908983428 + languageName: node + linkType: hard + +"sisteransi@npm:^1.0.5": + version: 1.0.5 + resolution: "sisteransi@npm:1.0.5" + checksum: aba6438f46d2bfcef94cf112c835ab395172c75f67453fe05c340c770d3c402363018ae1ab4172a1026a90c47eaccf3af7b6ff6fa749a680c2929bd7fa2b37a4 + languageName: node + linkType: hard + +"slash@npm:^3.0.0": + version: 3.0.0 + resolution: "slash@npm:3.0.0" + checksum: 94a93fff615f25a999ad4b83c9d5e257a7280c90a32a7cb8b4a87996e4babf322e469c42b7f649fd5796edd8687652f3fb452a86dc97a816f01113183393f11c + languageName: node + linkType: hard + +"slash@npm:^4.0.0": + version: 4.0.0 + resolution: "slash@npm:4.0.0" + checksum: da8e4af73712253acd21b7853b7e0dbba776b786e82b010a5bfc8b5051a1db38ed8aba8e1e8f400dd2c9f373be91eb1c42b66e91abb407ff42b10feece5e1d2d + languageName: node + linkType: hard + +"slice-ansi@npm:^3.0.0": + version: 3.0.0 + resolution: "slice-ansi@npm:3.0.0" + dependencies: + ansi-styles: ^4.0.0 + astral-regex: ^2.0.0 + is-fullwidth-code-point: ^3.0.0 + checksum: 5ec6d022d12e016347e9e3e98a7eb2a592213a43a65f1b61b74d2c78288da0aded781f665807a9f3876b9daa9ad94f64f77d7633a0458876c3a4fdc4eb223f24 + languageName: node + linkType: hard + +"slice-ansi@npm:^4.0.0": + version: 4.0.0 + resolution: "slice-ansi@npm:4.0.0" + dependencies: + ansi-styles: ^4.0.0 + astral-regex: ^2.0.0 + is-fullwidth-code-point: ^3.0.0 + checksum: 4a82d7f085b0e1b070e004941ada3c40d3818563ac44766cca4ceadd2080427d337554f9f99a13aaeb3b4a94d9964d9466c807b3d7b7541d1ec37ee32d308756 + languageName: node + linkType: hard + +"slice-ansi@npm:^5.0.0": + version: 5.0.0 + resolution: "slice-ansi@npm:5.0.0" + dependencies: + ansi-styles: ^6.0.0 + is-fullwidth-code-point: ^4.0.0 + checksum: 7e600a2a55e333a21ef5214b987c8358fe28bfb03c2867ff2cbf919d62143d1812ac27b4297a077fdaf27a03da3678e49551c93e35f9498a3d90221908a1180e + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: b5167a7142c1da704c0e3af85c402002b597081dd9575031a90b4f229ca5678e9a36e8a374f1814c8156a725d17008ae3bde63b92f9cfd132526379e580bec8b + languageName: node + linkType: hard + +"sockjs@npm:^0.3.24": + version: 0.3.24 + resolution: "sockjs@npm:0.3.24" + dependencies: + faye-websocket: ^0.11.3 + uuid: ^8.3.2 + websocket-driver: ^0.7.4 + checksum: 355309b48d2c4e9755349daa29cea1c0d9ee23e49b983841c6bf7a20276b00d3c02343f9f33f26d2ee8b261a5a02961b52a25c8da88b2538c5b68d3071b4934c + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^7.0.0": + version: 7.0.0 + resolution: "socks-proxy-agent@npm:7.0.0" + dependencies: + agent-base: ^6.0.2 + debug: ^4.3.3 + socks: ^2.6.2 + checksum: 720554370154cbc979e2e9ce6a6ec6ced205d02757d8f5d93fe95adae454fc187a5cbfc6b022afab850a5ce9b4c7d73e0f98e381879cf45f66317a4895953846 + languageName: node + linkType: hard + +"socks@npm:^2.6.2": + version: 2.7.1 + resolution: "socks@npm:2.7.1" + dependencies: + ip: ^2.0.0 + smart-buffer: ^4.2.0 + checksum: 259d9e3e8e1c9809a7f5c32238c3d4d2a36b39b83851d0f573bfde5f21c4b1288417ce1af06af1452569cd1eb0841169afd4998f0e04ba04656f6b7f0e46d748 + languageName: node + linkType: hard + +"source-list-map@npm:^2.0.0, source-list-map@npm:^2.0.1": + version: 2.0.1 + resolution: "source-list-map@npm:2.0.1" + checksum: 806efc6f75e7cd31e4815e7a3aaf75a45c704871ea4075cb2eb49882c6fca28998f44fc5ac91adb6de03b2882ee6fb02f951fdc85e6a22b338c32bfe19557938 + languageName: node + linkType: hard + +"source-map-js@npm:^1.0.1, source-map-js@npm:^1.0.2": + version: 1.0.2 + resolution: "source-map-js@npm:1.0.2" + checksum: c049a7fc4deb9a7e9b481ae3d424cc793cb4845daa690bc5a05d428bf41bf231ced49b4cf0c9e77f9d42fdb3d20d6187619fc586605f5eabe995a316da8d377c + languageName: node + linkType: hard + +"source-map-loader@npm:^3.0.0": + version: 3.0.2 + resolution: "source-map-loader@npm:3.0.2" + dependencies: + abab: ^2.0.5 + iconv-lite: ^0.6.3 + source-map-js: ^1.0.1 + peerDependencies: + webpack: ^5.0.0 + checksum: d5a4e2ab190c93ae5cba68c247fbaa9fd560333c91060602b634c399a8a4b3205b8c07714c3bcdb0a11c6cc5476c06256bd8e824e71fbbb7981e8fad5cba4a00 + languageName: node + linkType: hard + +"source-map-support@npm:^0.5.6, source-map-support@npm:~0.5.20": + version: 0.5.21 + resolution: "source-map-support@npm:0.5.21" + dependencies: + buffer-from: ^1.0.0 + source-map: ^0.6.0 + checksum: 43e98d700d79af1d36f859bdb7318e601dfc918c7ba2e98456118ebc4c4872b327773e5a1df09b0524e9e5063bb18f0934538eace60cca2710d1fa687645d137 + languageName: node + linkType: hard + +"source-map@npm:0.6.1, source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.0, source-map@npm:~0.6.1": + version: 0.6.1 + resolution: "source-map@npm:0.6.1" + checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2 + languageName: node + linkType: hard + +"source-map@npm:^0.5.7": + version: 0.5.7 + resolution: "source-map@npm:0.5.7" + checksum: 5dc2043b93d2f194142c7f38f74a24670cd7a0063acdaf4bf01d2964b402257ae843c2a8fa822ad5b71013b5fcafa55af7421383da919752f22ff488bc553f4d + languageName: node + linkType: hard + +"source-map@npm:^0.7.3": + version: 0.7.4 + resolution: "source-map@npm:0.7.4" + checksum: 01cc5a74b1f0e1d626a58d36ad6898ea820567e87f18dfc9d24a9843a351aaa2ec09b87422589906d6ff1deed29693e176194dc88bcae7c9a852dc74b311dbf5 + languageName: node + linkType: hard + +"source-map@npm:^0.8.0-beta.0": + version: 0.8.0-beta.0 + resolution: "source-map@npm:0.8.0-beta.0" + dependencies: + whatwg-url: ^7.0.0 + checksum: e94169be6461ab0ac0913313ad1719a14c60d402bd22b0ad96f4a6cffd79130d91ab5df0a5336a326b04d2df131c1409f563c9dc0d21a6ca6239a44b6c8dbd92 + languageName: node + linkType: hard + +"sourcemap-codec@npm:^1.4.8": + version: 1.4.8 + resolution: "sourcemap-codec@npm:1.4.8" + checksum: b57981c05611afef31605732b598ccf65124a9fcb03b833532659ac4d29ac0f7bfacbc0d6c5a28a03e84c7510e7e556d758d0bb57786e214660016fb94279316 + languageName: node + linkType: hard + +"spdy-transport@npm:^3.0.0": + version: 3.0.0 + resolution: "spdy-transport@npm:3.0.0" + 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 + checksum: 0fcaad3b836fb1ec0bdd39fa7008b9a7a84a553f12be6b736a2512613b323207ffc924b9551cef0378f7233c85916cff1118652e03a730bdb97c0e042243d56c + languageName: node + linkType: hard + +"spdy@npm:^4.0.2": + version: 4.0.2 + resolution: "spdy@npm:4.0.2" + 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 + checksum: 2c739d0ff6f56ad36d2d754d0261d5ec358457bea7cbf77b1b05b0c6464f2ce65b85f196305f50b7bd9120723eb94bae9933466f28e67e5cd8cde4e27f1d75f8 + languageName: node + linkType: hard + +"split@npm:0.3": + version: 0.3.3 + resolution: "split@npm:0.3.3" + dependencies: + through: 2 + checksum: 2e076634c9637cfdc54ab4387b6a243b8c33b360874a25adf6f327a5647f07cb3bf1c755d515248eb3afee4e382278d01f62c62d87263c118f28065b86f74f02 + languageName: node + linkType: hard + +"sprintf-js@npm:~1.0.2": + version: 1.0.3 + resolution: "sprintf-js@npm:1.0.3" + checksum: 19d79aec211f09b99ec3099b5b2ae2f6e9cdefe50bc91ac4c69144b6d3928a640bb6ae5b3def70c2e85a2c3d9f5ec2719921e3a59d3ca3ef4b2fd1a4656a0df3 + languageName: node + linkType: hard + +"sshpk@npm:^1.14.1": + version: 1.17.0 + resolution: "sshpk@npm:1.17.0" + dependencies: + asn1: ~0.2.3 + assert-plus: ^1.0.0 + bcrypt-pbkdf: ^1.0.0 + dashdash: ^1.12.0 + ecc-jsbn: ~0.1.1 + getpass: ^0.1.1 + jsbn: ~0.1.0 + safer-buffer: ^2.0.2 + tweetnacl: ~0.14.0 + bin: + sshpk-conv: bin/sshpk-conv + sshpk-sign: bin/sshpk-sign + sshpk-verify: bin/sshpk-verify + checksum: ba109f65c8e6c35133b8e6ed5576abeff8aa8d614824b7275ec3ca308f081fef483607c28d97780c1e235818b0f93ed8c8b56d0a5968d5a23fd6af57718c7597 + languageName: node + linkType: hard + +"ssri@npm:^9.0.0": + version: 9.0.1 + resolution: "ssri@npm:9.0.1" + dependencies: + minipass: ^3.1.1 + checksum: fb58f5e46b6923ae67b87ad5ef1c5ab6d427a17db0bead84570c2df3cd50b4ceb880ebdba2d60726588272890bae842a744e1ecce5bd2a2a582fccd5068309eb + languageName: node + linkType: hard + +"stable@npm:^0.1.8": + version: 0.1.8 + resolution: "stable@npm:0.1.8" + checksum: 2ff482bb100285d16dd75cd8f7c60ab652570e8952c0bfa91828a2b5f646a0ff533f14596ea4eabd48bb7f4aeea408dce8f8515812b975d958a4cc4fa6b9dfeb + languageName: node + linkType: hard + +"stack-utils@npm:^2.0.3": + version: 2.0.6 + resolution: "stack-utils@npm:2.0.6" + dependencies: + escape-string-regexp: ^2.0.0 + checksum: 052bf4d25bbf5f78e06c1d5e67de2e088b06871fa04107ca8d3f0e9d9263326e2942c8bedee3545795fc77d787d443a538345eef74db2f8e35db3558c6f91ff7 + languageName: node + linkType: hard + +"stackframe@npm:^1.3.4": + version: 1.3.4 + resolution: "stackframe@npm:1.3.4" + checksum: bae1596873595c4610993fa84f86a3387d67586401c1816ea048c0196800c0646c4d2da98c2ee80557fd9eff05877efe33b91ba6cd052658ed96ddc85d19067d + languageName: node + linkType: hard + +"start-server-and-test@npm:2.0.0": + version: 2.0.0 + resolution: "start-server-and-test@npm:2.0.0" + dependencies: + arg: ^5.0.2 + bluebird: 3.7.2 + check-more-types: 2.24.0 + debug: 4.3.4 + execa: 5.1.1 + lazy-ass: 1.6.0 + ps-tree: 1.2.0 + wait-on: 7.0.1 + bin: + server-test: src/bin/start.js + start-server-and-test: src/bin/start.js + start-test: src/bin/start.js + checksum: 8788e59ad78275332c78325a804504ac558f06a112d47cb5bc3d012d2bda46add72c863cae2357836fe245ee4e22e2fec0b6d47dbdf5e0f0f5cfd1a57544d100 + languageName: node + linkType: hard + +"statuses@npm:2.0.1": + version: 2.0.1 + resolution: "statuses@npm:2.0.1" + checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb + languageName: node + linkType: hard + +"statuses@npm:>= 1.4.0 < 2": + version: 1.5.0 + resolution: "statuses@npm:1.5.0" + checksum: c469b9519de16a4bb19600205cffb39ee471a5f17b82589757ca7bd40a8d92ebb6ed9f98b5a540c5d302ccbc78f15dc03cc0280dd6e00df1335568a5d5758a5c + languageName: node + linkType: hard + +"stop-iteration-iterator@npm:^1.0.0": + version: 1.0.0 + resolution: "stop-iteration-iterator@npm:1.0.0" + dependencies: + internal-slot: ^1.0.4 + checksum: d04173690b2efa40e24ab70e5e51a3ff31d56d699550cfad084104ab3381390daccb36652b25755e420245f3b0737de66c1879eaa2a8d4fc0a78f9bf892fcb42 + languageName: node + linkType: hard + +"stream-combiner@npm:~0.0.4": + version: 0.0.4 + resolution: "stream-combiner@npm:0.0.4" + dependencies: + duplexer: ~0.1.1 + checksum: 844b622cfe8b9de45a6007404f613b60aaf85200ab9862299066204242f89a7c8033b1c356c998aa6cfc630f6cd9eba119ec1c6dc1f93e245982be4a847aee7d + languageName: node + linkType: hard + +"string-argv@npm:0.3.2": + version: 0.3.2 + resolution: "string-argv@npm:0.3.2" + checksum: 8703ad3f3db0b2641ed2adbb15cf24d3945070d9a751f9e74a924966db9f325ac755169007233e8985a39a6a292f14d4fee20482989b89b96e473c4221508a0f + languageName: node + linkType: hard + +"string-length@npm:^4.0.1": + version: 4.0.2 + resolution: "string-length@npm:4.0.2" + dependencies: + char-regex: ^1.0.2 + strip-ansi: ^6.0.0 + checksum: ce85533ef5113fcb7e522bcf9e62cb33871aa99b3729cec5595f4447f660b0cefd542ca6df4150c97a677d58b0cb727a3fe09ac1de94071d05526c73579bf505 + languageName: node + linkType: hard + +"string-length@npm:^5.0.1": + version: 5.0.1 + resolution: "string-length@npm:5.0.1" + dependencies: + char-regex: ^2.0.0 + strip-ansi: ^7.0.1 + checksum: 71f73b8c8a743e01dcd001bcf1b197db78d5e5e53b12bd898cddaf0961be09f947dfd8c429783db3694b55b05cb5a51de6406c5085ff1aaa10c4771440c8396d + languageName: node + linkType: hard + +"string-natural-compare@npm:^3.0.1": + version: 3.0.1 + resolution: "string-natural-compare@npm:3.0.1" + checksum: 65910d9995074086e769a68728395effbba9b7186be5b4c16a7fad4f4ef50cae95ca16e3e9086e019cbb636ae8daac9c7b8fe91b5f21865c5c0f26e3c0725406 + languageName: node + linkType: hard + +"string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: ^8.0.0 + is-fullwidth-code-point: ^3.0.0 + strip-ansi: ^6.0.1 + checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb + languageName: node + linkType: hard + +"string-width@npm:^5.0.0, string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: ^0.2.0 + emoji-regex: ^9.2.2 + strip-ansi: ^7.0.1 + checksum: 7369deaa29f21dda9a438686154b62c2c5f661f8dda60449088f9f980196f7908fc39fdd1803e3e01541970287cf5deae336798337e9319a7055af89dafa7193 + languageName: node + linkType: hard + +"string.prototype.matchall@npm:^4.0.6, string.prototype.matchall@npm:^4.0.8": + version: 4.0.8 + resolution: "string.prototype.matchall@npm:4.0.8" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + get-intrinsic: ^1.1.3 + has-symbols: ^1.0.3 + internal-slot: ^1.0.3 + regexp.prototype.flags: ^1.4.3 + side-channel: ^1.0.4 + checksum: 952da3a818de42ad1c10b576140a5e05b4de7b34b8d9dbf00c3ac8c1293e9c0f533613a39c5cda53e0a8221f2e710bc2150e730b1c2278d60004a8a35726efb6 + languageName: node + linkType: hard + +"string.prototype.trimend@npm:^1.0.6": + version: 1.0.6 + resolution: "string.prototype.trimend@npm:1.0.6" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + checksum: 0fdc34645a639bd35179b5a08227a353b88dc089adf438f46be8a7c197fc3f22f8514c1c9be4629b3cd29c281582730a8cbbad6466c60f76b5f99cf2addb132e + languageName: node + linkType: hard + +"string.prototype.trimstart@npm:^1.0.6": + version: 1.0.6 + resolution: "string.prototype.trimstart@npm:1.0.6" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 + checksum: 89080feef416621e6ef1279588994305477a7a91648d9436490d56010a1f7adc39167cddac7ce0b9884b8cdbef086987c4dcb2960209f2af8bac0d23ceff4f41 + languageName: node + linkType: hard + +"string_decoder@npm:^1.1.1": + version: 1.3.0 + resolution: "string_decoder@npm:1.3.0" + dependencies: + safe-buffer: ~5.2.0 + checksum: 8417646695a66e73aefc4420eb3b84cc9ffd89572861fe004e6aeb13c7bc00e2f616247505d2dbbef24247c372f70268f594af7126f43548565c68c117bdeb56 + languageName: node + linkType: hard + +"string_decoder@npm:~1.1.1": + version: 1.1.1 + resolution: "string_decoder@npm:1.1.1" + dependencies: + safe-buffer: ~5.1.0 + checksum: 9ab7e56f9d60a28f2be697419917c50cac19f3e8e6c28ef26ed5f4852289fe0de5d6997d29becf59028556f2c62983790c1d9ba1e2a3cc401768ca12d5183a5b + languageName: node + linkType: hard + +"stringify-object@npm:^3.3.0": + version: 3.3.0 + resolution: "stringify-object@npm:3.3.0" + dependencies: + get-own-enumerable-property-symbols: ^3.0.0 + is-obj: ^1.0.1 + is-regexp: ^1.0.0 + checksum: 6827a3f35975cfa8572e8cd3ed4f7b262def260af18655c6fde549334acdac49ddba69f3c861ea5a6e9c5a4990fe4ae870b9c0e6c31019430504c94a83b7a154 + languageName: node + linkType: hard + +"strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: ^5.0.1 + checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.0.1 + resolution: "strip-ansi@npm:7.0.1" + dependencies: + ansi-regex: ^6.0.1 + checksum: 257f78fa433520e7f9897722731d78599cb3fce29ff26a20a5e12ba4957463b50a01136f37c43707f4951817a75e90820174853d6ccc240997adc5df8f966039 + languageName: node + linkType: hard + +"strip-bom@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-bom@npm:3.0.0" + checksum: 8d50ff27b7ebe5ecc78f1fe1e00fcdff7af014e73cf724b46fb81ef889eeb1015fc5184b64e81a2efe002180f3ba431bdd77e300da5c6685d702780fbf0c8d5b + languageName: node + linkType: hard + +"strip-bom@npm:^4.0.0": + version: 4.0.0 + resolution: "strip-bom@npm:4.0.0" + checksum: 9dbcfbaf503c57c06af15fe2c8176fb1bf3af5ff65003851a102749f875a6dbe0ab3b30115eccf6e805e9d756830d3e40ec508b62b3f1ddf3761a20ebe29d3f3 + languageName: node + linkType: hard + +"strip-comments@npm:^2.0.1": + version: 2.0.1 + resolution: "strip-comments@npm:2.0.1" + checksum: 36cd122e1c27b5be69df87e1687770a62fe183bdee9f3ff5cf85d30bbc98280afc012581f2fd50c7ad077c90f656f272560c9d2e520d28604b8b7ea3bc87d6f9 + languageName: node + linkType: hard + +"strip-final-newline@npm:^2.0.0": + version: 2.0.0 + resolution: "strip-final-newline@npm:2.0.0" + checksum: 69412b5e25731e1938184b5d489c32e340605bb611d6140344abc3421b7f3c6f9984b21dff296dfcf056681b82caa3bb4cc996a965ce37bcfad663e92eae9c64 + languageName: node + linkType: hard + +"strip-final-newline@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-final-newline@npm:3.0.0" + checksum: 23ee263adfa2070cd0f23d1ac14e2ed2f000c9b44229aec9c799f1367ec001478469560abefd00c5c99ee6f0b31c137d53ec6029c53e9f32a93804e18c201050 + languageName: node + linkType: hard + +"strip-indent@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-indent@npm:3.0.0" + dependencies: + min-indent: ^1.0.0 + checksum: 18f045d57d9d0d90cd16f72b2313d6364fd2cb4bf85b9f593523ad431c8720011a4d5f08b6591c9d580f446e78855c5334a30fb91aa1560f5d9f95ed1b4a0530 + languageName: node + linkType: hard + +"strip-json-comments@npm:^3.1.1": + version: 3.1.1 + resolution: "strip-json-comments@npm:3.1.1" + checksum: 492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443 + languageName: node + linkType: hard + +"strip-json-comments@npm:~2.0.1": + version: 2.0.1 + resolution: "strip-json-comments@npm:2.0.1" + checksum: 1074ccb63270d32ca28edfb0a281c96b94dc679077828135141f27d52a5a398ef5e78bcf22809d23cadc2b81dfbe345eb5fd8699b385c8b1128907dec4a7d1e1 + languageName: node + linkType: hard + +"style-loader@npm:^3.3.1": + version: 3.3.1 + resolution: "style-loader@npm:3.3.1" + peerDependencies: + webpack: ^5.0.0 + checksum: 470feef680f59e2fce4d6601b5c55b88c01ad8d1dd693c528ffd591ff5fd7c01a4eff3bdbe62f26f847d6bd2430c9ab594be23307cfe7a3446ab236683f0d066 + languageName: node + linkType: hard + +"stylehacks@npm:^5.1.1": + version: 5.1.1 + resolution: "stylehacks@npm:5.1.1" + dependencies: + browserslist: ^4.21.4 + postcss-selector-parser: ^6.0.4 + peerDependencies: + postcss: ^8.2.15 + checksum: 11175366ef52de65bf06cefba0ddc9db286dc3a1451fd2989e74c6ea47091a02329a4bf6ce10b1a36950056927b6bbbe47c5ab3a1f4c7032df932d010fbde5a2 + languageName: node + linkType: hard + +"stylis@npm:4.2.0": + version: 4.2.0 + resolution: "stylis@npm:4.2.0" + checksum: 0eb6cc1b866dc17a6037d0a82ac7fa877eba6a757443e79e7c4f35bacedbf6421fadcab4363b39667b43355cbaaa570a3cde850f776498e5450f32ed2f9b7584 + languageName: node + linkType: hard + +"supports-color@npm:^5.3.0": + version: 5.5.0 + resolution: "supports-color@npm:5.5.0" + dependencies: + has-flag: ^3.0.0 + checksum: 95f6f4ba5afdf92f495b5a912d4abee8dcba766ae719b975c56c084f5004845f6f5a5f7769f52d53f40e21952a6d87411bafe34af4a01e65f9926002e38e1dac + languageName: node + linkType: hard + +"supports-color@npm:^7.0.0, supports-color@npm:^7.1.0": + version: 7.2.0 + resolution: "supports-color@npm:7.2.0" + dependencies: + has-flag: ^4.0.0 + checksum: 3dda818de06ebbe5b9653e07842d9479f3555ebc77e9a0280caf5a14fb877ffee9ed57007c3b78f5a6324b8dbeec648d9e97a24e2ed9fdb81ddc69ea07100f4a + languageName: node + linkType: hard + +"supports-color@npm:^8.0.0, supports-color@npm:^8.1.1": + version: 8.1.1 + resolution: "supports-color@npm:8.1.1" + dependencies: + has-flag: ^4.0.0 + checksum: c052193a7e43c6cdc741eb7f378df605636e01ad434badf7324f17fb60c69a880d8d8fcdcb562cf94c2350e57b937d7425ab5b8326c67c2adc48f7c87c1db406 + languageName: node + linkType: hard + +"supports-hyperlinks@npm:^2.0.0": + version: 2.3.0 + resolution: "supports-hyperlinks@npm:2.3.0" + dependencies: + has-flag: ^4.0.0 + supports-color: ^7.0.0 + checksum: 9ee0de3c8ce919d453511b2b1588a8205bd429d98af94a01df87411391010fe22ca463f268c84b2ce2abad019dfff8452aa02806eeb5c905a8d7ad5c4f4c52b8 + languageName: node + linkType: hard + +"supports-preserve-symlinks-flag@npm:^1.0.0": + version: 1.0.0 + resolution: "supports-preserve-symlinks-flag@npm:1.0.0" + checksum: 53b1e247e68e05db7b3808b99b892bd36fb096e6fba213a06da7fab22045e97597db425c724f2bbd6c99a3c295e1e73f3e4de78592289f38431049e1277ca0ae + languageName: node + linkType: hard + +"svg-parser@npm:^2.0.2": + version: 2.0.4 + resolution: "svg-parser@npm:2.0.4" + checksum: b3de6653048212f2ae7afe4a423e04a76ec6d2d06e1bf7eacc618a7c5f7df7faa5105561c57b94579ec831fbbdbf5f190ba56a9205ff39ed13eabdf8ab086ddf + languageName: node + linkType: hard + +"svgo@npm:^1.2.2": + version: 1.3.2 + resolution: "svgo@npm:1.3.2" + dependencies: + chalk: ^2.4.1 + coa: ^2.0.2 + css-select: ^2.0.0 + css-select-base-adapter: ^0.1.1 + css-tree: 1.0.0-alpha.37 + csso: ^4.0.2 + js-yaml: ^3.13.1 + mkdirp: ~0.5.1 + object.values: ^1.1.0 + sax: ~1.2.4 + stable: ^0.1.8 + unquote: ~1.1.1 + util.promisify: ~1.0.0 + bin: + svgo: ./bin/svgo + checksum: 28a5680a61245eb4a1603bc03459095bb01ad5ebd23e95882d886c3c81752313c0a9a9fe48dd0bcbb9a27c52e11c603640df952971573b2b550d9e15a9ee6116 + languageName: node + linkType: hard + +"svgo@npm:^2.7.0": + version: 2.8.0 + resolution: "svgo@npm:2.8.0" + 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 + checksum: b92f71a8541468ffd0b81b8cdb36b1e242eea320bf3c1a9b2c8809945853e9d8c80c19744267eb91cabf06ae9d5fff3592d677df85a31be4ed59ff78534fa420 + languageName: node + linkType: hard + +"symbol-tree@npm:^3.2.4": + version: 3.2.4 + resolution: "symbol-tree@npm:3.2.4" + checksum: 6e8fc7e1486b8b54bea91199d9535bb72f10842e40c79e882fc94fb7b14b89866adf2fd79efa5ebb5b658bc07fb459ccce5ac0e99ef3d72f474e74aaf284029d + languageName: node + linkType: hard + +"tailwindcss@npm:^3.0.2": + version: 3.2.4 + resolution: "tailwindcss@npm:3.2.4" + dependencies: + arg: ^5.0.2 + chokidar: ^3.5.3 + color-name: ^1.1.4 + detective: ^5.2.1 + didyoumean: ^1.2.2 + dlv: ^1.1.3 + fast-glob: ^3.2.12 + glob-parent: ^6.0.2 + is-glob: ^4.0.3 + lilconfig: ^2.0.6 + micromatch: ^4.0.5 + normalize-path: ^3.0.0 + object-hash: ^3.0.0 + picocolors: ^1.0.0 + postcss: ^8.4.18 + postcss-import: ^14.1.0 + postcss-js: ^4.0.0 + postcss-load-config: ^3.1.4 + postcss-nested: 6.0.0 + postcss-selector-parser: ^6.0.10 + postcss-value-parser: ^4.2.0 + quick-lru: ^5.1.1 + resolve: ^1.22.1 + peerDependencies: + postcss: ^8.0.9 + bin: + tailwind: lib/cli.js + tailwindcss: lib/cli.js + checksum: ec187d180c722ec4f57537f2216c7b21269b525f12aaf353cea464d939c3e6286a1221eb3e1206e45d1f015f296171309ad4d9952899b0245cd07d9500a9401f + languageName: node + linkType: hard + +"tapable@npm:^1.0.0": + version: 1.1.3 + resolution: "tapable@npm:1.1.3" + checksum: 53ff4e7c3900051c38cc4faab428ebfd7e6ad0841af5a7ac6d5f3045c5b50e88497bfa8295b4b3fbcadd94993c9e358868b78b9fb249a76cb8b018ac8dccafd7 + languageName: node + linkType: hard + +"tapable@npm:^2.0.0, tapable@npm:^2.1.1, tapable@npm:^2.2.0": + version: 2.2.1 + resolution: "tapable@npm:2.2.1" + checksum: 3b7a1b4d86fa940aad46d9e73d1e8739335efd4c48322cb37d073eb6f80f5281889bf0320c6d8ffcfa1a0dd5bfdbd0f9d037e252ef972aca595330538aac4d51 + languageName: node + linkType: hard + +"tar@npm:^6.1.11, tar@npm:^6.1.2": + version: 6.2.1 + resolution: "tar@npm:6.2.1" + dependencies: + chownr: ^2.0.0 + fs-minipass: ^2.0.0 + minipass: ^5.0.0 + minizlib: ^2.1.1 + mkdirp: ^1.0.3 + yallist: ^4.0.0 + checksum: f1322768c9741a25356c11373bce918483f40fa9a25c69c59410c8a1247632487edef5fe76c5f12ac51a6356d2f1829e96d2bc34098668a2fc34d76050ac2b6c + languageName: node + linkType: hard + +"temp-dir@npm:^2.0.0": + version: 2.0.0 + resolution: "temp-dir@npm:2.0.0" + checksum: cc4f0404bf8d6ae1a166e0e64f3f409b423f4d1274d8c02814a59a5529f07db6cd070a749664141b992b2c1af337fa9bb451a460a43bb9bcddc49f235d3115aa + languageName: node + linkType: hard + +"tempy@npm:^0.6.0": + version: 0.6.0 + resolution: "tempy@npm:0.6.0" + dependencies: + is-stream: ^2.0.0 + temp-dir: ^2.0.0 + type-fest: ^0.16.0 + unique-string: ^2.0.0 + checksum: dd09c8b6615e4b785ea878e9a18b17ac0bfe5dccf5a0e205ebd274bb356356aff3f5c90a6c917077d51c75efb7648b113a78b0492e2ffc81a7c9912eb872ac52 + languageName: node + linkType: hard + +"terminal-link@npm:^2.0.0": + version: 2.1.1 + resolution: "terminal-link@npm:2.1.1" + dependencies: + ansi-escapes: ^4.2.1 + supports-hyperlinks: ^2.0.0 + checksum: ce3d2cd3a438c4a9453947aa664581519173ea40e77e2534d08c088ee6dda449eabdbe0a76d2a516b8b73c33262fedd10d5270ccf7576ae316e3db170ce6562f + languageName: node + linkType: hard + +"terser-webpack-plugin@npm:^5.1.3, terser-webpack-plugin@npm:^5.2.5": + version: 5.3.6 + resolution: "terser-webpack-plugin@npm:5.3.6" + dependencies: + "@jridgewell/trace-mapping": ^0.3.14 + jest-worker: ^27.4.5 + schema-utils: ^3.1.1 + serialize-javascript: ^6.0.0 + terser: ^5.14.1 + peerDependencies: + webpack: ^5.1.0 + peerDependenciesMeta: + "@swc/core": + optional: true + esbuild: + optional: true + uglify-js: + optional: true + checksum: 8f3448d7fdb0434ce6a0c09d95c462bfd2f4a5a430233d854163337f734a7f5c07c74513d16081e06d4ca33d366d5b1a36f5444219bc41a7403afd6162107bad + languageName: node + linkType: hard + +"terser@npm:^5.0.0, terser@npm:^5.10.0, terser@npm:^5.14.1": + version: 5.16.1 + resolution: "terser@npm:5.16.1" + dependencies: + "@jridgewell/source-map": ^0.3.2 + acorn: ^8.5.0 + commander: ^2.20.0 + source-map-support: ~0.5.20 + bin: + terser: bin/terser + checksum: cb524123504a2f0d9140c1e1a8628c83bba9cacc404c6aca79e2493a38dfdf21275617ba75b91006b3f1ff586e401ab31121160cd253699f334c6340ea2756f5 + languageName: node + linkType: hard + +"test-exclude@npm:^6.0.0": + version: 6.0.0 + resolution: "test-exclude@npm:6.0.0" + dependencies: + "@istanbuljs/schema": ^0.1.2 + glob: ^7.1.4 + minimatch: ^3.0.4 + checksum: 3b34a3d77165a2cb82b34014b3aba93b1c4637a5011807557dc2f3da826c59975a5ccad765721c4648b39817e3472789f9b0fa98fc854c5c1c7a1e632aacdc28 + languageName: node + linkType: hard + +"text-table@npm:^0.2.0": + version: 0.2.0 + resolution: "text-table@npm:0.2.0" + checksum: b6937a38c80c7f84d9c11dd75e49d5c44f71d95e810a3250bd1f1797fc7117c57698204adf676b71497acc205d769d65c16ae8fa10afad832ae1322630aef10a + languageName: node + linkType: hard + +"throat@npm:^6.0.1": + version: 6.0.2 + resolution: "throat@npm:6.0.2" + checksum: 463093768d4884772020bb18b0f33d3fec8a2b4173f7da3958dfbe88ff0f1e686ffadf0f87333bf6f6db7306b1450efc7855df69c78bf0bfa61f6d84a3361fe8 + languageName: node + linkType: hard + +"throttleit@npm:^1.0.0": + version: 1.0.0 + resolution: "throttleit@npm:1.0.0" + checksum: 1b2db4d2454202d589e8236c07a69d2fab838876d370030ebea237c34c0a7d1d9cf11c29f994531ebb00efd31e9728291042b7754f2798a8352ec4463455b659 + languageName: node + linkType: hard + +"through@npm:2, through@npm:^2.3.8, through@npm:~2.3, through@npm:~2.3.1": + version: 2.3.8 + resolution: "through@npm:2.3.8" + checksum: a38c3e059853c494af95d50c072b83f8b676a9ba2818dcc5b108ef252230735c54e0185437618596c790bbba8fcdaef5b290405981ffa09dce67b1f1bf190cbd + languageName: node + linkType: hard + +"thunky@npm:^1.0.2": + version: 1.1.0 + resolution: "thunky@npm:1.1.0" + checksum: 993096c472b6b8f30e29dc777a8d17720e4cab448375041f20c0cb802a09a7fb2217f2a3e8cdc11851faa71c957e2db309357367fc9d7af3cb7a4d00f4b66034 + languageName: node + linkType: hard + +"tiny-invariant@npm:^1.0.2": + version: 1.3.1 + resolution: "tiny-invariant@npm:1.3.1" + checksum: 872dbd1ff20a21303a2fd20ce3a15602cfa7fcf9b228bd694a52e2938224313b5385a1078cb667ed7375d1612194feaca81c4ecbe93121ca1baebe344de4f84c + languageName: node + linkType: hard + +"tiny-warning@npm:^1.0.0, tiny-warning@npm:^1.0.3": + version: 1.0.3 + resolution: "tiny-warning@npm:1.0.3" + checksum: da62c4acac565902f0624b123eed6dd3509bc9a8d30c06e017104bedcf5d35810da8ff72864400ad19c5c7806fc0a8323c68baf3e326af7cb7d969f846100d71 + languageName: node + linkType: hard + +"tmp@npm:~0.2.1": + version: 0.2.1 + resolution: "tmp@npm:0.2.1" + dependencies: + rimraf: ^3.0.0 + checksum: 8b1214654182575124498c87ca986ac53dc76ff36e8f0e0b67139a8d221eaecfdec108c0e6ec54d76f49f1f72ab9325500b246f562b926f85bcdfca8bf35df9e + languageName: node + linkType: hard + +"tmpl@npm:1.0.5": + version: 1.0.5 + resolution: "tmpl@npm:1.0.5" + checksum: cd922d9b853c00fe414c5a774817be65b058d54a2d01ebb415840960406c669a0fc632f66df885e24cb022ec812739199ccbdb8d1164c3e513f85bfca5ab2873 + languageName: node + linkType: hard + +"to-fast-properties@npm:^2.0.0": + version: 2.0.0 + resolution: "to-fast-properties@npm:2.0.0" + checksum: be2de62fe58ead94e3e592680052683b1ec986c72d589e7b21e5697f8744cdbf48c266fa72f6c15932894c10187b5f54573a3bcf7da0bfd964d5caf23d436168 + languageName: node + linkType: hard + +"to-regex-range@npm:^5.0.1": + version: 5.0.1 + resolution: "to-regex-range@npm:5.0.1" + dependencies: + is-number: ^7.0.0 + checksum: f76fa01b3d5be85db6a2a143e24df9f60dd047d151062d0ba3df62953f2f697b16fe5dad9b0ac6191c7efc7b1d9dcaa4b768174b7b29da89d4428e64bc0a20ed + languageName: node + linkType: hard + +"toidentifier@npm:1.0.1": + version: 1.0.1 + resolution: "toidentifier@npm:1.0.1" + checksum: 952c29e2a85d7123239b5cfdd889a0dde47ab0497f0913d70588f19c53f7e0b5327c95f4651e413c74b785147f9637b17410ac8c846d5d4a20a5a33eb6dc3a45 + languageName: node + linkType: hard + +"tough-cookie@npm:^4.0.0, tough-cookie@npm:^4.1.3": + version: 4.1.3 + resolution: "tough-cookie@npm:4.1.3" + dependencies: + psl: ^1.1.33 + punycode: ^2.1.1 + universalify: ^0.2.0 + url-parse: ^1.5.3 + checksum: c9226afff36492a52118432611af083d1d8493a53ff41ec4ea48e5b583aec744b989e4280bcf476c910ec1525a89a4a0f1cae81c08b18fb2ec3a9b3a72b91dcc + languageName: node + linkType: hard + +"tr46@npm:^1.0.1": + version: 1.0.1 + resolution: "tr46@npm:1.0.1" + dependencies: + punycode: ^2.1.0 + checksum: 96d4ed46bc161db75dbf9247a236ea0bfcaf5758baae6749e92afab0bc5a09cb59af21788ede7e55080f2bf02dce3e4a8f2a484cc45164e29f4b5e68f7cbcc1a + languageName: node + linkType: hard + +"tr46@npm:^2.1.0": + version: 2.1.0 + resolution: "tr46@npm:2.1.0" + dependencies: + punycode: ^2.1.1 + checksum: ffe6049b9dca3ae329b059aada7f515b0f0064c611b39b51ff6b53897e954650f6f63d9319c6c008d36ead477c7b55e5f64c9dc60588ddc91ff720d64eb710b3 + languageName: node + linkType: hard + +"tr46@npm:~0.0.3": + version: 0.0.3 + resolution: "tr46@npm:0.0.3" + checksum: 726321c5eaf41b5002e17ffbd1fb7245999a073e8979085dacd47c4b4e8068ff5777142fc6726d6ca1fd2ff16921b48788b87225cbc57c72636f6efa8efbffe3 + languageName: node + linkType: hard + +"tryer@npm:^1.0.1": + version: 1.0.1 + resolution: "tryer@npm:1.0.1" + checksum: 1cf14d7f67c79613f054b569bfc9a89c7020d331573a812dfcf7437244e8f8e6eb6893b210cbd9cc217f67c1d72617f89793df231e4fe7d53634ed91cf3a89d1 + languageName: node + linkType: hard + +"ts-node@npm:^10.7.0": + version: 10.9.1 + resolution: "ts-node@npm:10.9.1" + dependencies: + "@cspotcode/source-map-support": ^0.8.0 + "@tsconfig/node10": ^1.0.7 + "@tsconfig/node12": ^1.0.7 + "@tsconfig/node14": ^1.0.0 + "@tsconfig/node16": ^1.0.2 + acorn: ^8.4.1 + acorn-walk: ^8.1.1 + arg: ^4.1.0 + create-require: ^1.1.0 + diff: ^4.0.1 + make-error: ^1.1.1 + v8-compile-cache-lib: ^3.0.1 + yn: 3.1.1 + peerDependencies: + "@swc/core": ">=1.2.50" + "@swc/wasm": ">=1.2.50" + "@types/node": "*" + typescript: ">=2.7" + peerDependenciesMeta: + "@swc/core": + optional: true + "@swc/wasm": + optional: true + bin: + ts-node: dist/bin.js + ts-node-cwd: dist/bin-cwd.js + ts-node-esm: dist/bin-esm.js + ts-node-script: dist/bin-script.js + ts-node-transpile-only: dist/bin-transpile.js + ts-script: dist/bin-script-deprecated.js + checksum: 090adff1302ab20bd3486e6b4799e90f97726ed39e02b39e566f8ab674fd5bd5f727f43615debbfc580d33c6d9d1c6b1b3ce7d8e3cca3e20530a145ffa232c35 + languageName: node + linkType: hard + +"tsconfig-paths@npm:^3.14.1": + version: 3.14.1 + resolution: "tsconfig-paths@npm:3.14.1" + dependencies: + "@types/json5": ^0.0.29 + json5: ^1.0.1 + minimist: ^1.2.6 + strip-bom: ^3.0.0 + checksum: 8afa01c673ebb4782ba53d3a12df97fa837ce524f8ad38ee4e2b2fd57f5ac79abc21c574e9e9eb014d93efe7fe8214001b96233b5c6ea75bd1ea82afe17a4c6d + languageName: node + linkType: hard + +"tslib@npm:2.6.0, tslib@npm:^2.0.3, tslib@npm:^2.1.0": + version: 2.6.0 + resolution: "tslib@npm:2.6.0" + checksum: c01066038f950016a18106ddeca4649b4d76caa76ec5a31e2a26e10586a59fceb4ee45e96719bf6c715648e7c14085a81fee5c62f7e9ebee68e77a5396e5538f + languageName: node + linkType: hard + +"tslib@npm:^1.8.1": + version: 1.14.1 + resolution: "tslib@npm:1.14.1" + checksum: dbe628ef87f66691d5d2959b3e41b9ca0045c3ee3c7c7b906cc1e328b39f199bb1ad9e671c39025bd56122ac57dfbf7385a94843b1cc07c60a4db74795829acd + languageName: node + linkType: hard + +"tsutils@npm:^3.21.0": + version: 3.21.0 + resolution: "tsutils@npm:3.21.0" + dependencies: + tslib: ^1.8.1 + peerDependencies: + typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + checksum: 1843f4c1b2e0f975e08c4c21caa4af4f7f65a12ac1b81b3b8489366826259323feb3fc7a243123453d2d1a02314205a7634e048d4a8009921da19f99755cdc48 + languageName: node + linkType: hard + +"tunnel-agent@npm:^0.6.0": + version: 0.6.0 + resolution: "tunnel-agent@npm:0.6.0" + dependencies: + safe-buffer: ^5.0.1 + checksum: 05f6510358f8afc62a057b8b692f05d70c1782b70db86d6a1e0d5e28a32389e52fa6e7707b6c5ecccacc031462e4bc35af85ecfe4bbc341767917b7cf6965711 + languageName: node + linkType: hard + +"tweetnacl@npm:^0.14.3, tweetnacl@npm:~0.14.0": + version: 0.14.5 + resolution: "tweetnacl@npm:0.14.5" + checksum: 6061daba1724f59473d99a7bb82e13f211cdf6e31315510ae9656fefd4779851cb927adad90f3b488c8ed77c106adc0421ea8055f6f976ff21b27c5c4e918487 + languageName: node + linkType: hard + +"type-check@npm:^0.4.0, type-check@npm:~0.4.0": + version: 0.4.0 + resolution: "type-check@npm:0.4.0" + dependencies: + prelude-ls: ^1.2.1 + checksum: ec688ebfc9c45d0c30412e41ca9c0cdbd704580eb3a9ccf07b9b576094d7b86a012baebc95681999dd38f4f444afd28504cb3a89f2ef16b31d4ab61a0739025a + languageName: node + linkType: hard + +"type-check@npm:~0.3.2": + version: 0.3.2 + resolution: "type-check@npm:0.3.2" + dependencies: + prelude-ls: ~1.1.2 + checksum: dd3b1495642731bc0e1fc40abe5e977e0263005551ac83342ecb6f4f89551d106b368ec32ad3fb2da19b3bd7b2d1f64330da2ea9176d8ddbfe389fb286eb5124 + languageName: node + linkType: hard + +"type-detect@npm:4.0.8": + version: 4.0.8 + resolution: "type-detect@npm:4.0.8" + checksum: 62b5628bff67c0eb0b66afa371bd73e230399a8d2ad30d852716efcc4656a7516904570cd8631a49a3ce57c10225adf5d0cbdcb47f6b0255fe6557c453925a15 + languageName: node + linkType: hard + +"type-fest@npm:^0.16.0": + version: 0.16.0 + resolution: "type-fest@npm:0.16.0" + checksum: 1a4102c06dc109db00418c753062e206cab65befd469d000ece4452ee649bf2a9cf57686d96fb42326bc9d918d9a194d4452897b486dcc41989e5c99e4e87094 + languageName: node + linkType: hard + +"type-fest@npm:^0.20.2": + version: 0.20.2 + resolution: "type-fest@npm:0.20.2" + checksum: 4fb3272df21ad1c552486f8a2f8e115c09a521ad7a8db3d56d53718d0c907b62c6e9141ba5f584af3f6830d0872c521357e512381f24f7c44acae583ad517d73 + languageName: node + linkType: hard + +"type-fest@npm:^0.21.3": + version: 0.21.3 + resolution: "type-fest@npm:0.21.3" + checksum: e6b32a3b3877f04339bae01c193b273c62ba7bfc9e325b8703c4ee1b32dc8fe4ef5dfa54bf78265e069f7667d058e360ae0f37be5af9f153b22382cd55a9afe0 + languageName: node + linkType: hard + +"type-fest@npm:^1.0.2": + version: 1.4.0 + resolution: "type-fest@npm:1.4.0" + checksum: b011c3388665b097ae6a109a437a04d6f61d81b7357f74cbcb02246f2f5bd72b888ae33631b99871388122ba0a87f4ff1c94078e7119ff22c70e52c0ff828201 + languageName: node + linkType: hard + +"type-fest@npm:^2.13.0": + version: 2.19.0 + resolution: "type-fest@npm:2.19.0" + checksum: a4ef07ece297c9fba78fc1bd6d85dff4472fe043ede98bd4710d2615d15776902b595abf62bd78339ed6278f021235fb28a96361f8be86ed754f778973a0d278 + languageName: node + linkType: hard + +"type-is@npm:~1.6.18": + version: 1.6.18 + resolution: "type-is@npm:1.6.18" + dependencies: + media-typer: 0.3.0 + mime-types: ~2.1.24 + checksum: 2c8e47675d55f8b4e404bcf529abdf5036c537a04c2b20177bcf78c9e3c1da69da3942b1346e6edb09e823228c0ee656ef0e033765ec39a70d496ef601a0c657 + languageName: node + linkType: hard + +"typed-array-length@npm:^1.0.4": + version: 1.0.4 + resolution: "typed-array-length@npm:1.0.4" + dependencies: + call-bind: ^1.0.2 + for-each: ^0.3.3 + is-typed-array: ^1.1.9 + checksum: 2228febc93c7feff142b8c96a58d4a0d7623ecde6c7a24b2b98eb3170e99f7c7eff8c114f9b283085cd59dcd2bd43aadf20e25bba4b034a53c5bb292f71f8956 + languageName: node + linkType: hard + +"typedarray-to-buffer@npm:^3.1.5": + version: 3.1.5 + resolution: "typedarray-to-buffer@npm:3.1.5" + dependencies: + is-typedarray: ^1.0.0 + checksum: 99c11aaa8f45189fcfba6b8a4825fd684a321caa9bd7a76a27cf0c7732c174d198b99f449c52c3818107430b5f41c0ccbbfb75cb2ee3ca4a9451710986d61a60 + languageName: node + linkType: hard + +"typescript@npm:5.3.3": + version: 5.3.3 + resolution: "typescript@npm:5.3.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 2007ccb6e51bbbf6fde0a78099efe04dc1c3dfbdff04ca3b6a8bc717991862b39fd6126c0c3ebf2d2d98ac5e960bcaa873826bb2bb241f14277034148f41f6a2 + languageName: node + linkType: hard + +"typescript@patch:typescript@5.3.3#~builtin": + version: 5.3.3 + resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=e012d7" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 4e604a9e107ce0c23b16a2f8d79d0531d4d8fe9ebbb7a8c395c66998c39892f0e0a071ef0b0d4e66420a8ec2b8d6cfd9cdb29ba24f25b37cba072e9282376df9 + languageName: node + linkType: hard + +"unbox-primitive@npm:^1.0.2": + version: 1.0.2 + resolution: "unbox-primitive@npm:1.0.2" + dependencies: + call-bind: ^1.0.2 + has-bigints: ^1.0.2 + has-symbols: ^1.0.3 + which-boxed-primitive: ^1.0.2 + checksum: b7a1cf5862b5e4b5deb091672ffa579aa274f648410009c81cca63fed3b62b610c4f3b773f912ce545bb4e31edc3138975b5bc777fc6e4817dca51affb6380e9 + languageName: node + linkType: hard + +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487 + languageName: node + linkType: hard + +"unicode-canonical-property-names-ecmascript@npm:^2.0.0": + version: 2.0.0 + resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" + checksum: 39be078afd014c14dcd957a7a46a60061bc37c4508ba146517f85f60361acf4c7539552645ece25de840e17e293baa5556268d091ca6762747fdd0c705001a45 + languageName: node + linkType: hard + +"unicode-match-property-ecmascript@npm:^2.0.0": + version: 2.0.0 + resolution: "unicode-match-property-ecmascript@npm:2.0.0" + dependencies: + unicode-canonical-property-names-ecmascript: ^2.0.0 + unicode-property-aliases-ecmascript: ^2.0.0 + checksum: 1f34a7434a23df4885b5890ac36c5b2161a809887000be560f56ad4b11126d433c0c1c39baf1016bdabed4ec54829a6190ee37aa24919aa116dc1a5a8a62965a + languageName: node + linkType: hard + +"unicode-match-property-value-ecmascript@npm:^2.1.0": + version: 2.1.0 + resolution: "unicode-match-property-value-ecmascript@npm:2.1.0" + checksum: 8d6f5f586b9ce1ed0e84a37df6b42fdba1317a05b5df0c249962bd5da89528771e2d149837cad11aa26bcb84c35355cb9f58a10c3d41fa3b899181ece6c85220 + languageName: node + linkType: hard + +"unicode-property-aliases-ecmascript@npm:^2.0.0": + version: 2.1.0 + resolution: "unicode-property-aliases-ecmascript@npm:2.1.0" + checksum: 243524431893649b62cc674d877bd64ef292d6071dd2fd01ab4d5ad26efbc104ffcd064f93f8a06b7e4ec54c172bf03f6417921a0d8c3a9994161fe1f88f815b + languageName: node + linkType: hard + +"unique-filename@npm:^2.0.0": + version: 2.0.1 + resolution: "unique-filename@npm:2.0.1" + dependencies: + unique-slug: ^3.0.0 + checksum: 807acf3381aff319086b64dc7125a9a37c09c44af7620bd4f7f3247fcd5565660ac12d8b80534dcbfd067e6fe88a67e621386dd796a8af828d1337a8420a255f + languageName: node + linkType: hard + +"unique-slug@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-slug@npm:3.0.0" + dependencies: + imurmurhash: ^0.1.4 + checksum: 49f8d915ba7f0101801b922062ee46b7953256c93ceca74303bd8e6413ae10aa7e8216556b54dc5382895e8221d04f1efaf75f945c2e4a515b4139f77aa6640c + languageName: node + linkType: hard + +"unique-string@npm:^2.0.0": + version: 2.0.0 + resolution: "unique-string@npm:2.0.0" + dependencies: + crypto-random-string: ^2.0.0 + checksum: ef68f639136bcfe040cf7e3cd7a8dff076a665288122855148a6f7134092e6ed33bf83a7f3a9185e46c98dddc445a0da6ac25612afa1a7c38b8b654d6c02498e + languageName: node + linkType: hard + +"universalify@npm:^0.2.0": + version: 0.2.0 + resolution: "universalify@npm:0.2.0" + checksum: e86134cb12919d177c2353196a4cc09981524ee87abf621f7bc8d249dbbbebaec5e7d1314b96061497981350df786e4c5128dbf442eba104d6e765bc260678b5 + languageName: node + linkType: hard + +"universalify@npm:^2.0.0": + version: 2.0.0 + resolution: "universalify@npm:2.0.0" + checksum: 2406a4edf4a8830aa6813278bab1f953a8e40f2f63a37873ffa9a3bc8f9745d06cc8e88f3572cb899b7e509013f7f6fcc3e37e8a6d914167a5381d8440518c44 + languageName: node + linkType: hard + +"unload@npm:2.2.0": + version: 2.2.0 + resolution: "unload@npm:2.2.0" + dependencies: + "@babel/runtime": ^7.6.2 + detect-node: ^2.0.4 + checksum: 88ba950c5ff83ab4f9bbd8f63bbf19ba09687ed3c434efd43b7338cc595bc574df8f9b155ee6eee7a435de3d3a4a226726988428977a68ba4907045f1fac5d41 + languageName: node + linkType: hard + +"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 + languageName: node + linkType: hard + +"unquote@npm:~1.1.1": + version: 1.1.1 + resolution: "unquote@npm:1.1.1" + checksum: 71745867d09cba44ba2d26cb71d6dda7045a98b14f7405df4faaf2b0c90d24703ad027a9d90ba9a6e0d096de2c8d56f864fd03f1c0498c0b7a3990f73b4c8f5f + languageName: node + linkType: hard + +"untildify@npm:^4.0.0": + version: 4.0.0 + resolution: "untildify@npm:4.0.0" + checksum: 39ced9c418a74f73f0a56e1ba4634b4d959422dff61f4c72a8e39f60b99380c1b45ed776fbaa0a4101b157e4310d873ad7d114e8534ca02609b4916bb4187fb9 + languageName: node + linkType: hard + +"upath@npm:^1.2.0": + version: 1.2.0 + resolution: "upath@npm:1.2.0" + checksum: 4c05c094797cb733193a0784774dbea5b1889d502fc9f0572164177e185e4a59ba7099bf0b0adf945b232e2ac60363f9bf18aac9b2206fb99cbef971a8455445 + languageName: node + linkType: hard + +"update-browserslist-db@npm:^1.0.9": + version: 1.0.10 + resolution: "update-browserslist-db@npm:1.0.10" + dependencies: + escalade: ^3.1.1 + picocolors: ^1.0.0 + peerDependencies: + browserslist: ">= 4.21.0" + bin: + browserslist-lint: cli.js + checksum: 12db73b4f63029ac407b153732e7cd69a1ea8206c9100b482b7d12859cd3cd0bc59c602d7ae31e652706189f1acb90d42c53ab24a5ba563ed13aebdddc5561a0 + languageName: node + linkType: hard + +"update-check@npm:1.5.4": + version: 1.5.4 + resolution: "update-check@npm:1.5.4" + dependencies: + registry-auth-token: 3.3.2 + registry-url: 3.1.0 + checksum: 2c9f7de6f030364c5ea02a341e5ae2dfe76da6559b32d40dd3b047b3ac0927408cf92d322c51cd8e009688210a85ccbf1eba449762a65a0d1b14f3cdf1ea5c48 + languageName: node + linkType: hard + +"uri-js@npm:^4.2.2": + version: 4.4.1 + resolution: "uri-js@npm:4.4.1" + dependencies: + punycode: ^2.1.0 + checksum: 7167432de6817fe8e9e0c9684f1d2de2bb688c94388f7569f7dbdb1587c9f4ca2a77962f134ec90be0cc4d004c939ff0d05acc9f34a0db39a3c797dada262633 + languageName: node + linkType: hard + +"url-parse@npm:^1.5.3": + version: 1.5.10 + resolution: "url-parse@npm:1.5.10" + dependencies: + querystringify: ^2.1.1 + requires-port: ^1.0.0 + checksum: fbdba6b1d83336aca2216bbdc38ba658d9cfb8fc7f665eb8b17852de638ff7d1a162c198a8e4ed66001ddbf6c9888d41e4798912c62b4fd777a31657989f7bdf + languageName: node + linkType: hard + +"url-search-params-polyfill@npm:8.2.4": + version: 8.2.4 + resolution: "url-search-params-polyfill@npm:8.2.4" + checksum: 7009db6fcf4d091076a71592e685a0c63e275a9a7e9ac5bcec1defd16f5e976381656b2e0fe6e44c48a0a19954c0cd0654d40ae3c9b10803f8c65caf6b47d743 + languageName: node + linkType: hard + +"use-sync-external-store@npm:^1.0.0": + version: 1.2.0 + resolution: "use-sync-external-store@npm:1.2.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + checksum: 5c639e0f8da3521d605f59ce5be9e094ca772bd44a4ce7322b055a6f58eeed8dda3c94cabd90c7a41fb6fa852210092008afe48f7038792fd47501f33299116a + languageName: node + linkType: hard + +"util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": + version: 1.0.2 + resolution: "util-deprecate@npm:1.0.2" + checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 + languageName: node + linkType: hard + +"util.promisify@npm:~1.0.0": + version: 1.0.1 + resolution: "util.promisify@npm:1.0.1" + dependencies: + define-properties: ^1.1.3 + es-abstract: ^1.17.2 + has-symbols: ^1.0.1 + object.getownpropertydescriptors: ^2.1.0 + checksum: d823c75b3fc66510018596f128a6592c98991df38bc0464a633bdf9134e2de0a1a33199c5c21cc261048a3982d7a19e032ecff8835b3c587f843deba96063e37 + languageName: node + linkType: hard + +"utila@npm:~0.4": + version: 0.4.0 + resolution: "utila@npm:0.4.0" + checksum: 97ffd3bd2bb80c773429d3fb8396469115cd190dded1e733f190d8b602bd0a1bcd6216b7ce3c4395ee3c79e3c879c19d268dbaae3093564cb169ad1212d436f4 + languageName: node + linkType: hard + +"utils-merge@npm:1.0.1": + version: 1.0.1 + resolution: "utils-merge@npm:1.0.1" + checksum: c81095493225ecfc28add49c106ca4f09cdf56bc66731aa8dabc2edbbccb1e1bfe2de6a115e5c6a380d3ea166d1636410b62ef216bb07b3feb1cfde1d95d5080 + languageName: node + linkType: hard + +"uuid@npm:^8.3.2": + version: 8.3.2 + resolution: "uuid@npm:8.3.2" + bin: + uuid: dist/bin/uuid + checksum: 5575a8a75c13120e2f10e6ddc801b2c7ed7d8f3c8ac22c7ed0c7b2ba6383ec0abda88c905085d630e251719e0777045ae3236f04c812184b7c765f63a70e58df + languageName: node + linkType: hard + +"v8-compile-cache-lib@npm:^3.0.1": + version: 3.0.1 + resolution: "v8-compile-cache-lib@npm:3.0.1" + checksum: 78089ad549e21bcdbfca10c08850022b22024cdcc2da9b168bcf5a73a6ed7bf01a9cebb9eac28e03cd23a684d81e0502797e88f3ccd27a32aeab1cfc44c39da0 + languageName: node + linkType: hard + +"v8-to-istanbul@npm:^8.1.0": + version: 8.1.1 + resolution: "v8-to-istanbul@npm:8.1.1" + dependencies: + "@types/istanbul-lib-coverage": ^2.0.1 + convert-source-map: ^1.6.0 + source-map: ^0.7.3 + checksum: 54ce92bec2727879626f623d02c8d193f0c7e919941fa373ec135189a8382265117f5316ea317a1e12a5f9c13d84d8449052a731fe3306fa4beaafbfa4cab229 + languageName: node + linkType: hard + +"value-equal@npm:^1.0.1": + version: 1.0.1 + resolution: "value-equal@npm:1.0.1" + checksum: bb7ae1facc76b5cf8071aeb6c13d284d023fdb370478d10a5d64508e0e6e53bb459c4bbe34258df29d82e6f561f874f0105eba38de0e61fe9edd0bdce07a77a2 + languageName: node + linkType: hard + +"vary@npm:~1.1.2": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: ae0123222c6df65b437669d63dfa8c36cee20a504101b2fcd97b8bf76f91259c17f9f2b4d70a1e3c6bbcee7f51b28392833adb6b2770b23b01abec84e369660b + languageName: node + linkType: hard + +"verror@npm:1.10.0": + version: 1.10.0 + resolution: "verror@npm:1.10.0" + dependencies: + assert-plus: ^1.0.0 + core-util-is: 1.0.2 + extsprintf: ^1.2.0 + checksum: c431df0bedf2088b227a4e051e0ff4ca54df2c114096b0c01e1cbaadb021c30a04d7dd5b41ab277bcd51246ca135bf931d4c4c796ecae7a4fef6d744ecef36ea + languageName: node + linkType: hard + +"void-elements@npm:3.1.0": + version: 3.1.0 + resolution: "void-elements@npm:3.1.0" + checksum: 0390f818107fa8fce55bb0a5c3f661056001c1d5a2a48c28d582d4d847347c2ab5b7f8272314cac58acf62345126b6b09bea623a185935f6b1c3bbce0dfd7f7f + languageName: node + linkType: hard + +"w3c-hr-time@npm:^1.0.2": + version: 1.0.2 + resolution: "w3c-hr-time@npm:1.0.2" + dependencies: + browser-process-hrtime: ^1.0.0 + checksum: ec3c2dacbf8050d917bbf89537a101a08c2e333b4c19155f7d3bedde43529d4339db6b3d049d9610789cb915f9515f8be037e0c54c079e9d4735c50b37ed52b9 + languageName: node + linkType: hard + +"w3c-xmlserializer@npm:^2.0.0": + version: 2.0.0 + resolution: "w3c-xmlserializer@npm:2.0.0" + dependencies: + xml-name-validator: ^3.0.0 + checksum: ae25c51cf71f1fb2516df1ab33a481f83461a117565b95e3d0927432522323f93b1b2846cbb60196d337970c421adb604fc2d0d180c6a47a839da01db5b9973b + languageName: node + linkType: hard + +"wait-on@npm:7.0.1": + version: 7.0.1 + resolution: "wait-on@npm:7.0.1" + dependencies: + axios: ^0.27.2 + joi: ^17.7.0 + lodash: ^4.17.21 + minimist: ^1.2.7 + rxjs: ^7.8.0 + bin: + wait-on: bin/wait-on + checksum: 1e8a17d8ee6436f71d3ab82781ce31267481fcd7bbccde49b0f8124871e6e40a1acac3401f04f775ba6203853a5813352fa131620fc139914351f3b2894d573f + languageName: node + linkType: hard + +"walker@npm:^1.0.7": + version: 1.0.8 + resolution: "walker@npm:1.0.8" + dependencies: + makeerror: 1.0.12 + checksum: ad7a257ea1e662e57ef2e018f97b3c02a7240ad5093c392186ce0bcf1f1a60bbadd520d073b9beb921ed99f64f065efb63dfc8eec689a80e569f93c1c5d5e16c + languageName: node + linkType: hard + +"watchpack@npm:^2.4.0": + version: 2.4.0 + resolution: "watchpack@npm:2.4.0" + dependencies: + glob-to-regexp: ^0.4.1 + graceful-fs: ^4.1.2 + checksum: 23d4bc58634dbe13b86093e01c6a68d8096028b664ab7139d58f0c37d962d549a940e98f2f201cecdabd6f9c340338dc73ef8bf094a2249ef582f35183d1a131 + languageName: node + linkType: hard + +"wbuf@npm:^1.1.0, wbuf@npm:^1.7.3": + version: 1.7.3 + resolution: "wbuf@npm:1.7.3" + dependencies: + minimalistic-assert: ^1.0.0 + checksum: 2abc306c96930b757972a1c4650eb6b25b5d99f24088714957f88629e137db569368c5de0e57986c89ea70db2f1df9bba11a87cb6d0c8694b6f53a0159fab3bf + languageName: node + linkType: hard + +"webidl-conversions@npm:^3.0.0": + version: 3.0.1 + resolution: "webidl-conversions@npm:3.0.1" + checksum: c92a0a6ab95314bde9c32e1d0a6dfac83b578f8fa5f21e675bc2706ed6981bc26b7eb7e6a1fab158e5ce4adf9caa4a0aee49a52505d4d13c7be545f15021b17c + languageName: node + linkType: hard + +"webidl-conversions@npm:^4.0.2": + version: 4.0.2 + resolution: "webidl-conversions@npm:4.0.2" + checksum: c93d8dfe908a0140a4ae9c0ebc87a33805b416a33ee638a605b551523eec94a9632165e54632f6d57a39c5f948c4bab10e0e066525e9a4b87a79f0d04fbca374 + languageName: node + linkType: hard + +"webidl-conversions@npm:^5.0.0": + version: 5.0.0 + resolution: "webidl-conversions@npm:5.0.0" + checksum: ccf1ec2ca7c0b5671e5440ace4a66806ae09c49016ab821481bec0c05b1b82695082dc0a27d1fe9d804d475a408ba0c691e6803fd21be608e710955d4589cd69 + languageName: node + linkType: hard + +"webidl-conversions@npm:^6.1.0": + version: 6.1.0 + resolution: "webidl-conversions@npm:6.1.0" + checksum: 1f526507aa491f972a0c1409d07f8444e1d28778dfa269a9971f2e157182f3d496dc33296e4ed45b157fdb3bf535bb90c90bf10c50dcf1dd6caacb2a34cc84fb + languageName: node + linkType: hard + +"webpack-dev-middleware@npm:^5.3.1": + version: 5.3.4 + resolution: "webpack-dev-middleware@npm:5.3.4" + dependencies: + colorette: ^2.0.10 + memfs: ^3.4.3 + mime-types: ^2.1.31 + range-parser: ^1.2.1 + schema-utils: ^4.0.0 + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + checksum: 90cf3e27d0714c1a745454a1794f491b7076434939340605b9ee8718ba2b85385b120939754e9fdbd6569811e749dee53eec319e0d600e70e0b0baffd8e3fb13 + languageName: node + linkType: hard + +"webpack-dev-server@npm:^4.6.0": + version: 4.11.1 + resolution: "webpack-dev-server@npm:4.11.1" + 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/serve-static": ^1.13.10 + "@types/sockjs": ^0.3.33 + "@types/ws": ^8.5.1 + ansi-html-community: ^0.0.8 + bonjour-service: ^1.0.11 + chokidar: ^3.5.3 + colorette: ^2.0.10 + compression: ^1.7.4 + connect-history-api-fallback: ^2.0.0 + default-gateway: ^6.0.3 + express: ^4.17.3 + graceful-fs: ^4.2.6 + html-entities: ^2.3.2 + http-proxy-middleware: ^2.0.3 + ipaddr.js: ^2.0.1 + open: ^8.0.9 + p-retry: ^4.5.0 + rimraf: ^3.0.2 + schema-utils: ^4.0.0 + selfsigned: ^2.1.1 + serve-index: ^1.9.1 + sockjs: ^0.3.24 + spdy: ^4.0.2 + webpack-dev-middleware: ^5.3.1 + ws: ^8.4.2 + peerDependencies: + webpack: ^4.37.0 || ^5.0.0 + peerDependenciesMeta: + webpack-cli: + optional: true + bin: + webpack-dev-server: bin/webpack-dev-server.js + checksum: b7601a39ee0f413988259e29a36835b0a68522cfaa161de5b7ec99b3399acdd99d44189add4aaf4a5191258bb130f9cf3e68919324a1955c7557f5fe6ab0d96c + languageName: node + linkType: hard + +"webpack-manifest-plugin@npm:^4.0.2": + version: 4.1.1 + resolution: "webpack-manifest-plugin@npm:4.1.1" + dependencies: + tapable: ^2.0.0 + webpack-sources: ^2.2.0 + peerDependencies: + webpack: ^4.44.2 || ^5.47.0 + checksum: 426982030d3b0ef26432d98960ee1fa33889d8f0ed79b3d2c8e37be9b4e4beba7524c60631297ea557c642a340b76d70b0eb6a1e08b86a769409037185795038 + languageName: node + linkType: hard + +"webpack-merge@npm:^5.8.0": + version: 5.8.0 + resolution: "webpack-merge@npm:5.8.0" + dependencies: + clone-deep: ^4.0.1 + wildcard: ^2.0.0 + checksum: 88786ab91013f1bd2a683834ff381be81c245a4b0f63304a5103e90f6653f44dab496a0768287f8531761f8ad957d1f9f3ccb2cb55df0de1bd9ee343e079da26 + languageName: node + linkType: hard + +"webpack-sources@npm:^1.4.3": + version: 1.4.3 + resolution: "webpack-sources@npm:1.4.3" + dependencies: + source-list-map: ^2.0.0 + source-map: ~0.6.1 + checksum: 37463dad8d08114930f4bc4882a9602941f07c9f0efa9b6bc78738cd936275b990a596d801ef450d022bb005b109b9f451dd087db2f3c9baf53e8e22cf388f79 + languageName: node + linkType: hard + +"webpack-sources@npm:^2.2.0": + version: 2.3.1 + resolution: "webpack-sources@npm:2.3.1" + dependencies: + source-list-map: ^2.0.1 + source-map: ^0.6.1 + checksum: 6fd67f2274a84c5f51ad89767112ec8b47727134bf0f2ba0cff458c970f18966939a24128bdbddba621cd66eeb2bef0552642a9333cd8e54514f7b2a71776346 + languageName: node + linkType: hard + +"webpack-sources@npm:^3.2.3": + version: 3.2.3 + resolution: "webpack-sources@npm:3.2.3" + checksum: 989e401b9fe3536529e2a99dac8c1bdc50e3a0a2c8669cbafad31271eadd994bc9405f88a3039cd2e29db5e6d9d0926ceb7a1a4e7409ece021fe79c37d9c4607 + languageName: node + linkType: hard + +"webpack@npm:^5.64.4": + version: 5.76.1 + resolution: "webpack@npm:5.76.1" + dependencies: + "@types/eslint-scope": ^3.7.3 + "@types/estree": ^0.0.51 + "@webassemblyjs/ast": 1.11.1 + "@webassemblyjs/wasm-edit": 1.11.1 + "@webassemblyjs/wasm-parser": 1.11.1 + acorn: ^8.7.1 + acorn-import-assertions: ^1.7.6 + browserslist: ^4.14.5 + chrome-trace-event: ^1.0.2 + enhanced-resolve: ^5.10.0 + es-module-lexer: ^0.9.0 + eslint-scope: 5.1.1 + events: ^3.2.0 + glob-to-regexp: ^0.4.1 + graceful-fs: ^4.2.9 + json-parse-even-better-errors: ^2.3.1 + loader-runner: ^4.2.0 + mime-types: ^2.1.27 + neo-async: ^2.6.2 + schema-utils: ^3.1.0 + tapable: ^2.1.1 + terser-webpack-plugin: ^5.1.3 + watchpack: ^2.4.0 + webpack-sources: ^3.2.3 + peerDependenciesMeta: + webpack-cli: + optional: true + bin: + webpack: bin/webpack.js + checksum: b01fe0bc2dbca0e10d290ddb0bf81e807a031de48028176e2b21afd696b4d3f25ab9accdad888ef4a1f7c7f4d41f13d5bf2395b7653fdf3e5e3dafa54e56dab2 + languageName: node + linkType: hard + +"websocket-driver@npm:>=0.5.1, websocket-driver@npm:^0.7.4": + version: 0.7.4 + resolution: "websocket-driver@npm:0.7.4" + dependencies: + http-parser-js: ">=0.5.1" + safe-buffer: ">=5.1.0" + websocket-extensions: ">=0.1.1" + checksum: fffe5a33fe8eceafd21d2a065661d09e38b93877eae1de6ab5d7d2734c6ed243973beae10ae48c6613cfd675f200e5a058d1e3531bc9e6c5d4f1396ff1f0bfb9 + languageName: node + linkType: hard + +"websocket-extensions@npm:>=0.1.1": + version: 0.1.4 + resolution: "websocket-extensions@npm:0.1.4" + checksum: 5976835e68a86afcd64c7a9762ed85f2f27d48c488c707e67ba85e717b90fa066b98ab33c744d64255c9622d349eedecf728e65a5f921da71b58d0e9591b9038 + languageName: node + linkType: hard + +"whatwg-encoding@npm:^1.0.5": + version: 1.0.5 + resolution: "whatwg-encoding@npm:1.0.5" + dependencies: + iconv-lite: 0.4.24 + checksum: 5be4efe111dce29ddee3448d3915477fcc3b28f991d9cf1300b4e50d6d189010d47bca2f51140a844cf9b726e8f066f4aee72a04d687bfe4f2ee2767b2f5b1e6 + languageName: node + linkType: hard + +"whatwg-fetch@npm:^3.6.2": + version: 3.6.2 + resolution: "whatwg-fetch@npm:3.6.2" + checksum: ee976b7249e7791edb0d0a62cd806b29006ad7ec3a3d89145921ad8c00a3a67e4be8f3fb3ec6bc7b58498724fd568d11aeeeea1f7827e7e1e5eae6c8a275afed + languageName: node + linkType: hard + +"whatwg-mimetype@npm:^2.3.0": + version: 2.3.0 + resolution: "whatwg-mimetype@npm:2.3.0" + checksum: 23eb885940bcbcca4ff841c40a78e9cbb893ec42743993a42bf7aed16085b048b44b06f3402018931687153550f9a32d259dfa524e4f03577ab898b6965e5383 + languageName: node + linkType: hard + +"whatwg-url@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-url@npm:5.0.0" + dependencies: + tr46: ~0.0.3 + webidl-conversions: ^3.0.0 + checksum: b8daed4ad3356cc4899048a15b2c143a9aed0dfae1f611ebd55073310c7b910f522ad75d727346ad64203d7e6c79ef25eafd465f4d12775ca44b90fa82ed9e2c + languageName: node + linkType: hard + +"whatwg-url@npm:^7.0.0": + version: 7.1.0 + resolution: "whatwg-url@npm:7.1.0" + dependencies: + lodash.sortby: ^4.7.0 + tr46: ^1.0.1 + webidl-conversions: ^4.0.2 + checksum: fecb07c87290b47d2ec2fb6d6ca26daad3c9e211e0e531dd7566e7ff95b5b3525a57d4f32640ad4adf057717e0c215731db842ad761e61d947e81010e05cf5fd + languageName: node + linkType: hard + +"whatwg-url@npm:^8.0.0, whatwg-url@npm:^8.5.0": + version: 8.7.0 + resolution: "whatwg-url@npm:8.7.0" + dependencies: + lodash: ^4.7.0 + tr46: ^2.1.0 + webidl-conversions: ^6.1.0 + checksum: a87abcc6cefcece5311eb642858c8fdb234e51ec74196bfacf8def2edae1bfbffdf6acb251646ed6301f8cee44262642d8769c707256125a91387e33f405dd1e + languageName: node + linkType: hard + +"which-boxed-primitive@npm:^1.0.2": + version: 1.0.2 + resolution: "which-boxed-primitive@npm:1.0.2" + dependencies: + is-bigint: ^1.0.1 + is-boolean-object: ^1.1.0 + is-number-object: ^1.0.4 + is-string: ^1.0.5 + is-symbol: ^1.0.3 + checksum: 53ce774c7379071729533922adcca47220228405e1895f26673bbd71bdf7fb09bee38c1d6399395927c6289476b5ae0629863427fd151491b71c4b6cb04f3a5e + languageName: node + linkType: hard + +"which-collection@npm:^1.0.1": + version: 1.0.1 + resolution: "which-collection@npm:1.0.1" + dependencies: + is-map: ^2.0.1 + is-set: ^2.0.1 + is-weakmap: ^2.0.1 + is-weakset: ^2.0.1 + checksum: c815bbd163107ef9cb84f135e6f34453eaf4cca994e7ba85ddb0d27cea724c623fae2a473ceccfd5549c53cc65a5d82692de418166df3f858e1e5dc60818581c + languageName: node + linkType: hard + +"which-typed-array@npm:^1.1.9": + version: 1.1.9 + resolution: "which-typed-array@npm:1.1.9" + dependencies: + available-typed-arrays: ^1.0.5 + call-bind: ^1.0.2 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-tostringtag: ^1.0.0 + is-typed-array: ^1.1.10 + checksum: fe0178ca44c57699ca2c0e657b64eaa8d2db2372a4e2851184f568f98c478ae3dc3fdb5f7e46c384487046b0cf9e23241423242b277e03e8ba3dabc7c84c98ef + languageName: node + linkType: hard + +"which@npm:^1.3.1": + version: 1.3.1 + resolution: "which@npm:1.3.1" + dependencies: + isexe: ^2.0.0 + bin: + which: ./bin/which + checksum: f2e185c6242244b8426c9df1510e86629192d93c1a986a7d2a591f2c24869e7ffd03d6dac07ca863b2e4c06f59a4cc9916c585b72ee9fa1aa609d0124df15e04 + languageName: node + linkType: hard + +"which@npm:^2.0.1, which@npm:^2.0.2": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: ^2.0.0 + bin: + node-which: ./bin/node-which + checksum: 1a5c563d3c1b52d5f893c8b61afe11abc3bab4afac492e8da5bde69d550de701cf9806235f20a47b5c8fa8a1d6a9135841de2596535e998027a54589000e66d1 + languageName: node + linkType: hard + +"wide-align@npm:^1.1.5": + version: 1.1.5 + resolution: "wide-align@npm:1.1.5" + dependencies: + string-width: ^1.0.2 || 2 || 3 || 4 + checksum: d5fc37cd561f9daee3c80e03b92ed3e84d80dde3365a8767263d03dacfc8fa06b065ffe1df00d8c2a09f731482fcacae745abfbb478d4af36d0a891fad4834d3 + languageName: node + linkType: hard + +"widest-line@npm:^4.0.1": + version: 4.0.1 + resolution: "widest-line@npm:4.0.1" + dependencies: + string-width: ^5.0.1 + checksum: 64c48cf27171221be5f86fc54b94dd29879165bdff1a7aa92dde723d9a8c99fb108312768a5d62c8c2b80b701fa27bbd36a1ddc58367585cd45c0db7920a0cba + languageName: node + linkType: hard + +"wildcard@npm:^2.0.0": + version: 2.0.0 + resolution: "wildcard@npm:2.0.0" + checksum: 1f4fe4c03dfc492777c60f795bbba597ac78794f1b650d68f398fbee9adb765367c516ebd4220889b6a81e9626e7228bbe0d66237abb311573c2ee1f4902a5ad + languageName: node + linkType: hard + +"word-wrap@npm:~1.2.3": + version: 1.2.4 + resolution: "word-wrap@npm:1.2.4" + checksum: 8f1f2e0a397c0e074ca225ba9f67baa23f99293bc064e31355d426ae91b8b3f6b5f6c1fc9ae5e9141178bb362d563f55e62fd8d5c31f2a77e3ade56cb3e35bd1 + languageName: node + linkType: hard + +"workbox-background-sync@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-background-sync@npm:6.5.4" + dependencies: + idb: ^7.0.1 + workbox-core: 6.5.4 + checksum: 60ac80275cc9083b82eb53b6034e3d555d15146927a21c6017329e2b5de12d802619cc2cc6cf023f534a1f1a51671d89cdb59b26a80587d5391e8dc4b7f7dd1d + languageName: node + linkType: hard + +"workbox-broadcast-update@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-broadcast-update@npm:6.5.4" + dependencies: + workbox-core: 6.5.4 + checksum: 63cbab2012456871ffeae401e10b16668a0654fa3fa311743cf14e05b8719b797ac3afb47dc8955d87e24f0f1199a547b090bcfdbddd67191b07697d24ac5746 + languageName: node + linkType: hard + +"workbox-build@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-build@npm:6.5.4" + dependencies: + "@apideck/better-ajv-errors": ^0.3.1 + "@babel/core": ^7.11.1 + "@babel/preset-env": ^7.11.0 + "@babel/runtime": ^7.11.2 + "@rollup/plugin-babel": ^5.2.0 + "@rollup/plugin-node-resolve": ^11.2.1 + "@rollup/plugin-replace": ^2.4.1 + "@surma/rollup-plugin-off-main-thread": ^2.2.3 + ajv: ^8.6.0 + common-tags: ^1.8.0 + fast-json-stable-stringify: ^2.1.0 + fs-extra: ^9.0.1 + glob: ^7.1.6 + lodash: ^4.17.20 + pretty-bytes: ^5.3.0 + rollup: ^2.43.1 + rollup-plugin-terser: ^7.0.0 + source-map: ^0.8.0-beta.0 + stringify-object: ^3.3.0 + strip-comments: ^2.0.1 + tempy: ^0.6.0 + upath: ^1.2.0 + workbox-background-sync: 6.5.4 + workbox-broadcast-update: 6.5.4 + workbox-cacheable-response: 6.5.4 + workbox-core: 6.5.4 + workbox-expiration: 6.5.4 + workbox-google-analytics: 6.5.4 + workbox-navigation-preload: 6.5.4 + workbox-precaching: 6.5.4 + workbox-range-requests: 6.5.4 + workbox-recipes: 6.5.4 + workbox-routing: 6.5.4 + workbox-strategies: 6.5.4 + workbox-streams: 6.5.4 + workbox-sw: 6.5.4 + workbox-window: 6.5.4 + checksum: 7336bbab4ce8e6e43a17873beedf7360ec32e72310306c670cd4d9ebd7e5a6a729257b2806e63830136a9bf01955632c96b27edf7a00d52c7744dbe875cca6c1 + languageName: node + linkType: hard + +"workbox-cacheable-response@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-cacheable-response@npm:6.5.4" + dependencies: + workbox-core: 6.5.4 + checksum: f7545b71c1505d6f56f4ba1191989ea7af7119e67fa4eb414d80603221acd0fa31362014106c1df9b9ea0e28bdcf1e2b440859acab06a75e38e978a0d1c2e489 + languageName: node + linkType: hard + +"workbox-core@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-core@npm:6.5.4" + checksum: d973cc6c1c5fdbde7f6642632384c2e0de48f08228eb234db2c97a18a7e5422b483005767e7b447ea774abc0772dfc1edef2ef2b5df174df4d40ae61d4c49719 + languageName: node + linkType: hard + +"workbox-expiration@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-expiration@npm:6.5.4" + dependencies: + idb: ^7.0.1 + workbox-core: 6.5.4 + checksum: 4b012b69ceafeb5afb3dd6c5c9abe6d55f2eb70666ab603bd78ff839f602336e7493990f729d507ded1fa505b852a5f9135f63afb75b9554c8f948e571143fce + languageName: node + linkType: hard + +"workbox-google-analytics@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-google-analytics@npm:6.5.4" + dependencies: + workbox-background-sync: 6.5.4 + workbox-core: 6.5.4 + workbox-routing: 6.5.4 + workbox-strategies: 6.5.4 + checksum: fcce5e313780cb4f74ac962c4809fe04f9a93d3d3905d282552a2cbe6d5c6c1b8744641fe7c57d1e4b62754b90c56155e97e589712f99f6a4cab750731d60b93 + languageName: node + linkType: hard + +"workbox-navigation-preload@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-navigation-preload@npm:6.5.4" + dependencies: + workbox-core: 6.5.4 + checksum: c8c341b799f328bb294de8eb9e331a55501d495153237e4ddbaa08bf8630efa700621df5d81f08fb9bffc0f40ecd191a60581f72a3cd5cc72ed2e5baa318c63a + languageName: node + linkType: hard + +"workbox-precaching@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-precaching@npm:6.5.4" + dependencies: + workbox-core: 6.5.4 + workbox-routing: 6.5.4 + workbox-strategies: 6.5.4 + checksum: 15ef24ffb04edd13bcdfa6c4e7f64002551badce2d507031c343019b3bcdc569591fdff8f8e30cf1262d641d3eff611115bdda7b2ad0deb9d4ccef8f4be8bd20 + languageName: node + linkType: hard + +"workbox-range-requests@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-range-requests@npm:6.5.4" + dependencies: + workbox-core: 6.5.4 + checksum: 50f144ced7af7db77b3c64c06c0f9924db5b8573ff2c50b3899fc22c4a360baaf6b332e65f47cf812adfc9dec882a94556fed1cf90ae4ef20b645caa03d1149e + languageName: node + linkType: hard + +"workbox-recipes@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-recipes@npm:6.5.4" + dependencies: + workbox-cacheable-response: 6.5.4 + workbox-core: 6.5.4 + workbox-expiration: 6.5.4 + workbox-precaching: 6.5.4 + workbox-routing: 6.5.4 + workbox-strategies: 6.5.4 + checksum: 397befeb7c4c63adb0eb1913934ecaf496846844124044f0b39348288ad5950ffb45eb488cfef2504adeafe28a51cdbcc21af2a234813d81ab3da0949942c265 + languageName: node + linkType: hard + +"workbox-routing@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-routing@npm:6.5.4" + dependencies: + workbox-core: 6.5.4 + checksum: 7198c50b9016d3cea0e5b51512d66f5813d6e6ad5e99c201435d6c0ab3baee1c90aa2bbdd72dd954f439267b6e6196fb04ec96e62347e6c89385db6c1a4dec79 + languageName: node + linkType: hard + +"workbox-strategies@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-strategies@npm:6.5.4" + dependencies: + workbox-core: 6.5.4 + checksum: 52134ecd6c05f4edd31e7b022b33a91b7b59c215bfdfb987bc0f10be02fea4d4e6385a9638a2303ba336190c5d28f9721182cd78a6779b9c817a66ec12cb1c6b + languageName: node + linkType: hard + +"workbox-streams@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-streams@npm:6.5.4" + dependencies: + workbox-core: 6.5.4 + workbox-routing: 6.5.4 + checksum: efd6917ead915011be2b25dc3ebbb9d051dbd10ba2d91cdaec36ca742360e2c33627564653fc40f336dee874d501e94bcc4a25d1b65eaf5a6ee5f1a8b894af44 + languageName: node + linkType: hard + +"workbox-sw@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-sw@npm:6.5.4" + checksum: b95c76a74b84ff268ef7691447125697f4de85b076ebc33c9545fb7532b020b6f66b37f7a4bedbc21ab45473d1109337a5f037c45b3d99126ae8f5eeb898a687 + languageName: node + linkType: hard + +"workbox-webpack-plugin@npm:^6.4.1": + version: 6.5.4 + resolution: "workbox-webpack-plugin@npm:6.5.4" + dependencies: + fast-json-stable-stringify: ^2.1.0 + pretty-bytes: ^5.4.1 + upath: ^1.2.0 + webpack-sources: ^1.4.3 + workbox-build: 6.5.4 + peerDependencies: + webpack: ^4.4.0 || ^5.9.0 + checksum: d42ab213994767863711d54b6e2ea277839bd731430f7f3f826ccbb8927c6e9e42e2bea6316358d715a8f90f445ce2c094a46018c8a3b3e7035acc7b2822574e + languageName: node + linkType: hard + +"workbox-window@npm:6.5.4": + version: 6.5.4 + resolution: "workbox-window@npm:6.5.4" + dependencies: + "@types/trusted-types": ^2.0.2 + workbox-core: 6.5.4 + checksum: bc43c8d31908ab564d740eb1041180c0b0ca4d1f0a3ccde59c5764a8f96d7b08edb7df975360fd37c2bec9f3f57ca9de6c7e34fd252aa1a4a075b5b002f74f60 + languageName: node + linkType: hard + +"wrap-ansi@npm:^6.2.0": + version: 6.2.0 + resolution: "wrap-ansi@npm:6.2.0" + dependencies: + ansi-styles: ^4.0.0 + string-width: ^4.1.0 + strip-ansi: ^6.0.0 + checksum: 6cd96a410161ff617b63581a08376f0cb9162375adeb7956e10c8cd397821f7eb2a6de24eb22a0b28401300bf228c86e50617cd568209b5f6775b93c97d2fe3a + languageName: node + linkType: hard + +"wrap-ansi@npm:^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: ^4.0.0 + string-width: ^4.1.0 + strip-ansi: ^6.0.0 + checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.0.1, wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: ^6.1.0 + string-width: ^5.0.1 + strip-ansi: ^7.0.1 + checksum: 371733296dc2d616900ce15a0049dca0ef67597d6394c57347ba334393599e800bab03c41d4d45221b6bc967b8c453ec3ae4749eff3894202d16800fdfe0e238 + languageName: node + linkType: hard + +"wrappy@npm:1": + version: 1.0.2 + resolution: "wrappy@npm:1.0.2" + checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 + languageName: node + linkType: hard + +"write-file-atomic@npm:^3.0.0": + version: 3.0.3 + resolution: "write-file-atomic@npm:3.0.3" + dependencies: + imurmurhash: ^0.1.4 + is-typedarray: ^1.0.0 + signal-exit: ^3.0.2 + typedarray-to-buffer: ^3.1.5 + checksum: c55b24617cc61c3a4379f425fc62a386cc51916a9b9d993f39734d005a09d5a4bb748bc251f1304e7abd71d0a26d339996c275955f527a131b1dcded67878280 + languageName: node + linkType: hard + +"ws@npm:^7.4.6": + version: 7.5.10 + resolution: "ws@npm:7.5.10" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: f9bb062abf54cc8f02d94ca86dcd349c3945d63851f5d07a3a61c2fcb755b15a88e943a63cf580cbdb5b74436d67ef6b67f745b8f7c0814e411379138e1863cb + languageName: node + linkType: hard + +"ws@npm:^8.4.2": + version: 8.12.0 + resolution: "ws@npm:8.12.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 818ff3f8749c172a95a114cceb8b89cedd27e43a82d65c7ad0f7882b1e96a2ee6709e3746a903c3fa88beec0c8bae9a9fcd75f20858b32a166dfb7519316a5d7 + languageName: node + linkType: hard + +"xml-name-validator@npm:^3.0.0": + version: 3.0.0 + resolution: "xml-name-validator@npm:3.0.0" + checksum: b3ac459afed783c285bb98e4960bd1f3ba12754fd4f2320efa0f9181ca28928c53cc75ca660d15d205e81f92304419afe94c531c7cfb3e0649aa6d140d53ecb0 + languageName: node + linkType: hard + +"xmlchars@npm:^2.2.0": + version: 2.2.0 + resolution: "xmlchars@npm:2.2.0" + checksum: 8c70ac94070ccca03f47a81fcce3b271bd1f37a591bf5424e787ae313fcb9c212f5f6786e1fa82076a2c632c0141552babcd85698c437506dfa6ae2d58723062 + languageName: node + linkType: hard + +"xtend@npm:^4.0.2": + version: 4.0.2 + resolution: "xtend@npm:4.0.2" + checksum: ac5dfa738b21f6e7f0dd6e65e1b3155036d68104e67e5d5d1bde74892e327d7e5636a076f625599dc394330a731861e87343ff184b0047fef1360a7ec0a5a36a + languageName: node + linkType: hard + +"y18n@npm:^5.0.5": + version: 5.0.8 + resolution: "y18n@npm:5.0.8" + checksum: 54f0fb95621ee60898a38c572c515659e51cc9d9f787fb109cef6fde4befbe1c4602dc999d30110feee37456ad0f1660fa2edcfde6a9a740f86a290999550d30 + languageName: node + linkType: hard + +"yallist@npm:^3.0.2": + version: 3.1.1 + resolution: "yallist@npm:3.1.1" + checksum: 48f7bb00dc19fc635a13a39fe547f527b10c9290e7b3e836b9a8f1ca04d4d342e85714416b3c2ab74949c9c66f9cebb0473e6bc353b79035356103b47641285d + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5 + languageName: node + linkType: hard + +"yaml@npm:2.3.1": + version: 2.3.1 + resolution: "yaml@npm:2.3.1" + checksum: 2c7bc9a7cd4c9f40d3b0b0a98e370781b68b8b7c4515720869aced2b00d92f5da1762b4ffa947f9e795d6cd6b19f410bd4d15fdd38aca7bd96df59bd9486fb54 + languageName: node + linkType: hard + +"yaml@npm:^1.10.0, yaml@npm:^1.10.2, yaml@npm:^1.7.2": + version: 1.10.2 + resolution: "yaml@npm:1.10.2" + checksum: ce4ada136e8a78a0b08dc10b4b900936912d15de59905b2bf415b4d33c63df1d555d23acb2a41b23cf9fb5da41c256441afca3d6509de7247daa062fd2c5ea5f + languageName: node + linkType: hard + +"yargs-parser@npm:^20.2.2": + version: 20.2.9 + resolution: "yargs-parser@npm:20.2.9" + checksum: 8bb69015f2b0ff9e17b2c8e6bfe224ab463dd00ca211eece72a4cd8a906224d2703fb8a326d36fdd0e68701e201b2a60ed7cf81ce0fd9b3799f9fe7745977ae3 + languageName: node + linkType: hard + +"yargs@npm:^16.2.0": + version: 16.2.0 + resolution: "yargs@npm:16.2.0" + 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 + checksum: b14afbb51e3251a204d81937c86a7e9d4bdbf9a2bcee38226c900d00f522969ab675703bee2a6f99f8e20103f608382936034e64d921b74df82b63c07c5e8f59 + languageName: node + linkType: hard + +"yauzl@npm:^2.10.0": + version: 2.10.0 + resolution: "yauzl@npm:2.10.0" + dependencies: + buffer-crc32: ~0.2.3 + fd-slicer: ~1.1.0 + checksum: 7f21fe0bbad6e2cb130044a5d1d0d5a0e5bf3d8d4f8c4e6ee12163ce798fee3de7388d22a7a0907f563ac5f9d40f8699a223d3d5c1718da90b0156da6904022b + languageName: node + linkType: hard + +"yn@npm:3.1.1": + version: 3.1.1 + resolution: "yn@npm:3.1.1" + checksum: 2c487b0e149e746ef48cda9f8bad10fc83693cd69d7f9dcd8be4214e985de33a29c9e24f3c0d6bcf2288427040a8947406ab27f7af67ee9456e6b84854f02dd6 + languageName: node + linkType: hard + +"yocto-queue@npm:^0.1.0": + version: 0.1.0 + resolution: "yocto-queue@npm:0.1.0" + checksum: f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700 + languageName: node + linkType: hard