diff --git a/.cookiecutter/includes/.github/workflows/environments.json b/.cookiecutter/includes/.github/workflows/environments.json index c6b2d513e5f..b06bae38aaa 100644 --- a/.cookiecutter/includes/.github/workflows/environments.json +++ b/.cookiecutter/includes/.github/workflows/environments.json @@ -1,20 +1,20 @@ { - "qa": { - "github_environment_name": "QA", - "github_environment_url": "https://qa.hypothes.is/search", + "staging": { + "github_environment_name": "Staging", + "github_environment_url": "https://staging.hypothes.is/search", "aws_region": "us-west-1", "elasticbeanstalk_application": "h", - "elasticbeanstalk_environment": "qa" + "elasticbeanstalk_environment": "staging" }, - "qa_websocket": { - "github_environment_name": "QA (WebSocket)", - "github_environment_url": "https://qa.hypothes.is/docs/help", + "staging_websocket": { + "github_environment_name": "Staging (WebSocket)", + "github_environment_url": "https://staging.hypothes.is/docs/help", "aws_region": "us-west-1", "elasticbeanstalk_application": "h-websocket", - "elasticbeanstalk_environment": "qa" + "elasticbeanstalk_environment": "staging" }, "production": { - "needs": ["qa", "qa_websocket"], + "needs": ["staging", "staging_websocket"], "github_environment_name": "Production", "github_environment_url": "https://hypothes.is/search", "aws_region": "us-west-1", @@ -22,7 +22,7 @@ "elasticbeanstalk_environment": "prod" }, "production_websocket": { - "needs": ["qa", "qa_websocket"], + "needs": ["staging", "staging_websocket"], "github_environment_name": "Production (WebSocket)", "github_environment_url": "https://hypothes.is/docs/help", "aws_region": "us-west-1", @@ -30,7 +30,7 @@ "elasticbeanstalk_environment": "prod" }, "production_canada": { - "needs": ["qa", "qa_websocket"], + "needs": ["staging", "staging_websocket"], "github_environment_name": "Production (Canada)", "github_environment_url": "https://ca.hypothes.is/search", "aws_region": "ca-central-1", diff --git a/.coveragerc b/.coveragerc index 10e7ca73018..715ffd61209 100644 --- a/.coveragerc +++ b/.coveragerc @@ -3,14 +3,17 @@ branch = True parallel = True source = h - tests/h + tests/unit omit = h/debug.py h/migrations/* h/cli/* + h/__main__.py + h/pshell.py [report] show_missing = True precision = 2 -fail_under = 98.26 +fail_under = 100 + skip_covered = True diff --git a/.eslintrc b/.eslintrc index e00669670d0..c99f78f2eab 100644 --- a/.eslintrc +++ b/.eslintrc @@ -6,9 +6,9 @@ }, "overrides": [ { - "files": ["*.mjs"], + "files": ["*.js"], + "excludedFiles": ["h/**"], "env": { "node": true }, - "parserOptions": { "sourceType": "module" } } ] } diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1d900fc314a..d335678149c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,17 +1,15 @@ version: 2 updates: - - package-ecosystem: pip directory: "/" schedule: - interval: daily - time: "10:00" + interval: weekly open-pull-requests-limit: 10 - package-ecosystem: docker directory: "/" schedule: - interval: daily + interval: monthly open-pull-requests-limit: 10 ignore: # Only send PRs for patch versions of Python. @@ -22,5 +20,4 @@ updates: directory: "/" schedule: interval: monthly - time: "10:00" open-pull-requests-limit: 10 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index facc0794790..a244d13b17a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,76 +1,142 @@ -name: Continuous integration - +name: CI on: - workflow_dispatch: - pull_request: + push: paths-ignore: - '.cookiecutter/*' - - '.gitignore' - - 'HACKING.md' + - '.github/dependabot.yml' + - '.github/workflows/deploy.yml' + - '.github/workflows/redeploy.yml' + - 'bin/logger' + - 'conf/development.ini' + - 'production.ini' + - 'conf/supervisord*.conf' + - 'docs/*' + - 'requirements/*.in' + - 'requirements/dev.txt' + - '**/.gitignore' + - 'Dockerfile' - 'LICENSE' + - '*.md' + - 'docker-compose.yml' + workflow_dispatch: workflow_call: - -env: - TOX_PARALLEL_NO_SPINNER: 1 - PYTEST_ADDOPTS: --exitfirst - + schedule: + - cron: '0 1 * * *' jobs: - backend: - name: Backend + Format: runs-on: ubuntu-latest - + steps: + - uses: actions/checkout@v3 + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Cache the .tox dir + uses: actions/cache@v3 + with: + path: .tox + key: format-${{ runner.os }}-tox-${{ hashFiles('tox.ini') }}-${{ hashFiles('requirements/*') }} + restore-keys: | + format-${{ runner.os }}-tox- + - run: python -m pip install 'tox<4' + - run: tox -e checkformatting + Lint: + runs-on: ubuntu-latest-32-cores + steps: + - uses: actions/checkout@v3 + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Cache the .tox dir + uses: actions/cache@v3 + with: + path: .tox + key: lint-${{ runner.os }}-tox-${{ hashFiles('tox.ini') }}-${{ hashFiles('requirements/*') }} + restore-keys: | + lint-${{ runner.os }}-tox- + - run: python -m pip install 'tox<4' + - run: tox -e lint + Tests: + runs-on: ubuntu-latest-32-cores services: postgres: - image: postgres:11.5-alpine + image: postgres:15.6-alpine ports: - 5432:5432 - + env: + POSTGRES_HOST_AUTH_METHOD: trust + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 elasticsearch: image: hypothesis/elasticsearch:latest ports: - 9200:9200 env: discovery.type: single-node - steps: - - name: Checkout git repo - uses: actions/checkout@v3 - - - name: Setup python - uses: actions/setup-python@v4 - with: - python-version-file: '.python-version' - - - name: Update pip - run: python -m pip install --upgrade pip - - - name: Install tox - run: python -m pip install 'tox<4' - - - name: Create test databases - run: psql -U postgres -h localhost -p 5432 -c 'CREATE DATABASE htest' - - - name: Cache the .tox dir - uses: actions/cache@v3 - with: - path: | - .tox/lint - .tox/checkformatting - .tox/tests - .tox/coverage - key: ${{ runner.os }}-tox-backend-${{ hashFiles('tox.ini', 'requirements/**', 'setup.py', 'setup.cfg') }} - - name: Run tox - run: tox --parallel auto -e checkformatting,tests,coverage,lint - - functests: - name: Functional tests + - uses: actions/checkout@v3 + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Cache the .tox dir + uses: actions/cache@v3 + with: + path: .tox + key: tests-${{ runner.os }}-tox-${{ hashFiles('tox.ini') }}-${{ hashFiles('requirements/*') }} + restore-keys: | + tests-${{ runner.os }}-tox- + - name: Create test database + run: psql -U postgres -h localhost -p 5432 -c 'CREATE DATABASE h_tests' + - run: python -m pip install 'tox<4' + - run: tox -e tests + env: + COVERAGE_FILE: .coverage.${{ matrix.python-version }} + - name: Upload coverage file + uses: actions/upload-artifact@v3 + with: + name: coverage + path: .coverage.* + Coverage: + needs: tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Cache the .tox dir + uses: actions/cache@v3 + with: + path: .tox + key: coverage-${{ runner.os }}-tox-${{ hashFiles('tox.ini') }}-${{ hashFiles('requirements/*') }} + restore-keys: | + coverage-${{ runner.os }}-tox- + - name: Download coverage files + uses: actions/download-artifact@v3 + with: + name: coverage + - run: python -m pip install 'tox<4' + - run: tox -e coverage + Functests: runs-on: ubuntu-latest - services: postgres: - image: postgres:11.5-alpine + image: postgres:15.6-alpine ports: - 5432:5432 + env: + POSTGRES_HOST_AUTH_METHOD: trust + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 elasticsearch: image: hypothesis/elasticsearch:latest ports: @@ -78,71 +144,27 @@ jobs: env: discovery.type: single-node rabbitmq: - image: rabbitmq:3.6-management-alpine + image: rabbitmq:3.12-management-alpine ports: - 5672:5672 - - steps: - - name: Checkout git repo - uses: actions/checkout@v3 - - - name: Setup python - uses: actions/setup-python@v4 - with: - python-version-file: '.python-version' - - - name: Update pip - run: python -m pip install --upgrade pip - - - name: Install tox - run: python -m pip install 'tox<4' - - - name: Create test databases - run: psql -U postgres -h localhost -p 5432 -c 'CREATE DATABASE htest' - - - name: Cache the .tox dir - uses: actions/cache@v3 - with: - path: | - .tox/functests - key: ${{ runner.os }}-tox-functests-${{ hashFiles('tox.ini', 'requirements/**', 'setup.py', 'setup.cfg') }} - - - name: Cache the node_modules dir - uses: actions/cache@v3 - with: - path: node_modules - key: ${{ runner.os }}-node_modules-${{ hashFiles('package-lock.json') }} - - - name: npm install - run: npm install - - - name: gulp build - run: gulp build - - - name: Run tox - # Note we run the func tests backwards here to prove there are no order - # dependent tests - run: tox -e functests -- tests/functional --reverse - - frontend: - name: Frontend - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Cache the node_modules dir - uses: actions/cache@v3 - with: - path: node_modules - key: ${{ runner.os }}-node_modules-${{ hashFiles('package-lock.json') }} - - - name: Format - run: make frontend-checkformatting - - - name: Lint - run: make frontend-lint - - - name: Test - run: gulp test + - uses: actions/checkout@v3 + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Cache the .tox dir + uses: actions/cache@v3 + with: + path: .tox + key: functests-${{ runner.os }}-tox-${{ hashFiles('tox.ini') }}-${{ hashFiles('requirements/*') }} + restore-keys: | + functests-${{ runner.os }}-tox- + - name: Create test database + run: psql -U postgres -h localhost -p 5432 -c 'CREATE DATABASE h_functests' + - run: python -m pip install 'tox<4' + - run: yarn install --immutable + - run: yarn build + - run: tox -e functests + Frontend: + uses: ./.github/workflows/frontend.yml diff --git a/.github/workflows/data_tasks.yml b/.github/workflows/data_tasks.yml index 6bdb96f2e1b..9f534d2cff5 100644 --- a/.github/workflows/data_tasks.yml +++ b/.github/workflows/data_tasks.yml @@ -16,9 +16,9 @@ on: type: choice description: "The environment to target" required: true - default: 'qa' + default: 'staging' options: - - 'qa' + - 'staging' - 'prod' Region: type: choice @@ -53,7 +53,7 @@ jobs: with: App: ${{ github.event.repository.name }} Env: ${{ inputs.Environment }} - Timeout: 3600 + Timeout: 7200 Region: ${{ inputs.Region }} - Command: 'newrelic-admin run-program python bin/run_data_task.py --config-file conf/app.ini --task ${{ inputs.Task }}' + Command: 'newrelic-admin run-program python bin/run_data_task.py --config-file conf/production.ini --task ${{ inputs.Task }}' secrets: inherit diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b3561b0bf65..e20c551ed8a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -12,12 +12,12 @@ on: - '.github/*' - 'bin/create-testdb' - 'bin/install-python' - - 'conf/development-app.ini' + - 'conf/development.ini' - 'conf/supervisord-dev.conf' - 'conf/websocket-dev.ini' - 'docs/*' - 'requirements/*' - - '!requirements/requirements.txt' + - '!requirements/prod.txt' - 'tests/*' - '.coveragerc' - '.eslintrc' @@ -32,45 +32,41 @@ on: - 'setup.cfg' - 'tox.ini' jobs: - ci: - name: CI - uses: ./.github/workflows/ci.yml docker_hub: name: Docker Hub - needs: [ci] uses: hypothesis/workflows/.github/workflows/dockerhub.yml@main with: Application: hypothesis secrets: inherit - qa: - name: QA + staging: + name: Staging needs: [docker_hub] uses: hypothesis/workflows/.github/workflows/deploy.yml@main with: operation: deploy - github_environment_name: QA - github_environment_url: https://qa.hypothes.is/search + github_environment_name: Staging + github_environment_url: https://staging.hypothes.is/search aws_region: us-west-1 elasticbeanstalk_application: h - elasticbeanstalk_environment: qa + elasticbeanstalk_environment: staging docker_tag: ${{ needs.Docker_Hub.outputs.docker_tag }} secrets: inherit - qa_websocket: - name: QA (WebSocket) + staging_websocket: + name: Staging (WebSocket) needs: [docker_hub] uses: hypothesis/workflows/.github/workflows/deploy.yml@main with: operation: deploy - github_environment_name: QA (WebSocket) - github_environment_url: https://qa.hypothes.is/docs/help + github_environment_name: Staging (WebSocket) + github_environment_url: https://staging.hypothes.is/docs/help aws_region: us-west-1 elasticbeanstalk_application: h-websocket - elasticbeanstalk_environment: qa + elasticbeanstalk_environment: staging docker_tag: ${{ needs.Docker_Hub.outputs.docker_tag }} secrets: inherit production: name: Production - needs: [docker_hub, qa, qa_websocket] + needs: [docker_hub, staging, staging_websocket] uses: hypothesis/workflows/.github/workflows/deploy.yml@main with: operation: deploy @@ -83,7 +79,7 @@ jobs: secrets: inherit production_websocket: name: Production (WebSocket) - needs: [docker_hub, qa, qa_websocket] + needs: [docker_hub, staging, staging_websocket] uses: hypothesis/workflows/.github/workflows/deploy.yml@main with: operation: deploy @@ -96,7 +92,7 @@ jobs: secrets: inherit production_canada: name: Production (Canada) - needs: [docker_hub, qa, qa_websocket] + needs: [docker_hub, staging, staging_websocket] uses: hypothesis/workflows/.github/workflows/deploy.yml@main with: operation: deploy diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml new file mode 100644 index 00000000000..ee150022a3e --- /dev/null +++ b/.github/workflows/frontend.yml @@ -0,0 +1,21 @@ +name: Frontend +on: + workflow_call: + workflow_dispatch: +jobs: + Frontend: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Cache the node_modules dir + uses: actions/cache@v3 + with: + path: node_modules + key: ${{ runner.os }}-node_modules-${{ hashFiles('package-lock.json') }} + - name: Format + run: make frontend-checkformatting + - name: Lint + run: make frontend-lint + - name: Test + run: make frontend-tests diff --git a/.github/workflows/redeploy.yml b/.github/workflows/redeploy.yml index 913aebd32f0..f828825a7c2 100644 --- a/.github/workflows/redeploy.yml +++ b/.github/workflows/redeploy.yml @@ -5,12 +5,12 @@ concurrency: on: workflow_dispatch: inputs: - qa: + staging: type: boolean - description: Redeploy QA - qa_websocket: + description: Redeploy Staging + staging_websocket: type: boolean - description: Redeploy QA (WebSocket) + description: Redeploy Staging (WebSocket) production: type: boolean description: Redeploy Production @@ -21,29 +21,29 @@ on: type: boolean description: Redeploy Production (Canada) jobs: - qa: - name: QA - if: inputs.qa + staging: + name: Staging + if: inputs.staging uses: hypothesis/workflows/.github/workflows/deploy.yml@main with: operation: redeploy - github_environment_name: QA - github_environment_url: https://qa.hypothes.is/search + github_environment_name: Staging + github_environment_url: https://staging.hypothes.is/search aws_region: us-west-1 elasticbeanstalk_application: h - elasticbeanstalk_environment: qa + elasticbeanstalk_environment: staging secrets: inherit - qa_websocket: - name: QA (WebSocket) - if: inputs.qa_websocket + staging_websocket: + name: Staging (WebSocket) + if: inputs.staging_websocket uses: hypothesis/workflows/.github/workflows/deploy.yml@main with: operation: redeploy - github_environment_name: QA (WebSocket) - github_environment_url: https://qa.hypothes.is/docs/help + github_environment_name: Staging (WebSocket) + github_environment_url: https://staging.hypothes.is/docs/help aws_region: us-west-1 elasticbeanstalk_application: h-websocket - elasticbeanstalk_environment: qa + elasticbeanstalk_environment: staging secrets: inherit production: name: Production diff --git a/.github/workflows/report_refresh.yml b/.github/workflows/report_refresh.yml index 2435778539c..657c3850e69 100644 --- a/.github/workflows/report_refresh.yml +++ b/.github/workflows/report_refresh.yml @@ -4,7 +4,7 @@ name: Report refresh on: workflow_dispatch: schedule: - - cron: '0 15 * * *' + - cron: '0 05 * * *' jobs: refresh: @@ -15,5 +15,5 @@ jobs: Env: 'prod' Timeout: 3600 Region: 'all' - Command: 'newrelic-admin run-program python bin/run_data_task.py --config-file conf/app.ini --task report/refresh' + Command: 'newrelic-admin run-program python bin/run_data_task.py --config-file conf/production.ini --task report/refresh' secrets: inherit diff --git a/.github/workflows/slack.yml b/.github/workflows/slack.yml new file mode 100644 index 00000000000..3198a29b744 --- /dev/null +++ b/.github/workflows/slack.yml @@ -0,0 +1,18 @@ +name: Slack +on: + workflow_run: + workflows: [CI] + types: [completed] + branches: [main] +jobs: + on-failure: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'failure' }} + steps: + - name: Post to Slack + uses: slackapi/slack-github-action@v1.24.0 + with: + channel-id: 'C4K6M7P5E' + slack-message: "A workflow run failed\n*Repo:* `${{ github.event.repository.full_name }}` (${{ github.event.repository.html_url }})\n*Workflow:* ${{ github.event.workflow.name }} (${{ github.event.workflow.html_url }})\n*Branch:* `${{ github.event.workflow_run.head_branch }}`\n*Commit:* `${{ github.event.workflow_run.head_commit.id }}`\n*Run:* ${{ github.event.workflow_run.html_url }}\n*Conclusion:* ${{ github.event.workflow_run.conclusion }}" + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} diff --git a/.github/workflows/tasks.yml b/.github/workflows/tasks.yml index 18931f75e3e..45461772169 100644 --- a/.github/workflows/tasks.yml +++ b/.github/workflows/tasks.yml @@ -20,9 +20,9 @@ on: type: choice description: "The environment to target" required: true - default: 'qa' + default: 'staging' options: - - 'qa' + - 'staging' - 'prod' Timeout: type: string @@ -76,7 +76,7 @@ jobs: Env: ${{ inputs.Environment }} Timeout: ${{ inputs.Timeout }} Region: ${{ inputs.Region }} - Command: 'hypothesis migrate current' + Command: 'alembic -c conf/alembic.ini current' secrets: inherit head: @@ -88,7 +88,7 @@ jobs: Env: ${{ inputs.Environment }} Timeout: ${{ inputs.Timeout }} Region: ${{ inputs.Region }} - Command: 'hypothesis migrate upgrade head' + Command: 'alembic -c conf/alembic.ini upgrade head' secrets: inherit next: @@ -100,7 +100,7 @@ jobs: Env: ${{ inputs.Environment }} Timeout: ${{ inputs.Timeout }} Region: ${{ inputs.Region }} - Command: 'hypothesis migrate upgrade +1' + Command: 'alembic -c conf/alembic.ini upgrade +1' secrets: inherit downgrade: @@ -112,7 +112,7 @@ jobs: Env: ${{ inputs.Environment }} Timeout: ${{ inputs.Timeout }} Region: ${{ inputs.Region }} - Command: 'hypothesis migrate downgrade -1' + Command: 'alembic -c conf/alembic.ini downgrade -1' secrets: inherit search: diff --git a/.gitignore b/.gitignore index 10813fee544..b2d3363f813 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,13 @@ mail/ tests/py3-actual-failures.txt .devdata.env + +# See https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored. +# This is the "If you're not using Zero-Installs" list. +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000000..32b7f0122bd --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,36 @@ +# You can override the included template(s) by including variable overrides +# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings +# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings +# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings +# Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings +# Note that environment variables can be set in several places +# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence + +stages: +- publish + + +docker-nightly: + stage: publish + image: + name: gcr.io/kaniko-project/executor:v1.9.0-debug + entrypoint: + - '' + script: + - /kaniko/executor --context "${CI_PROJECT_DIR}" --dockerfile "${CI_PROJECT_DIR}/Dockerfile" + --destination "${CI_REGISTRY_IMAGE}:nightly" + rules: + - if: $CI_COMMIT_BRANCH == "phoenix-integration" + + +docker-prod: + stage: publish + image: + name: gcr.io/kaniko-project/executor:v1.9.0-debug + entrypoint: + - '' + script: + - /kaniko/executor --context "${CI_PROJECT_DIR}" --dockerfile "${CI_PROJECT_DIR}/Dockerfile" + --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}" --destination "${CI_REGISTRY_IMAGE}:stable" + rules: + - if: $CI_COMMIT_TAG diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index a6abbf78f1c..00000000000 --- a/.pylintrc +++ /dev/null @@ -1,77 +0,0 @@ -[MASTER] -jobs=0 # Speed up PyLint by using one process per CPU core. -load-plugins=pylint.extensions.bad_builtin, - pylint.extensions.broad_try_clause, - pylint.extensions.check_elif, - pylint.extensions.comparetozero, - pylint.extensions.docparams, - pylint.extensions.emptystring, - pylint.extensions.mccabe, - pylint.extensions.overlapping_exceptions, - pylint.extensions.redefined_variable_type, - -# Fail if there are *any* messages from PyLint. -# The letters refer to PyLint's message categories, see -# https://pylint.pycqa.org/en/latest/messages/messages_introduction.html -fail-on=C,E,F,I,R,W - -[MESSAGES CONTROL] -disable=missing-docstring, - missing-type-doc, - missing-yield-doc, - missing-return-type-doc, - missing-yield-type-doc, - missing-return-doc, - missing-raises-doc, - missing-param-doc, - wrong-import-order, - # We use isort to sort and group our imports, so we don't need PyLint to - # check them for us. - ungrouped-imports, - - # We use Black to format our code automatically, so we don't need PyLint to - # check formatting for us. - line-too-long, - too-few-public-methods, - duplicate-code, - - # Ignored during pep8 -> pylint transition - super-init-not-called, - fixme, - - # Ignored until https://github.com/PyCQA/pylint/issues/3804 is closed - comparison-with-callable, - -good-names= - # PyLint's default good names. - i,j,k,ex,Run,_,ok, - - # The standard name used for the pyramid_tm transaction manager. - tm, - - # websocket - ws, - # request.db - db, - # request.es - es, - # Primary key on models - id, - -[REPORTS] -output-format=colorized -score=no - -[SIMILARITIES] - -# Ignore comments when computing similarities. -ignore-comments=no - -# Ignore docstrings when computing similarities. -ignore-docstrings=no - -# Ignore imports when computing similarities. -ignore-imports=yes - -# Set a slightly higher base for repeated code -min-similarity-lines=14 diff --git a/.python-version b/.python-version index 89a1ad7ad3c..d4b278f0a7d 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.8.12 +3.11.7 diff --git a/.yarn/releases/yarn-3.6.1.cjs b/.yarn/releases/yarn-3.6.1.cjs new file mode 100755 index 00000000000..5227385a9ec --- /dev/null +++ b/.yarn/releases/yarn-3.6.1.cjs @@ -0,0 +1,874 @@ +#!/usr/bin/env node +/* eslint-disable */ +//prettier-ignore +(()=>{var xge=Object.create;var lS=Object.defineProperty;var Pge=Object.getOwnPropertyDescriptor;var Dge=Object.getOwnPropertyNames;var kge=Object.getPrototypeOf,Rge=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 Fge=(r,e)=>()=>(r&&(e=r(r=0)),e);var w=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),ut=(r,e)=>{for(var t in e)lS(r,t,{get:e[t],enumerable:!0})},Nge=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Dge(e))!Rge.call(r,n)&&n!==t&&lS(r,n,{get:()=>e[n],enumerable:!(i=Pge(e,n))||i.enumerable});return r};var Pe=(r,e,t)=>(t=r!=null?xge(kge(r)):{},Nge(e||!r||!r.__esModule?lS(t,"default",{value:r,enumerable:!0}):t,r));var vK=w((JXe,SK)=>{SK.exports=QK;QK.sync=tfe;var BK=J("fs");function efe(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{kK.exports=PK;PK.sync=rfe;var xK=J("fs");function PK(r,e,t){xK.stat(r,function(i,n){t(i,i?!1:DK(n,e))})}function rfe(r,e){return DK(xK.statSync(r),e)}function DK(r,e){return r.isFile()&&ife(r,e)}function ife(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 NK=w((VXe,FK)=>{var zXe=J("fs"),lI;process.platform==="win32"||global.TESTING_WINDOWS?lI=vK():lI=RK();FK.exports=SS;SS.sync=nfe;function SS(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){SS(r,e||{},function(s,o){s?n(s):i(o)})})}lI(r,e||{},function(i,n){i&&(i.code==="EACCES"||e&&e.ignoreErrors)&&(i=null,n=!1),t(i,n)})}function nfe(r,e){try{return lI.sync(r,e||{})}catch(t){if(e&&e.ignoreErrors||t.code==="EACCES")return!1;throw t}}});var HK=w((XXe,UK)=>{var Dg=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",TK=J("path"),sfe=Dg?";":":",LK=NK(),MK=r=>Object.assign(new Error(`not found: ${r}`),{code:"ENOENT"}),OK=(r,e)=>{let t=e.colon||sfe,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}},KK=(r,e,t)=>{typeof e=="function"&&(t=e,e={}),e||(e={});let{pathEnv:i,pathExt:n,pathExtExe:s}=OK(r,e),o=[],a=c=>new Promise((u,g)=>{if(c===i.length)return e.all&&o.length?u(o):g(MK(r));let f=i[c],h=/^".*"$/.test(f)?f.slice(1,-1):f,p=TK.join(h,r),C=!h&&/^\.[\\\/]/.test(r)?r.slice(0,2)+p:p;u(l(C,c,0))}),l=(c,u,g)=>new Promise((f,h)=>{if(g===n.length)return f(a(u+1));let p=n[g];LK(c+p,{pathExt:s},(C,y)=>{if(!C&&y)if(e.all)o.push(c+p);else return f(c+p);return f(l(c,u,g+1))})});return t?a(0).then(c=>t(null,c),t):a(0)},ofe=(r,e)=>{e=e||{};let{pathEnv:t,pathExt:i,pathExtExe:n}=OK(r,e),s=[];for(let o=0;o{"use strict";var GK=(r={})=>{let e=r.env||process.env;return(r.platform||process.platform)!=="win32"?"PATH":Object.keys(e).reverse().find(i=>i.toUpperCase()==="PATH")||"Path"};vS.exports=GK;vS.exports.default=GK});var WK=w((_Xe,JK)=>{"use strict";var jK=J("path"),afe=HK(),Afe=YK();function qK(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=afe.sync(r.command,{path:t[Afe({env:t})],pathExt:e?jK.delimiter:void 0})}catch{}finally{s&&process.chdir(i)}return o&&(o=jK.resolve(n?r.options.cwd:"",o)),o}function lfe(r){return qK(r)||qK(r,!0)}JK.exports=lfe});var zK=w(($Xe,PS)=>{"use strict";var xS=/([()\][%!^"`<>&|;, *?])/g;function cfe(r){return r=r.replace(xS,"^$1"),r}function ufe(r,e){return r=`${r}`,r=r.replace(/(\\*)"/g,'$1$1\\"'),r=r.replace(/(\\*)$/,"$1$1"),r=`"${r}"`,r=r.replace(xS,"^$1"),e&&(r=r.replace(xS,"^$1")),r}PS.exports.command=cfe;PS.exports.argument=ufe});var XK=w((eZe,VK)=>{"use strict";VK.exports=/^#!(.*)/});var _K=w((tZe,ZK)=>{"use strict";var gfe=XK();ZK.exports=(r="")=>{let e=r.match(gfe);if(!e)return null;let[t,i]=e[0].replace(/#! ?/,"").split(" "),n=t.split("/").pop();return n==="env"?i:i?`${n} ${i}`:n}});var eU=w((rZe,$K)=>{"use strict";var DS=J("fs"),ffe=_K();function hfe(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 ffe(t.toString())}$K.exports=hfe});var nU=w((iZe,iU)=>{"use strict";var pfe=J("path"),tU=WK(),rU=zK(),dfe=eU(),Cfe=process.platform==="win32",mfe=/\.(?:com|exe)$/i,Efe=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function Ife(r){r.file=tU(r);let e=r.file&&dfe(r.file);return e?(r.args.unshift(r.file),r.command=e,tU(r)):r.file}function yfe(r){if(!Cfe)return r;let e=Ife(r),t=!mfe.test(e);if(r.options.forceShell||t){let i=Efe.test(e);r.command=pfe.normalize(r.command),r.command=rU.command(r.command),r.args=r.args.map(s=>rU.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 wfe(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:yfe(i)}iU.exports=wfe});var aU=w((nZe,oU)=>{"use strict";var kS=process.platform==="win32";function RS(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 Bfe(r,e){if(!kS)return;let t=r.emit;r.emit=function(i,n){if(i==="exit"){let s=sU(n,e,"spawn");if(s)return t.call(r,"error",s)}return t.apply(r,arguments)}}function sU(r,e){return kS&&r===1&&!e.file?RS(e.original,"spawn"):null}function bfe(r,e){return kS&&r===1&&!e.file?RS(e.original,"spawnSync"):null}oU.exports={hookChildProcess:Bfe,verifyENOENT:sU,verifyENOENTSync:bfe,notFoundError:RS}});var TS=w((sZe,kg)=>{"use strict";var AU=J("child_process"),FS=nU(),NS=aU();function lU(r,e,t){let i=FS(r,e,t),n=AU.spawn(i.command,i.args,i.options);return NS.hookChildProcess(n,i),n}function Qfe(r,e,t){let i=FS(r,e,t),n=AU.spawnSync(i.command,i.args,i.options);return n.error=n.error||NS.verifyENOENTSync(n.status,i),n}kg.exports=lU;kg.exports.spawn=lU;kg.exports.sync=Qfe;kg.exports._parse=FS;kg.exports._enoent=NS});var uU=w((oZe,cU)=>{"use strict";function Sfe(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function Zl(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,Zl)}Sfe(Zl,Error);Zl.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,f=1;g>",ie=me(">>",!1),de=">&",_e=me(">&",!1),Pt=">",It=me(">",!1),Mr="<<<",ii=me("<<<",!1),gi="<&",hr=me("<&",!1),fi="<",ni=me("<",!1),Ks=function(m){return{type:"argument",segments:[].concat(...m)}},pr=function(m){return m},Ii="$'",rs=me("$'",!1),fa="'",CA=me("'",!1),cg=function(m){return[{type:"text",text:m}]},is='""',mA=me('""',!1),ha=function(){return{type:"text",text:""}},wp='"',EA=me('"',!1),IA=function(m){return m},wr=function(m){return{type:"arithmetic",arithmetic:m,quoted:!0}},Tl=function(m){return{type:"shell",shell:m,quoted:!0}},ug=function(m){return{type:"variable",...m,quoted:!0}},Io=function(m){return{type:"text",text:m}},gg=function(m){return{type:"arithmetic",arithmetic:m,quoted:!1}},Bp=function(m){return{type:"shell",shell:m,quoted:!1}},bp=function(m){return{type:"variable",...m,quoted:!1}},vr=function(m){return{type:"glob",pattern:m}},se=/^[^']/,yo=Je(["'"],!0,!1),Fn=function(m){return m.join("")},fg=/^[^$"]/,bt=Je(["$",'"'],!0,!1),Ll=`\\ +`,Nn=me(`\\ +`,!1),ns=function(){return""},ss="\\",gt=me("\\",!1),wo=/^[\\$"`]/,At=Je(["\\","$",'"',"`"],!1,!1),ln=function(m){return m},S="\\a",Lt=me("\\a",!1),hg=function(){return"a"},Ml="\\b",Qp=me("\\b",!1),Sp=function(){return"\b"},vp=/^[Ee]/,xp=Je(["E","e"],!1,!1),Pp=function(){return"\x1B"},G="\\f",yt=me("\\f",!1),yA=function(){return"\f"},zi="\\n",Ol=me("\\n",!1),Xe=function(){return` +`},pa="\\r",pg=me("\\r",!1),ME=function(){return"\r"},Dp="\\t",OE=me("\\t",!1),ar=function(){return" "},Tn="\\v",Kl=me("\\v",!1),kp=function(){return"\v"},Us=/^[\\'"?]/,da=Je(["\\","'",'"',"?"],!1,!1),cn=function(m){return String.fromCharCode(parseInt(m,16))},Le="\\x",dg=me("\\x",!1),Ul="\\u",Hs=me("\\u",!1),Hl="\\U",wA=me("\\U",!1),Cg=function(m){return String.fromCodePoint(parseInt(m,16))},mg=/^[0-7]/,Ca=Je([["0","7"]],!1,!1),ma=/^[0-9a-fA-f]/,rt=Je([["0","9"],["a","f"],["A","f"]],!1,!1),Bo=nt(),BA="-",Gl=me("-",!1),Gs="+",Yl=me("+",!1),KE=".",Rp=me(".",!1),Eg=function(m,Q,N){return{type:"number",value:(m==="-"?-1:1)*parseFloat(Q.join("")+"."+N.join(""))}},Fp=function(m,Q){return{type:"number",value:(m==="-"?-1:1)*parseInt(Q.join(""))}},UE=function(m){return{type:"variable",...m}},jl=function(m){return{type:"variable",name:m}},HE=function(m){return m},Ig="*",bA=me("*",!1),Rr="/",GE=me("/",!1),Ys=function(m,Q,N){return{type:Q==="*"?"multiplication":"division",right:N}},js=function(m,Q){return Q.reduce((N,U)=>({left:N,...U}),m)},yg=function(m,Q,N){return{type:Q==="+"?"addition":"subtraction",right:N}},QA="$((",R=me("$((",!1),q="))",Ce=me("))",!1),Ke=function(m){return m},Re="$(",ze=me("$(",!1),dt=function(m){return m},Ft="${",Ln=me("${",!1),JQ=":-",P1=me(":-",!1),D1=function(m,Q){return{name:m,defaultValue:Q}},WQ=":-}",k1=me(":-}",!1),R1=function(m){return{name:m,defaultValue:[]}},zQ=":+",F1=me(":+",!1),N1=function(m,Q){return{name:m,alternativeValue:Q}},VQ=":+}",T1=me(":+}",!1),L1=function(m){return{name:m,alternativeValue:[]}},XQ=function(m){return{name:m}},M1="$",O1=me("$",!1),K1=function(m){return e.isGlobPattern(m)},U1=function(m){return m},ZQ=/^[a-zA-Z0-9_]/,_Q=Je([["a","z"],["A","Z"],["0","9"],"_"],!1,!1),$Q=function(){return L()},eS=/^[$@*?#a-zA-Z0-9_\-]/,tS=Je(["$","@","*","?","#",["a","z"],["A","Z"],["0","9"],"_","-"],!1,!1),H1=/^[(){}<>$|&; \t"']/,wg=Je(["(",")","{","}","<",">","$","|","&",";"," "," ",'"',"'"],!1,!1),rS=/^[<>&; \t"']/,iS=Je(["<",">","&",";"," "," ",'"',"'"],!1,!1),YE=/^[ \t]/,jE=Je([" "," "],!1,!1),b=0,Oe=0,SA=[{line:1,column:1}],d=0,E=[],I=0,k;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 L(){return r.substring(Oe,b)}function Z(){return Et(Oe,b)}function te(m,Q){throw Q=Q!==void 0?Q:Et(Oe,b),Ri([lt(m)],r.substring(Oe,b),Q)}function we(m,Q){throw Q=Q!==void 0?Q:Et(Oe,b),Mn(m,Q)}function me(m,Q){return{type:"literal",text:m,ignoreCase:Q}}function Je(m,Q,N){return{type:"class",parts:m,inverted:Q,ignoreCase:N}}function nt(){return{type:"any"}}function wt(){return{type:"end"}}function lt(m){return{type:"other",description:m}}function it(m){var Q=SA[m],N;if(Q)return Q;for(N=m-1;!SA[N];)N--;for(Q=SA[N],Q={line:Q.line,column:Q.column};Nd&&(d=b,E=[]),E.push(m))}function Mn(m,Q){return new Zl(m,null,null,Q)}function Ri(m,Q,N){return new Zl(Zl.buildMessage(m,Q),m,Q,N)}function vA(){var m,Q;return m=b,Q=Or(),Q===t&&(Q=null),Q!==t&&(Oe=m,Q=s(Q)),m=Q,m}function Or(){var m,Q,N,U,ce;if(m=b,Q=Kr(),Q!==t){for(N=[],U=He();U!==t;)N.push(U),U=He();N!==t?(U=Ea(),U!==t?(ce=os(),ce===t&&(ce=null),ce!==t?(Oe=m,Q=o(Q,U,ce),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;if(m===t)if(m=b,Q=Kr(),Q!==t){for(N=[],U=He();U!==t;)N.push(U),U=He();N!==t?(U=Ea(),U===t&&(U=null),U!==t?(Oe=m,Q=a(Q,U),m=Q):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;return m}function os(){var m,Q,N,U,ce;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(N=Or(),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();U!==t?(Oe=m,Q=l(N),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t;return m}function Ea(){var m;return r.charCodeAt(b)===59?(m=c,b++):(m=t,I===0&&be(u)),m===t&&(r.charCodeAt(b)===38?(m=g,b++):(m=t,I===0&&be(f))),m}function Kr(){var m,Q,N;return m=b,Q=G1(),Q!==t?(N=uge(),N===t&&(N=null),N!==t?(Oe=m,Q=h(Q,N),m=Q):(b=m,m=t)):(b=m,m=t),m}function uge(){var m,Q,N,U,ce,Se,ht;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(N=gge(),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t)if(ce=Kr(),ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();Se!==t?(Oe=m,Q=p(N,ce),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t;return m}function gge(){var m;return r.substr(b,2)===C?(m=C,b+=2):(m=t,I===0&&be(y)),m===t&&(r.substr(b,2)===B?(m=B,b+=2):(m=t,I===0&&be(v))),m}function G1(){var m,Q,N;return m=b,Q=pge(),Q!==t?(N=fge(),N===t&&(N=null),N!==t?(Oe=m,Q=D(Q,N),m=Q):(b=m,m=t)):(b=m,m=t),m}function fge(){var m,Q,N,U,ce,Se,ht;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(N=hge(),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t)if(ce=G1(),ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();Se!==t?(Oe=m,Q=T(N,ce),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t;return m}function hge(){var m;return r.substr(b,2)===H?(m=H,b+=2):(m=t,I===0&&be(j)),m===t&&(r.charCodeAt(b)===124?(m=$,b++):(m=t,I===0&&be(V))),m}function qE(){var m,Q,N,U,ce,Se;if(m=b,Q=eK(),Q!==t)if(r.charCodeAt(b)===61?(N=W,b++):(N=t,I===0&&be(_)),N!==t)if(U=q1(),U!==t){for(ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();ce!==t?(Oe=m,Q=A(Q,U),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t;else b=m,m=t;if(m===t)if(m=b,Q=eK(),Q!==t)if(r.charCodeAt(b)===61?(N=W,b++):(N=t,I===0&&be(_)),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();U!==t?(Oe=m,Q=Ae(Q),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t;return m}function pge(){var m,Q,N,U,ce,Se,ht,Bt,Jr,hi,as;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(r.charCodeAt(b)===40?(N=ge,b++):(N=t,I===0&&be(re)),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t)if(ce=Or(),ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();if(Se!==t)if(r.charCodeAt(b)===41?(ht=M,b++):(ht=t,I===0&&be(F)),ht!==t){for(Bt=[],Jr=He();Jr!==t;)Bt.push(Jr),Jr=He();if(Bt!==t){for(Jr=[],hi=Np();hi!==t;)Jr.push(hi),hi=Np();if(Jr!==t){for(hi=[],as=He();as!==t;)hi.push(as),as=He();hi!==t?(Oe=m,Q=ue(ce,Jr),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t;if(m===t){for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(r.charCodeAt(b)===123?(N=pe,b++):(N=t,I===0&&be(ke)),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t)if(ce=Or(),ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();if(Se!==t)if(r.charCodeAt(b)===125?(ht=Fe,b++):(ht=t,I===0&&be(Ne)),ht!==t){for(Bt=[],Jr=He();Jr!==t;)Bt.push(Jr),Jr=He();if(Bt!==t){for(Jr=[],hi=Np();hi!==t;)Jr.push(hi),hi=Np();if(Jr!==t){for(hi=[],as=He();as!==t;)hi.push(as),as=He();hi!==t?(Oe=m,Q=oe(ce,Jr),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t;if(m===t){for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t){for(N=[],U=qE();U!==t;)N.push(U),U=qE();if(N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t){if(ce=[],Se=j1(),Se!==t)for(;Se!==t;)ce.push(Se),Se=j1();else ce=t;if(ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();Se!==t?(Oe=m,Q=le(N,ce),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t}else b=m,m=t}else b=m,m=t;if(m===t){for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t){if(N=[],U=qE(),U!==t)for(;U!==t;)N.push(U),U=qE();else N=t;if(N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();U!==t?(Oe=m,Q=Be(N),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t}}}return m}function Y1(){var m,Q,N,U,ce;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t){if(N=[],U=JE(),U!==t)for(;U!==t;)N.push(U),U=JE();else N=t;if(N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();U!==t?(Oe=m,Q=fe(N),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t;return m}function j1(){var m,Q,N;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t?(N=Np(),N!==t?(Oe=m,Q=ae(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t){for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();Q!==t?(N=JE(),N!==t?(Oe=m,Q=ae(N),m=Q):(b=m,m=t)):(b=m,m=t)}return m}function Np(){var m,Q,N,U,ce;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();return Q!==t?(qe.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(ne)),N===t&&(N=null),N!==t?(U=dge(),U!==t?(ce=JE(),ce!==t?(Oe=m,Q=Y(N,U,ce),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m}function dge(){var m;return r.substr(b,2)===he?(m=he,b+=2):(m=t,I===0&&be(ie)),m===t&&(r.substr(b,2)===de?(m=de,b+=2):(m=t,I===0&&be(_e)),m===t&&(r.charCodeAt(b)===62?(m=Pt,b++):(m=t,I===0&&be(It)),m===t&&(r.substr(b,3)===Mr?(m=Mr,b+=3):(m=t,I===0&&be(ii)),m===t&&(r.substr(b,2)===gi?(m=gi,b+=2):(m=t,I===0&&be(hr)),m===t&&(r.charCodeAt(b)===60?(m=fi,b++):(m=t,I===0&&be(ni))))))),m}function JE(){var m,Q,N;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();return Q!==t?(N=q1(),N!==t?(Oe=m,Q=ae(N),m=Q):(b=m,m=t)):(b=m,m=t),m}function q1(){var m,Q,N;if(m=b,Q=[],N=J1(),N!==t)for(;N!==t;)Q.push(N),N=J1();else Q=t;return Q!==t&&(Oe=m,Q=Ks(Q)),m=Q,m}function J1(){var m,Q;return m=b,Q=Cge(),Q!==t&&(Oe=m,Q=pr(Q)),m=Q,m===t&&(m=b,Q=mge(),Q!==t&&(Oe=m,Q=pr(Q)),m=Q,m===t&&(m=b,Q=Ege(),Q!==t&&(Oe=m,Q=pr(Q)),m=Q,m===t&&(m=b,Q=Ige(),Q!==t&&(Oe=m,Q=pr(Q)),m=Q))),m}function Cge(){var m,Q,N,U;return m=b,r.substr(b,2)===Ii?(Q=Ii,b+=2):(Q=t,I===0&&be(rs)),Q!==t?(N=Bge(),N!==t?(r.charCodeAt(b)===39?(U=fa,b++):(U=t,I===0&&be(CA)),U!==t?(Oe=m,Q=cg(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m}function mge(){var m,Q,N,U;return m=b,r.charCodeAt(b)===39?(Q=fa,b++):(Q=t,I===0&&be(CA)),Q!==t?(N=yge(),N!==t?(r.charCodeAt(b)===39?(U=fa,b++):(U=t,I===0&&be(CA)),U!==t?(Oe=m,Q=cg(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m}function Ege(){var m,Q,N,U;if(m=b,r.substr(b,2)===is?(Q=is,b+=2):(Q=t,I===0&&be(mA)),Q!==t&&(Oe=m,Q=ha()),m=Q,m===t)if(m=b,r.charCodeAt(b)===34?(Q=wp,b++):(Q=t,I===0&&be(EA)),Q!==t){for(N=[],U=W1();U!==t;)N.push(U),U=W1();N!==t?(r.charCodeAt(b)===34?(U=wp,b++):(U=t,I===0&&be(EA)),U!==t?(Oe=m,Q=IA(N),m=Q):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;return m}function Ige(){var m,Q,N;if(m=b,Q=[],N=z1(),N!==t)for(;N!==t;)Q.push(N),N=z1();else Q=t;return Q!==t&&(Oe=m,Q=IA(Q)),m=Q,m}function W1(){var m,Q;return m=b,Q=_1(),Q!==t&&(Oe=m,Q=wr(Q)),m=Q,m===t&&(m=b,Q=$1(),Q!==t&&(Oe=m,Q=Tl(Q)),m=Q,m===t&&(m=b,Q=aS(),Q!==t&&(Oe=m,Q=ug(Q)),m=Q,m===t&&(m=b,Q=wge(),Q!==t&&(Oe=m,Q=Io(Q)),m=Q))),m}function z1(){var m,Q;return m=b,Q=_1(),Q!==t&&(Oe=m,Q=gg(Q)),m=Q,m===t&&(m=b,Q=$1(),Q!==t&&(Oe=m,Q=Bp(Q)),m=Q,m===t&&(m=b,Q=aS(),Q!==t&&(Oe=m,Q=bp(Q)),m=Q,m===t&&(m=b,Q=Sge(),Q!==t&&(Oe=m,Q=vr(Q)),m=Q,m===t&&(m=b,Q=Qge(),Q!==t&&(Oe=m,Q=Io(Q)),m=Q)))),m}function yge(){var m,Q,N;for(m=b,Q=[],se.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(yo));N!==t;)Q.push(N),se.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(yo));return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function wge(){var m,Q,N;if(m=b,Q=[],N=V1(),N===t&&(fg.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(bt))),N!==t)for(;N!==t;)Q.push(N),N=V1(),N===t&&(fg.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(bt)));else Q=t;return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function V1(){var m,Q,N;return m=b,r.substr(b,2)===Ll?(Q=Ll,b+=2):(Q=t,I===0&&be(Nn)),Q!==t&&(Oe=m,Q=ns()),m=Q,m===t&&(m=b,r.charCodeAt(b)===92?(Q=ss,b++):(Q=t,I===0&&be(gt)),Q!==t?(wo.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(At)),N!==t?(Oe=m,Q=ln(N),m=Q):(b=m,m=t)):(b=m,m=t)),m}function Bge(){var m,Q,N;for(m=b,Q=[],N=X1(),N===t&&(se.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(yo)));N!==t;)Q.push(N),N=X1(),N===t&&(se.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(yo)));return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function X1(){var m,Q,N;return m=b,r.substr(b,2)===S?(Q=S,b+=2):(Q=t,I===0&&be(Lt)),Q!==t&&(Oe=m,Q=hg()),m=Q,m===t&&(m=b,r.substr(b,2)===Ml?(Q=Ml,b+=2):(Q=t,I===0&&be(Qp)),Q!==t&&(Oe=m,Q=Sp()),m=Q,m===t&&(m=b,r.charCodeAt(b)===92?(Q=ss,b++):(Q=t,I===0&&be(gt)),Q!==t?(vp.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(xp)),N!==t?(Oe=m,Q=Pp(),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===G?(Q=G,b+=2):(Q=t,I===0&&be(yt)),Q!==t&&(Oe=m,Q=yA()),m=Q,m===t&&(m=b,r.substr(b,2)===zi?(Q=zi,b+=2):(Q=t,I===0&&be(Ol)),Q!==t&&(Oe=m,Q=Xe()),m=Q,m===t&&(m=b,r.substr(b,2)===pa?(Q=pa,b+=2):(Q=t,I===0&&be(pg)),Q!==t&&(Oe=m,Q=ME()),m=Q,m===t&&(m=b,r.substr(b,2)===Dp?(Q=Dp,b+=2):(Q=t,I===0&&be(OE)),Q!==t&&(Oe=m,Q=ar()),m=Q,m===t&&(m=b,r.substr(b,2)===Tn?(Q=Tn,b+=2):(Q=t,I===0&&be(Kl)),Q!==t&&(Oe=m,Q=kp()),m=Q,m===t&&(m=b,r.charCodeAt(b)===92?(Q=ss,b++):(Q=t,I===0&&be(gt)),Q!==t?(Us.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(da)),N!==t?(Oe=m,Q=ln(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=bge()))))))))),m}function bge(){var m,Q,N,U,ce,Se,ht,Bt,Jr,hi,as,AS;return m=b,r.charCodeAt(b)===92?(Q=ss,b++):(Q=t,I===0&&be(gt)),Q!==t?(N=nS(),N!==t?(Oe=m,Q=cn(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Le?(Q=Le,b+=2):(Q=t,I===0&&be(dg)),Q!==t?(N=b,U=b,ce=nS(),ce!==t?(Se=On(),Se!==t?(ce=[ce,Se],U=ce):(b=U,U=t)):(b=U,U=t),U===t&&(U=nS()),U!==t?N=r.substring(N,b):N=U,N!==t?(Oe=m,Q=cn(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ul?(Q=Ul,b+=2):(Q=t,I===0&&be(Hs)),Q!==t?(N=b,U=b,ce=On(),ce!==t?(Se=On(),Se!==t?(ht=On(),ht!==t?(Bt=On(),Bt!==t?(ce=[ce,Se,ht,Bt],U=ce):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t),U!==t?N=r.substring(N,b):N=U,N!==t?(Oe=m,Q=cn(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Hl?(Q=Hl,b+=2):(Q=t,I===0&&be(wA)),Q!==t?(N=b,U=b,ce=On(),ce!==t?(Se=On(),Se!==t?(ht=On(),ht!==t?(Bt=On(),Bt!==t?(Jr=On(),Jr!==t?(hi=On(),hi!==t?(as=On(),as!==t?(AS=On(),AS!==t?(ce=[ce,Se,ht,Bt,Jr,hi,as,AS],U=ce):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t),U!==t?N=r.substring(N,b):N=U,N!==t?(Oe=m,Q=Cg(N),m=Q):(b=m,m=t)):(b=m,m=t)))),m}function nS(){var m;return mg.test(r.charAt(b))?(m=r.charAt(b),b++):(m=t,I===0&&be(Ca)),m}function On(){var m;return ma.test(r.charAt(b))?(m=r.charAt(b),b++):(m=t,I===0&&be(rt)),m}function Qge(){var m,Q,N,U,ce;if(m=b,Q=[],N=b,r.charCodeAt(b)===92?(U=ss,b++):(U=t,I===0&&be(gt)),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(Bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t),N===t&&(N=b,U=b,I++,ce=tK(),I--,ce===t?U=void 0:(b=U,U=t),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(Bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t)),N!==t)for(;N!==t;)Q.push(N),N=b,r.charCodeAt(b)===92?(U=ss,b++):(U=t,I===0&&be(gt)),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(Bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t),N===t&&(N=b,U=b,I++,ce=tK(),I--,ce===t?U=void 0:(b=U,U=t),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(Bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t));else Q=t;return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function sS(){var m,Q,N,U,ce,Se;if(m=b,r.charCodeAt(b)===45?(Q=BA,b++):(Q=t,I===0&&be(Gl)),Q===t&&(r.charCodeAt(b)===43?(Q=Gs,b++):(Q=t,I===0&&be(Yl))),Q===t&&(Q=null),Q!==t){if(N=[],qe.test(r.charAt(b))?(U=r.charAt(b),b++):(U=t,I===0&&be(ne)),U!==t)for(;U!==t;)N.push(U),qe.test(r.charAt(b))?(U=r.charAt(b),b++):(U=t,I===0&&be(ne));else N=t;if(N!==t)if(r.charCodeAt(b)===46?(U=KE,b++):(U=t,I===0&&be(Rp)),U!==t){if(ce=[],qe.test(r.charAt(b))?(Se=r.charAt(b),b++):(Se=t,I===0&&be(ne)),Se!==t)for(;Se!==t;)ce.push(Se),qe.test(r.charAt(b))?(Se=r.charAt(b),b++):(Se=t,I===0&&be(ne));else ce=t;ce!==t?(Oe=m,Q=Eg(Q,N,ce),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t;if(m===t){if(m=b,r.charCodeAt(b)===45?(Q=BA,b++):(Q=t,I===0&&be(Gl)),Q===t&&(r.charCodeAt(b)===43?(Q=Gs,b++):(Q=t,I===0&&be(Yl))),Q===t&&(Q=null),Q!==t){if(N=[],qe.test(r.charAt(b))?(U=r.charAt(b),b++):(U=t,I===0&&be(ne)),U!==t)for(;U!==t;)N.push(U),qe.test(r.charAt(b))?(U=r.charAt(b),b++):(U=t,I===0&&be(ne));else N=t;N!==t?(Oe=m,Q=Fp(Q,N),m=Q):(b=m,m=t)}else b=m,m=t;if(m===t&&(m=b,Q=aS(),Q!==t&&(Oe=m,Q=UE(Q)),m=Q,m===t&&(m=b,Q=ql(),Q!==t&&(Oe=m,Q=jl(Q)),m=Q,m===t)))if(m=b,r.charCodeAt(b)===40?(Q=ge,b++):(Q=t,I===0&&be(re)),Q!==t){for(N=[],U=He();U!==t;)N.push(U),U=He();if(N!==t)if(U=Z1(),U!==t){for(ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();ce!==t?(r.charCodeAt(b)===41?(Se=M,b++):(Se=t,I===0&&be(F)),Se!==t?(Oe=m,Q=HE(U),m=Q):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t}return m}function oS(){var m,Q,N,U,ce,Se,ht,Bt;if(m=b,Q=sS(),Q!==t){for(N=[],U=b,ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();if(ce!==t)if(r.charCodeAt(b)===42?(Se=Ig,b++):(Se=t,I===0&&be(bA)),Se===t&&(r.charCodeAt(b)===47?(Se=Rr,b++):(Se=t,I===0&&be(GE))),Se!==t){for(ht=[],Bt=He();Bt!==t;)ht.push(Bt),Bt=He();ht!==t?(Bt=sS(),Bt!==t?(Oe=U,ce=Ys(Q,Se,Bt),U=ce):(b=U,U=t)):(b=U,U=t)}else b=U,U=t;else b=U,U=t;for(;U!==t;){for(N.push(U),U=b,ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();if(ce!==t)if(r.charCodeAt(b)===42?(Se=Ig,b++):(Se=t,I===0&&be(bA)),Se===t&&(r.charCodeAt(b)===47?(Se=Rr,b++):(Se=t,I===0&&be(GE))),Se!==t){for(ht=[],Bt=He();Bt!==t;)ht.push(Bt),Bt=He();ht!==t?(Bt=sS(),Bt!==t?(Oe=U,ce=Ys(Q,Se,Bt),U=ce):(b=U,U=t)):(b=U,U=t)}else b=U,U=t;else b=U,U=t}N!==t?(Oe=m,Q=js(Q,N),m=Q):(b=m,m=t)}else b=m,m=t;return m}function Z1(){var m,Q,N,U,ce,Se,ht,Bt;if(m=b,Q=oS(),Q!==t){for(N=[],U=b,ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();if(ce!==t)if(r.charCodeAt(b)===43?(Se=Gs,b++):(Se=t,I===0&&be(Yl)),Se===t&&(r.charCodeAt(b)===45?(Se=BA,b++):(Se=t,I===0&&be(Gl))),Se!==t){for(ht=[],Bt=He();Bt!==t;)ht.push(Bt),Bt=He();ht!==t?(Bt=oS(),Bt!==t?(Oe=U,ce=yg(Q,Se,Bt),U=ce):(b=U,U=t)):(b=U,U=t)}else b=U,U=t;else b=U,U=t;for(;U!==t;){for(N.push(U),U=b,ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();if(ce!==t)if(r.charCodeAt(b)===43?(Se=Gs,b++):(Se=t,I===0&&be(Yl)),Se===t&&(r.charCodeAt(b)===45?(Se=BA,b++):(Se=t,I===0&&be(Gl))),Se!==t){for(ht=[],Bt=He();Bt!==t;)ht.push(Bt),Bt=He();ht!==t?(Bt=oS(),Bt!==t?(Oe=U,ce=yg(Q,Se,Bt),U=ce):(b=U,U=t)):(b=U,U=t)}else b=U,U=t;else b=U,U=t}N!==t?(Oe=m,Q=js(Q,N),m=Q):(b=m,m=t)}else b=m,m=t;return m}function _1(){var m,Q,N,U,ce,Se;if(m=b,r.substr(b,3)===QA?(Q=QA,b+=3):(Q=t,I===0&&be(R)),Q!==t){for(N=[],U=He();U!==t;)N.push(U),U=He();if(N!==t)if(U=Z1(),U!==t){for(ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();ce!==t?(r.substr(b,2)===q?(Se=q,b+=2):(Se=t,I===0&&be(Ce)),Se!==t?(Oe=m,Q=Ke(U),m=Q):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t;return m}function $1(){var m,Q,N,U;return m=b,r.substr(b,2)===Re?(Q=Re,b+=2):(Q=t,I===0&&be(ze)),Q!==t?(N=Or(),N!==t?(r.charCodeAt(b)===41?(U=M,b++):(U=t,I===0&&be(F)),U!==t?(Oe=m,Q=dt(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m}function aS(){var m,Q,N,U,ce,Se;return m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.substr(b,2)===JQ?(U=JQ,b+=2):(U=t,I===0&&be(P1)),U!==t?(ce=Y1(),ce!==t?(r.charCodeAt(b)===125?(Se=Fe,b++):(Se=t,I===0&&be(Ne)),Se!==t?(Oe=m,Q=D1(N,ce),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.substr(b,3)===WQ?(U=WQ,b+=3):(U=t,I===0&&be(k1)),U!==t?(Oe=m,Q=R1(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.substr(b,2)===zQ?(U=zQ,b+=2):(U=t,I===0&&be(F1)),U!==t?(ce=Y1(),ce!==t?(r.charCodeAt(b)===125?(Se=Fe,b++):(Se=t,I===0&&be(Ne)),Se!==t?(Oe=m,Q=N1(N,ce),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.substr(b,3)===VQ?(U=VQ,b+=3):(U=t,I===0&&be(T1)),U!==t?(Oe=m,Q=L1(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.charCodeAt(b)===125?(U=Fe,b++):(U=t,I===0&&be(Ne)),U!==t?(Oe=m,Q=XQ(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.charCodeAt(b)===36?(Q=M1,b++):(Q=t,I===0&&be(O1)),Q!==t?(N=ql(),N!==t?(Oe=m,Q=XQ(N),m=Q):(b=m,m=t)):(b=m,m=t)))))),m}function Sge(){var m,Q,N;return m=b,Q=vge(),Q!==t?(Oe=b,N=K1(Q),N?N=void 0:N=t,N!==t?(Oe=m,Q=U1(Q),m=Q):(b=m,m=t)):(b=m,m=t),m}function vge(){var m,Q,N,U,ce;if(m=b,Q=[],N=b,U=b,I++,ce=rK(),I--,ce===t?U=void 0:(b=U,U=t),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(Bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t),N!==t)for(;N!==t;)Q.push(N),N=b,U=b,I++,ce=rK(),I--,ce===t?U=void 0:(b=U,U=t),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(Bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t);else Q=t;return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function eK(){var m,Q,N;if(m=b,Q=[],ZQ.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(_Q)),N!==t)for(;N!==t;)Q.push(N),ZQ.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(_Q));else Q=t;return Q!==t&&(Oe=m,Q=$Q()),m=Q,m}function ql(){var m,Q,N;if(m=b,Q=[],eS.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(tS)),N!==t)for(;N!==t;)Q.push(N),eS.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(tS));else Q=t;return Q!==t&&(Oe=m,Q=$Q()),m=Q,m}function tK(){var m;return H1.test(r.charAt(b))?(m=r.charAt(b),b++):(m=t,I===0&&be(wg)),m}function rK(){var m;return rS.test(r.charAt(b))?(m=r.charAt(b),b++):(m=t,I===0&&be(iS)),m}function He(){var m,Q;if(m=[],YE.test(r.charAt(b))?(Q=r.charAt(b),b++):(Q=t,I===0&&be(jE)),Q!==t)for(;Q!==t;)m.push(Q),YE.test(r.charAt(b))?(Q=r.charAt(b),b++):(Q=t,I===0&&be(jE));else m=t;return m}if(k=n(),k!==t&&b===r.length)return k;throw k!==t&&b{"use strict";function xfe(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)}xfe($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,f=1;gH&&(H=v,j=[]),j.push(ne))}function Ne(ne,Y){return new $l(ne,null,null,Y)}function oe(ne,Y,he){return new $l($l.buildMessage(ne,Y),ne,Y,he)}function le(){var ne,Y,he,ie;return ne=v,Y=Be(),Y!==t?(r.charCodeAt(v)===47?(he=s,v++):(he=t,$===0&&Fe(o)),he!==t?(ie=Be(),ie!==t?(D=ne,Y=a(Y,ie),ne=Y):(v=ne,ne=t)):(v=ne,ne=t)):(v=ne,ne=t),ne===t&&(ne=v,Y=Be(),Y!==t&&(D=ne,Y=l(Y)),ne=Y),ne}function Be(){var ne,Y,he,ie;return ne=v,Y=fe(),Y!==t?(r.charCodeAt(v)===64?(he=c,v++):(he=t,$===0&&Fe(u)),he!==t?(ie=qe(),ie!==t?(D=ne,Y=g(Y,ie),ne=Y):(v=ne,ne=t)):(v=ne,ne=t)):(v=ne,ne=t),ne===t&&(ne=v,Y=fe(),Y!==t&&(D=ne,Y=f(Y)),ne=Y),ne}function fe(){var ne,Y,he,ie,de;return ne=v,r.charCodeAt(v)===64?(Y=c,v++):(Y=t,$===0&&Fe(u)),Y!==t?(he=ae(),he!==t?(r.charCodeAt(v)===47?(ie=s,v++):(ie=t,$===0&&Fe(o)),ie!==t?(de=ae(),de!==t?(D=ne,Y=h(),ne=Y):(v=ne,ne=t)):(v=ne,ne=t)):(v=ne,ne=t)):(v=ne,ne=t),ne===t&&(ne=v,Y=ae(),Y!==t&&(D=ne,Y=h()),ne=Y),ne}function ae(){var ne,Y,he;if(ne=v,Y=[],p.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Fe(C)),he!==t)for(;he!==t;)Y.push(he),p.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Fe(C));else Y=t;return Y!==t&&(D=ne,Y=h()),ne=Y,ne}function qe(){var ne,Y,he;if(ne=v,Y=[],y.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Fe(B)),he!==t)for(;he!==t;)Y.push(he),y.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Fe(B));else Y=t;return Y!==t&&(D=ne,Y=h()),ne=Y,ne}if(V=n(),V!==t&&v===r.length)return V;throw V!==t&&v{"use strict";function dU(r){return typeof r>"u"||r===null}function Dfe(r){return typeof r=="object"&&r!==null}function kfe(r){return Array.isArray(r)?r:dU(r)?[]:[r]}function Rfe(r,e){var t,i,n,s;if(e)for(s=Object.keys(e),t=0,i=s.length;t{"use strict";function Vp(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||""}Vp.prototype=Object.create(Error.prototype);Vp.prototype.constructor=Vp;Vp.prototype.toString=function(e){var t=this.name+": ";return t+=this.reason||"(unknown reason)",!e&&this.mark&&(t+=" "+this.mark.toString()),t};CU.exports=Vp});var IU=w((bZe,EU)=>{"use strict";var mU=tc();function HS(r,e,t,i,n){this.name=r,this.buffer=e,this.position=t,this.line=i,this.column=n}HS.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),mU.repeat(" ",e)+i+a+s+` +`+mU.repeat(" ",e+this.position-n+i.length)+"^"};HS.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};EU.exports=HS});var si=w((QZe,wU)=>{"use strict";var yU=Ng(),Tfe=["kind","resolve","construct","instanceOf","predicate","represent","defaultStyle","styleAliases"],Lfe=["scalar","sequence","mapping"];function Mfe(r){var e={};return r!==null&&Object.keys(r).forEach(function(t){r[t].forEach(function(i){e[String(i)]=t})}),e}function Ofe(r,e){if(e=e||{},Object.keys(e).forEach(function(t){if(Tfe.indexOf(t)===-1)throw new yU('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=Mfe(e.styleAliases||null),Lfe.indexOf(this.kind)===-1)throw new yU('Unknown kind "'+this.kind+'" is specified for "'+r+'" YAML type.')}wU.exports=Ofe});var rc=w((SZe,bU)=>{"use strict";var BU=tc(),dI=Ng(),Kfe=si();function GS(r,e,t){var i=[];return r.include.forEach(function(n){t=GS(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 Ufe(){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 Hfe=si();QU.exports=new Hfe("tag:yaml.org,2002:str",{kind:"scalar",construct:function(r){return r!==null?r:""}})});var xU=w((xZe,vU)=>{"use strict";var Gfe=si();vU.exports=new Gfe("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(r){return r!==null?r:[]}})});var DU=w((PZe,PU)=>{"use strict";var Yfe=si();PU.exports=new Yfe("tag:yaml.org,2002:map",{kind:"mapping",construct:function(r){return r!==null?r:{}}})});var CI=w((DZe,kU)=>{"use strict";var jfe=rc();kU.exports=new jfe({explicit:[SU(),xU(),DU()]})});var FU=w((kZe,RU)=>{"use strict";var qfe=si();function Jfe(r){if(r===null)return!0;var e=r.length;return e===1&&r==="~"||e===4&&(r==="null"||r==="Null"||r==="NULL")}function Wfe(){return null}function zfe(r){return r===null}RU.exports=new qfe("tag:yaml.org,2002:null",{kind:"scalar",resolve:Jfe,construct:Wfe,predicate:zfe,represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"}},defaultStyle:"lowercase"})});var TU=w((RZe,NU)=>{"use strict";var Vfe=si();function Xfe(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 Zfe(r){return r==="true"||r==="True"||r==="TRUE"}function _fe(r){return Object.prototype.toString.call(r)==="[object Boolean]"}NU.exports=new Vfe("tag:yaml.org,2002:bool",{kind:"scalar",resolve:Xfe,construct:Zfe,predicate:_fe,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 MU=w((FZe,LU)=>{"use strict";var $fe=tc(),ehe=si();function the(r){return 48<=r&&r<=57||65<=r&&r<=70||97<=r&&r<=102}function rhe(r){return 48<=r&&r<=55}function ihe(r){return 48<=r&&r<=57}function nhe(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 UU=w((NZe,KU)=>{"use strict";var OU=tc(),ahe=si(),Ahe=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 lhe(r){return!(r===null||!Ahe.test(r)||r[r.length-1]==="_")}function che(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 uhe=/^[-+]?[0-9]+e/;function ghe(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(OU.isNegativeZero(r))return"-0.0";return t=r.toString(10),uhe.test(t)?t.replace("e",".e"):t}function fhe(r){return Object.prototype.toString.call(r)==="[object Number]"&&(r%1!==0||OU.isNegativeZero(r))}KU.exports=new ahe("tag:yaml.org,2002:float",{kind:"scalar",resolve:lhe,construct:che,predicate:fhe,represent:ghe,defaultStyle:"lowercase"})});var YS=w((TZe,HU)=>{"use strict";var hhe=rc();HU.exports=new hhe({include:[CI()],implicit:[FU(),TU(),MU(),UU()]})});var jS=w((LZe,GU)=>{"use strict";var phe=rc();GU.exports=new phe({include:[YS()]})});var JU=w((MZe,qU)=>{"use strict";var dhe=si(),YU=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),jU=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 Che(r){return r===null?!1:YU.exec(r)!==null||jU.exec(r)!==null}function mhe(r){var e,t,i,n,s,o,a,l=0,c=null,u,g,f;if(e=YU.exec(r),e===null&&(e=jU.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)),f=new Date(Date.UTC(t,i,n,s,o,a,l)),c&&f.setTime(f.getTime()-c),f}function Ehe(r){return r.toISOString()}qU.exports=new dhe("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:Che,construct:mhe,instanceOf:Date,represent:Ehe})});var zU=w((OZe,WU)=>{"use strict";var Ihe=si();function yhe(r){return r==="<<"||r===null}WU.exports=new Ihe("tag:yaml.org,2002:merge",{kind:"scalar",resolve:yhe})});var ZU=w((KZe,XU)=>{"use strict";var ic;try{VU=J,ic=VU("buffer").Buffer}catch{}var VU,whe=si(),qS=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= +\r`;function Bhe(r){if(r===null)return!1;var e,t,i=0,n=r.length,s=qS;for(t=0;t64)){if(e<0)return!1;i+=6}return i%8===0}function bhe(r){var e,t,i=r.replace(/[\r\n=]/g,""),n=i.length,s=qS,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),ic?ic.from?ic.from(a):new ic(a):a}function Qhe(r){var e="",t=0,i,n,s=r.length,o=qS;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 She(r){return ic&&ic.isBuffer(r)}XU.exports=new whe("tag:yaml.org,2002:binary",{kind:"scalar",resolve:Bhe,construct:bhe,predicate:She,represent:Qhe})});var $U=w((HZe,_U)=>{"use strict";var vhe=si(),xhe=Object.prototype.hasOwnProperty,Phe=Object.prototype.toString;function Dhe(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 Rhe=si(),Fhe=Object.prototype.toString;function Nhe(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 Lhe=si(),Mhe=Object.prototype.hasOwnProperty;function Ohe(r){if(r===null)return!0;var e,t=r;for(e in t)if(Mhe.call(t,e)&&t[e]!==null)return!1;return!0}function Khe(r){return r!==null?r:{}}r2.exports=new Lhe("tag:yaml.org,2002:set",{kind:"mapping",resolve:Ohe,construct:Khe})});var Lg=w((jZe,n2)=>{"use strict";var Uhe=rc();n2.exports=new Uhe({include:[jS()],implicit:[JU(),zU()],explicit:[ZU(),$U(),t2(),i2()]})});var o2=w((qZe,s2)=>{"use strict";var Hhe=si();function Ghe(){return!0}function Yhe(){}function jhe(){return""}function qhe(r){return typeof r>"u"}s2.exports=new Hhe("tag:yaml.org,2002:js/undefined",{kind:"scalar",resolve:Ghe,construct:Yhe,predicate:qhe,represent:jhe})});var A2=w((JZe,a2)=>{"use strict";var Jhe=si();function Whe(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 zhe(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 Vhe(r){var e="/"+r.source+"/";return r.global&&(e+="g"),r.multiline&&(e+="m"),r.ignoreCase&&(e+="i"),e}function Xhe(r){return Object.prototype.toString.call(r)==="[object RegExp]"}a2.exports=new Jhe("tag:yaml.org,2002:js/regexp",{kind:"scalar",resolve:Whe,construct:zhe,predicate:Xhe,represent:Vhe})});var u2=w((WZe,c2)=>{"use strict";var mI;try{l2=J,mI=l2("esprima")}catch{typeof window<"u"&&(mI=window.esprima)}var l2,Zhe=si();function _he(r){if(r===null)return!1;try{var e="("+r+")",t=mI.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 $he(r){var e="("+r+")",t=mI.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 epe(r){return r.toString()}function tpe(r){return Object.prototype.toString.call(r)==="[object Function]"}c2.exports=new Zhe("tag:yaml.org,2002:js/function",{kind:"scalar",resolve:_he,construct:$he,predicate:tpe,represent:epe})});var Xp=w((VZe,f2)=>{"use strict";var g2=rc();f2.exports=g2.DEFAULT=new g2({include:[Lg()],explicit:[o2(),A2(),u2()]})});var R2=w((XZe,Zp)=>{"use strict";var Ba=tc(),I2=Ng(),rpe=IU(),y2=Lg(),ipe=Xp(),RA=Object.prototype.hasOwnProperty,EI=1,w2=2,B2=3,II=4,JS=1,npe=2,h2=3,spe=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,ope=/[\x85\u2028\u2029]/,ape=/[,\[\]\{\}]/,b2=/^(?:!|!!|![a-z\-]+!)$/i,Q2=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;function p2(r){return Object.prototype.toString.call(r)}function vo(r){return r===10||r===13}function sc(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 Ape(r){var e;return 48<=r&&r<=57?r-48:(e=r|32,97<=e&&e<=102?e-97+10:-1)}function lpe(r){return r===120?2:r===117?4:r===85?8:0}function cpe(r){return 48<=r&&r<=57?r-48:-1}function d2(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 upe(r){return r<=65535?String.fromCharCode(r):String.fromCharCode((r-65536>>10)+55296,(r-65536&1023)+56320)}var S2=new Array(256),v2=new Array(256);for(nc=0;nc<256;nc++)S2[nc]=d2(nc)?1:0,v2[nc]=d2(nc);var nc;function gpe(r,e){this.input=r,this.filename=e.filename||null,this.schema=e.schema||ipe,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 x2(r,e){return new I2(e,new rpe(r.filename,r.input,r.position,r.line,r.position-r.lineStart))}function ft(r,e){throw x2(r,e)}function yI(r,e){r.onWarning&&r.onWarning.call(null,x2(r,e))}var C2={YAML:function(e,t,i){var n,s,o;e.version!==null&&ft(e,"duplication of %YAML directive"),i.length!==1&&ft(e,"YAML directive accepts exactly one argument"),n=/^([0-9]+)\.([0-9]+)$/.exec(i[0]),n===null&&ft(e,"ill-formed argument of the YAML directive"),s=parseInt(n[1],10),o=parseInt(n[2],10),s!==1&&ft(e,"unacceptable YAML version of the document"),e.version=i[0],e.checkLineBreaks=o<2,o!==1&&o!==2&&yI(e,"unsupported YAML version of the document")},TAG:function(e,t,i){var n,s;i.length!==2&&ft(e,"TAG directive accepts exactly two arguments"),n=i[0],s=i[1],b2.test(n)||ft(e,"ill-formed tag handle (first argument) of the TAG directive"),RA.call(e.tagMap,n)&&ft(e,'there is a previously declared suffix for "'+n+'" tag handle'),Q2.test(s)||ft(e,"ill-formed tag prefix (second argument) of the TAG directive"),e.tagMap[n]=s}};function kA(r,e,t,i){var n,s,o,a;if(e1&&(r.result+=Ba.repeat(` +`,e-1))}function fpe(r,e,t){var i,n,s,o,a,l,c,u,g=r.kind,f=r.result,h;if(h=r.input.charCodeAt(r.position),fn(h)||Mg(h)||h===35||h===38||h===42||h===33||h===124||h===62||h===39||h===34||h===37||h===64||h===96||(h===63||h===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;h!==0;){if(h===58){if(n=r.input.charCodeAt(r.position+1),fn(n)||t&&Mg(n))break}else if(h===35){if(i=r.input.charCodeAt(r.position-1),fn(i))break}else{if(r.position===r.lineStart&&wI(r)||t&&Mg(h))break;if(vo(h))if(l=r.line,c=r.lineStart,u=r.lineIndent,zr(r,!1,-1),r.lineIndent>=e){a=!0,h=r.input.charCodeAt(r.position);continue}else{r.position=o,r.line=l,r.lineStart=c,r.lineIndent=u;break}}a&&(kA(r,s,o,!1),zS(r,r.line-l),s=o=r.position,a=!1),sc(h)||(o=r.position+1),h=r.input.charCodeAt(++r.position)}return kA(r,s,o,!1),r.result?!0:(r.kind=g,r.result=f,!1)}function hpe(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(kA(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)?(kA(r,i,n,!0),zS(r,zr(r,!1,e)),i=n=r.position):r.position===r.lineStart&&wI(r)?ft(r,"unexpected end of the document within a single quoted scalar"):(r.position++,n=r.position);ft(r,"unexpected end of the stream within a single quoted scalar")}function ppe(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 kA(r,t,r.position,!0),r.position++,!0;if(a===92){if(kA(r,t,r.position,!0),a=r.input.charCodeAt(++r.position),vo(a))zr(r,!1,e);else if(a<256&&S2[a])r.result+=v2[a],r.position++;else if((o=lpe(a))>0){for(n=o,s=0;n>0;n--)a=r.input.charCodeAt(++r.position),(o=Ape(a))>=0?s=(s<<4)+o:ft(r,"expected hexadecimal character");r.result+=upe(s),r.position++}else ft(r,"unknown escape sequence");t=i=r.position}else vo(a)?(kA(r,t,i,!0),zS(r,zr(r,!1,e)),t=i=r.position):r.position===r.lineStart&&wI(r)?ft(r,"unexpected end of the document within a double quoted scalar"):(r.position++,i=r.position)}ft(r,"unexpected end of the stream within a double quoted scalar")}function dpe(r,e){var t=!0,i,n=r.tag,s,o=r.anchor,a,l,c,u,g,f={},h,p,C,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(zr(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||ft(r,"missed comma between flow collection entries"),p=h=C=null,c=u=!1,y===63&&(a=r.input.charCodeAt(r.position+1),fn(a)&&(c=u=!0,r.position++,zr(r,!0,e))),i=r.line,Kg(r,e,EI,!1,!0),p=r.tag,h=r.result,zr(r,!0,e),y=r.input.charCodeAt(r.position),(u||r.line===i)&&y===58&&(c=!0,y=r.input.charCodeAt(++r.position),zr(r,!0,e),Kg(r,e,EI,!1,!0),C=r.result),g?Og(r,s,f,p,h,C):c?s.push(Og(r,null,f,p,h,C)):s.push(h),zr(r,!0,e),y=r.input.charCodeAt(r.position),y===44?(t=!0,y=r.input.charCodeAt(++r.position)):t=!1}ft(r,"unexpected end of the stream within a flow collection")}function Cpe(r,e){var t,i,n=JS,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)JS===n?n=g===43?h2:npe:ft(r,"repeat of a chomping mode identifier");else if((u=cpe(g))>=0)u===0?ft(r,"bad explicit indentation width of a block scalar; it cannot be less than one"):o?ft(r,"repeat of an indentation width identifier"):(a=e+u-1,o=!0);else break;if(sc(g)){do g=r.input.charCodeAt(++r.position);while(sc(g));if(g===35)do g=r.input.charCodeAt(++r.position);while(!vo(g)&&g!==0)}for(;g!==0;){for(WS(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)ft(r,"bad indentation of a sequence entry");else if(r.lineIndente)&&(Kg(r,e,II,!0,n)&&(p?f=r.result:h=r.result),p||(Og(r,c,u,g,f,h,s,o),g=f=h=null),zr(r,!0,-1),y=r.input.charCodeAt(r.position)),r.lineIndent>e&&y!==0)ft(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,f=r.implicitTypes.length;g tag; it should be "'+h.kind+'", not "'+r.kind+'"'),h.resolve(r.result)?(r.result=h.construct(r.result),r.anchor!==null&&(r.anchorMap[r.anchor]=r.result)):ft(r,"cannot resolve a node with !<"+r.tag+"> explicit tag")):ft(r,"unknown tag !<"+r.tag+">");return r.listener!==null&&r.listener("close",r),r.tag!==null||r.anchor!==null||u}function wpe(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&&(zr(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&&ft(r,"directive name must not be less than one character in length");o!==0;){for(;sc(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&&WS(r),RA.call(C2,i)?C2[i](r,i,n):yI(r,'unknown document directive "'+i+'"')}if(zr(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,zr(r,!0,-1)):s&&ft(r,"directives end mark is expected"),Kg(r,r.lineIndent-1,II,!1,!0),zr(r,!0,-1),r.checkLineBreaks&&ope.test(r.input.slice(e,r.position))&&yI(r,"non-ASCII line breaks are interpreted as content"),r.documents.push(r.result),r.position===r.lineStart&&wI(r)){r.input.charCodeAt(r.position)===46&&(r.position+=3,zr(r,!0,-1));return}if(r.position"u"&&(t=e,e=null);var i=P2(r,t);if(typeof e!="function")return i;for(var n=0,s=i.length;n"u"&&(t=e,e=null),D2(r,e,Ba.extend({schema:y2},t))}function bpe(r,e){return k2(r,Ba.extend({schema:y2},e))}Zp.exports.loadAll=D2;Zp.exports.load=k2;Zp.exports.safeLoadAll=Bpe;Zp.exports.safeLoad=bpe});var tH=w((ZZe,_S)=>{"use strict";var $p=tc(),ed=Ng(),Qpe=Xp(),Spe=Lg(),U2=Object.prototype.toString,H2=Object.prototype.hasOwnProperty,vpe=9,_p=10,xpe=13,Ppe=32,Dpe=33,kpe=34,G2=35,Rpe=37,Fpe=38,Npe=39,Tpe=42,Y2=44,Lpe=45,j2=58,Mpe=61,Ope=62,Kpe=63,Upe=64,q2=91,J2=93,Hpe=96,W2=123,Gpe=124,z2=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 Ype=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"];function jpe(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,f=f&&T2(o,a)}else{for(s=0;si&&r[g+1]!==" ",g=s);else if(!Ug(o))return BI;a=s>0?r.charCodeAt(s-1):null,f=f&&T2(o,a)}c=c||u&&s-g-1>i&&r[g+1]!==" "}return!l&&!c?f&&!n(r)?X2:Z2:t>9&&V2(r)?BI:c?$2:_2}function Xpe(r,e,t,i){r.dump=function(){if(e.length===0)return"''";if(!r.noCompatMode&&Ype.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 Jpe(r,l)}switch(Vpe(e,o,r.indent,s,a)){case X2:return e;case Z2:return"'"+e.replace(/'/g,"''")+"'";case _2:return"|"+L2(e,r.indent)+M2(N2(e,n));case $2:return">"+L2(e,r.indent)+M2(N2(Zpe(e,s),n));case BI:return'"'+_pe(e,s)+'"';default:throw new ed("impossible error: invalid scalar style")}}()}function L2(r,e){var t=V2(r)?String(e):"",i=r[r.length-1]===` +`,n=i&&(r[r.length-2]===` +`||r===` +`),s=n?"+":i?"":"-";return t+s+` +`}function M2(r){return r[r.length-1]===` +`?r.slice(0,-1):r}function Zpe(r,e){for(var t=/(\n+)([^\n]*)/g,i=function(){var c=r.indexOf(` +`);return c=c!==-1?c:r.length,t.lastIndex=c,O2(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!==""?` +`:"")+O2(l,e),n=s}return i}function O2(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 _pe(r){for(var e="",t,i,n,s=0;s=55296&&t<=56319&&(i=r.charCodeAt(s+1),i>=56320&&i<=57343)){e+=F2((t-55296)*1024+i-56320+65536),s++;continue}n=Ni[t],e+=!n&&Ug(t)?r[s]:n||F2(t)}return e}function $pe(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?"":" "),oc(r,e,c,!1,!1)&&(u+=r.dump,i+=u));r.tag=n,r.dump="{"+i+"}"}function rde(r,e,t,i){var n="",s=r.tag,o=Object.keys(t),a,l,c,u,g,f;if(r.sortKeys===!0)o.sort();else if(typeof r.sortKeys=="function")o.sort(r.sortKeys);else if(r.sortKeys)throw new ed("sortKeys must be a boolean or a function");for(a=0,l=o.length;a1024,g&&(r.dump&&_p===r.dump.charCodeAt(0)?f+="?":f+="? "),f+=r.dump,g&&(f+=VS(r,e)),oc(r,e+1,u,!0,g)&&(r.dump&&_p===r.dump.charCodeAt(0)?f+=":":f+=": ",f+=r.dump,n+=f));r.tag=s,r.dump=n||"{}"}function K2(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 oc(r,e,t,i,n,s){r.tag=null,r.dump=t,K2(r,t,!1)||K2(r,t,!0);var o=U2.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?(rde(r,e,r.dump,n),c&&(r.dump="&ref_"+l+r.dump)):(tde(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?(ede(r,u,r.dump,n),c&&(r.dump="&ref_"+l+r.dump)):($pe(r,u,r.dump),c&&(r.dump="&ref_"+l+" "+r.dump))}else if(o==="[object String]")r.tag!=="?"&&Xpe(r,r.dump,e,s);else{if(r.skipInvalid)return!1;throw new ed("unacceptable kind of an object to dump "+o)}r.tag!==null&&r.tag!=="?"&&(r.dump="!<"+r.tag+"> "+r.dump)}return!0}function ide(r,e){var t=[],i=[],n,s;for(XS(r,t,i),n=0,s=i.length;n{"use strict";var bI=R2(),rH=tH();function QI(r){return function(){throw new Error("Function "+r+" is deprecated and cannot be used.")}}Fr.exports.Type=si();Fr.exports.Schema=rc();Fr.exports.FAILSAFE_SCHEMA=CI();Fr.exports.JSON_SCHEMA=YS();Fr.exports.CORE_SCHEMA=jS();Fr.exports.DEFAULT_SAFE_SCHEMA=Lg();Fr.exports.DEFAULT_FULL_SCHEMA=Xp();Fr.exports.load=bI.load;Fr.exports.loadAll=bI.loadAll;Fr.exports.safeLoad=bI.safeLoad;Fr.exports.safeLoadAll=bI.safeLoadAll;Fr.exports.dump=rH.dump;Fr.exports.safeDump=rH.safeDump;Fr.exports.YAMLException=Ng();Fr.exports.MINIMAL_SCHEMA=CI();Fr.exports.SAFE_SCHEMA=Lg();Fr.exports.DEFAULT_SCHEMA=Xp();Fr.exports.scan=QI("scan");Fr.exports.parse=QI("parse");Fr.exports.compose=QI("compose");Fr.exports.addConstructor=QI("addConstructor")});var sH=w(($Ze,nH)=>{"use strict";var sde=iH();nH.exports=sde});var aH=w((e_e,oH)=>{"use strict";function ode(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function ac(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,ac)}ode(ac,Error);ac.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,f=1;g({[Ke]:Ce})))},H=function(R){return R},j=function(R){return R},$=Us("correct indentation"),V=" ",W=ar(" ",!1),_=function(R){return R.length===QA*yg},A=function(R){return R.length===(QA+1)*yg},Ae=function(){return QA++,!0},ge=function(){return QA--,!0},re=function(){return pg()},M=Us("pseudostring"),F=/^[^\r\n\t ?:,\][{}#&*!|>'"%@`\-]/,ue=Tn(["\r",` +`," "," ","?",":",",","]","[","{","}","#","&","*","!","|",">","'",'"',"%","@","`","-"],!0,!1),pe=/^[^\r\n\t ,\][{}:#"']/,ke=Tn(["\r",` +`," "," ",",","]","[","{","}",":","#",'"',"'"],!0,!1),Fe=function(){return pg().replace(/^ *| *$/g,"")},Ne="--",oe=ar("--",!1),le=/^[a-zA-Z\/0-9]/,Be=Tn([["a","z"],["A","Z"],"/",["0","9"]],!1,!1),fe=/^[^\r\n\t :,]/,ae=Tn(["\r",` +`," "," ",":",","],!0,!1),qe="null",ne=ar("null",!1),Y=function(){return null},he="true",ie=ar("true",!1),de=function(){return!0},_e="false",Pt=ar("false",!1),It=function(){return!1},Mr=Us("string"),ii='"',gi=ar('"',!1),hr=function(){return""},fi=function(R){return R},ni=function(R){return R.join("")},Ks=/^[^"\\\0-\x1F\x7F]/,pr=Tn(['"',"\\",["\0",""],"\x7F"],!0,!1),Ii='\\"',rs=ar('\\"',!1),fa=function(){return'"'},CA="\\\\",cg=ar("\\\\",!1),is=function(){return"\\"},mA="\\/",ha=ar("\\/",!1),wp=function(){return"/"},EA="\\b",IA=ar("\\b",!1),wr=function(){return"\b"},Tl="\\f",ug=ar("\\f",!1),Io=function(){return"\f"},gg="\\n",Bp=ar("\\n",!1),bp=function(){return` +`},vr="\\r",se=ar("\\r",!1),yo=function(){return"\r"},Fn="\\t",fg=ar("\\t",!1),bt=function(){return" "},Ll="\\u",Nn=ar("\\u",!1),ns=function(R,q,Ce,Ke){return String.fromCharCode(parseInt(`0x${R}${q}${Ce}${Ke}`))},ss=/^[0-9a-fA-F]/,gt=Tn([["0","9"],["a","f"],["A","F"]],!1,!1),wo=Us("blank space"),At=/^[ \t]/,ln=Tn([" "," "],!1,!1),S=Us("white space"),Lt=/^[ \t\n\r]/,hg=Tn([" "," ",` +`,"\r"],!1,!1),Ml=`\r +`,Qp=ar(`\r +`,!1),Sp=` +`,vp=ar(` +`,!1),xp="\r",Pp=ar("\r",!1),G=0,yt=0,yA=[{line:1,column:1}],zi=0,Ol=[],Xe=0,pa;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 pg(){return r.substring(yt,G)}function ME(){return cn(yt,G)}function Dp(R,q){throw q=q!==void 0?q:cn(yt,G),Ul([Us(R)],r.substring(yt,G),q)}function OE(R,q){throw q=q!==void 0?q:cn(yt,G),dg(R,q)}function ar(R,q){return{type:"literal",text:R,ignoreCase:q}}function Tn(R,q,Ce){return{type:"class",parts:R,inverted:q,ignoreCase:Ce}}function Kl(){return{type:"any"}}function kp(){return{type:"end"}}function Us(R){return{type:"other",description:R}}function da(R){var q=yA[R],Ce;if(q)return q;for(Ce=R-1;!yA[Ce];)Ce--;for(q=yA[Ce],q={line:q.line,column:q.column};Cezi&&(zi=G,Ol=[]),Ol.push(R))}function dg(R,q){return new ac(R,null,null,q)}function Ul(R,q,Ce){return new ac(ac.buildMessage(R,q),R,q,Ce)}function Hs(){var R;return R=Cg(),R}function Hl(){var R,q,Ce;for(R=G,q=[],Ce=wA();Ce!==t;)q.push(Ce),Ce=wA();return q!==t&&(yt=R,q=s(q)),R=q,R}function wA(){var R,q,Ce,Ke,Re;return R=G,q=ma(),q!==t?(r.charCodeAt(G)===45?(Ce=o,G++):(Ce=t,Xe===0&&Le(a)),Ce!==t?(Ke=Rr(),Ke!==t?(Re=Ca(),Re!==t?(yt=R,q=l(Re),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R}function Cg(){var R,q,Ce;for(R=G,q=[],Ce=mg();Ce!==t;)q.push(Ce),Ce=mg();return q!==t&&(yt=R,q=c(q)),R=q,R}function mg(){var R,q,Ce,Ke,Re,ze,dt,Ft,Ln;if(R=G,q=Rr(),q===t&&(q=null),q!==t){if(Ce=G,r.charCodeAt(G)===35?(Ke=u,G++):(Ke=t,Xe===0&&Le(g)),Ke!==t){if(Re=[],ze=G,dt=G,Xe++,Ft=js(),Xe--,Ft===t?dt=void 0:(G=dt,dt=t),dt!==t?(r.length>G?(Ft=r.charAt(G),G++):(Ft=t,Xe===0&&Le(f)),Ft!==t?(dt=[dt,Ft],ze=dt):(G=ze,ze=t)):(G=ze,ze=t),ze!==t)for(;ze!==t;)Re.push(ze),ze=G,dt=G,Xe++,Ft=js(),Xe--,Ft===t?dt=void 0:(G=dt,dt=t),dt!==t?(r.length>G?(Ft=r.charAt(G),G++):(Ft=t,Xe===0&&Le(f)),Ft!==t?(dt=[dt,Ft],ze=dt):(G=ze,ze=t)):(G=ze,ze=t);else Re=t;Re!==t?(Ke=[Ke,Re],Ce=Ke):(G=Ce,Ce=t)}else G=Ce,Ce=t;if(Ce===t&&(Ce=null),Ce!==t){if(Ke=[],Re=Ys(),Re!==t)for(;Re!==t;)Ke.push(Re),Re=Ys();else Ke=t;Ke!==t?(yt=R,q=h(),R=q):(G=R,R=t)}else G=R,R=t}else G=R,R=t;if(R===t&&(R=G,q=ma(),q!==t?(Ce=Gl(),Ce!==t?(Ke=Rr(),Ke===t&&(Ke=null),Ke!==t?(r.charCodeAt(G)===58?(Re=p,G++):(Re=t,Xe===0&&Le(C)),Re!==t?(ze=Rr(),ze===t&&(ze=null),ze!==t?(dt=Ca(),dt!==t?(yt=R,q=y(Ce,dt),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R===t&&(R=G,q=ma(),q!==t?(Ce=Gs(),Ce!==t?(Ke=Rr(),Ke===t&&(Ke=null),Ke!==t?(r.charCodeAt(G)===58?(Re=p,G++):(Re=t,Xe===0&&Le(C)),Re!==t?(ze=Rr(),ze===t&&(ze=null),ze!==t?(dt=Ca(),dt!==t?(yt=R,q=y(Ce,dt),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R===t))){if(R=G,q=ma(),q!==t)if(Ce=Gs(),Ce!==t)if(Ke=Rr(),Ke!==t)if(Re=KE(),Re!==t){if(ze=[],dt=Ys(),dt!==t)for(;dt!==t;)ze.push(dt),dt=Ys();else ze=t;ze!==t?(yt=R,q=y(Ce,Re),R=q):(G=R,R=t)}else G=R,R=t;else G=R,R=t;else G=R,R=t;else G=R,R=t;if(R===t)if(R=G,q=ma(),q!==t)if(Ce=Gs(),Ce!==t){if(Ke=[],Re=G,ze=Rr(),ze===t&&(ze=null),ze!==t?(r.charCodeAt(G)===44?(dt=B,G++):(dt=t,Xe===0&&Le(v)),dt!==t?(Ft=Rr(),Ft===t&&(Ft=null),Ft!==t?(Ln=Gs(),Ln!==t?(yt=Re,ze=D(Ce,Ln),Re=ze):(G=Re,Re=t)):(G=Re,Re=t)):(G=Re,Re=t)):(G=Re,Re=t),Re!==t)for(;Re!==t;)Ke.push(Re),Re=G,ze=Rr(),ze===t&&(ze=null),ze!==t?(r.charCodeAt(G)===44?(dt=B,G++):(dt=t,Xe===0&&Le(v)),dt!==t?(Ft=Rr(),Ft===t&&(Ft=null),Ft!==t?(Ln=Gs(),Ln!==t?(yt=Re,ze=D(Ce,Ln),Re=ze):(G=Re,Re=t)):(G=Re,Re=t)):(G=Re,Re=t)):(G=Re,Re=t);else Ke=t;Ke!==t?(Re=Rr(),Re===t&&(Re=null),Re!==t?(r.charCodeAt(G)===58?(ze=p,G++):(ze=t,Xe===0&&Le(C)),ze!==t?(dt=Rr(),dt===t&&(dt=null),dt!==t?(Ft=Ca(),Ft!==t?(yt=R,q=T(Ce,Ke,Ft),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)}else G=R,R=t;else G=R,R=t}return R}function Ca(){var R,q,Ce,Ke,Re,ze,dt;if(R=G,q=G,Xe++,Ce=G,Ke=js(),Ke!==t?(Re=rt(),Re!==t?(r.charCodeAt(G)===45?(ze=o,G++):(ze=t,Xe===0&&Le(a)),ze!==t?(dt=Rr(),dt!==t?(Ke=[Ke,Re,ze,dt],Ce=Ke):(G=Ce,Ce=t)):(G=Ce,Ce=t)):(G=Ce,Ce=t)):(G=Ce,Ce=t),Xe--,Ce!==t?(G=q,q=void 0):q=t,q!==t?(Ce=Ys(),Ce!==t?(Ke=Bo(),Ke!==t?(Re=Hl(),Re!==t?(ze=BA(),ze!==t?(yt=R,q=H(Re),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R===t&&(R=G,q=js(),q!==t?(Ce=Bo(),Ce!==t?(Ke=Cg(),Ke!==t?(Re=BA(),Re!==t?(yt=R,q=H(Ke),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R===t))if(R=G,q=Yl(),q!==t){if(Ce=[],Ke=Ys(),Ke!==t)for(;Ke!==t;)Ce.push(Ke),Ke=Ys();else Ce=t;Ce!==t?(yt=R,q=j(q),R=q):(G=R,R=t)}else G=R,R=t;return R}function ma(){var R,q,Ce;for(Xe++,R=G,q=[],r.charCodeAt(G)===32?(Ce=V,G++):(Ce=t,Xe===0&&Le(W));Ce!==t;)q.push(Ce),r.charCodeAt(G)===32?(Ce=V,G++):(Ce=t,Xe===0&&Le(W));return q!==t?(yt=G,Ce=_(q),Ce?Ce=void 0:Ce=t,Ce!==t?(q=[q,Ce],R=q):(G=R,R=t)):(G=R,R=t),Xe--,R===t&&(q=t,Xe===0&&Le($)),R}function rt(){var R,q,Ce;for(R=G,q=[],r.charCodeAt(G)===32?(Ce=V,G++):(Ce=t,Xe===0&&Le(W));Ce!==t;)q.push(Ce),r.charCodeAt(G)===32?(Ce=V,G++):(Ce=t,Xe===0&&Le(W));return q!==t?(yt=G,Ce=A(q),Ce?Ce=void 0:Ce=t,Ce!==t?(q=[q,Ce],R=q):(G=R,R=t)):(G=R,R=t),R}function Bo(){var R;return yt=G,R=Ae(),R?R=void 0:R=t,R}function BA(){var R;return yt=G,R=ge(),R?R=void 0:R=t,R}function Gl(){var R;return R=jl(),R===t&&(R=Rp()),R}function Gs(){var R,q,Ce;if(R=jl(),R===t){if(R=G,q=[],Ce=Eg(),Ce!==t)for(;Ce!==t;)q.push(Ce),Ce=Eg();else q=t;q!==t&&(yt=R,q=re()),R=q}return R}function Yl(){var R;return R=Fp(),R===t&&(R=UE(),R===t&&(R=jl(),R===t&&(R=Rp()))),R}function KE(){var R;return R=Fp(),R===t&&(R=jl(),R===t&&(R=Eg())),R}function Rp(){var R,q,Ce,Ke,Re,ze;if(Xe++,R=G,F.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(ue)),q!==t){for(Ce=[],Ke=G,Re=Rr(),Re===t&&(Re=null),Re!==t?(pe.test(r.charAt(G))?(ze=r.charAt(G),G++):(ze=t,Xe===0&&Le(ke)),ze!==t?(Re=[Re,ze],Ke=Re):(G=Ke,Ke=t)):(G=Ke,Ke=t);Ke!==t;)Ce.push(Ke),Ke=G,Re=Rr(),Re===t&&(Re=null),Re!==t?(pe.test(r.charAt(G))?(ze=r.charAt(G),G++):(ze=t,Xe===0&&Le(ke)),ze!==t?(Re=[Re,ze],Ke=Re):(G=Ke,Ke=t)):(G=Ke,Ke=t);Ce!==t?(yt=R,q=Fe(),R=q):(G=R,R=t)}else G=R,R=t;return Xe--,R===t&&(q=t,Xe===0&&Le(M)),R}function Eg(){var R,q,Ce,Ke,Re;if(R=G,r.substr(G,2)===Ne?(q=Ne,G+=2):(q=t,Xe===0&&Le(oe)),q===t&&(q=null),q!==t)if(le.test(r.charAt(G))?(Ce=r.charAt(G),G++):(Ce=t,Xe===0&&Le(Be)),Ce!==t){for(Ke=[],fe.test(r.charAt(G))?(Re=r.charAt(G),G++):(Re=t,Xe===0&&Le(ae));Re!==t;)Ke.push(Re),fe.test(r.charAt(G))?(Re=r.charAt(G),G++):(Re=t,Xe===0&&Le(ae));Ke!==t?(yt=R,q=Fe(),R=q):(G=R,R=t)}else G=R,R=t;else G=R,R=t;return R}function Fp(){var R,q;return R=G,r.substr(G,4)===qe?(q=qe,G+=4):(q=t,Xe===0&&Le(ne)),q!==t&&(yt=R,q=Y()),R=q,R}function UE(){var R,q;return R=G,r.substr(G,4)===he?(q=he,G+=4):(q=t,Xe===0&&Le(ie)),q!==t&&(yt=R,q=de()),R=q,R===t&&(R=G,r.substr(G,5)===_e?(q=_e,G+=5):(q=t,Xe===0&&Le(Pt)),q!==t&&(yt=R,q=It()),R=q),R}function jl(){var R,q,Ce,Ke;return Xe++,R=G,r.charCodeAt(G)===34?(q=ii,G++):(q=t,Xe===0&&Le(gi)),q!==t?(r.charCodeAt(G)===34?(Ce=ii,G++):(Ce=t,Xe===0&&Le(gi)),Ce!==t?(yt=R,q=hr(),R=q):(G=R,R=t)):(G=R,R=t),R===t&&(R=G,r.charCodeAt(G)===34?(q=ii,G++):(q=t,Xe===0&&Le(gi)),q!==t?(Ce=HE(),Ce!==t?(r.charCodeAt(G)===34?(Ke=ii,G++):(Ke=t,Xe===0&&Le(gi)),Ke!==t?(yt=R,q=fi(Ce),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)),Xe--,R===t&&(q=t,Xe===0&&Le(Mr)),R}function HE(){var R,q,Ce;if(R=G,q=[],Ce=Ig(),Ce!==t)for(;Ce!==t;)q.push(Ce),Ce=Ig();else q=t;return q!==t&&(yt=R,q=ni(q)),R=q,R}function Ig(){var R,q,Ce,Ke,Re,ze;return Ks.test(r.charAt(G))?(R=r.charAt(G),G++):(R=t,Xe===0&&Le(pr)),R===t&&(R=G,r.substr(G,2)===Ii?(q=Ii,G+=2):(q=t,Xe===0&&Le(rs)),q!==t&&(yt=R,q=fa()),R=q,R===t&&(R=G,r.substr(G,2)===CA?(q=CA,G+=2):(q=t,Xe===0&&Le(cg)),q!==t&&(yt=R,q=is()),R=q,R===t&&(R=G,r.substr(G,2)===mA?(q=mA,G+=2):(q=t,Xe===0&&Le(ha)),q!==t&&(yt=R,q=wp()),R=q,R===t&&(R=G,r.substr(G,2)===EA?(q=EA,G+=2):(q=t,Xe===0&&Le(IA)),q!==t&&(yt=R,q=wr()),R=q,R===t&&(R=G,r.substr(G,2)===Tl?(q=Tl,G+=2):(q=t,Xe===0&&Le(ug)),q!==t&&(yt=R,q=Io()),R=q,R===t&&(R=G,r.substr(G,2)===gg?(q=gg,G+=2):(q=t,Xe===0&&Le(Bp)),q!==t&&(yt=R,q=bp()),R=q,R===t&&(R=G,r.substr(G,2)===vr?(q=vr,G+=2):(q=t,Xe===0&&Le(se)),q!==t&&(yt=R,q=yo()),R=q,R===t&&(R=G,r.substr(G,2)===Fn?(q=Fn,G+=2):(q=t,Xe===0&&Le(fg)),q!==t&&(yt=R,q=bt()),R=q,R===t&&(R=G,r.substr(G,2)===Ll?(q=Ll,G+=2):(q=t,Xe===0&&Le(Nn)),q!==t?(Ce=bA(),Ce!==t?(Ke=bA(),Ke!==t?(Re=bA(),Re!==t?(ze=bA(),ze!==t?(yt=R,q=ns(Ce,Ke,Re,ze),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)))))))))),R}function bA(){var R;return ss.test(r.charAt(G))?(R=r.charAt(G),G++):(R=t,Xe===0&&Le(gt)),R}function Rr(){var R,q;if(Xe++,R=[],At.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(ln)),q!==t)for(;q!==t;)R.push(q),At.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(ln));else R=t;return Xe--,R===t&&(q=t,Xe===0&&Le(wo)),R}function GE(){var R,q;if(Xe++,R=[],Lt.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(hg)),q!==t)for(;q!==t;)R.push(q),Lt.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(hg));else R=t;return Xe--,R===t&&(q=t,Xe===0&&Le(S)),R}function Ys(){var R,q,Ce,Ke,Re,ze;if(R=G,q=js(),q!==t){for(Ce=[],Ke=G,Re=Rr(),Re===t&&(Re=null),Re!==t?(ze=js(),ze!==t?(Re=[Re,ze],Ke=Re):(G=Ke,Ke=t)):(G=Ke,Ke=t);Ke!==t;)Ce.push(Ke),Ke=G,Re=Rr(),Re===t&&(Re=null),Re!==t?(ze=js(),ze!==t?(Re=[Re,ze],Ke=Re):(G=Ke,Ke=t)):(G=Ke,Ke=t);Ce!==t?(q=[q,Ce],R=q):(G=R,R=t)}else G=R,R=t;return R}function js(){var R;return r.substr(G,2)===Ml?(R=Ml,G+=2):(R=t,Xe===0&&Le(Qp)),R===t&&(r.charCodeAt(G)===10?(R=Sp,G++):(R=t,Xe===0&&Le(vp)),R===t&&(r.charCodeAt(G)===13?(R=xp,G++):(R=t,Xe===0&&Le(Pp)))),R}let yg=2,QA=0;if(pa=n(),pa!==t&&G===r.length)return pa;throw pa!==t&&G{"use strict";var gde=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=gde(r)),r=r.replace(/^[_.\- ]+/,"").toLowerCase().replace(/[_.\- ]+(\w|$)/g,(n,s)=>s.toUpperCase()).replace(/\d+(\w|$)/g,n=>n.toUpperCase()),t(r))};ev.exports=gH;ev.exports.default=gH});var hH=w((o_e,fde)=>{fde.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 Ac=w(Un=>{"use strict";var dH=hH(),xo=process.env;Object.defineProperty(Un,"_vendors",{value:dH.map(function(r){return r.constant})});Un.name=null;Un.isPR=null;dH.forEach(function(r){let t=(Array.isArray(r.env)?r.env:[r.env]).every(function(i){return pH(i)});if(Un[r.constant]=t,t)switch(Un.name=r.name,typeof r.pr){case"string":Un.isPR=!!xo[r.pr];break;case"object":"env"in r.pr?Un.isPR=r.pr.env in xo&&xo[r.pr.env]!==r.pr.ne:"any"in r.pr?Un.isPR=r.pr.any.some(function(i){return!!xo[i]}):Un.isPR=pH(r.pr);break;default:Un.isPR=null}});Un.isCI=!!(xo.CI||xo.CONTINUOUS_INTEGRATION||xo.BUILD_NUMBER||xo.RUN_ID||Un.name);function pH(r){return typeof r=="string"?!!xo[r]:Object.keys(r).every(function(e){return xo[e]===r[e]})}});var hn={};ut(hn,{KeyRelationship:()=>lc,applyCascade:()=>od,base64RegExp:()=>yH,colorStringAlphaRegExp:()=>IH,colorStringRegExp:()=>EH,computeKey:()=>FA,getPrintable:()=>Vr,hasExactLength:()=>SH,hasForbiddenKeys:()=>qde,hasKeyRelationship:()=>av,hasMaxLength:()=>xde,hasMinLength:()=>vde,hasMutuallyExclusiveKeys:()=>Jde,hasRequiredKeys:()=>jde,hasUniqueItems:()=>Pde,isArray:()=>Ede,isAtLeast:()=>Rde,isAtMost:()=>Fde,isBase64:()=>Gde,isBoolean:()=>dde,isDate:()=>mde,isDict:()=>yde,isEnum:()=>Zi,isHexColor:()=>Hde,isISO8601:()=>Ude,isInExclusiveRange:()=>Tde,isInInclusiveRange:()=>Nde,isInstanceOf:()=>Bde,isInteger:()=>Lde,isJSON:()=>Yde,isLiteral:()=>hde,isLowerCase:()=>Mde,isNegative:()=>Dde,isNullable:()=>Sde,isNumber:()=>Cde,isObject:()=>wde,isOneOf:()=>bde,isOptional:()=>Qde,isPositive:()=>kde,isString:()=>sd,isTuple:()=>Ide,isUUID4:()=>Kde,isUnknown:()=>QH,isUpperCase:()=>Ode,iso8601RegExp:()=>ov,makeCoercionFn:()=>cc,makeSetter:()=>bH,makeTrait:()=>BH,makeValidator:()=>Qt,matchesRegExp:()=>ad,plural:()=>kI,pushError:()=>pt,simpleKeyRegExp:()=>mH,uuid4RegExp:()=>wH});function Qt({test:r}){return BH(r)()}function Vr(r){return r===null?"null":r===void 0?"undefined":r===""?"an empty string":JSON.stringify(r)}function FA(r,e){var t,i,n;return typeof e=="number"?`${(t=r==null?void 0:r.p)!==null&&t!==void 0?t:"."}[${e}]`:mH.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 cc(r,e){return t=>{let i=r[e];return r[e]=t,cc(r,e).bind(null,i)}}function bH(r,e){return t=>{r[e]=t}}function kI(r,e,t){return r===1?e:t}function pt({errors:r,p:e}={},t){return r==null||r.push(`${e!=null?e:"."}: ${t}`),!1}function hde(r){return Qt({test:(e,t)=>e!==r?pt(t,`Expected a literal (got ${Vr(r)})`):!0})}function Zi(r){let e=Array.isArray(r)?r:Object.values(r),t=new Set(e);return Qt({test:(i,n)=>t.has(i)?!0:pt(n,`Expected a valid enumeration value (got ${Vr(i)})`)})}var mH,EH,IH,yH,wH,ov,BH,QH,sd,pde,dde,Cde,mde,Ede,Ide,yde,wde,Bde,bde,od,Qde,Sde,vde,xde,SH,Pde,Dde,kde,Rde,Fde,Nde,Tde,Lde,ad,Mde,Ode,Kde,Ude,Hde,Gde,Yde,jde,qde,Jde,lc,Wde,av,ls=Fge(()=>{mH=/^[a-zA-Z_][a-zA-Z0-9_]*$/,EH=/^#[0-9a-f]{6}$/i,IH=/^#[0-9a-f]{6}([0-9a-f]{2})?$/i,yH=/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/,wH=/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$/i,ov=/^(?:[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)?)$/,BH=r=>()=>r;QH=()=>Qt({test:(r,e)=>!0});sd=()=>Qt({test:(r,e)=>typeof r!="string"?pt(e,`Expected a string (got ${Vr(r)})`):!0});pde=new Map([["true",!0],["True",!0],["1",!0],[1,!0],["false",!1],["False",!1],["0",!1],[0,!1]]),dde=()=>Qt({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 pt(e,"Unbound coercion result");let i=pde.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 pt(e,`Expected a boolean (got ${Vr(r)})`)}return!0}}),Cde=()=>Qt({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 pt(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 pt(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 pt(e,`Expected a number (got ${Vr(r)})`)}return!0}}),mde=()=>Qt({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 pt(e,"Unbound coercion result");let i;if(typeof r=="string"&&ov.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 pt(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 pt(e,`Expected a date (got ${Vr(r)})`)}return!0}}),Ede=(r,{delimiter:e}={})=>Qt({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 pt(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 pt(i,`Expected an array (got ${Vr(t)})`);let s=!0;for(let o=0,a=t.length;o{let t=SH(r.length);return Qt({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 pt(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 pt(n,`Expected a tuple (got ${Vr(i)})`);let o=t(i,Object.assign({},n));for(let a=0,l=i.length;aQt({test:(t,i)=>{if(typeof t!="object"||t===null)return pt(i,`Expected an object (got ${Vr(t)})`);let n=Object.keys(t),s=!0;for(let o=0,a=n.length;o{let t=Object.keys(r);return Qt({test:(i,n)=>{if(typeof i!="object"||i===null)return pt(n,`Expected an object (got ${Vr(i)})`);let s=new Set([...t,...Object.keys(i)]),o={},a=!0;for(let l of s){if(l==="constructor"||l==="__proto__")a=pt(Object.assign(Object.assign({},n),{p:FA(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:FA(n,l),coercion:cc(i,l)}))&&a:e===null?a=pt(Object.assign(Object.assign({},n),{p:FA(n,l)}),`Extraneous property (got ${Vr(u)})`):Object.defineProperty(o,l,{enumerable:!0,get:()=>u,set:bH(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}})},Bde=r=>Qt({test:(e,t)=>e instanceof r?!0:pt(t,`Expected an instance of ${r.name} (got ${Vr(e)})`)}),bde=(r,{exclusive:e=!1}={})=>Qt({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?pt(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}}),od=(r,e)=>Qt({test:(t,i)=>{var n,s;let o={value:t},a=typeof(i==null?void 0:i.coercions)<"u"?cc(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 pt(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()}}}),Qde=r=>Qt({test:(e,t)=>typeof e>"u"?!0:r(e,t)}),Sde=r=>Qt({test:(e,t)=>e===null?!0:r(e,t)}),vde=r=>Qt({test:(e,t)=>e.length>=r?!0:pt(t,`Expected to have a length of at least ${r} elements (got ${e.length})`)}),xde=r=>Qt({test:(e,t)=>e.length<=r?!0:pt(t,`Expected to have a length of at most ${r} elements (got ${e.length})`)}),SH=r=>Qt({test:(e,t)=>e.length!==r?pt(t,`Expected to have a length of exactly ${r} elements (got ${e.length})`):!0}),Pde=({map:r}={})=>Qt({test:(e,t)=>{let i=new Set,n=new Set;for(let s=0,o=e.length;sQt({test:(r,e)=>r<=0?!0:pt(e,`Expected to be negative (got ${r})`)}),kde=()=>Qt({test:(r,e)=>r>=0?!0:pt(e,`Expected to be positive (got ${r})`)}),Rde=r=>Qt({test:(e,t)=>e>=r?!0:pt(t,`Expected to be at least ${r} (got ${e})`)}),Fde=r=>Qt({test:(e,t)=>e<=r?!0:pt(t,`Expected to be at most ${r} (got ${e})`)}),Nde=(r,e)=>Qt({test:(t,i)=>t>=r&&t<=e?!0:pt(i,`Expected to be in the [${r}; ${e}] range (got ${t})`)}),Tde=(r,e)=>Qt({test:(t,i)=>t>=r&&tQt({test:(e,t)=>e!==Math.round(e)?pt(t,`Expected to be an integer (got ${e})`):Number.isSafeInteger(e)?!0:pt(t,`Expected to be a safe integer (got ${e})`)}),ad=r=>Qt({test:(e,t)=>r.test(e)?!0:pt(t,`Expected to match the pattern ${r.toString()} (got ${Vr(e)})`)}),Mde=()=>Qt({test:(r,e)=>r!==r.toLowerCase()?pt(e,`Expected to be all-lowercase (got ${r})`):!0}),Ode=()=>Qt({test:(r,e)=>r!==r.toUpperCase()?pt(e,`Expected to be all-uppercase (got ${r})`):!0}),Kde=()=>Qt({test:(r,e)=>wH.test(r)?!0:pt(e,`Expected to be a valid UUID v4 (got ${Vr(r)})`)}),Ude=()=>Qt({test:(r,e)=>ov.test(r)?!1:pt(e,`Expected to be a valid ISO 8601 date string (got ${Vr(r)})`)}),Hde=({alpha:r=!1})=>Qt({test:(e,t)=>(r?EH.test(e):IH.test(e))?!0:pt(t,`Expected to be a valid hexadecimal color string (got ${Vr(e)})`)}),Gde=()=>Qt({test:(r,e)=>yH.test(r)?!0:pt(e,`Expected to be a valid base 64 string (got ${Vr(r)})`)}),Yde=(r=QH())=>Qt({test:(e,t)=>{let i;try{i=JSON.parse(e)}catch{return pt(t,`Expected to be a valid JSON string (got ${Vr(e)})`)}return r(i,t)}}),jde=r=>{let e=new Set(r);return Qt({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?pt(i,`Missing required ${kI(s.length,"property","properties")} ${s.map(o=>`"${o}"`).join(", ")}`):!0}})},qde=r=>{let e=new Set(r);return Qt({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?pt(i,`Forbidden ${kI(s.length,"property","properties")} ${s.map(o=>`"${o}"`).join(", ")}`):!0}})},Jde=r=>{let e=new Set(r);return Qt({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?pt(i,`Mutually exclusive properties ${s.map(o=>`"${o}"`).join(", ")}`):!0}})};(function(r){r.Forbids="Forbids",r.Requires="Requires"})(lc||(lc={}));Wde={[lc.Forbids]:{expect:!1,message:"forbids using"},[lc.Requires]:{expect:!0,message:"requires using"}},av=(r,e,t,{ignore:i=[]}={})=>{let n=new Set(i),s=new Set(t),o=Wde[e];return Qt({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?pt(l,`Property "${r}" ${o.message} ${kI(u.length,"property","properties")} ${u.map(g=>`"${g}"`).join(", ")}`):!0}})}});var YH=w((o$e,GH)=>{"use strict";GH.exports=(r,...e)=>new Promise(t=>{t(r(...e))})});var Jg=w((a$e,pv)=>{"use strict";var cCe=YH(),jH=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=cCe(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};pv.exports=jH;pv.exports.default=jH});var gd=w((l$e,qH)=>{var uCe="2.0.0",gCe=Number.MAX_SAFE_INTEGER||9007199254740991,fCe=16;qH.exports={SEMVER_SPEC_VERSION:uCe,MAX_LENGTH:256,MAX_SAFE_INTEGER:gCe,MAX_SAFE_COMPONENT_LENGTH:fCe}});var fd=w((c$e,JH)=>{var hCe=typeof process=="object"&&process.env&&process.env.NODE_DEBUG&&/\bsemver\b/i.test(process.env.NODE_DEBUG)?(...r)=>console.error("SEMVER",...r):()=>{};JH.exports=hCe});var uc=w((TA,WH)=>{var{MAX_SAFE_COMPONENT_LENGTH:dv}=gd(),pCe=fd();TA=WH.exports={};var dCe=TA.re=[],et=TA.src=[],tt=TA.t={},CCe=0,St=(r,e,t)=>{let i=CCe++;pCe(i,e),tt[r]=i,et[i]=e,dCe[i]=new RegExp(e,t?"g":void 0)};St("NUMERICIDENTIFIER","0|[1-9]\\d*");St("NUMERICIDENTIFIERLOOSE","[0-9]+");St("NONNUMERICIDENTIFIER","\\d*[a-zA-Z-][a-zA-Z0-9-]*");St("MAINVERSION",`(${et[tt.NUMERICIDENTIFIER]})\\.(${et[tt.NUMERICIDENTIFIER]})\\.(${et[tt.NUMERICIDENTIFIER]})`);St("MAINVERSIONLOOSE",`(${et[tt.NUMERICIDENTIFIERLOOSE]})\\.(${et[tt.NUMERICIDENTIFIERLOOSE]})\\.(${et[tt.NUMERICIDENTIFIERLOOSE]})`);St("PRERELEASEIDENTIFIER",`(?:${et[tt.NUMERICIDENTIFIER]}|${et[tt.NONNUMERICIDENTIFIER]})`);St("PRERELEASEIDENTIFIERLOOSE",`(?:${et[tt.NUMERICIDENTIFIERLOOSE]}|${et[tt.NONNUMERICIDENTIFIER]})`);St("PRERELEASE",`(?:-(${et[tt.PRERELEASEIDENTIFIER]}(?:\\.${et[tt.PRERELEASEIDENTIFIER]})*))`);St("PRERELEASELOOSE",`(?:-?(${et[tt.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${et[tt.PRERELEASEIDENTIFIERLOOSE]})*))`);St("BUILDIDENTIFIER","[0-9A-Za-z-]+");St("BUILD",`(?:\\+(${et[tt.BUILDIDENTIFIER]}(?:\\.${et[tt.BUILDIDENTIFIER]})*))`);St("FULLPLAIN",`v?${et[tt.MAINVERSION]}${et[tt.PRERELEASE]}?${et[tt.BUILD]}?`);St("FULL",`^${et[tt.FULLPLAIN]}$`);St("LOOSEPLAIN",`[v=\\s]*${et[tt.MAINVERSIONLOOSE]}${et[tt.PRERELEASELOOSE]}?${et[tt.BUILD]}?`);St("LOOSE",`^${et[tt.LOOSEPLAIN]}$`);St("GTLT","((?:<|>)?=?)");St("XRANGEIDENTIFIERLOOSE",`${et[tt.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);St("XRANGEIDENTIFIER",`${et[tt.NUMERICIDENTIFIER]}|x|X|\\*`);St("XRANGEPLAIN",`[v=\\s]*(${et[tt.XRANGEIDENTIFIER]})(?:\\.(${et[tt.XRANGEIDENTIFIER]})(?:\\.(${et[tt.XRANGEIDENTIFIER]})(?:${et[tt.PRERELEASE]})?${et[tt.BUILD]}?)?)?`);St("XRANGEPLAINLOOSE",`[v=\\s]*(${et[tt.XRANGEIDENTIFIERLOOSE]})(?:\\.(${et[tt.XRANGEIDENTIFIERLOOSE]})(?:\\.(${et[tt.XRANGEIDENTIFIERLOOSE]})(?:${et[tt.PRERELEASELOOSE]})?${et[tt.BUILD]}?)?)?`);St("XRANGE",`^${et[tt.GTLT]}\\s*${et[tt.XRANGEPLAIN]}$`);St("XRANGELOOSE",`^${et[tt.GTLT]}\\s*${et[tt.XRANGEPLAINLOOSE]}$`);St("COERCE",`(^|[^\\d])(\\d{1,${dv}})(?:\\.(\\d{1,${dv}}))?(?:\\.(\\d{1,${dv}}))?(?:$|[^\\d])`);St("COERCERTL",et[tt.COERCE],!0);St("LONETILDE","(?:~>?)");St("TILDETRIM",`(\\s*)${et[tt.LONETILDE]}\\s+`,!0);TA.tildeTrimReplace="$1~";St("TILDE",`^${et[tt.LONETILDE]}${et[tt.XRANGEPLAIN]}$`);St("TILDELOOSE",`^${et[tt.LONETILDE]}${et[tt.XRANGEPLAINLOOSE]}$`);St("LONECARET","(?:\\^)");St("CARETTRIM",`(\\s*)${et[tt.LONECARET]}\\s+`,!0);TA.caretTrimReplace="$1^";St("CARET",`^${et[tt.LONECARET]}${et[tt.XRANGEPLAIN]}$`);St("CARETLOOSE",`^${et[tt.LONECARET]}${et[tt.XRANGEPLAINLOOSE]}$`);St("COMPARATORLOOSE",`^${et[tt.GTLT]}\\s*(${et[tt.LOOSEPLAIN]})$|^$`);St("COMPARATOR",`^${et[tt.GTLT]}\\s*(${et[tt.FULLPLAIN]})$|^$`);St("COMPARATORTRIM",`(\\s*)${et[tt.GTLT]}\\s*(${et[tt.LOOSEPLAIN]}|${et[tt.XRANGEPLAIN]})`,!0);TA.comparatorTrimReplace="$1$2$3";St("HYPHENRANGE",`^\\s*(${et[tt.XRANGEPLAIN]})\\s+-\\s+(${et[tt.XRANGEPLAIN]})\\s*$`);St("HYPHENRANGELOOSE",`^\\s*(${et[tt.XRANGEPLAINLOOSE]})\\s+-\\s+(${et[tt.XRANGEPLAINLOOSE]})\\s*$`);St("STAR","(<|>)?=?\\s*\\*");St("GTE0","^\\s*>=\\s*0.0.0\\s*$");St("GTE0PRE","^\\s*>=\\s*0.0.0-0\\s*$")});var hd=w((u$e,zH)=>{var mCe=["includePrerelease","loose","rtl"],ECe=r=>r?typeof r!="object"?{loose:!0}:mCe.filter(e=>r[e]).reduce((e,t)=>(e[t]=!0,e),{}):{};zH.exports=ECe});var MI=w((g$e,ZH)=>{var VH=/^[0-9]+$/,XH=(r,e)=>{let t=VH.test(r),i=VH.test(e);return t&&i&&(r=+r,e=+e),r===e?0:t&&!i?-1:i&&!t?1:rXH(e,r);ZH.exports={compareIdentifiers:XH,rcompareIdentifiers:ICe}});var Li=w((f$e,tG)=>{var OI=fd(),{MAX_LENGTH:_H,MAX_SAFE_INTEGER:KI}=gd(),{re:$H,t:eG}=uc(),yCe=hd(),{compareIdentifiers:pd}=MI(),Yn=class{constructor(e,t){if(t=yCe(t),e instanceof Yn){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>_H)throw new TypeError(`version is longer than ${_H} characters`);OI("SemVer",e,t),this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease;let i=e.trim().match(t.loose?$H[eG.LOOSE]:$H[eG.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>KI||this.major<0)throw new TypeError("Invalid major version");if(this.minor>KI||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>KI||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}};tG.exports=Yn});var gc=w((h$e,sG)=>{var{MAX_LENGTH:wCe}=gd(),{re:rG,t:iG}=uc(),nG=Li(),BCe=hd(),bCe=(r,e)=>{if(e=BCe(e),r instanceof nG)return r;if(typeof r!="string"||r.length>wCe||!(e.loose?rG[iG.LOOSE]:rG[iG.FULL]).test(r))return null;try{return new nG(r,e)}catch{return null}};sG.exports=bCe});var aG=w((p$e,oG)=>{var QCe=gc(),SCe=(r,e)=>{let t=QCe(r,e);return t?t.version:null};oG.exports=SCe});var lG=w((d$e,AG)=>{var vCe=gc(),xCe=(r,e)=>{let t=vCe(r.trim().replace(/^[=v]+/,""),e);return t?t.version:null};AG.exports=xCe});var uG=w((C$e,cG)=>{var PCe=Li(),DCe=(r,e,t,i)=>{typeof t=="string"&&(i=t,t=void 0);try{return new PCe(r,t).inc(e,i).version}catch{return null}};cG.exports=DCe});var cs=w((m$e,fG)=>{var gG=Li(),kCe=(r,e,t)=>new gG(r,t).compare(new gG(e,t));fG.exports=kCe});var UI=w((E$e,hG)=>{var RCe=cs(),FCe=(r,e,t)=>RCe(r,e,t)===0;hG.exports=FCe});var CG=w((I$e,dG)=>{var pG=gc(),NCe=UI(),TCe=(r,e)=>{if(NCe(r,e))return null;{let t=pG(r),i=pG(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}};dG.exports=TCe});var EG=w((y$e,mG)=>{var LCe=Li(),MCe=(r,e)=>new LCe(r,e).major;mG.exports=MCe});var yG=w((w$e,IG)=>{var OCe=Li(),KCe=(r,e)=>new OCe(r,e).minor;IG.exports=KCe});var BG=w((B$e,wG)=>{var UCe=Li(),HCe=(r,e)=>new UCe(r,e).patch;wG.exports=HCe});var QG=w((b$e,bG)=>{var GCe=gc(),YCe=(r,e)=>{let t=GCe(r,e);return t&&t.prerelease.length?t.prerelease:null};bG.exports=YCe});var vG=w((Q$e,SG)=>{var jCe=cs(),qCe=(r,e,t)=>jCe(e,r,t);SG.exports=qCe});var PG=w((S$e,xG)=>{var JCe=cs(),WCe=(r,e)=>JCe(r,e,!0);xG.exports=WCe});var HI=w((v$e,kG)=>{var DG=Li(),zCe=(r,e,t)=>{let i=new DG(r,t),n=new DG(e,t);return i.compare(n)||i.compareBuild(n)};kG.exports=zCe});var FG=w((x$e,RG)=>{var VCe=HI(),XCe=(r,e)=>r.sort((t,i)=>VCe(t,i,e));RG.exports=XCe});var TG=w((P$e,NG)=>{var ZCe=HI(),_Ce=(r,e)=>r.sort((t,i)=>ZCe(i,t,e));NG.exports=_Ce});var dd=w((D$e,LG)=>{var $Ce=cs(),eme=(r,e,t)=>$Ce(r,e,t)>0;LG.exports=eme});var GI=w((k$e,MG)=>{var tme=cs(),rme=(r,e,t)=>tme(r,e,t)<0;MG.exports=rme});var Cv=w((R$e,OG)=>{var ime=cs(),nme=(r,e,t)=>ime(r,e,t)!==0;OG.exports=nme});var YI=w((F$e,KG)=>{var sme=cs(),ome=(r,e,t)=>sme(r,e,t)>=0;KG.exports=ome});var jI=w((N$e,UG)=>{var ame=cs(),Ame=(r,e,t)=>ame(r,e,t)<=0;UG.exports=Ame});var mv=w((T$e,HG)=>{var lme=UI(),cme=Cv(),ume=dd(),gme=YI(),fme=GI(),hme=jI(),pme=(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 lme(r,t,i);case"!=":return cme(r,t,i);case">":return ume(r,t,i);case">=":return gme(r,t,i);case"<":return fme(r,t,i);case"<=":return hme(r,t,i);default:throw new TypeError(`Invalid operator: ${e}`)}};HG.exports=pme});var YG=w((L$e,GG)=>{var dme=Li(),Cme=gc(),{re:qI,t:JI}=uc(),mme=(r,e)=>{if(r instanceof dme)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(qI[JI.COERCE]);else{let i;for(;(i=qI[JI.COERCERTL].exec(r))&&(!t||t.index+t[0].length!==r.length);)(!t||i.index+i[0].length!==t.index+t[0].length)&&(t=i),qI[JI.COERCERTL].lastIndex=i.index+i[1].length+i[2].length;qI[JI.COERCERTL].lastIndex=-1}return t===null?null:Cme(`${t[2]}.${t[3]||"0"}.${t[4]||"0"}`,e)};GG.exports=mme});var qG=w((M$e,jG)=>{"use strict";jG.exports=function(r){r.prototype[Symbol.iterator]=function*(){for(let e=this.head;e;e=e.next)yield e.value}}});var WI=w((O$e,JG)=>{"use strict";JG.exports=Ht;Ht.Node=fc;Ht.create=Ht;function Ht(r){var e=this;if(e instanceof Ht||(e=new Ht),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};Ht.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};Ht.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};Ht.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};Ht.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 Ht;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};Ht.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 wme=WI(),hc=Symbol("max"),va=Symbol("length"),Wg=Symbol("lengthCalculator"),md=Symbol("allowStale"),pc=Symbol("maxAge"),Sa=Symbol("dispose"),WG=Symbol("noDisposeOnSet"),di=Symbol("lruList"),Zs=Symbol("cache"),VG=Symbol("updateAgeOnGet"),Ev=()=>1,yv=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[hc]=e.max||1/0,i=e.length||Ev;if(this[Wg]=typeof i!="function"?Ev:i,this[md]=e.stale||!1,e.maxAge&&typeof e.maxAge!="number")throw new TypeError("maxAge must be a number");this[pc]=e.maxAge||0,this[Sa]=e.dispose,this[WG]=e.noDisposeOnSet||!1,this[VG]=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[hc]=e||1/0,Cd(this)}get max(){return this[hc]}set allowStale(e){this[md]=!!e}get allowStale(){return this[md]}set maxAge(e){if(typeof e!="number")throw new TypeError("maxAge must be a non-negative number");this[pc]=e,Cd(this)}get maxAge(){return this[pc]}set lengthCalculator(e){typeof e!="function"&&(e=Ev),e!==this[Wg]&&(this[Wg]=e,this[va]=0,this[di].forEach(t=>{t.length=this[Wg](t.value,t.key),this[va]+=t.length})),Cd(this)}get lengthCalculator(){return this[Wg]}get length(){return this[va]}get itemCount(){return this[di].length}rforEach(e,t){t=t||this;for(let i=this[di].tail;i!==null;){let n=i.prev;zG(this,e,i,t),i=n}}forEach(e,t){t=t||this;for(let i=this[di].head;i!==null;){let n=i.next;zG(this,e,i,t),i=n}}keys(){return this[di].toArray().map(e=>e.key)}values(){return this[di].toArray().map(e=>e.value)}reset(){this[Sa]&&this[di]&&this[di].length&&this[di].forEach(e=>this[Sa](e.key,e.value)),this[Zs]=new Map,this[di]=new wme,this[va]=0}dump(){return this[di].map(e=>zI(this,e)?!1:{k:e.key,v:e.value,e:e.now+(e.maxAge||0)}).toArray().filter(e=>e)}dumpLru(){return this[di]}set(e,t,i){if(i=i||this[pc],i&&typeof i!="number")throw new TypeError("maxAge must be a number");let n=i?Date.now():0,s=this[Wg](t,e);if(this[Zs].has(e)){if(s>this[hc])return zg(this,this[Zs].get(e)),!1;let l=this[Zs].get(e).value;return this[Sa]&&(this[WG]||this[Sa](e,l.value)),l.now=n,l.maxAge=i,l.value=t,this[va]+=s-l.length,l.length=s,this.get(e),Cd(this),!0}let o=new wv(e,t,s,n,i);return o.length>this[hc]?(this[Sa]&&this[Sa](e,t),!1):(this[va]+=o.length,this[di].unshift(o),this[Zs].set(e,this[di].head),Cd(this),!0)}has(e){if(!this[Zs].has(e))return!1;let t=this[Zs].get(e).value;return!zI(this,t)}get(e){return Iv(this,e,!0)}peek(e){return Iv(this,e,!1)}pop(){let e=this[di].tail;return e?(zg(this,e),e.value):null}del(e){zg(this,this[Zs].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[Zs].forEach((e,t)=>Iv(this,t,!1))}},Iv=(r,e,t)=>{let i=r[Zs].get(e);if(i){let n=i.value;if(zI(r,n)){if(zg(r,i),!r[md])return}else t&&(r[VG]&&(i.value.now=Date.now()),r[di].unshiftNode(i));return n.value}},zI=(r,e)=>{if(!e||!e.maxAge&&!r[pc])return!1;let t=Date.now()-e.now;return e.maxAge?t>e.maxAge:r[pc]&&t>r[pc]},Cd=r=>{if(r[va]>r[hc])for(let e=r[di].tail;r[va]>r[hc]&&e!==null;){let t=e.prev;zg(r,e),e=t}},zg=(r,e)=>{if(e){let t=e.value;r[Sa]&&r[Sa](t.key,t.value),r[va]-=t.length,r[Zs].delete(t.key),r[di].removeNode(e)}},wv=class{constructor(e,t,i,n,s){this.key=e,this.value=t,this.length=i,this.now=n,this.maxAge=s||0}},zG=(r,e,t,i)=>{let n=t.value;zI(r,n)&&(zg(r,t),r[md]||(n=void 0)),n&&e.call(i,n.value,n.key,r)};XG.exports=yv});var us=w((U$e,tY)=>{var dc=class{constructor(e,t){if(t=bme(t),e instanceof dc)return e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease?e:new dc(e.raw,t);if(e instanceof Bv)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=>!$G(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&&Pme(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=_G.get(i);if(n)return n;let s=this.options.loose,o=s?Mi[bi.HYPHENRANGELOOSE]:Mi[bi.HYPHENRANGE];e=e.replace(o,Kme(this.options.includePrerelease)),Gr("hyphen replace",e),e=e.replace(Mi[bi.COMPARATORTRIM],Sme),Gr("comparator trim",e,Mi[bi.COMPARATORTRIM]),e=e.replace(Mi[bi.TILDETRIM],vme),e=e.replace(Mi[bi.CARETTRIM],xme),e=e.split(/\s+/).join(" ");let a=s?Mi[bi.COMPARATORLOOSE]:Mi[bi.COMPARATOR],l=e.split(" ").map(f=>Dme(f,this.options)).join(" ").split(/\s+/).map(f=>Ome(f,this.options)).filter(this.options.loose?f=>!!f.match(a):()=>!0).map(f=>new Bv(f,this.options)),c=l.length,u=new Map;for(let f of l){if($G(f))return[f];u.set(f.value,f)}u.size>1&&u.has("")&&u.delete("");let g=[...u.values()];return _G.set(i,g),g}intersects(e,t){if(!(e instanceof dc))throw new TypeError("a Range is required");return this.set.some(i=>eY(i,t)&&e.set.some(n=>eY(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 Qme(e,this.options)}catch{return!1}for(let t=0;tr.value==="<0.0.0-0",Pme=r=>r.value==="",eY=(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},Dme=(r,e)=>(Gr("comp",r,e),r=Fme(r,e),Gr("caret",r),r=kme(r,e),Gr("tildes",r),r=Tme(r,e),Gr("xrange",r),r=Mme(r,e),Gr("stars",r),r),$i=r=>!r||r.toLowerCase()==="x"||r==="*",kme=(r,e)=>r.trim().split(/\s+/).map(t=>Rme(t,e)).join(" "),Rme=(r,e)=>{let t=e.loose?Mi[bi.TILDELOOSE]:Mi[bi.TILDE];return r.replace(t,(i,n,s,o,a)=>{Gr("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?(Gr("replaceTilde pr",a),l=`>=${n}.${s}.${o}-${a} <${n}.${+s+1}.0-0`):l=`>=${n}.${s}.${o} <${n}.${+s+1}.0-0`,Gr("tilde return",l),l})},Fme=(r,e)=>r.trim().split(/\s+/).map(t=>Nme(t,e)).join(" "),Nme=(r,e)=>{Gr("caret",r,e);let t=e.loose?Mi[bi.CARETLOOSE]:Mi[bi.CARET],i=e.includePrerelease?"-0":"";return r.replace(t,(n,s,o,a,l)=>{Gr("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?(Gr("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`):(Gr("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`),Gr("caret return",c),c})},Tme=(r,e)=>(Gr("replaceXRanges",r,e),r.split(/\s+/).map(t=>Lme(t,e)).join(" ")),Lme=(r,e)=>{r=r.trim();let t=e.loose?Mi[bi.XRANGELOOSE]:Mi[bi.XRANGE];return r.replace(t,(i,n,s,o,a,l)=>{Gr("xRange",r,i,n,s,o,a,l);let c=$i(s),u=c||$i(o),g=u||$i(a),f=g;return n==="="&&f&&(n=""),l=e.includePrerelease?"-0":"",c?n===">"||n==="<"?i="<0.0.0-0":i="*":n&&f?(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`),Gr("xRange return",i),i})},Mme=(r,e)=>(Gr("replaceStars",r,e),r.trim().replace(Mi[bi.STAR],"")),Ome=(r,e)=>(Gr("replaceGTE0",r,e),r.trim().replace(Mi[e.includePrerelease?bi.GTE0PRE:bi.GTE0],"")),Kme=r=>(e,t,i,n,s,o,a,l,c,u,g,f,h)=>($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`:f?l=`<=${c}.${u}.${g}-${f}`:r?l=`<${c}.${u}.${+g+1}-0`:l=`<=${l}`,`${t} ${l}`.trim()),Ume=(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 Ed=w((H$e,oY)=>{var Id=Symbol("SemVer ANY"),Vg=class{static get ANY(){return Id}constructor(e,t){if(t=Hme(t),e instanceof Vg){if(e.loose===!!t.loose)return e;e=e.value}Qv("comparator",e,t),this.options=t,this.loose=!!t.loose,this.parse(e),this.semver===Id?this.value="":this.value=this.operator+this.semver.version,Qv("comp",this)}parse(e){let t=this.options.loose?rY[iY.COMPARATORLOOSE]:rY[iY.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 nY(i[2],this.options.loose):this.semver=Id}toString(){return this.value}test(e){if(Qv("Comparator.test",e,this.options.loose),this.semver===Id||e===Id)return!0;if(typeof e=="string")try{e=new nY(e,this.options)}catch{return!1}return bv(e,this.operator,this.semver,this.options)}intersects(e,t){if(!(e instanceof Vg))throw new TypeError("a Comparator is required");if((!t||typeof t!="object")&&(t={loose:!!t,includePrerelease:!1}),this.operator==="")return this.value===""?!0:new sY(e.value,t).test(this.value);if(e.operator==="")return e.value===""?!0:new sY(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}};oY.exports=Vg;var Hme=hd(),{re:rY,t:iY}=uc(),bv=mv(),Qv=fd(),nY=Li(),sY=us()});var yd=w((G$e,aY)=>{var Gme=us(),Yme=(r,e,t)=>{try{e=new Gme(e,t)}catch{return!1}return e.test(r)};aY.exports=Yme});var lY=w((Y$e,AY)=>{var jme=us(),qme=(r,e)=>new jme(r,e).set.map(t=>t.map(i=>i.value).join(" ").trim().split(" "));AY.exports=qme});var uY=w((j$e,cY)=>{var Jme=Li(),Wme=us(),zme=(r,e,t)=>{let i=null,n=null,s=null;try{s=new Wme(e,t)}catch{return null}return r.forEach(o=>{s.test(o)&&(!i||n.compare(o)===-1)&&(i=o,n=new Jme(i,t))}),i};cY.exports=zme});var fY=w((q$e,gY)=>{var Vme=Li(),Xme=us(),Zme=(r,e,t)=>{let i=null,n=null,s=null;try{s=new Xme(e,t)}catch{return null}return r.forEach(o=>{s.test(o)&&(!i||n.compare(o)===1)&&(i=o,n=new Vme(i,t))}),i};gY.exports=Zme});var dY=w((J$e,pY)=>{var Sv=Li(),_me=us(),hY=dd(),$me=(r,e)=>{r=new _me(r,e);let t=new Sv("0.0.0");if(r.test(t)||(t=new Sv("0.0.0-0"),r.test(t)))return t;t=null;for(let i=0;i{let a=new Sv(o.semver.version);switch(o.operator){case">":a.prerelease.length===0?a.patch++:a.prerelease.push(0),a.raw=a.format();case"":case">=":(!s||hY(a,s))&&(s=a);break;case"<":case"<=":break;default:throw new Error(`Unexpected operation: ${o.operator}`)}}),s&&(!t||hY(t,s))&&(t=s)}return t&&r.test(t)?t:null};pY.exports=$me});var mY=w((W$e,CY)=>{var eEe=us(),tEe=(r,e)=>{try{return new eEe(r,e).range||"*"}catch{return null}};CY.exports=tEe});var VI=w((z$e,wY)=>{var rEe=Li(),yY=Ed(),{ANY:iEe}=yY,nEe=us(),sEe=yd(),EY=dd(),IY=GI(),oEe=jI(),aEe=YI(),AEe=(r,e,t,i)=>{r=new rEe(r,i),e=new nEe(e,i);let n,s,o,a,l;switch(t){case">":n=EY,s=oEe,o=IY,a=">",l=">=";break;case"<":n=IY,s=aEe,o=EY,a="<",l="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(sEe(r,e,i))return!1;for(let c=0;c{h.semver===iEe&&(h=new yY(">=0.0.0")),g=g||h,f=f||h,n(h.semver,g.semver,i)?g=h:o(h.semver,f.semver,i)&&(f=h)}),g.operator===a||g.operator===l||(!f.operator||f.operator===a)&&s(r,f.semver))return!1;if(f.operator===l&&o(r,f.semver))return!1}return!0};wY.exports=AEe});var bY=w((V$e,BY)=>{var lEe=VI(),cEe=(r,e,t)=>lEe(r,e,">",t);BY.exports=cEe});var SY=w((X$e,QY)=>{var uEe=VI(),gEe=(r,e,t)=>uEe(r,e,"<",t);QY.exports=gEe});var PY=w((Z$e,xY)=>{var vY=us(),fEe=(r,e,t)=>(r=new vY(r,t),e=new vY(e,t),r.intersects(e));xY.exports=fEe});var kY=w((_$e,DY)=>{var hEe=yd(),pEe=cs();DY.exports=(r,e,t)=>{let i=[],n=null,s=null,o=r.sort((u,g)=>pEe(u,g,t));for(let u of o)hEe(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 RY=us(),XI=Ed(),{ANY:vv}=XI,wd=yd(),xv=cs(),dEe=(r,e,t={})=>{if(r===e)return!0;r=new RY(r,t),e=new RY(e,t);let i=!1;e:for(let n of r.set){for(let s of e.set){let o=CEe(n,s,t);if(i=i||o!==null,o)continue e}if(i)return!1}return!0},CEe=(r,e,t)=>{if(r===e)return!0;if(r.length===1&&r[0].semver===vv){if(e.length===1&&e[0].semver===vv)return!0;t.includePrerelease?r=[new XI(">=0.0.0-0")]:r=[new XI(">=0.0.0")]}if(e.length===1&&e[0].semver===vv){if(t.includePrerelease)return!0;e=[new XI(">=0.0.0")]}let i=new Set,n,s;for(let h of r)h.operator===">"||h.operator===">="?n=FY(n,h,t):h.operator==="<"||h.operator==="<="?s=NY(s,h,t):i.add(h.semver);if(i.size>1)return null;let o;if(n&&s){if(o=xv(n.semver,s.semver,t),o>0)return null;if(o===0&&(n.operator!==">="||s.operator!=="<="))return null}for(let h of i){if(n&&!wd(h,String(n),t)||s&&!wd(h,String(s),t))return null;for(let p of e)if(!wd(h,String(p),t))return!1;return!0}let a,l,c,u,g=s&&!t.includePrerelease&&s.semver.prerelease.length?s.semver:!1,f=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 h of e){if(u=u||h.operator===">"||h.operator===">=",c=c||h.operator==="<"||h.operator==="<=",n){if(f&&h.semver.prerelease&&h.semver.prerelease.length&&h.semver.major===f.major&&h.semver.minor===f.minor&&h.semver.patch===f.patch&&(f=!1),h.operator===">"||h.operator===">="){if(a=FY(n,h,t),a===h&&a!==n)return!1}else if(n.operator===">="&&!wd(n.semver,String(h),t))return!1}if(s){if(g&&h.semver.prerelease&&h.semver.prerelease.length&&h.semver.major===g.major&&h.semver.minor===g.minor&&h.semver.patch===g.patch&&(g=!1),h.operator==="<"||h.operator==="<="){if(l=NY(s,h,t),l===h&&l!==s)return!1}else if(s.operator==="<="&&!wd(s.semver,String(h),t))return!1}if(!h.operator&&(s||n)&&o!==0)return!1}return!(n&&c&&!s&&o!==0||s&&u&&!n&&o!==0||f||g)},FY=(r,e,t)=>{if(!r)return e;let i=xv(r.semver,e.semver,t);return i>0?r:i<0||e.operator===">"&&r.operator===">="?e:r},NY=(r,e,t)=>{if(!r)return e;let i=xv(r.semver,e.semver,t);return i<0?r:i>0||e.operator==="<"&&r.operator==="<="?e:r};TY.exports=dEe});var Xr=w((eet,MY)=>{var Pv=uc();MY.exports={re:Pv.re,src:Pv.src,tokens:Pv.t,SEMVER_SPEC_VERSION:gd().SEMVER_SPEC_VERSION,SemVer:Li(),compareIdentifiers:MI().compareIdentifiers,rcompareIdentifiers:MI().rcompareIdentifiers,parse:gc(),valid:aG(),clean:lG(),inc:uG(),diff:CG(),major:EG(),minor:yG(),patch:BG(),prerelease:QG(),compare:cs(),rcompare:vG(),compareLoose:PG(),compareBuild:HI(),sort:FG(),rsort:TG(),gt:dd(),lt:GI(),eq:UI(),neq:Cv(),gte:YI(),lte:jI(),cmp:mv(),coerce:YG(),Comparator:Ed(),Range:us(),satisfies:yd(),toComparators:lY(),maxSatisfying:uY(),minSatisfying:fY(),minVersion:dY(),validRange:mY(),outside:VI(),gtr:bY(),ltr:SY(),intersects:PY(),simplifyRange:kY(),subset:LY()}});var Dv=w(ZI=>{"use strict";Object.defineProperty(ZI,"__esModule",{value:!0});ZI.VERSION=void 0;ZI.VERSION="9.1.0"});var Gt=w((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:OY,function(){function r(){}r.prototype.saveState=function(){return{idx:this.idx,input:this.input,groupIdx:this.groupIdx}},r.prototype.restoreState=function(p){this.idx=p.idx,this.input=p.input,this.groupIdx=p.groupIdx},r.prototype.pattern=function(p){this.idx=0,this.input=p,this.groupIdx=0,this.consumeChar("/");var C=this.disjunction();this.consumeChar("/");for(var y={type:"Flags",loc:{begin:this.idx,end:p.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:C,loc:this.loc(0)}},r.prototype.disjunction=function(){var p=[],C=this.idx;for(p.push(this.alternative());this.peekChar()==="|";)this.consumeChar("|"),p.push(this.alternative());return{type:"Disjunction",value:p,loc:this.loc(C)}},r.prototype.alternative=function(){for(var p=[],C=this.idx;this.isTerm();)p.push(this.term());return{type:"Alternative",value:p,loc:this.loc(C)}},r.prototype.term=function(){return this.isAssertion()?this.assertion():this.atom()},r.prototype.assertion=function(){var p=this.idx;switch(this.popChar()){case"^":return{type:"StartAnchor",loc:this.loc(p)};case"$":return{type:"EndAnchor",loc:this.loc(p)};case"\\":switch(this.popChar()){case"b":return{type:"WordBoundary",loc:this.loc(p)};case"B":return{type:"NonWordBoundary",loc:this.loc(p)}}throw Error("Invalid Assertion Escape");case"(":this.consumeChar("?");var C;switch(this.popChar()){case"=":C="Lookahead";break;case"!":C="NegativeLookahead";break}a(C);var y=this.disjunction();return this.consumeChar(")"),{type:C,value:y,loc:this.loc(p)}}l()},r.prototype.quantifier=function(p){var C,y=this.idx;switch(this.popChar()){case"*":C={atLeast:0,atMost:1/0};break;case"+":C={atLeast:1,atMost:1/0};break;case"?":C={atLeast:0,atMost:1};break;case"{":var B=this.integerIncludingZero();switch(this.popChar()){case"}":C={atLeast:B,atMost:B};break;case",":var v;this.isDigit()?(v=this.integerIncludingZero(),C={atLeast:B,atMost:v}):C={atLeast:B,atMost:1/0},this.consumeChar("}");break}if(p===!0&&C===void 0)return;a(C);break}if(!(p===!0&&C===void 0))return a(C),this.peekChar(0)==="?"?(this.consumeChar("?"),C.greedy=!1):C.greedy=!0,C.type="Quantifier",C.loc=this.loc(y),C},r.prototype.atom=function(){var p,C=this.idx;switch(this.peekChar()){case".":p=this.dotAll();break;case"\\":p=this.atomEscape();break;case"[":p=this.characterClass();break;case"(":p=this.group();break}return p===void 0&&this.isPatternCharacter()&&(p=this.patternCharacter()),a(p),p.loc=this.loc(C),this.isQuantifier()&&(p.quantifier=this.quantifier()),p},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 p=this.positiveInteger();return{type:"GroupBackReference",value:p}},r.prototype.characterClassEscape=function(){var p,C=!1;switch(this.popChar()){case"d":p=u;break;case"D":p=u,C=!0;break;case"s":p=f;break;case"S":p=f,C=!0;break;case"w":p=g;break;case"W":p=g,C=!0;break}return a(p),{type:"Set",value:p,complement:C}},r.prototype.controlEscapeAtom=function(){var p;switch(this.popChar()){case"f":p=n("\f");break;case"n":p=n(` +`);break;case"r":p=n("\r");break;case"t":p=n(" ");break;case"v":p=n("\v");break}return a(p),{type:"Character",value:p}},r.prototype.controlLetterEscapeAtom=function(){this.consumeChar("c");var p=this.popChar();if(/[a-zA-Z]/.test(p)===!1)throw Error("Invalid ");var C=p.toUpperCase().charCodeAt(0)-64;return{type:"Character",value:C}},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 p=this.popChar();return{type:"Character",value:n(p)}},r.prototype.classPatternCharacterAtom=function(){switch(this.peekChar()){case` +`:case"\r":case"\u2028":case"\u2029":case"\\":case"]":throw Error("TBD");default:var p=this.popChar();return{type:"Character",value:n(p)}}},r.prototype.characterClass=function(){var p=[],C=!1;for(this.consumeChar("["),this.peekChar(0)==="^"&&(this.consumeChar("^"),C=!0);this.isClassAtom();){var y=this.classAtom(),B=y.type==="Character";if(B&&this.isRangeDash()){this.consumeChar("-");var v=this.classAtom(),D=v.type==="Character";if(D){if(v.value=this.input.length)throw Error("Unexpected end of input");this.idx++},r.prototype.loc=function(p){return{begin:p,end:this.idx}};var e=/[0-9a-fA-F]/,t=/[0-9]/,i=/[1-9]/;function n(p){return p.charCodeAt(0)}function s(p,C){p.length!==void 0?p.forEach(function(y){C.push(y)}):C.push(p)}function o(p,C){if(p[C]===!0)throw"duplicate flag "+C;p[C]=!0}function a(p){if(p===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 f=[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 h(){}return h.prototype.visitChildren=function(p){for(var C in p){var y=p[C];p.hasOwnProperty(C)&&(y.type!==void 0?this.visit(y):Array.isArray(y)&&y.forEach(function(B){this.visit(B)},this))}},h.prototype.visit=function(p){switch(p.type){case"Pattern":this.visitPattern(p);break;case"Flags":this.visitFlags(p);break;case"Disjunction":this.visitDisjunction(p);break;case"Alternative":this.visitAlternative(p);break;case"StartAnchor":this.visitStartAnchor(p);break;case"EndAnchor":this.visitEndAnchor(p);break;case"WordBoundary":this.visitWordBoundary(p);break;case"NonWordBoundary":this.visitNonWordBoundary(p);break;case"Lookahead":this.visitLookahead(p);break;case"NegativeLookahead":this.visitNegativeLookahead(p);break;case"Character":this.visitCharacter(p);break;case"Set":this.visitSet(p);break;case"Group":this.visitGroup(p);break;case"GroupBackReference":this.visitGroupBackReference(p);break;case"Quantifier":this.visitQuantifier(p);break}this.visitChildren(p)},h.prototype.visitPattern=function(p){},h.prototype.visitFlags=function(p){},h.prototype.visitDisjunction=function(p){},h.prototype.visitAlternative=function(p){},h.prototype.visitStartAnchor=function(p){},h.prototype.visitEndAnchor=function(p){},h.prototype.visitWordBoundary=function(p){},h.prototype.visitNonWordBoundary=function(p){},h.prototype.visitLookahead=function(p){},h.prototype.visitNegativeLookahead=function(p){},h.prototype.visitCharacter=function(p){},h.prototype.visitSet=function(p){},h.prototype.visitGroup=function(p){},h.prototype.visitGroupBackReference=function(p){},h.prototype.visitQuantifier=function(p){},{RegExpParser:r,BaseRegExpVisitor:h,VERSION:"0.5.0"}})});var ty=w(Xg=>{"use strict";Object.defineProperty(Xg,"__esModule",{value:!0});Xg.clearRegExpParserCache=Xg.getRegExpAst=void 0;var mEe=$I(),ey={},EEe=new mEe.RegExpParser;function IEe(r){var e=r.toString();if(ey.hasOwnProperty(e))return ey[e];var t=EEe.pattern(e);return ey[e]=t,t}Xg.getRegExpAst=IEe;function yEe(){ey={}}Xg.clearRegExpParserCache=yEe});var YY=w(Cn=>{"use strict";var wEe=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 UY=$I(),gs=Gt(),HY=ty(),xa=Rv(),GY="Complement Sets are not supported for first char optimization";Cn.failedOptimizationPrefixMsg=`Unable to use "first char" lexer optimizations: +`;function BEe(r,e){e===void 0&&(e=!1);try{var t=(0,HY.getRegExpAst)(r),i=iy(t.value,{},t.flags.ignoreCase);return i}catch(s){if(s.message===GY)e&&(0,gs.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,gs.PRINT_ERROR)(Cn.failedOptimizationPrefixMsg+` +`+(" Failed parsing: < "+r.toString()+` > +`)+(" Using the regexp-to-ast library version: "+UY.VERSION+` +`)+" Please open an issue at: https://github.com/bd82/regexp-to-ast/issues"+n)}}return[]}Cn.getOptimizedStartCodesIndices=BEe;function iy(r,e,t){switch(r.type){case"Disjunction":for(var i=0;i=xa.minOptimizationVal)for(var f=u.from>=xa.minOptimizationVal?u.from:xa.minOptimizationVal,h=u.to,p=(0,xa.charCodeToOptimizedIndex)(f),C=(0,xa.charCodeToOptimizedIndex)(h),y=p;y<=C;y++)e[y]=y}}});break;case"Group":iy(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"&&kv(o)===!1||o.type!=="Group"&&a===!1)break}break;default:throw Error("non exhaustive match!")}return(0,gs.values)(e)}Cn.firstCharOptimizedIndices=iy;function ry(r,e,t){var i=(0,xa.charCodeToOptimizedIndex)(r);e[i]=i,t===!0&&bEe(r,e)}function bEe(r,e){var t=String.fromCharCode(r),i=t.toUpperCase();if(i!==t){var n=(0,xa.charCodeToOptimizedIndex)(i.charCodeAt(0));e[n]=n}else{var s=t.toLowerCase();if(s!==t){var n=(0,xa.charCodeToOptimizedIndex)(s.charCodeAt(0));e[n]=n}}}function KY(r,e){return(0,gs.find)(r.value,function(t){if(typeof t=="number")return(0,gs.contains)(e,t);var i=t;return(0,gs.find)(e,function(n){return i.from<=n&&n<=i.to})!==void 0})}function kv(r){return r.quantifier&&r.quantifier.atLeast===0?!0:r.value?(0,gs.isArray)(r.value)?(0,gs.every)(r.value,kv):kv(r.value):!1}var QEe=function(r){wEe(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,gs.contains)(this.targetCharCodes,t.value)&&(this.found=!0)},e.prototype.visitSet=function(t){t.complement?KY(t,this.targetCharCodes)===void 0&&(this.found=!0):KY(t,this.targetCharCodes)!==void 0&&(this.found=!0)},e}(UY.BaseRegExpVisitor);function SEe(r,e){if(e instanceof RegExp){var t=(0,HY.getRegExpAst)(e),i=new QEe(r);return i.visit(t),i.found}else return(0,gs.find)(e,function(n){return(0,gs.contains)(r,n.charCodeAt(0))})!==void 0}Cn.canMatchCharCode=SEe});var Rv=w(Ve=>{"use strict";var jY=Ve&&Ve.__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(Ve,"__esModule",{value:!0});Ve.charCodeToOptimizedIndex=Ve.minOptimizationVal=Ve.buildLineBreakIssueMessage=Ve.LineTerminatorOptimizedTester=Ve.isShortPattern=Ve.isCustomPattern=Ve.cloneEmptyGroups=Ve.performWarningRuntimeChecks=Ve.performRuntimeChecks=Ve.addStickyFlag=Ve.addStartOfInput=Ve.findUnreachablePatterns=Ve.findModesThatDoNotExist=Ve.findInvalidGroupType=Ve.findDuplicatePatterns=Ve.findUnsupportedFlags=Ve.findStartOfInputAnchor=Ve.findEmptyMatchRegExps=Ve.findEndOfInputAnchor=Ve.findInvalidPatterns=Ve.findMissingPatterns=Ve.validatePatterns=Ve.analyzeTokenTypes=Ve.enableSticky=Ve.disableSticky=Ve.SUPPORT_STICKY=Ve.MODES=Ve.DEFAULT_MODE=void 0;var qY=$I(),ir=Bd(),xe=Gt(),Zg=YY(),JY=ty(),Do="PATTERN";Ve.DEFAULT_MODE="defaultMode";Ve.MODES="modes";Ve.SUPPORT_STICKY=typeof new RegExp("(?:)").sticky=="boolean";function vEe(){Ve.SUPPORT_STICKY=!1}Ve.disableSticky=vEe;function xEe(){Ve.SUPPORT_STICKY=!0}Ve.enableSticky=xEe;function PEe(r,e){e=(0,xe.defaults)(e,{useSticky:Ve.SUPPORT_STICKY,debug:!1,safeMode:!1,positionTracking:"full",lineTerminatorCharacters:["\r",` +`],tracer:function(v,D){return D()}});var t=e.tracer;t("initCharCodeToOptimizedIndexMap",function(){KEe()});var i;t("Reject Lexer.NA",function(){i=(0,xe.reject)(r,function(v){return v[Do]===ir.Lexer.NA})});var n=!1,s;t("Transform Patterns",function(){n=!1,s=(0,xe.map)(i,function(v){var D=v[Do];if((0,xe.isRegExp)(D)){var T=D.source;return T.length===1&&T!=="^"&&T!=="$"&&T!=="."&&!D.ignoreCase?T:T.length===2&&T[0]==="\\"&&!(0,xe.contains)(["d","D","s","S","t","r","n","t","0","c","b","B","f","v","w","W"],T[1])?T[1]:e.useSticky?Tv(D):Nv(D)}else{if((0,xe.isFunction)(D))return n=!0,{exec:D};if((0,xe.has)(D,"exec"))return n=!0,D;if(typeof D=="string"){if(D.length===1)return D;var H=D.replace(/[\\^$.*+?()[\]{}|]/g,"\\$&"),j=new RegExp(H);return e.useSticky?Tv(j):Nv(j)}else throw Error("non exhaustive match")}})});var o,a,l,c,u;t("misc mapping",function(){o=(0,xe.map)(i,function(v){return v.tokenTypeIdx}),a=(0,xe.map)(i,function(v){var D=v.GROUP;if(D!==ir.Lexer.SKIPPED){if((0,xe.isString)(D))return D;if((0,xe.isUndefined)(D))return!1;throw Error("non exhaustive match")}}),l=(0,xe.map)(i,function(v){var D=v.LONGER_ALT;if(D){var T=(0,xe.isArray)(D)?(0,xe.map)(D,function(H){return(0,xe.indexOf)(i,H)}):[(0,xe.indexOf)(i,D)];return T}}),c=(0,xe.map)(i,function(v){return v.PUSH_MODE}),u=(0,xe.map)(i,function(v){return(0,xe.has)(v,"POP_MODE")})});var g;t("Line Terminator Handling",function(){var v=oj(e.lineTerminatorCharacters);g=(0,xe.map)(i,function(D){return!1}),e.positionTracking!=="onlyOffset"&&(g=(0,xe.map)(i,function(D){if((0,xe.has)(D,"LINE_BREAKS"))return D.LINE_BREAKS;if(nj(D,v)===!1)return(0,Zg.canMatchCharCode)(v,D.PATTERN)}))});var f,h,p,C;t("Misc Mapping #2",function(){f=(0,xe.map)(i,Mv),h=(0,xe.map)(s,ij),p=(0,xe.reduce)(i,function(v,D){var T=D.GROUP;return(0,xe.isString)(T)&&T!==ir.Lexer.SKIPPED&&(v[T]=[]),v},{}),C=(0,xe.map)(s,function(v,D){return{pattern:s[D],longerAlt:l[D],canLineTerminator:g[D],isCustom:f[D],short:h[D],group:a[D],push:c[D],pop:u[D],tokenTypeIdx:o[D],tokenType:i[D]}})});var y=!0,B=[];return e.safeMode||t("First Char Optimization",function(){B=(0,xe.reduce)(i,function(v,D,T){if(typeof D.PATTERN=="string"){var H=D.PATTERN.charCodeAt(0),j=Lv(H);Fv(v,j,C[T])}else if((0,xe.isArray)(D.START_CHARS_HINT)){var $;(0,xe.forEach)(D.START_CHARS_HINT,function(W){var _=typeof W=="string"?W.charCodeAt(0):W,A=Lv(_);$!==A&&($=A,Fv(v,A,C[T]))})}else if((0,xe.isRegExp)(D.PATTERN))if(D.PATTERN.unicode)y=!1,e.ensureOptimizations&&(0,xe.PRINT_ERROR)(""+Zg.failedOptimizationPrefixMsg+(" Unable to analyze < "+D.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 V=(0,Zg.getOptimizedStartCodesIndices)(D.PATTERN,e.ensureOptimizations);(0,xe.isEmpty)(V)&&(y=!1),(0,xe.forEach)(V,function(W){Fv(v,W,C[T])})}else e.ensureOptimizations&&(0,xe.PRINT_ERROR)(""+Zg.failedOptimizationPrefixMsg+(" TokenType: <"+D.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 v},[])}),t("ArrayPacking",function(){B=(0,xe.packArray)(B)}),{emptyGroups:p,patternIdxToConfig:C,charCodeToPatternIdxToConfig:B,hasCustom:n,canBeOptimized:y}}Ve.analyzeTokenTypes=PEe;function DEe(r,e){var t=[],i=WY(r);t=t.concat(i.errors);var n=zY(i.valid),s=n.valid;return t=t.concat(n.errors),t=t.concat(kEe(s)),t=t.concat(ej(s)),t=t.concat(tj(s,e)),t=t.concat(rj(s)),t}Ve.validatePatterns=DEe;function kEe(r){var e=[],t=(0,xe.filter)(r,function(i){return(0,xe.isRegExp)(i[Do])});return e=e.concat(VY(t)),e=e.concat(ZY(t)),e=e.concat(_Y(t)),e=e.concat($Y(t)),e=e.concat(XY(t)),e}function WY(r){var e=(0,xe.filter)(r,function(n){return!(0,xe.has)(n,Do)}),t=(0,xe.map)(e,function(n){return{message:"Token Type: ->"+n.name+"<- missing static 'PATTERN' property",type:ir.LexerDefinitionErrorType.MISSING_PATTERN,tokenTypes:[n]}}),i=(0,xe.difference)(r,e);return{errors:t,valid:i}}Ve.findMissingPatterns=WY;function zY(r){var e=(0,xe.filter)(r,function(n){var s=n[Do];return!(0,xe.isRegExp)(s)&&!(0,xe.isFunction)(s)&&!(0,xe.has)(s,"exec")&&!(0,xe.isString)(s)}),t=(0,xe.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:ir.LexerDefinitionErrorType.INVALID_PATTERN,tokenTypes:[n]}}),i=(0,xe.difference)(r,e);return{errors:t,valid:i}}Ve.findInvalidPatterns=zY;var REe=/[^\\][\$]/;function VY(r){var e=function(n){jY(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}(qY.BaseRegExpVisitor),t=(0,xe.filter)(r,function(n){var s=n[Do];try{var o=(0,JY.getRegExpAst)(s),a=new e;return a.visit(o),a.found}catch{return REe.test(s.source)}}),i=(0,xe.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:ir.LexerDefinitionErrorType.EOI_ANCHOR_FOUND,tokenTypes:[n]}});return i}Ve.findEndOfInputAnchor=VY;function XY(r){var e=(0,xe.filter)(r,function(i){var n=i[Do];return n.test("")}),t=(0,xe.map)(e,function(i){return{message:"Token Type: ->"+i.name+"<- static 'PATTERN' must not match an empty string",type:ir.LexerDefinitionErrorType.EMPTY_MATCH_PATTERN,tokenTypes:[i]}});return t}Ve.findEmptyMatchRegExps=XY;var FEe=/[^\\[][\^]|^\^/;function ZY(r){var e=function(n){jY(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}(qY.BaseRegExpVisitor),t=(0,xe.filter)(r,function(n){var s=n[Do];try{var o=(0,JY.getRegExpAst)(s),a=new e;return a.visit(o),a.found}catch{return FEe.test(s.source)}}),i=(0,xe.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:ir.LexerDefinitionErrorType.SOI_ANCHOR_FOUND,tokenTypes:[n]}});return i}Ve.findStartOfInputAnchor=ZY;function _Y(r){var e=(0,xe.filter)(r,function(i){var n=i[Do];return n instanceof RegExp&&(n.multiline||n.global)}),t=(0,xe.map)(e,function(i){return{message:"Token Type: ->"+i.name+"<- static 'PATTERN' may NOT contain global('g') or multiline('m')",type:ir.LexerDefinitionErrorType.UNSUPPORTED_FLAGS_FOUND,tokenTypes:[i]}});return t}Ve.findUnsupportedFlags=_Y;function $Y(r){var e=[],t=(0,xe.map)(r,function(s){return(0,xe.reduce)(r,function(o,a){return s.PATTERN.source===a.PATTERN.source&&!(0,xe.contains)(e,a)&&a.PATTERN!==ir.Lexer.NA&&(e.push(a),o.push(a)),o},[])});t=(0,xe.compact)(t);var i=(0,xe.filter)(t,function(s){return s.length>1}),n=(0,xe.map)(i,function(s){var o=(0,xe.map)(s,function(l){return l.name}),a=(0,xe.first)(s).PATTERN;return{message:"The same RegExp pattern ->"+a+"<-"+("has been used in all of the following Token Types: "+o.join(", ")+" <-"),type:ir.LexerDefinitionErrorType.DUPLICATE_PATTERNS_FOUND,tokenTypes:s}});return n}Ve.findDuplicatePatterns=$Y;function ej(r){var e=(0,xe.filter)(r,function(i){if(!(0,xe.has)(i,"GROUP"))return!1;var n=i.GROUP;return n!==ir.Lexer.SKIPPED&&n!==ir.Lexer.NA&&!(0,xe.isString)(n)}),t=(0,xe.map)(e,function(i){return{message:"Token Type: ->"+i.name+"<- static 'GROUP' can only be Lexer.SKIPPED/Lexer.NA/A String",type:ir.LexerDefinitionErrorType.INVALID_GROUP_TYPE_FOUND,tokenTypes:[i]}});return t}Ve.findInvalidGroupType=ej;function tj(r,e){var t=(0,xe.filter)(r,function(n){return n.PUSH_MODE!==void 0&&!(0,xe.contains)(e,n.PUSH_MODE)}),i=(0,xe.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:ir.LexerDefinitionErrorType.PUSH_MODE_DOES_NOT_EXIST,tokenTypes:[n]}});return i}Ve.findModesThatDoNotExist=tj;function rj(r){var e=[],t=(0,xe.reduce)(r,function(i,n,s){var o=n.PATTERN;return o===ir.Lexer.NA||((0,xe.isString)(o)?i.push({str:o,idx:s,tokenType:n}):(0,xe.isRegExp)(o)&&TEe(o)&&i.push({str:o.source,idx:s,tokenType:n})),i},[]);return(0,xe.forEach)(r,function(i,n){(0,xe.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:ir.LexerDefinitionErrorType.UNREACHABLE_PATTERN,tokenTypes:[i,l]})}})}),e}Ve.findUnreachablePatterns=rj;function NEe(r,e){if((0,xe.isRegExp)(e)){var t=e.exec(r);return t!==null&&t.index===0}else{if((0,xe.isFunction)(e))return e(r,0,[],{});if((0,xe.has)(e,"exec"))return e.exec(r,0,[],{});if(typeof e=="string")return e===r;throw Error("non exhaustive match")}}function TEe(r){var e=[".","\\","[","]","|","^","$","(",")","?","*","+","{"];return(0,xe.find)(e,function(t){return r.source.indexOf(t)!==-1})===void 0}function Nv(r){var e=r.ignoreCase?"i":"";return new RegExp("^(?:"+r.source+")",e)}Ve.addStartOfInput=Nv;function Tv(r){var e=r.ignoreCase?"iy":"y";return new RegExp(""+r.source,e)}Ve.addStickyFlag=Tv;function LEe(r,e,t){var i=[];return(0,xe.has)(r,Ve.DEFAULT_MODE)||i.push({message:"A MultiMode Lexer cannot be initialized without a <"+Ve.DEFAULT_MODE+`> property in its definition +`,type:ir.LexerDefinitionErrorType.MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE}),(0,xe.has)(r,Ve.MODES)||i.push({message:"A MultiMode Lexer cannot be initialized without a <"+Ve.MODES+`> property in its definition +`,type:ir.LexerDefinitionErrorType.MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY}),(0,xe.has)(r,Ve.MODES)&&(0,xe.has)(r,Ve.DEFAULT_MODE)&&!(0,xe.has)(r.modes,r.defaultMode)&&i.push({message:"A MultiMode Lexer cannot be initialized with a "+Ve.DEFAULT_MODE+": <"+r.defaultMode+`>which does not exist +`,type:ir.LexerDefinitionErrorType.MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST}),(0,xe.has)(r,Ve.MODES)&&(0,xe.forEach)(r.modes,function(n,s){(0,xe.forEach)(n,function(o,a){(0,xe.isUndefined)(o)&&i.push({message:"A Lexer cannot be initialized using an undefined Token Type. Mode:"+("<"+s+"> at index: <"+a+`> +`),type:ir.LexerDefinitionErrorType.LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED})})}),i}Ve.performRuntimeChecks=LEe;function MEe(r,e,t){var i=[],n=!1,s=(0,xe.compact)((0,xe.flatten)((0,xe.mapValues)(r.modes,function(l){return l}))),o=(0,xe.reject)(s,function(l){return l[Do]===ir.Lexer.NA}),a=oj(t);return e&&(0,xe.forEach)(o,function(l){var c=nj(l,a);if(c!==!1){var u=sj(l,c),g={message:u,type:c.issue,tokenType:l};i.push(g)}else(0,xe.has)(l,"LINE_BREAKS")?l.LINE_BREAKS===!0&&(n=!0):(0,Zg.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:ir.LexerDefinitionErrorType.NO_LINE_BREAKS_FLAGS}),i}Ve.performWarningRuntimeChecks=MEe;function OEe(r){var e={},t=(0,xe.keys)(r);return(0,xe.forEach)(t,function(i){var n=r[i];if((0,xe.isArray)(n))e[i]=[];else throw Error("non exhaustive match")}),e}Ve.cloneEmptyGroups=OEe;function Mv(r){var e=r.PATTERN;if((0,xe.isRegExp)(e))return!1;if((0,xe.isFunction)(e))return!0;if((0,xe.has)(e,"exec"))return!0;if((0,xe.isString)(e))return!1;throw Error("non exhaustive match")}Ve.isCustomPattern=Mv;function ij(r){return(0,xe.isString)(r)&&r.length===1?r.charCodeAt(0):!1}Ve.isShortPattern=ij;Ve.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===ir.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")}Ve.buildLineBreakIssueMessage=sj;function oj(r){var e=(0,xe.map)(r,function(t){return(0,xe.isString)(t)&&t.length>0?t.charCodeAt(0):t});return e}function Fv(r,e,t){r[e]===void 0?r[e]=[t]:r[e].push(t)}Ve.minOptimizationVal=256;var ny=[];function Lv(r){return r255?255+~~(r/255):r}}});var _g=w(Nt=>{"use strict";Object.defineProperty(Nt,"__esModule",{value:!0});Nt.isTokenType=Nt.hasExtendingTokensTypesMapProperty=Nt.hasExtendingTokensTypesProperty=Nt.hasCategoriesProperty=Nt.hasShortKeyProperty=Nt.singleAssignCategoriesToksMap=Nt.assignCategoriesMapProp=Nt.assignCategoriesTokensProp=Nt.assignTokenDefaultProps=Nt.expandCategories=Nt.augmentTokenTypes=Nt.tokenIdxToClass=Nt.tokenShortNameIdx=Nt.tokenStructuredMatcherNoCategories=Nt.tokenStructuredMatcher=void 0;var Zr=Gt();function UEe(r,e){var t=r.tokenTypeIdx;return t===e.tokenTypeIdx?!0:e.isParent===!0&&e.categoryMatchesMap[t]===!0}Nt.tokenStructuredMatcher=UEe;function HEe(r,e){return r.tokenTypeIdx===e.tokenTypeIdx}Nt.tokenStructuredMatcherNoCategories=HEe;Nt.tokenShortNameIdx=1;Nt.tokenIdxToClass={};function GEe(r){var e=aj(r);Aj(e),cj(e),lj(e),(0,Zr.forEach)(e,function(t){t.isParent=t.categoryMatches.length>0})}Nt.augmentTokenTypes=GEe;function aj(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}Nt.expandCategories=aj;function Aj(r){(0,Zr.forEach)(r,function(e){uj(e)||(Nt.tokenIdxToClass[Nt.tokenShortNameIdx]=e,e.tokenTypeIdx=Nt.tokenShortNameIdx++),Ov(e)&&!(0,Zr.isArray)(e.CATEGORIES)&&(e.CATEGORIES=[e.CATEGORIES]),Ov(e)||(e.CATEGORIES=[]),gj(e)||(e.categoryMatches=[]),fj(e)||(e.categoryMatchesMap={})})}Nt.assignTokenDefaultProps=Aj;function lj(r){(0,Zr.forEach)(r,function(e){e.categoryMatches=[],(0,Zr.forEach)(e.categoryMatchesMap,function(t,i){e.categoryMatches.push(Nt.tokenIdxToClass[i].tokenTypeIdx)})})}Nt.assignCategoriesTokensProp=lj;function cj(r){(0,Zr.forEach)(r,function(e){Kv([],e)})}Nt.assignCategoriesMapProp=cj;function Kv(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)||Kv(i,t)})}Nt.singleAssignCategoriesToksMap=Kv;function uj(r){return(0,Zr.has)(r,"tokenTypeIdx")}Nt.hasShortKeyProperty=uj;function Ov(r){return(0,Zr.has)(r,"CATEGORIES")}Nt.hasCategoriesProperty=Ov;function gj(r){return(0,Zr.has)(r,"categoryMatches")}Nt.hasExtendingTokensTypesProperty=gj;function fj(r){return(0,Zr.has)(r,"categoryMatchesMap")}Nt.hasExtendingTokensTypesMapProperty=fj;function YEe(r){return(0,Zr.has)(r,"tokenTypeIdx")}Nt.isTokenType=YEe});var Uv=w(sy=>{"use strict";Object.defineProperty(sy,"__esModule",{value:!0});sy.defaultLexerErrorProvider=void 0;sy.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=w(Cc=>{"use strict";Object.defineProperty(Cc,"__esModule",{value:!0});Cc.Lexer=Cc.LexerDefinitionErrorType=void 0;var _s=Rv(),nr=Gt(),jEe=_g(),qEe=Uv(),JEe=ty(),WEe;(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"})(WEe=Cc.LexerDefinitionErrorType||(Cc.LexerDefinitionErrorType={}));var bd={deferDefinitionErrorsHandling:!1,positionTracking:"full",lineTerminatorsPattern:/\n|\r\n?/g,lineTerminatorCharacters:[` +`,"\r"],ensureOptimizations:!1,safeMode:!1,errorMessageProvider:qEe.defaultLexerErrorProvider,traceInitPerf:!1,skipValidations:!1};Object.freeze(bd);var zEe=function(){function r(e,t){var i=this;if(t===void 0&&(t=bd),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,nr.merge)(bd,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===bd.lineTerminatorsPattern)i.config.lineTerminatorsPattern=_s.LineTerminatorOptimizedTester;else if(i.config.lineTerminatorCharacters===bd.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,nr.isArray)(e)?(s={modes:{}},s.modes[_s.DEFAULT_MODE]=(0,nr.cloneArr)(e),s[_s.DEFAULT_MODE]=_s.DEFAULT_MODE):(o=!1,s=(0,nr.cloneObj)(e))}),i.config.skipValidations===!1&&(i.TRACE_INIT("performRuntimeChecks",function(){i.lexerDefinitionErrors=i.lexerDefinitionErrors.concat((0,_s.performRuntimeChecks)(s,i.trackStartLines,i.config.lineTerminatorCharacters))}),i.TRACE_INIT("performWarningRuntimeChecks",function(){i.lexerDefinitionWarning=i.lexerDefinitionWarning.concat((0,_s.performWarningRuntimeChecks)(s,i.trackStartLines,i.config.lineTerminatorCharacters))})),s.modes=s.modes?s.modes:{},(0,nr.forEach)(s.modes,function(u,g){s.modes[g]=(0,nr.reject)(u,function(f){return(0,nr.isUndefined)(f)})});var a=(0,nr.keys)(s.modes);if((0,nr.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,_s.validatePatterns)(u,a))}),(0,nr.isEmpty)(i.lexerDefinitionErrors)){(0,jEe.augmentTokenTypes)(u);var f;i.TRACE_INIT("analyzeTokenTypes",function(){f=(0,_s.analyzeTokenTypes)(u,{lineTerminatorCharacters:i.config.lineTerminatorCharacters,positionTracking:t.positionTracking,ensureOptimizations:t.ensureOptimizations,safeMode:t.safeMode,tracer:i.TRACE_INIT.bind(i)})}),i.patternIdxToConfig[g]=f.patternIdxToConfig,i.charCodeToPatternIdxToConfig[g]=f.charCodeToPatternIdxToConfig,i.emptyGroups=(0,nr.merge)(i.emptyGroups,f.emptyGroups),i.hasCustom=f.hasCustom||i.hasCustom,i.canModeBeOptimized[g]=f.canBeOptimized}})}),i.defaultMode=s.defaultMode,!(0,nr.isEmpty)(i.lexerDefinitionErrors)&&!i.config.deferDefinitionErrorsHandling){var l=(0,nr.map)(i.lexerDefinitionErrors,function(u){return u.message}),c=l.join(`----------------------- +`);throw new Error(`Errors detected in definition of Lexer: +`+c)}(0,nr.forEach)(i.lexerDefinitionWarning,function(u){(0,nr.PRINT_WARNING)(u.message)}),i.TRACE_INIT("Choosing sub-methods implementations",function(){if(_s.SUPPORT_STICKY?(i.chopInput=nr.IDENTITY,i.match=i.matchWithTest):(i.updateLastIndex=nr.NOOP,i.match=i.matchWithExec),o&&(i.handleModes=nr.NOOP),i.trackStartLines===!1&&(i.computeNewColumn=nr.IDENTITY),i.trackEndLines===!1&&(i.updateTokenEndLineColumnLocation=nr.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,nr.reduce)(i.canModeBeOptimized,function(g,f,h){return f===!1&&g.push(h),g},[]);if(t.ensureOptimizations&&!(0,nr.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,JEe.clearRegExpParserCache)()}),i.TRACE_INIT("toFastProperties",function(){(0,nr.toFastProperties)(i)})})}return r.prototype.tokenize=function(e,t){if(t===void 0&&(t=this.defaultMode),!(0,nr.isEmpty)(this.lexerDefinitionErrors)){var i=(0,nr.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,f,h,p,C,y,B,v,D,T=e,H=T.length,j=0,$=0,V=this.hasCustom?0:Math.floor(e.length/10),W=new Array(V),_=[],A=this.trackStartLines?1:void 0,Ae=this.trackStartLines?1:void 0,ge=(0,_s.cloneEmptyGroups)(this.emptyGroups),re=this.trackStartLines,M=this.config.lineTerminatorsPattern,F=0,ue=[],pe=[],ke=[],Fe=[];Object.freeze(Fe);var Ne=void 0;function oe(){return ue}function le(pr){var Ii=(0,_s.charCodeToOptimizedIndex)(pr),rs=pe[Ii];return rs===void 0?Fe:rs}var Be=function(pr){if(ke.length===1&&pr.tokenType.PUSH_MODE===void 0){var Ii=i.config.errorMessageProvider.buildUnableToPopLexerModeMessage(pr);_.push({offset:pr.startOffset,line:pr.startLine!==void 0?pr.startLine:void 0,column:pr.startColumn!==void 0?pr.startColumn:void 0,length:pr.image.length,message:Ii})}else{ke.pop();var rs=(0,nr.last)(ke);ue=i.patternIdxToConfig[rs],pe=i.charCodeToPatternIdxToConfig[rs],F=ue.length;var fa=i.canModeBeOptimized[rs]&&i.config.safeMode===!1;pe&&fa?Ne=le:Ne=oe}};function fe(pr){ke.push(pr),pe=this.charCodeToPatternIdxToConfig[pr],ue=this.patternIdxToConfig[pr],F=ue.length,F=ue.length;var Ii=this.canModeBeOptimized[pr]&&this.config.safeMode===!1;pe&&Ii?Ne=le:Ne=oe}fe.call(this,t);for(var ae;jc.length){c=a,u=g,ae=_e;break}}}break}}if(c!==null){if(f=c.length,h=ae.group,h!==void 0&&(p=ae.tokenTypeIdx,C=this.createTokenInstance(c,j,p,ae.tokenType,A,Ae,f),this.handlePayload(C,u),h===!1?$=this.addToken(W,$,C):ge[h].push(C)),e=this.chopInput(e,f),j=j+f,Ae=this.computeNewColumn(Ae,f),re===!0&&ae.canLineTerminator===!0){var It=0,Mr=void 0,ii=void 0;M.lastIndex=0;do Mr=M.test(c),Mr===!0&&(ii=M.lastIndex-1,It++);while(Mr===!0);It!==0&&(A=A+It,Ae=f-ii,this.updateTokenEndLineColumnLocation(C,h,ii,It,A,Ae,f))}this.handleModes(ae,Be,fe,C)}else{for(var gi=j,hr=A,fi=Ae,ni=!1;!ni&&j <"+e+">");var n=(0,nr.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}();Cc.Lexer=zEe});var LA=w(Qi=>{"use strict";Object.defineProperty(Qi,"__esModule",{value:!0});Qi.tokenMatcher=Qi.createTokenInstance=Qi.EOF=Qi.createToken=Qi.hasTokenLabel=Qi.tokenName=Qi.tokenLabel=void 0;var $s=Gt(),VEe=Bd(),Hv=_g();function XEe(r){return wj(r)?r.LABEL:r.name}Qi.tokenLabel=XEe;function ZEe(r){return r.name}Qi.tokenName=ZEe;function wj(r){return(0,$s.isString)(r.LABEL)&&r.LABEL!==""}Qi.hasTokenLabel=wj;var _Ee="parent",hj="categories",pj="label",dj="group",Cj="push_mode",mj="pop_mode",Ej="longer_alt",Ij="line_breaks",yj="start_chars_hint";function Bj(r){return $Ee(r)}Qi.createToken=Bj;function $Ee(r){var e=r.pattern,t={};if(t.name=r.name,(0,$s.isUndefined)(e)||(t.PATTERN=e),(0,$s.has)(r,_Ee))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,hj)&&(t.CATEGORIES=r[hj]),(0,Hv.augmentTokenTypes)([t]),(0,$s.has)(r,pj)&&(t.LABEL=r[pj]),(0,$s.has)(r,dj)&&(t.GROUP=r[dj]),(0,$s.has)(r,mj)&&(t.POP_MODE=r[mj]),(0,$s.has)(r,Cj)&&(t.PUSH_MODE=r[Cj]),(0,$s.has)(r,Ej)&&(t.LONGER_ALT=r[Ej]),(0,$s.has)(r,Ij)&&(t.LINE_BREAKS=r[Ij]),(0,$s.has)(r,yj)&&(t.START_CHARS_HINT=r[yj]),t}Qi.EOF=Bj({name:"EOF",pattern:VEe.Lexer.NA});(0,Hv.augmentTokenTypes)([Qi.EOF]);function eIe(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}}Qi.createTokenInstance=eIe;function tIe(r,e){return(0,Hv.tokenStructuredMatcher)(r,e)}Qi.tokenMatcher=tIe});var mn=w(zt=>{"use strict";var Pa=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.serializeProduction=zt.serializeGrammar=zt.Terminal=zt.Alternation=zt.RepetitionWithSeparator=zt.Repetition=zt.RepetitionMandatoryWithSeparator=zt.RepetitionMandatory=zt.Option=zt.Alternative=zt.Rule=zt.NonTerminal=zt.AbstractProduction=void 0;var Ar=Gt(),rIe=LA(),ko=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,Ar.forEach)(this.definition,function(t){t.accept(e)})},r}();zt.AbstractProduction=ko;var bj=function(r){Pa(e,r);function e(t){var i=r.call(this,[])||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.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}(ko);zt.NonTerminal=bj;var Qj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.orgText="",(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(ko);zt.Rule=Qj;var Sj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.ignoreAmbiguities=!1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(ko);zt.Alternative=Sj;var vj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(ko);zt.Option=vj;var xj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(ko);zt.RepetitionMandatory=xj;var Pj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(ko);zt.RepetitionMandatoryWithSeparator=Pj;var Dj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(ko);zt.Repetition=Dj;var kj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(ko);zt.RepetitionWithSeparator=kj;var Rj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,i.ignoreAmbiguities=!1,i.hasPredicates=!1,(0,Ar.assign)(i,(0,Ar.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}(ko);zt.Alternation=Rj;var oy=function(){function r(e){this.idx=1,(0,Ar.assign)(this,(0,Ar.pick)(e,function(t){return t!==void 0}))}return r.prototype.accept=function(e){e.visit(this)},r}();zt.Terminal=oy;function iIe(r){return(0,Ar.map)(r,Qd)}zt.serializeGrammar=iIe;function Qd(r){function e(s){return(0,Ar.map)(s,Qd)}if(r instanceof bj){var t={type:"NonTerminal",name:r.nonTerminalName,idx:r.idx};return(0,Ar.isString)(r.label)&&(t.label=r.label),t}else{if(r instanceof Sj)return{type:"Alternative",definition:e(r.definition)};if(r instanceof vj)return{type:"Option",idx:r.idx,definition:e(r.definition)};if(r instanceof xj)return{type:"RepetitionMandatory",idx:r.idx,definition:e(r.definition)};if(r instanceof Pj)return{type:"RepetitionMandatoryWithSeparator",idx:r.idx,separator:Qd(new oy({terminalType:r.separator})),definition:e(r.definition)};if(r instanceof kj)return{type:"RepetitionWithSeparator",idx:r.idx,separator:Qd(new oy({terminalType:r.separator})),definition:e(r.definition)};if(r instanceof Dj)return{type:"Repetition",idx:r.idx,definition:e(r.definition)};if(r instanceof Rj)return{type:"Alternation",idx:r.idx,definition:e(r.definition)};if(r instanceof oy){var i={type:"Terminal",name:r.terminalType.name,label:(0,rIe.tokenLabel)(r.terminalType),idx:r.idx};(0,Ar.isString)(r.label)&&(i.terminalLabel=r.label);var n=r.terminalType.PATTERN;return r.terminalType.PATTERN&&(i.pattern=(0,Ar.isRegExp)(n)?n.source:n),i}else{if(r instanceof Qj)return{type:"Rule",name:r.name,orgText:r.orgText,definition:e(r.definition)};throw Error("non exhaustive match")}}}zt.serializeProduction=Qd});var Ay=w(ay=>{"use strict";Object.defineProperty(ay,"__esModule",{value:!0});ay.RestWalker=void 0;var Gv=Gt(),En=mn(),nIe=function(){function r(){}return r.prototype.walk=function(e,t){var i=this;t===void 0&&(t=[]),(0,Gv.forEach)(e.definition,function(n,s){var o=(0,Gv.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=Fj(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=Fj(e,t,i);this.walk(e,n)},r.prototype.walkOr=function(e,t,i){var n=this,s=t.concat(i);(0,Gv.forEach)(e.definition,function(o){var a=new En.Alternative({definition:[o]});n.walk(a,s)})},r}();ay.RestWalker=nIe;function Fj(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 $g=w(ly=>{"use strict";Object.defineProperty(ly,"__esModule",{value:!0});ly.GAstVisitor=void 0;var Ro=mn(),sIe=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}();ly.GAstVisitor=sIe});var vd=w(Oi=>{"use strict";var oIe=Oi&&Oi.__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(Oi,"__esModule",{value:!0});Oi.collectMethods=Oi.DslMethodsCollectorVisitor=Oi.getProductionDslName=Oi.isBranchingProd=Oi.isOptionalProd=Oi.isSequenceProd=void 0;var Sd=Gt(),br=mn(),aIe=$g();function AIe(r){return r instanceof br.Alternative||r instanceof br.Option||r instanceof br.Repetition||r instanceof br.RepetitionMandatory||r instanceof br.RepetitionMandatoryWithSeparator||r instanceof br.RepetitionWithSeparator||r instanceof br.Terminal||r instanceof br.Rule}Oi.isSequenceProd=AIe;function Yv(r,e){e===void 0&&(e=[]);var t=r instanceof br.Option||r instanceof br.Repetition||r instanceof br.RepetitionWithSeparator;return t?!0:r instanceof br.Alternation?(0,Sd.some)(r.definition,function(i){return Yv(i,e)}):r instanceof br.NonTerminal&&(0,Sd.contains)(e,r)?!1:r instanceof br.AbstractProduction?(r instanceof br.NonTerminal&&e.push(r),(0,Sd.every)(r.definition,function(i){return Yv(i,e)})):!1}Oi.isOptionalProd=Yv;function lIe(r){return r instanceof br.Alternation}Oi.isBranchingProd=lIe;function cIe(r){if(r instanceof br.NonTerminal)return"SUBRULE";if(r instanceof br.Option)return"OPTION";if(r instanceof br.Alternation)return"OR";if(r instanceof br.RepetitionMandatory)return"AT_LEAST_ONE";if(r instanceof br.RepetitionMandatoryWithSeparator)return"AT_LEAST_ONE_SEP";if(r instanceof br.RepetitionWithSeparator)return"MANY_SEP";if(r instanceof br.Repetition)return"MANY";if(r instanceof br.Terminal)return"CONSUME";throw Error("non exhaustive match")}Oi.getProductionDslName=cIe;var Nj=function(r){oIe(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,Sd.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,Sd.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}(aIe.GAstVisitor);Oi.DslMethodsCollectorVisitor=Nj;var cy=new Nj;function uIe(r){cy.reset(),r.accept(cy);var e=cy.dslMethods;return cy.reset(),e}Oi.collectMethods=uIe});var qv=w(Fo=>{"use strict";Object.defineProperty(Fo,"__esModule",{value:!0});Fo.firstForTerminal=Fo.firstForBranching=Fo.firstForSequence=Fo.first=void 0;var uy=Gt(),Tj=mn(),jv=vd();function gy(r){if(r instanceof Tj.NonTerminal)return gy(r.referencedRule);if(r instanceof Tj.Terminal)return Oj(r);if((0,jv.isSequenceProd)(r))return Lj(r);if((0,jv.isBranchingProd)(r))return Mj(r);throw Error("non exhaustive match")}Fo.first=gy;function Lj(r){for(var e=[],t=r.definition,i=0,n=t.length>i,s,o=!0;n&&o;)s=t[i],o=(0,jv.isOptionalProd)(s),e=e.concat(gy(s)),i=i+1,n=t.length>i;return(0,uy.uniq)(e)}Fo.firstForSequence=Lj;function Mj(r){var e=(0,uy.map)(r.definition,function(t){return gy(t)});return(0,uy.uniq)((0,uy.flatten)(e))}Fo.firstForBranching=Mj;function Oj(r){return[r.terminalType]}Fo.firstForTerminal=Oj});var Jv=w(fy=>{"use strict";Object.defineProperty(fy,"__esModule",{value:!0});fy.IN=void 0;fy.IN="_~IN~_"});var Yj=w(fs=>{"use strict";var gIe=fs&&fs.__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(fs,"__esModule",{value:!0});fs.buildInProdFollowPrefix=fs.buildBetweenProdsFollowPrefix=fs.computeAllProdsFollows=fs.ResyncFollowsWalker=void 0;var fIe=Ay(),hIe=qv(),Kj=Gt(),Uj=Jv(),pIe=mn(),Hj=function(r){gIe(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=Gj(t.referencedRule,t.idx)+this.topProd.name,o=i.concat(n),a=new pIe.Alternative({definition:o}),l=(0,hIe.first)(a);this.follows[s]=l},e}(fIe.RestWalker);fs.ResyncFollowsWalker=Hj;function dIe(r){var e={};return(0,Kj.forEach)(r,function(t){var i=new Hj(t).startWalking();(0,Kj.assign)(e,i)}),e}fs.computeAllProdsFollows=dIe;function Gj(r,e){return r.name+e+Uj.IN}fs.buildBetweenProdsFollowPrefix=Gj;function CIe(r){var e=r.terminalType.name;return e+r.idx+Uj.IN}fs.buildInProdFollowPrefix=CIe});var xd=w(Da=>{"use strict";Object.defineProperty(Da,"__esModule",{value:!0});Da.defaultGrammarValidatorErrorProvider=Da.defaultGrammarResolverErrorProvider=Da.defaultParserErrorProvider=void 0;var ef=LA(),mIe=Gt(),eo=Gt(),Wv=mn(),jj=vd();Da.defaultParserErrorProvider={buildMismatchTokenMessage:function(r){var e=r.expected,t=r.actual,i=r.previous,n=r.ruleName,s=(0,ef.hasTokenLabel)(e),o=s?"--> "+(0,ef.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,eo.first)(t).image,l=` +but found: '`+a+"'";if(n)return o+n+l;var c=(0,eo.reduce)(e,function(h,p){return h.concat(p)},[]),u=(0,eo.map)(c,function(h){return"["+(0,eo.map)(h,function(p){return(0,ef.tokenLabel)(p)}).join(", ")+"]"}),g=(0,eo.map)(u,function(h,p){return" "+(p+1)+". "+h}),f=`one of these possible Token sequences: +`+g.join(` +`);return o+f+l},buildEarlyExitMessage:function(r){var e=r.expectedIterationPaths,t=r.actual,i=r.customUserDescription,n=r.ruleName,s="Expecting: ",o=(0,eo.first)(t).image,a=` +but found: '`+o+"'";if(i)return s+i+a;var l=(0,eo.map)(e,function(u){return"["+(0,eo.map)(u,function(g){return(0,ef.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 Wv.Terminal?u.terminalType.name:u instanceof Wv.NonTerminal?u.nonTerminalName:""}var i=r.name,n=(0,eo.first)(e),s=n.idx,o=(0,jj.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,eo.map)(r.prefixPath,function(n){return(0,ef.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,eo.map)(r.prefixPath,function(n){return(0,ef.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,jj.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=mIe.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 Wv.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 Wj=w(MA=>{"use strict";var EIe=MA&&MA.__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(MA,"__esModule",{value:!0});MA.GastRefResolverVisitor=MA.resolveGrammar=void 0;var IIe=jn(),qj=Gt(),yIe=$g();function wIe(r,e){var t=new Jj(r,e);return t.resolveRefs(),t.errors}MA.resolveGrammar=wIe;var Jj=function(r){EIe(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,qj.forEach)((0,qj.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:IIe.ParserDefinitionErrorType.UNRESOLVED_SUBRULE_REF,ruleName:this.currTopLevel.name,unresolvedRefName:t.nonTerminalName})}},e}(yIe.GAstVisitor);MA.GastRefResolverVisitor=Jj});var Dd=w(Nr=>{"use strict";var mc=Nr&&Nr.__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(Nr,"__esModule",{value:!0});Nr.nextPossibleTokensAfter=Nr.possiblePathsFrom=Nr.NextTerminalAfterAtLeastOneSepWalker=Nr.NextTerminalAfterAtLeastOneWalker=Nr.NextTerminalAfterManySepWalker=Nr.NextTerminalAfterManyWalker=Nr.AbstractNextTerminalAfterProductionWalker=Nr.NextAfterTokenWalker=Nr.AbstractNextPossibleTokensWalker=void 0;var zj=Ay(),Kt=Gt(),BIe=qv(),kt=mn(),Vj=function(r){mc(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,Kt.cloneArr)(this.path.ruleStack).reverse(),this.occurrenceStack=(0,Kt.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,Kt.isEmpty)(this.ruleStack)?(this.nextProductionName="",this.nextProductionOccurrence=0,this.isAtEndOfPath=!0):(this.nextProductionName=this.ruleStack.pop(),this.nextProductionOccurrence=this.occurrenceStack.pop())},e}(zj.RestWalker);Nr.AbstractNextPossibleTokensWalker=Vj;var bIe=function(r){mc(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 kt.Alternative({definition:s});this.possibleTokTypes=(0,BIe.first)(o),this.found=!0}},e}(Vj);Nr.NextAfterTokenWalker=bIe;var Pd=function(r){mc(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}(zj.RestWalker);Nr.AbstractNextTerminalAfterProductionWalker=Pd;var QIe=function(r){mc(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,Kt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof kt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkMany.call(this,t,i,n)},e}(Pd);Nr.NextTerminalAfterManyWalker=QIe;var SIe=function(r){mc(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,Kt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof kt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkManySep.call(this,t,i,n)},e}(Pd);Nr.NextTerminalAfterManySepWalker=SIe;var vIe=function(r){mc(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,Kt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof kt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkAtLeastOne.call(this,t,i,n)},e}(Pd);Nr.NextTerminalAfterAtLeastOneWalker=vIe;var xIe=function(r){mc(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,Kt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof kt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkAtLeastOneSep.call(this,t,i,n)},e}(Pd);Nr.NextTerminalAfterAtLeastOneSepWalker=xIe;function Xj(r,e,t){t===void 0&&(t=[]),t=(0,Kt.cloneArr)(t);var i=[],n=0;function s(c){return c.concat((0,Kt.drop)(r,n+1))}function o(c){var u=Xj(s(c),e,t);return i.concat(u)}for(;t.length=0;ge--){var re=B.definition[ge],M={idx:p,def:re.definition.concat((0,Kt.drop)(h)),ruleStack:C,occurrenceStack:y};g.push(M),g.push(o)}else if(B instanceof kt.Alternative)g.push({idx:p,def:B.definition.concat((0,Kt.drop)(h)),ruleStack:C,occurrenceStack:y});else if(B instanceof kt.Rule)g.push(DIe(B,p,C,y));else throw Error("non exhaustive match")}}return u}Nr.nextPossibleTokensAfter=PIe;function DIe(r,e,t,i){var n=(0,Kt.cloneArr)(t);n.push(r.name);var s=(0,Kt.cloneArr)(i);return s.push(1),{idx:e,def:r.definition,ruleStack:n,occurrenceStack:s}}});var kd=w(Zt=>{"use strict";var $j=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 sr=Gt(),Zj=Dd(),kIe=Ay(),hy=_g(),OA=mn(),RIe=$g(),oi;(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"})(oi=Zt.PROD_TYPE||(Zt.PROD_TYPE={}));function FIe(r){if(r instanceof OA.Option)return oi.OPTION;if(r instanceof OA.Repetition)return oi.REPETITION;if(r instanceof OA.RepetitionMandatory)return oi.REPETITION_MANDATORY;if(r instanceof OA.RepetitionMandatoryWithSeparator)return oi.REPETITION_MANDATORY_WITH_SEPARATOR;if(r instanceof OA.RepetitionWithSeparator)return oi.REPETITION_WITH_SEPARATOR;if(r instanceof OA.Alternation)return oi.ALTERNATION;throw Error("non exhaustive match")}Zt.getProdType=FIe;function NIe(r,e,t,i,n,s){var o=tq(r,e,t),a=Xv(o)?hy.tokenStructuredMatcherNoCategories:hy.tokenStructuredMatcher;return s(o,i,a,n)}Zt.buildLookaheadFuncForOr=NIe;function TIe(r,e,t,i,n,s){var o=rq(r,e,n,t),a=Xv(o)?hy.tokenStructuredMatcherNoCategories:hy.tokenStructuredMatcher;return s(o[0],a,i)}Zt.buildLookaheadFuncForOptionalProd=TIe;function LIe(r,e,t,i){var n=r.length,s=(0,sr.every)(r,function(l){return(0,sr.every)(l,function(c){return c.length===1})});if(e)return function(l){for(var c=(0,sr.map)(l,function(D){return D.GATE}),u=0;u{"use strict";var Zv=Vt&&Vt.__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(Vt,"__esModule",{value:!0});Vt.checkPrefixAlternativesAmbiguities=Vt.validateSomeNonEmptyLookaheadPath=Vt.validateTooManyAlts=Vt.RepetionCollector=Vt.validateAmbiguousAlternationAlternatives=Vt.validateEmptyOrAlternative=Vt.getFirstNoneTerminal=Vt.validateNoLeftRecursion=Vt.validateRuleIsOverridden=Vt.validateRuleDoesNotAlreadyExist=Vt.OccurrenceValidationCollector=Vt.identifyProductionForDuplicates=Vt.validateGrammar=void 0;var er=Gt(),Qr=Gt(),No=jn(),_v=vd(),tf=kd(),HIe=Dd(),to=mn(),$v=$g();function GIe(r,e,t,i,n){var s=er.map(r,function(h){return YIe(h,i)}),o=er.map(r,function(h){return ex(h,h,i)}),a=[],l=[],c=[];(0,Qr.every)(o,Qr.isEmpty)&&(a=(0,Qr.map)(r,function(h){return Aq(h,i)}),l=(0,Qr.map)(r,function(h){return lq(h,e,i)}),c=gq(r,e,i));var u=JIe(r,t,i),g=(0,Qr.map)(r,function(h){return uq(h,i)}),f=(0,Qr.map)(r,function(h){return aq(h,r,n,i)});return er.flatten(s.concat(c,o,a,l,u,g,f))}Vt.validateGrammar=GIe;function YIe(r,e){var t=new oq;r.accept(t);var i=t.allProductions,n=er.groupBy(i,nq),s=er.pick(n,function(a){return a.length>1}),o=er.map(er.values(s),function(a){var l=er.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},f=sq(l);return f&&(g.parameter=f),g});return o}function nq(r){return(0,_v.getProductionDslName)(r)+"_#_"+r.idx+"_#_"+sq(r)}Vt.identifyProductionForDuplicates=nq;function sq(r){return r instanceof to.Terminal?r.terminalType.name:r instanceof to.NonTerminal?r.nonTerminalName:""}var oq=function(r){Zv(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}($v.GAstVisitor);Vt.OccurrenceValidationCollector=oq;function aq(r,e,t,i){var n=[],s=(0,Qr.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}Vt.validateRuleDoesNotAlreadyExist=aq;function jIe(r,e,t){var i=[],n;return er.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}Vt.validateRuleIsOverridden=jIe;function ex(r,e,t,i){i===void 0&&(i=[]);var n=[],s=Rd(e.definition);if(er.isEmpty(s))return[];var o=r.name,a=er.contains(s,r);a&&n.push({message:t.buildLeftRecursionError({topLevelRule:r,leftRecursionPath:i}),type:No.ParserDefinitionErrorType.LEFT_RECURSION,ruleName:o});var l=er.difference(s,i.concat([r])),c=er.map(l,function(u){var g=er.cloneArr(i);return g.push(u),ex(r,u,t,g)});return n.concat(er.flatten(c))}Vt.validateNoLeftRecursion=ex;function Rd(r){var e=[];if(er.isEmpty(r))return e;var t=er.first(r);if(t instanceof to.NonTerminal)e.push(t.referencedRule);else if(t instanceof to.Alternative||t instanceof to.Option||t instanceof to.RepetitionMandatory||t instanceof to.RepetitionMandatoryWithSeparator||t instanceof to.RepetitionWithSeparator||t instanceof to.Repetition)e=e.concat(Rd(t.definition));else if(t instanceof to.Alternation)e=er.flatten(er.map(t.definition,function(o){return Rd(o.definition)}));else if(!(t instanceof to.Terminal))throw Error("non exhaustive match");var i=(0,_v.isOptionalProd)(t),n=r.length>1;if(i&&n){var s=er.drop(r);return e.concat(Rd(s))}else return e}Vt.getFirstNoneTerminal=Rd;var tx=function(r){Zv(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}($v.GAstVisitor);function Aq(r,e){var t=new tx;r.accept(t);var i=t.alternations,n=er.reduce(i,function(s,o){var a=er.dropRight(o.definition),l=er.map(a,function(c,u){var g=(0,HIe.nextPossibleTokensAfter)([c],[],null,1);return er.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(er.compact(l))},[]);return n}Vt.validateEmptyOrAlternative=Aq;function lq(r,e,t){var i=new tx;r.accept(i);var n=i.alternations;n=(0,Qr.reject)(n,function(o){return o.ignoreAmbiguities===!0});var s=er.reduce(n,function(o,a){var l=a.idx,c=a.maxLookahead||e,u=(0,tf.getLookaheadPathsForOr)(l,r,c,a),g=qIe(u,a,r,t),f=fq(u,a,r,t);return o.concat(g,f)},[]);return s}Vt.validateAmbiguousAlternationAlternatives=lq;var cq=function(r){Zv(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}($v.GAstVisitor);Vt.RepetionCollector=cq;function uq(r,e){var t=new tx;r.accept(t);var i=t.alternations,n=er.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}Vt.validateTooManyAlts=uq;function gq(r,e,t){var i=[];return(0,Qr.forEach)(r,function(n){var s=new cq;n.accept(s);var o=s.allProductions;(0,Qr.forEach)(o,function(a){var l=(0,tf.getProdType)(a),c=a.maxLookahead||e,u=a.idx,g=(0,tf.getLookaheadPathsForOptionalProd)(u,n,l,c),f=g[0];if((0,Qr.isEmpty)((0,Qr.flatten)(f))){var h=t.buildEmptyRepetitionError({topLevelRule:n,repetition:a});i.push({message:h,type:No.ParserDefinitionErrorType.NO_NON_EMPTY_LOOKAHEAD,ruleName:n.name})}})}),i}Vt.validateSomeNonEmptyLookaheadPath=gq;function qIe(r,e,t,i){var n=[],s=(0,Qr.reduce)(r,function(a,l,c){return e.definition[c].ignoreAmbiguities===!0||(0,Qr.forEach)(l,function(u){var g=[c];(0,Qr.forEach)(r,function(f,h){c!==h&&(0,tf.containsPath)(f,u)&&e.definition[h].ignoreAmbiguities!==!0&&g.push(h)}),g.length>1&&!(0,tf.containsPath)(n,u)&&(n.push(u),a.push({alts:g,path:u}))}),a},[]),o=er.map(s,function(a){var l=(0,Qr.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 fq(r,e,t,i){var n=[],s=(0,Qr.reduce)(r,function(o,a,l){var c=(0,Qr.map)(a,function(u){return{idx:l,path:u}});return o.concat(c)},[]);return(0,Qr.forEach)(s,function(o){var a=e.definition[o.idx];if(a.ignoreAmbiguities!==!0){var l=o.idx,c=o.path,u=(0,Qr.findAll)(s,function(f){return e.definition[f.idx].ignoreAmbiguities!==!0&&f.idx{"use strict";Object.defineProperty(rf,"__esModule",{value:!0});rf.validateGrammar=rf.resolveGrammar=void 0;var ix=Gt(),WIe=Wj(),zIe=rx(),hq=xd();function VIe(r){r=(0,ix.defaults)(r,{errMsgProvider:hq.defaultGrammarResolverErrorProvider});var e={};return(0,ix.forEach)(r.rules,function(t){e[t.name]=t}),(0,WIe.resolveGrammar)(e,r.errMsgProvider)}rf.resolveGrammar=VIe;function XIe(r){return r=(0,ix.defaults)(r,{errMsgProvider:hq.defaultGrammarValidatorErrorProvider}),(0,zIe.validateGrammar)(r.rules,r.maxLookahead,r.tokenTypes,r.errMsgProvider,r.grammarName)}rf.validateGrammar=XIe});var nf=w(In=>{"use strict";var Fd=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 ZIe=Gt(),dq="MismatchedTokenException",Cq="NoViableAltException",mq="EarlyExitException",Eq="NotAllInputParsedException",Iq=[dq,Cq,mq,Eq];Object.freeze(Iq);function _Ie(r){return(0,ZIe.contains)(Iq,r.name)}In.isRecognitionException=_Ie;var py=function(r){Fd(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),$Ie=function(r){Fd(e,r);function e(t,i,n){var s=r.call(this,t,i)||this;return s.previousToken=n,s.name=dq,s}return e}(py);In.MismatchedTokenException=$Ie;var eye=function(r){Fd(e,r);function e(t,i,n){var s=r.call(this,t,i)||this;return s.previousToken=n,s.name=Cq,s}return e}(py);In.NoViableAltException=eye;var tye=function(r){Fd(e,r);function e(t,i){var n=r.call(this,t,i)||this;return n.name=Eq,n}return e}(py);In.NotAllInputParsedException=tye;var rye=function(r){Fd(e,r);function e(t,i,n){var s=r.call(this,t,i)||this;return s.previousToken=n,s.name=mq,s}return e}(py);In.EarlyExitException=rye});var sx=w(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 dy=LA(),hs=Gt(),iye=nf(),nye=Jv(),sye=jn();Ki.EOF_FOLLOW_KEY={};Ki.IN_RULE_RECOVERY_EXCEPTION="InRuleRecoveryException";function nx(r){this.name=Ki.IN_RULE_RECOVERY_EXCEPTION,this.message=r}Ki.InRuleRecoveryException=nx;nx.prototype=Error.prototype;var oye=function(){function r(){}return r.prototype.initRecoverable=function(e){this.firstAfterRepMap={},this.resyncFollows={},this.recoveryEnabled=(0,hs.has)(e,"recoveryEnabled")?e.recoveryEnabled:sye.DEFAULT_PARSER_CONFIG.recoveryEnabled,this.recoveryEnabled&&(this.attemptInRepetitionRecovery=yq)},r.prototype.getTokenToInsert=function(e){var t=(0,dy.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),f=function(){var h=s.LA(0),p=s.errorMessageProvider.buildMismatchTokenMessage({expected:n,actual:u,previous:h,ruleName:s.getCurrRuleFullName()}),C=new iye.MismatchedTokenException(p,u,s.LA(0));C.resyncedTokens=(0,hs.dropRight)(l),s.SAVE_ERROR(C)};!c;)if(this.tokenMatcher(g,n)){f();return}else if(i.call(this)){f(),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 nx("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,hs.isEmpty)(t))return!1;var n=this.LA(1),s=(0,hs.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,hs.contains)(i,e)},r.prototype.findReSyncTokenType=function(){for(var e=this.flattenFollowSet(),t=this.LA(1),i=2;;){var n=t.tokenType;if((0,hs.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,hs.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,hs.map)(this.buildFullFollowKeyStack(),function(i){return e.getFollowSetFromFollowKey(i)});return(0,hs.flatten)(t)},r.prototype.getFollowSetFromFollowKey=function(e){if(e===Ki.EOF_FOLLOW_KEY)return[dy.EOF];var t=e.ruleName+e.idxInCallingRule+nye.IN+e.inRule;return this.resyncFollows[t]},r.prototype.addToResyncTokens=function(e,t){return this.tokenMatcher(e,dy.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,hs.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,hs.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,hs.map)(this.RULE_STACK,function(t){return e.shortRuleNameToFullName(t)})},r}();Ki.Recoverable=oye;function yq(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 f=l.token,h=l.occurrence,p=l.isEndOfRule;this.RULE_STACK.length===1&&p&&f===void 0&&(f=dy.EOF,h=1),this.shouldInRepetitionRecoveryBeTried(f,h,o)&&this.tryInRepetitionRecovery(r,e,t,f)}Ki.attemptInRepetitionRecovery=yq});var Cy=w(Jt=>{"use strict";Object.defineProperty(Jt,"__esModule",{value:!0});Jt.getKeyForAutomaticLookahead=Jt.AT_LEAST_ONE_SEP_IDX=Jt.MANY_SEP_IDX=Jt.AT_LEAST_ONE_IDX=Jt.MANY_IDX=Jt.OPTION_IDX=Jt.OR_IDX=Jt.BITS_FOR_ALT_IDX=Jt.BITS_FOR_RULE_IDX=Jt.BITS_FOR_OCCURRENCE_IDX=Jt.BITS_FOR_METHOD_TYPE=void 0;Jt.BITS_FOR_METHOD_TYPE=4;Jt.BITS_FOR_OCCURRENCE_IDX=8;Jt.BITS_FOR_RULE_IDX=12;Jt.BITS_FOR_ALT_IDX=8;Jt.OR_IDX=1<{"use strict";Object.defineProperty(my,"__esModule",{value:!0});my.LooksAhead=void 0;var ka=kd(),ro=Gt(),wq=jn(),Ra=Cy(),Ec=vd(),Aye=function(){function r(){}return r.prototype.initLooksAhead=function(e){this.dynamicTokensEnabled=(0,ro.has)(e,"dynamicTokensEnabled")?e.dynamicTokensEnabled:wq.DEFAULT_PARSER_CONFIG.dynamicTokensEnabled,this.maxLookahead=(0,ro.has)(e,"maxLookahead")?e.maxLookahead:wq.DEFAULT_PARSER_CONFIG.maxLookahead,this.lookAheadFuncsCache=(0,ro.isES2015MapSupported)()?new Map:[],(0,ro.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,ro.forEach)(e,function(i){t.TRACE_INIT(i.name+" Rule Lookahead",function(){var n=(0,Ec.collectMethods)(i),s=n.alternation,o=n.repetition,a=n.option,l=n.repetitionMandatory,c=n.repetitionMandatoryWithSeparator,u=n.repetitionWithSeparator;(0,ro.forEach)(s,function(g){var f=g.idx===0?"":g.idx;t.TRACE_INIT(""+(0,Ec.getProductionDslName)(g)+f,function(){var h=(0,ka.buildLookaheadFuncForOr)(g.idx,i,g.maxLookahead||t.maxLookahead,g.hasPredicates,t.dynamicTokensEnabled,t.lookAheadBuilderForAlternatives),p=(0,Ra.getKeyForAutomaticLookahead)(t.fullRuleNameToShort[i.name],Ra.OR_IDX,g.idx);t.setLaFuncCache(p,h)})}),(0,ro.forEach)(o,function(g){t.computeLookaheadFunc(i,g.idx,Ra.MANY_IDX,ka.PROD_TYPE.REPETITION,g.maxLookahead,(0,Ec.getProductionDslName)(g))}),(0,ro.forEach)(a,function(g){t.computeLookaheadFunc(i,g.idx,Ra.OPTION_IDX,ka.PROD_TYPE.OPTION,g.maxLookahead,(0,Ec.getProductionDslName)(g))}),(0,ro.forEach)(l,function(g){t.computeLookaheadFunc(i,g.idx,Ra.AT_LEAST_ONE_IDX,ka.PROD_TYPE.REPETITION_MANDATORY,g.maxLookahead,(0,Ec.getProductionDslName)(g))}),(0,ro.forEach)(c,function(g){t.computeLookaheadFunc(i,g.idx,Ra.AT_LEAST_ONE_SEP_IDX,ka.PROD_TYPE.REPETITION_MANDATORY_WITH_SEPARATOR,g.maxLookahead,(0,Ec.getProductionDslName)(g))}),(0,ro.forEach)(u,function(g){t.computeLookaheadFunc(i,g.idx,Ra.MANY_SEP_IDX,ka.PROD_TYPE.REPETITION_WITH_SEPARATOR,g.maxLookahead,(0,Ec.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,ka.buildLookaheadFuncForOptionalProd)(t,e,s||a.maxLookahead,a.dynamicTokensEnabled,n,a.lookAheadBuilderForOptional),c=(0,Ra.getKeyForAutomaticLookahead)(a.fullRuleNameToShort[e.name],i,t);a.setLaFuncCache(c,l)})},r.prototype.lookAheadBuilderForOptional=function(e,t,i){return(0,ka.buildSingleAlternativeLookaheadFunction)(e,t,i)},r.prototype.lookAheadBuilderForAlternatives=function(e,t,i,n){return(0,ka.buildAlternativesLookAheadFunc)(e,t,i,n)},r.prototype.getKeyForAutomaticLookahead=function(e,t){var i=this.getLastExplicitRuleShortName();return(0,Ra.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}();my.LooksAhead=Aye});var bq=w(To=>{"use strict";Object.defineProperty(To,"__esModule",{value:!0});To.addNoneTerminalToCst=To.addTerminalToCst=To.setNodeLocationFull=To.setNodeLocationOnlyOffset=void 0;function lye(r,e){isNaN(r.startOffset)===!0?(r.startOffset=e.startOffset,r.endOffset=e.endOffset):r.endOffset{"use strict";Object.defineProperty(KA,"__esModule",{value:!0});KA.defineNameProp=KA.functionName=KA.classNameFromInstance=void 0;var fye=Gt();function hye(r){return Sq(r.constructor)}KA.classNameFromInstance=hye;var Qq="name";function Sq(r){var e=r.name;return e||"anonymous"}KA.functionName=Sq;function pye(r,e){var t=Object.getOwnPropertyDescriptor(r,Qq);return(0,fye.isUndefined)(t)||t.configurable?(Object.defineProperty(r,Qq,{enumerable:!1,configurable:!0,writable:!1,value:e}),!0):!1}KA.defineNameProp=pye});var kq=w(Si=>{"use strict";Object.defineProperty(Si,"__esModule",{value:!0});Si.validateRedundantMethods=Si.validateMissingCstMethods=Si.validateVisitor=Si.CstVisitorDefinitionError=Si.createBaseVisitorConstructorWithDefaults=Si.createBaseSemanticVisitorConstructor=Si.defaultVisit=void 0;var ps=Gt(),Nd=ox();function vq(r,e){for(var t=(0,ps.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}Si.createBaseSemanticVisitorConstructor=dye;function Cye(r,e,t){var i=function(){};(0,Nd.defineNameProp)(i,r+"BaseSemanticsWithDefaults");var n=Object.create(t.prototype);return(0,ps.forEach)(e,function(s){n[s]=vq}),i.prototype=n,i.prototype.constructor=i,i}Si.createBaseVisitorConstructorWithDefaults=Cye;var ax;(function(r){r[r.REDUNDANT_METHOD=0]="REDUNDANT_METHOD",r[r.MISSING_METHOD=1]="MISSING_METHOD"})(ax=Si.CstVisitorDefinitionError||(Si.CstVisitorDefinitionError={}));function xq(r,e){var t=Pq(r,e),i=Dq(r,e);return t.concat(i)}Si.validateVisitor=xq;function Pq(r,e){var t=(0,ps.map)(e,function(i){if(!(0,ps.isFunction)(r[i]))return{msg:"Missing visitor method: <"+i+"> on "+(0,Nd.functionName)(r.constructor)+" CST Visitor.",type:ax.MISSING_METHOD,methodName:i}});return(0,ps.compact)(t)}Si.validateMissingCstMethods=Pq;var mye=["constructor","visit","validateVisitor"];function Dq(r,e){var t=[];for(var i in r)(0,ps.isFunction)(r[i])&&!(0,ps.contains)(mye,i)&&!(0,ps.contains)(e,i)&&t.push({msg:"Redundant visitor method: <"+i+"> on "+(0,Nd.functionName)(r.constructor)+` CST Visitor +There is no Grammar Rule corresponding to this method's name. +`,type:ax.REDUNDANT_METHOD,methodName:i});return t}Si.validateRedundantMethods=Dq});var Fq=w(Ey=>{"use strict";Object.defineProperty(Ey,"__esModule",{value:!0});Ey.TreeBuilder=void 0;var sf=bq(),_r=Gt(),Rq=kq(),Eye=jn(),Iye=function(){function r(){}return r.prototype.initTreeBuilder=function(e){if(this.CST_STACK=[],this.outputCst=e.outputCst,this.nodeLocationTracking=(0,_r.has)(e,"nodeLocationTracking")?e.nodeLocationTracking:Eye.DEFAULT_PARSER_CONFIG.nodeLocationTracking,!this.outputCst)this.cstInvocationStateUpdate=_r.NOOP,this.cstFinallyStateUpdate=_r.NOOP,this.cstPostTerminal=_r.NOOP,this.cstPostNonTerminal=_r.NOOP,this.cstPostRule=_r.NOOP;else if(/full/i.test(this.nodeLocationTracking))this.recoveryEnabled?(this.setNodeLocationFromToken=sf.setNodeLocationFull,this.setNodeLocationFromNode=sf.setNodeLocationFull,this.cstPostRule=_r.NOOP,this.setInitialNodeLocation=this.setInitialNodeLocationFullRecovery):(this.setNodeLocationFromToken=_r.NOOP,this.setNodeLocationFromNode=_r.NOOP,this.cstPostRule=this.cstPostRuleFull,this.setInitialNodeLocation=this.setInitialNodeLocationFullRegular);else if(/onlyOffset/i.test(this.nodeLocationTracking))this.recoveryEnabled?(this.setNodeLocationFromToken=sf.setNodeLocationOnlyOffset,this.setNodeLocationFromNode=sf.setNodeLocationOnlyOffset,this.cstPostRule=_r.NOOP,this.setInitialNodeLocation=this.setInitialNodeLocationOnlyOffsetRecovery):(this.setNodeLocationFromToken=_r.NOOP,this.setNodeLocationFromNode=_r.NOOP,this.cstPostRule=this.cstPostRuleOnlyOffset,this.setInitialNodeLocation=this.setInitialNodeLocationOnlyOffsetRegular);else if(/none/i.test(this.nodeLocationTracking))this.setNodeLocationFromToken=_r.NOOP,this.setNodeLocationFromNode=_r.NOOP,this.cstPostRule=_r.NOOP,this.setInitialNodeLocation=_r.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,sf.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,sf.addNoneTerminalToCst)(i,t,e),this.setNodeLocationFromNode(i.location,e.location)},r.prototype.getBaseCstVisitorConstructor=function(){if((0,_r.isUndefined)(this.baseCstVisitorConstructor)){var e=(0,Rq.createBaseSemanticVisitorConstructor)(this.className,(0,_r.keys)(this.gastProductionsCache));return this.baseCstVisitorConstructor=e,e}return this.baseCstVisitorConstructor},r.prototype.getBaseCstVisitorConstructorWithDefaults=function(){if((0,_r.isUndefined)(this.baseCstVisitorWithDefaultsConstructor)){var e=(0,Rq.createBaseVisitorConstructorWithDefaults)(this.className,(0,_r.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}();Ey.TreeBuilder=Iye});var Tq=w(Iy=>{"use strict";Object.defineProperty(Iy,"__esModule",{value:!0});Iy.LexerAdapter=void 0;var Nq=jn(),yye=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)):Nq.END_OF_FILE},r.prototype.LA=function(e){var t=this.currIdx+e;return t<0||this.tokVectorLength<=t?Nq.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}();Iy.LexerAdapter=yye});var Mq=w(yy=>{"use strict";Object.defineProperty(yy,"__esModule",{value:!0});yy.RecognizerApi=void 0;var Lq=Gt(),wye=nf(),Ax=jn(),Bye=xd(),bye=rx(),Qye=mn(),Sye=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=Ax.DEFAULT_RULE_CONFIG),(0,Lq.contains)(this.definedRulesNames,e)){var n=Bye.defaultGrammarValidatorErrorProvider.buildDuplicateRuleNameError({topLevelRule:e,grammarName:this.className}),s={message:n,type:Ax.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=Ax.DEFAULT_RULE_CONFIG);var n=[];n=n.concat((0,bye.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,wye.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,Qye.serializeGrammar)((0,Lq.values)(this.gastProductionsCache))},r}();yy.RecognizerApi=Sye});var Hq=w(By=>{"use strict";Object.defineProperty(By,"__esModule",{value:!0});By.RecognizerEngine=void 0;var Pr=Gt(),qn=Cy(),wy=nf(),Oq=kd(),of=Dd(),Kq=jn(),vye=sx(),Uq=LA(),Td=_g(),xye=ox(),Pye=function(){function r(){}return r.prototype.initRecognizerEngine=function(e,t){if(this.className=(0,xye.classNameFromInstance)(this),this.shortRuleNameToFull={},this.fullRuleNameToShort={},this.ruleShortNameIdx=256,this.tokenMatcher=Td.tokenStructuredMatcherNoCategories,this.definedRulesNames=[],this.tokensMap={},this.isBackTrackingStack=[],this.RULE_STACK=[],this.RULE_OCCURRENCE_STACK=[],this.gastProductionsCache={},(0,Pr.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,Pr.isArray)(e)){if((0,Pr.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,Pr.isArray)(e))this.tokensMap=(0,Pr.reduce)(e,function(o,a){return o[a.name]=a,o},{});else if((0,Pr.has)(e,"modes")&&(0,Pr.every)((0,Pr.flatten)((0,Pr.values)(e.modes)),Td.isTokenType)){var i=(0,Pr.flatten)((0,Pr.values)(e.modes)),n=(0,Pr.uniq)(i);this.tokensMap=(0,Pr.reduce)(n,function(o,a){return o[a.name]=a,o},{})}else if((0,Pr.isObject)(e))this.tokensMap=(0,Pr.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=Uq.EOF;var s=(0,Pr.every)((0,Pr.values)(e),function(o){return(0,Pr.isEmpty)(o.categoryMatches)});this.tokenMatcher=s?Td.tokenStructuredMatcherNoCategories:Td.tokenStructuredMatcher,(0,Td.augmentTokenTypes)((0,Pr.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,Pr.has)(i,"resyncEnabled")?i.resyncEnabled:Kq.DEFAULT_RULE_CONFIG.resyncEnabled,s=(0,Pr.has)(i,"recoveryValueFunc")?i.recoveryValueFunc:Kq.DEFAULT_RULE_CONFIG.recoveryValueFunc,o=this.ruleShortNameIdx<t},r.prototype.orInternal=function(e,t){var i=this.getKeyForAutomaticLookahead(qn.OR_IDX,t),n=(0,Pr.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 wy.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,wy.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 wy.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===vye.IN_RULE_RECOVERY_EXCEPTION?i:s}}else throw i},r.prototype.saveRecogState=function(){var e=this.errors,t=(0,Pr.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),Uq.EOF)},r.prototype.reset=function(){this.resetLexerState(),this.isBackTrackingStack=[],this.errors=[],this.RULE_STACK=[],this.CST_STACK=[],this.RULE_OCCURRENCE_STACK=[]},r}();By.RecognizerEngine=Pye});var Yq=w(by=>{"use strict";Object.defineProperty(by,"__esModule",{value:!0});by.ErrorHandler=void 0;var lx=nf(),cx=Gt(),Gq=kd(),Dye=jn(),kye=function(){function r(){}return r.prototype.initErrorHandler=function(e){this._errors=[],this.errorMessageProvider=(0,cx.has)(e,"errorMessageProvider")?e.errorMessageProvider:Dye.DEFAULT_PARSER_CONFIG.errorMessageProvider},r.prototype.SAVE_ERROR=function(e){if((0,lx.isRecognitionException)(e))return e.context={ruleStack:this.getHumanReadableRuleStack(),ruleOccurrenceStack:(0,cx.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,cx.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,Gq.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 lx.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,Gq.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 lx.NoViableAltException(c,this.LA(1),l))},r}();by.ErrorHandler=kye});var Jq=w(Qy=>{"use strict";Object.defineProperty(Qy,"__esModule",{value:!0});Qy.ContentAssist=void 0;var jq=Dd(),qq=Gt(),Rye=function(){function r(){}return r.prototype.initContentAssist=function(){},r.prototype.computeContentAssist=function(e,t){var i=this.gastProductionsCache[e];if((0,qq.isUndefined)(i))throw Error("Rule ->"+e+"<- does not exist in this grammar.");return(0,jq.nextPossibleTokensAfter)([i],t,this.tokenMatcher,this.maxLookahead)},r.prototype.getNextPossibleTokenTypes=function(e){var t=(0,qq.first)(e.ruleStack),i=this.getGAstProductions(),n=i[t],s=new jq.NextAfterTokenWalker(n,e).startWalking();return s},r}();Qy.ContentAssist=Rye});var eJ=w(xy=>{"use strict";Object.defineProperty(xy,"__esModule",{value:!0});xy.GastRecorder=void 0;var yn=Gt(),Lo=mn(),Fye=Bd(),Xq=_g(),Zq=LA(),Nye=jn(),Tye=Cy(),vy={description:"This Object indicates the Parser is during Recording Phase"};Object.freeze(vy);var Wq=!0,zq=Math.pow(2,Tye.BITS_FOR_OCCURRENCE_IDX)-1,_q=(0,Zq.createToken)({name:"RECORDING_PHASE_TOKEN",pattern:Fye.Lexer.NA});(0,Xq.augmentTokenTypes)([_q]);var $q=(0,Zq.createTokenInstance)(_q,`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($q);var Lye={name:`This CSTNode indicates the Parser is in Recording Phase + See: https://chevrotain.io/docs/guide/internals.html#grammar-recording for details`,children:{}},Mye=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 Nye.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 Ld.call(this,Lo.Option,e,t)},r.prototype.atLeastOneInternalRecord=function(e,t){Ld.call(this,Lo.RepetitionMandatory,t,e)},r.prototype.atLeastOneSepFirstInternalRecord=function(e,t){Ld.call(this,Lo.RepetitionMandatoryWithSeparator,t,e,Wq)},r.prototype.manyInternalRecord=function(e,t){Ld.call(this,Lo.Repetition,t,e)},r.prototype.manySepFirstInternalRecord=function(e,t){Ld.call(this,Lo.RepetitionWithSeparator,t,e,Wq)},r.prototype.orInternalRecord=function(e,t){return Oye.call(this,e,t)},r.prototype.subruleInternalRecord=function(e,t,i){if(Sy(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?Lye:vy},r.prototype.consumeInternalRecord=function(e,t,i){if(Sy(t),!(0,Xq.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),$q},r}();xy.GastRecorder=Mye;function Ld(r,e,t,i){i===void 0&&(i=!1),Sy(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(),vy}function Oye(r,e){var t=this;Sy(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()}),vy}function Vq(r){return r===0?"":""+r}function Sy(r){if(r<0||r>zq){var e=new Error("Invalid DSL Method idx value: <"+r+`> + `+("Idx value must be a none negative value smaller than "+(zq+1)));throw e.KNOWN_RECORDER_ERROR=!0,e}}});var rJ=w(Py=>{"use strict";Object.defineProperty(Py,"__esModule",{value:!0});Py.PerformanceTracer=void 0;var tJ=Gt(),Kye=jn(),Uye=function(){function r(){}return r.prototype.initPerformanceTracer=function(e){if((0,tJ.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=Kye.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,tJ.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}();Py.PerformanceTracer=Uye});var iJ=w(Dy=>{"use strict";Object.defineProperty(Dy,"__esModule",{value:!0});Dy.applyMixins=void 0;function Hye(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=Hye});var jn=w(dr=>{"use strict";var oJ=dr&&dr.__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(dr,"__esModule",{value:!0});dr.EmbeddedActionsParser=dr.CstParser=dr.Parser=dr.EMPTY_ALT=dr.ParserDefinitionErrorType=dr.DEFAULT_RULE_CONFIG=dr.DEFAULT_PARSER_CONFIG=dr.END_OF_FILE=void 0;var en=Gt(),Gye=Yj(),nJ=LA(),aJ=xd(),sJ=pq(),Yye=sx(),jye=Bq(),qye=Fq(),Jye=Tq(),Wye=Mq(),zye=Hq(),Vye=Yq(),Xye=Jq(),Zye=eJ(),_ye=rJ(),$ye=iJ();dr.END_OF_FILE=(0,nJ.createTokenInstance)(nJ.EOF,"",NaN,NaN,NaN,NaN,NaN,NaN);Object.freeze(dr.END_OF_FILE);dr.DEFAULT_PARSER_CONFIG=Object.freeze({recoveryEnabled:!1,maxLookahead:3,dynamicTokensEnabled:!1,outputCst:!0,errorMessageProvider:aJ.defaultParserErrorProvider,nodeLocationTracking:"none",traceInitPerf:!1,skipValidations:!1});dr.DEFAULT_RULE_CONFIG=Object.freeze({recoveryValueFunc:function(){},resyncEnabled:!0});var ewe;(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"})(ewe=dr.ParserDefinitionErrorType||(dr.ParserDefinitionErrorType={}));function twe(r){return r===void 0&&(r=void 0),function(){return r}}dr.EMPTY_ALT=twe;var ky=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,en.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,en.has)(t,"skipValidations")?t.skipValidations:dr.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,en.toFastProperties)(e)}),e.TRACE_INIT("Grammar Recording",function(){try{e.enableRecording(),(0,en.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,sJ.resolveGrammar)({rules:(0,en.values)(e.gastProductionsCache)}),e.definitionErrors=e.definitionErrors.concat(n)}),e.TRACE_INIT("Grammar Validations",function(){if((0,en.isEmpty)(n)&&e.skipValidations===!1){var s=(0,sJ.validateGrammar)({rules:(0,en.values)(e.gastProductionsCache),maxLookahead:e.maxLookahead,tokenTypes:(0,en.values)(e.tokensMap),errMsgProvider:aJ.defaultGrammarValidatorErrorProvider,grammarName:i});e.definitionErrors=e.definitionErrors.concat(s)}}),(0,en.isEmpty)(e.definitionErrors)&&(e.recoveryEnabled&&e.TRACE_INIT("computeAllProdsFollows",function(){var s=(0,Gye.computeAllProdsFollows)((0,en.values)(e.gastProductionsCache));e.resyncFollows=s}),e.TRACE_INIT("ComputeLookaheadFunctions",function(){e.preComputeLookaheadFunctions((0,en.values)(e.gastProductionsCache))})),!r.DEFER_DEFINITION_ERRORS_HANDLING&&!(0,en.isEmpty)(e.definitionErrors))throw t=(0,en.map)(e.definitionErrors,function(s){return s.message}),new Error(`Parser Definition Errors detected: + `+t.join(` +------------------------------- +`))})},r.DEFER_DEFINITION_ERRORS_HANDLING=!1,r}();dr.Parser=ky;(0,$ye.applyMixins)(ky,[Yye.Recoverable,jye.LooksAhead,qye.TreeBuilder,Jye.LexerAdapter,zye.RecognizerEngine,Wye.RecognizerApi,Vye.ErrorHandler,Xye.ContentAssist,Zye.GastRecorder,_ye.PerformanceTracer]);var rwe=function(r){oJ(e,r);function e(t,i){i===void 0&&(i=dr.DEFAULT_PARSER_CONFIG);var n=this,s=(0,en.cloneObj)(i);return s.outputCst=!0,n=r.call(this,t,s)||this,n}return e}(ky);dr.CstParser=rwe;var iwe=function(r){oJ(e,r);function e(t,i){i===void 0&&(i=dr.DEFAULT_PARSER_CONFIG);var n=this,s=(0,en.cloneObj)(i);return s.outputCst=!1,n=r.call(this,t,s)||this,n}return e}(ky);dr.EmbeddedActionsParser=iwe});var lJ=w(Ry=>{"use strict";Object.defineProperty(Ry,"__esModule",{value:!0});Ry.createSyntaxDiagramsCode=void 0;var AJ=Dv();function nwe(r,e){var t=e===void 0?{}:e,i=t.resourceBase,n=i===void 0?"https://unpkg.com/chevrotain@"+AJ.VERSION+"/diagrams/":i,s=t.css,o=s===void 0?"https://unpkg.com/chevrotain@"+AJ.VERSION+"/diagrams/diagrams.css":s,a=` + + + + + +`,l=` + +`,c=` + - {# N.B. The "ga" command queue is set up by header.js. The meta tag must be + {% if gtm_container_id %} + + + {# N.B. gtag is configured in header.js. The meta tag must be in the DOM before header.js is included. #} {% endif %} diff --git a/h/traversal/annotation.py b/h/traversal/annotation.py index 991a45e7715..48476dad654 100644 --- a/h/traversal/annotation.py +++ b/h/traversal/annotation.py @@ -1,7 +1,7 @@ from dataclasses import dataclass -from h import storage from h.models import Annotation +from h.services.annotation_read import AnnotationReadService @dataclass @@ -19,10 +19,12 @@ class AnnotationRoot: """Root factory for routes whose context is an `AnnotationContext`.""" def __init__(self, request): - self.request = request + self._annotation_read_service: AnnotationReadService = request.find_service( + AnnotationReadService + ) def __getitem__(self, annotation_id): - annotation = storage.fetch_annotation(self.request.db, annotation_id) + annotation = self._annotation_read_service.get_annotation_by_id(annotation_id) if annotation is None: raise KeyError() diff --git a/h/tweens.py b/h/tweens.py index 685e00e7744..e1ce3942f7a 100644 --- a/h/tweens.py +++ b/h/tweens.py @@ -13,7 +13,7 @@ resolver = DottedNameResolver(None) -def conditional_http_tween_factory(handler, registry): +def conditional_http_tween_factory(handler, registry): # pragma: no cover """Set up conditional response handling for some requests.""" def conditional_http_tween(request): @@ -38,7 +38,7 @@ def conditional_http_tween(request): isinstance(response.app_iter, Sequence) and len(response.app_iter) == 1 ) cacheable = request.method in {"GET", "HEAD"} and response.status_code == 200 - if have_buffered_response and cacheable: + if have_buffered_response and cacheable: # pragma: no cover response.conditional_response = True response.md5_etag() @@ -47,7 +47,7 @@ def conditional_http_tween(request): return conditional_http_tween -def invalid_path_tween_factory(handler, registry): +def invalid_path_tween_factory(handler, registry): # pragma: no cover def invalid_path_tween(request): # Due to a bug in WebOb accessing request.path (or request.path_info # etc) will raise UnicodeDecodeError if the requested path doesn't @@ -100,9 +100,9 @@ def security_header_tween(request): # list, thus browsers that don't support # strict-origin-when-cross-origin will fall back to # origin-when-cross-origin. - resp.headers[ - "Referrer-Policy" - ] = "origin-when-cross-origin, strict-origin-when-cross-origin" + resp.headers["Referrer-Policy"] = ( + "origin-when-cross-origin, strict-origin-when-cross-origin" + ) # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection resp.headers["X-XSS-Protection"] = "1; mode=block" return resp diff --git a/h/util/group.py b/h/util/group.py index 71441d95642..2d39ea5b3c0 100644 --- a/h/util/group.py +++ b/h/util/group.py @@ -1,4 +1,5 @@ """Some shared utility functions for manipulating group data.""" + import re GROUPID_PATTERN = r"^group:([a-zA-Z0-9._\-+!~*()']{1,1024})@(.*)$" diff --git a/h/util/group_scope.py b/h/util/group_scope.py index c5bae4c7e7c..54c52fa8c7e 100644 --- a/h/util/group_scope.py +++ b/h/util/group_scope.py @@ -31,7 +31,7 @@ def parse_scope_from_url(url): def _parse_path(url): """Return the path component of a URL string.""" - if url is None: + if url is None: # pragma: no cover# pragma: no cover return None parsed = urlsplit(url) return parsed.path @@ -49,7 +49,7 @@ def parse_origin(url): :rtype: str or None """ - if url is None: + if url is None: # pragma: no cover return None parsed = urlsplit(url) diff --git a/h/util/query.py b/h/util/query.py deleted file mode 100644 index 62f8df1bb4c..00000000000 --- a/h/util/query.py +++ /dev/null @@ -1,61 +0,0 @@ -"""Database query utilities.""" -import sqlalchemy as sa - - -def column_windows(session, column, windowsize=2000, where=None): - """ - Return a series of WHERE clauses against a given column that break it into windows. - - :param session: the SQLAlchemy session object - :param column: the SQLAlchemy column object with which to generate windows - :param windowsize: how many rows to include in each window - :param where: an optional SQLAlchemy expression to filter the base query - - Returns an iterable of SQLAlchemy expressions which can be used in a - .filter(...) clause. - """ - - # This function is adapted from a recipe supplied by the SQLAlchemy - # maintainers: - # - # https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/WindowedRangeQuery - # - # In overview: we generate a list of all the possible values of `column` - # on the server, and then turn that list into a subquery with - # Query#from_self(). We then use the row number of the inner query to - # select every `windowsize`'th row. The resulting values are then - # translated into an iterable of SQLAlchemy expressions suitable for use - # in Query#filter(...). - - def interval_for_range(start_id, end_id): - if end_id: - return sa.and_(column >= start_id, column < end_id) - - return column >= start_id - - query = session.query( - column, sa.func.row_number().over(order_by=column).label("rownum") - ) - - if where is not None: - query = query.filter(where) - - query = query.from_self(column) - - # Select every "windowsize'th" row from the inner query. - if windowsize > 1: - query = query.filter( - sa.text( - "rownum %% %d=1" % windowsize # pylint:disable=consider-using-f-string - ) - ) - - intervals = [id for id, in query] - - while intervals: - start = intervals.pop(0) - if intervals: - end = intervals[0] - else: - end = None - yield interval_for_range(start, end) diff --git a/h/util/redirects.py b/h/util/redirects.py index 886fda0fda8..d9eeb54a8a0 100644 --- a/h/util/redirects.py +++ b/h/util/redirects.py @@ -21,6 +21,7 @@ Lines that contain only whitespace, or which start with a '#' character, will be ignored. """ + from collections import namedtuple diff --git a/h/util/session_tracker.py b/h/util/session_tracker.py deleted file mode 100644 index 21f61a3eeb3..00000000000 --- a/h/util/session_tracker.py +++ /dev/null @@ -1,71 +0,0 @@ -from copy import copy -from enum import Enum - -from sqlalchemy.event import listen -from sqlalchemy.orm.util import identity_key - - -class ObjectState(Enum): - ADDED = "added" - DELETED = "deleted" - CHANGED = "changed" - - -class Tracker: - """Observer which tracks whether a SQLAlchemy `Session` has uncommitted changes.""" - - def __init__(self, session): - self.session = session - - # Changes which have been flushed to the database (and thus not present - # in `session.new`, `session.dirty` or `session.deleted) but have not - # yet been _committed_. - self._flushed_changes = {} - - listen(session, "after_flush", self._after_flush) - listen(session, "after_commit", self._after_commit) - listen(session, "after_rollback", self._after_rollback) - - def uncommitted_changes(self): - """ - Return a list of changes to the `Session` which have not yet been _committed_ to the DB. - - The result is a list of (identity key, ObjectState) tuples. - """ - changed = copy(self._flushed_changes) - changed.update(self._unflushed_changes()) - - return list(changed.items()) - - def _unflushed_changes(self): - """ - Return a map of changes which have not yet been flushed to the DB. - - In the context of the "after_flush" event handler, this returns changes - which have just been flushed. - - If an object goes through multiple states in the same session (eg. - added, then flushed, then changed) then only the last state for a given - object is recorded. - """ - changes = {} - - for obj in self.session.new: - changes[identity_key(instance=obj)] = ObjectState.ADDED - - for obj in self.session.dirty: - changes[identity_key(instance=obj)] = ObjectState.CHANGED - - for obj in self.session.deleted: - changes[identity_key(instance=obj)] = ObjectState.DELETED - - return changes - - def _after_rollback(self, *args): # pylint: disable=unused-argument - self._flushed_changes = {} - - def _after_commit(self, *args): # pylint: disable=unused-argument - self._flushed_changes = {} - - def _after_flush(self, *args): # pylint: disable=unused-argument - self._flushed_changes.update(self._unflushed_changes()) diff --git a/h/util/uri.py b/h/util/uri.py index 44db9605090..114f10fd1b4 100644 --- a/h/util/uri.py +++ b/h/util/uri.py @@ -60,6 +60,7 @@ elsewhere in the Hypothesis application. URI expansion is handled by :py:func:`h.storage.expand_uri`. """ + import re from urllib.parse import ( SplitResult, @@ -191,7 +192,7 @@ def origin(url): def _normalize_scheme(uri): scheme = uri.scheme - if scheme in URL_SCHEMES: + if scheme in URL_SCHEMES: # pragma: no cover scheme = "httpx" return scheme diff --git a/h/util/user.py b/h/util/user.py index 3b4501461ba..27df745608c 100644 --- a/h/util/user.py +++ b/h/util/user.py @@ -1,4 +1,5 @@ """Some shared utility functions for manipulating user data.""" + import re from h.exceptions import InvalidUserId @@ -18,3 +19,7 @@ def split_user(userid): if match: return {"username": match.groups()[0], "domain": match.groups()[1]} raise InvalidUserId(userid) + + +def format_userid(username, authority): + return f"acct:{username}@{authority}" diff --git a/h/util/view.py b/h/util/view.py index 0847c6469bf..0d72dcea7c8 100644 --- a/h/util/view.py +++ b/h/util/view.py @@ -1,13 +1,6 @@ -import sys - from pyramid.view import view_config -# Test seam. Patching `sys.exc_info` directly causes problems with pytest. -def _exc_info(): - return sys.exc_info() - - def handle_exception(request, exception): # pylint: disable=unused-argument """ Handle an uncaught exception for the passed request. diff --git a/h/viewderivers.py b/h/viewderivers.py index 6306d4b0dda..d27f56a374d 100644 --- a/h/viewderivers.py +++ b/h/viewderivers.py @@ -37,5 +37,5 @@ def wrapper_view(context, request): csp_protected_view.options = ("csp_insecure_optout",) -def includeme(config): +def includeme(config): # pragma: nocover config.add_view_deriver(csp_protected_view) diff --git a/h/viewpredicates.py b/h/viewpredicates.py index dec8c2aa862..ad2767ba782 100644 --- a/h/viewpredicates.py +++ b/h/viewpredicates.py @@ -16,5 +16,5 @@ def __call__(self, _context, request): return request.feature(self.feature) -def includeme(config): +def includeme(config): # pragma: nocover config.add_view_predicate("feature", FeaturePredicate) diff --git a/h/views/__init__.py b/h/views/__init__.py index 70a77b44c5f..5c07f22cbb5 100644 --- a/h/views/__init__.py +++ b/h/views/__init__.py @@ -1,2 +1,2 @@ -def includeme(config): +def includeme(config): # pragma: nocover config.scan(__name__) diff --git a/h/views/accounts.py b/h/views/accounts.py index e30315c303c..b368c3c5463 100644 --- a/h/views/accounts.py +++ b/h/views/accounts.py @@ -4,7 +4,7 @@ import colander import deform -import jinja2 +from markupsafe import Markup from pyramid import httpexceptions, security from pyramid.exceptions import BadCSRFToken from pyramid.view import view_config, view_defaults @@ -34,7 +34,7 @@ # A little helper to ensure that session data is returned in every ajax # response payload. -def ajax_payload(request, data): +def ajax_payload(request, data): # pragma: no cover payload = {"flash": session.pop_flash(request), "model": session.model(request)} payload.update(data) return payload @@ -62,20 +62,20 @@ def bad_csrf_token_html(_context, request): @json_view(context=BadCSRFToken) -def bad_csrf_token_json(_context, request): +def bad_csrf_token_json(_context, request): # pragma: no cover request.response.status_code = 403 reason = _("Session is invalid. Please try again.") return {"status": "failure", "reason": reason, "model": session.model(request)} @json_view(context=accounts.JSONError) -def error_json(error, request): +def error_json(error, request): # pragma: no cover request.response.status_code = 400 return {"status": "failure", "reason": str(error)} @json_view(context=deform.ValidationFailure) -def error_validation(error, request): +def error_validation(error, request): # pragma: no cover request.response.status_code = 400 return ajax_payload(request, {"status": "failure", "errors": error.error.asdict()}) @@ -173,7 +173,7 @@ def __init__(self, request): self.form = request.create_form(self.schema, buttons=(_("Reset"),)) @view_config(request_method="GET") - def get(self): + def get(self): # pragma: no cover """Render the forgot password page, including the form.""" self._redirect_if_logged_in() @@ -262,7 +262,7 @@ def post(self): appstruct = self.form.validate(self.request.POST.items()) except deform.ValidationFailure: # If the code is valid, hide the field. - if not self.form["user"].error: + if not self.form["user"].error: # pragma: no cover self.form.set_widgets({"user": deform.widget.HiddenWidget()}) return {"form": self.form.render()} @@ -277,7 +277,7 @@ def post(self): ) def _redirect_if_logged_in(self): - if self.request.authenticated_userid is not None: + if self.request.authenticated_userid is not None: # pragma: no cover raise httpexceptions.HTTPFound(self.request.route_path("index")) def _reset_password(self, user, password): @@ -285,7 +285,7 @@ def _reset_password(self, user, password): svc.update_password(user, password) self.request.session.flash( - jinja2.Markup( + Markup( _( "Your password has been reset. You can now log in with " "your new password." @@ -321,7 +321,7 @@ def get_when_not_logged_in(self): activation = models.Activation.get_by_code(self.request.db, code) if activation is None: self.request.session.flash( - jinja2.Markup( + Markup( _( "We didn't recognize that activation link. " "Have you already activated your account? " @@ -340,7 +340,7 @@ def get_when_not_logged_in(self): user.activate() self.request.session.flash( - jinja2.Markup( + Markup( _( "Your account has been activated! " "You can now log in using the password you provided." @@ -369,14 +369,12 @@ def get_when_logged_in(self): # The user is already logged in to the account (so the account # must already be activated). self.request.session.flash( - jinja2.Markup( - _("Your account has been activated and you're logged in.") - ), + Markup(_("Your account has been activated and you're logged in.")), "success", ) else: self.request.session.flash( - jinja2.Markup( + Markup( _( "You're already logged in to a different account. " 'Log out and open the activation link ' @@ -619,7 +617,7 @@ def post(self): request_method="GET", renderer="h:templates/accounts/claim_account_legacy.html.jinja2", ) -def claim_account_legacy(_request): +def claim_account_legacy(_request): # pragma: no cover """Render a page explaining that claim links are no longer valid.""" return {} @@ -627,7 +625,7 @@ def claim_account_legacy(_request): @view_config( route_name="dismiss_sidebar_tutorial", request_method="POST", renderer="json" ) -def dismiss_sidebar_tutorial(request): +def dismiss_sidebar_tutorial(request): # pragma: no cover if request.authenticated_userid is None: raise accounts.JSONError() diff --git a/h/views/activity.py b/h/views/activity.py index 29c97800716..6ad5e426f6d 100644 --- a/h/views/activity.py +++ b/h/views/activity.py @@ -2,7 +2,7 @@ from urllib.parse import urlparse -from jinja2 import Markup +from markupsafe import Markup from pyramid import httpexceptions from pyramid.view import view_config, view_defaults @@ -34,7 +34,7 @@ def __init__(self, request): self.parsed_query_params = query.extract(self.request) @view_config(request_method="GET") - def search(self): + def search(self): # pragma: no cover # Make a copy of the query params to be consumed by search. query_params = self.parsed_query_params.copy() @@ -172,7 +172,7 @@ def user_annotation_count(aggregation, userid): "share_subtitle": _("Share group"), "share_msg": _("Sharing the link lets people view this group:"), } - if self.group.organization: + if self.group.organization: # pragma: no cover result["group"]["organization"] = OrganizationJSONPresenter( self.group.organization, self.request ).asdict(summary=True) @@ -359,7 +359,7 @@ def search(self): result["opts"] = {"search_username": self.user.username} result["more_info"] = "more_info" in self.request.params - def domain(user): + def domain(user): # pragma: no cover if not user.uri: return None return urlparse(user.uri).netloc @@ -480,7 +480,7 @@ def _redirect_to_user_or_group_search(request, params): slug=request.matchdict["slug"], _query=params, ) - elif request.matched_route.name == "activity.user_search": + elif request.matched_route.name == "activity.user_search": # pragma: no cover location = request.route_url( "activity.user_search", username=request.matchdict["username"], diff --git a/h/views/admin/__init__.py b/h/views/admin/__init__.py index 70a77b44c5f..5c07f22cbb5 100644 --- a/h/views/admin/__init__.py +++ b/h/views/admin/__init__.py @@ -1,2 +1,2 @@ -def includeme(config): +def includeme(config): # pragma: nocover config.scan(__name__) diff --git a/h/views/admin/features.py b/h/views/admin/features.py index 9606d43ff07..9bb62e323c5 100644 --- a/h/views/admin/features.py +++ b/h/views/admin/features.py @@ -27,9 +27,9 @@ def features_index(request): permission=Permission.AdminPage.HIGH_RISK, require_csrf=True, ) -def features_save(request): +def features_save(request): # pragma: no cover for feat in models.Feature.all(request.db): - for attr in ["everyone", "admins", "staff"]: + for attr in ["everyone", "first_party", "admins", "staff"]: val = request.POST.get(f"{feat.name}[{attr}]") if val == "on": setattr(feat, attr, True) @@ -85,7 +85,7 @@ def cohorts_add(request): ) def cohorts_edit(_context, request): id_ = request.matchdict["id"] - cohort = request.db.query(models.FeatureCohort).get(id_) + cohort = request.db.get(models.FeatureCohort, id_) return { "cohort": cohort, "members": cohort.members, @@ -101,7 +101,7 @@ def cohorts_edit(_context, request): ) def cohorts_delete(_context, request): id_ = request.matchdict["id"] - cohort = request.db.query(models.FeatureCohort).get(id_) + cohort = request.db.get(models.FeatureCohort, id_) request.db.delete(cohort) return httpexceptions.HTTPFound(location=request.route_url("admin.cohorts")) @@ -120,7 +120,7 @@ def cohorts_edit_add(request): cohort_id = request.matchdict["id"] member = models.User.get_by_username(request.db, member_name, member_authority) - if member is None: + if member is None: # pragma: no cover request.session.flash( _( # pylint:disable=consider-using-f-string @@ -131,7 +131,7 @@ def cohorts_edit_add(request): "error", ) else: - cohort = request.db.query(models.FeatureCohort).get(cohort_id) + cohort = request.db.get(models.FeatureCohort, cohort_id) cohort.members.append(member) url = request.route_url("admin.cohorts_edit", id=cohort_id) @@ -150,11 +150,11 @@ def cohorts_edit_remove(request): member_userid = request.params["remove"] cohort_id = request.matchdict["id"] - cohort = request.db.query(models.FeatureCohort).get(cohort_id) + cohort = request.db.get(models.FeatureCohort, cohort_id) member = request.db.query(models.User).filter_by(userid=member_userid).first() try: cohort.members.remove(member) - except ValueError: + except ValueError: # pragma: no cover request.session.flash( _( # pylint:disable=consider-using-f-string diff --git a/h/views/admin/groups.py b/h/views/admin/groups.py index bf0fe03d2d1..f8719d94339 100644 --- a/h/views/admin/groups.py +++ b/h/views/admin/groups.py @@ -1,4 +1,4 @@ -from jinja2 import Markup +from markupsafe import Markup from pyramid.httpexceptions import HTTPFound from pyramid.view import view_config, view_defaults @@ -83,7 +83,7 @@ def on_success(appstruct): } type_ = appstruct["group_type"] - if type_ not in ["open", "restricted"]: + if type_ not in ["open", "restricted"]: # pragma: no cover raise ValueError(f"Unsupported group type {type_}") group = create_fns[type_]( @@ -158,7 +158,7 @@ def read(self): @view_config(request_method="POST", route_name="admin.groups_delete") def delete(self): - self.request.find_service(name="delete_group").delete(self.group) + self.request.find_service(name="group_delete").delete(self.group) self.request.session.flash( # pylint:disable=consider-using-f-string @@ -238,7 +238,7 @@ def _template_context(self): } -def _userid(username, authority): +def _userid(username, authority): # pragma: no cover return models.User(username=username, authority=authority).userid diff --git a/h/views/admin/nipsa.py b/h/views/admin/nipsa.py index 421281fc00f..60ea12fa1c4 100644 --- a/h/views/admin/nipsa.py +++ b/h/views/admin/nipsa.py @@ -74,6 +74,6 @@ def nipsa_remove(request): @view_config(context=UserNotFoundError) -def user_not_found(exc, request): +def user_not_found(exc, request): # pragma: no cover request.session.flash(str(exc), "error") return httpexceptions.HTTPFound(location=request.route_path("admin.nipsa")) diff --git a/h/views/admin/organizations.py b/h/views/admin/organizations.py index 8217e1098fa..07c292e6496 100644 --- a/h/views/admin/organizations.py +++ b/h/views/admin/organizations.py @@ -1,4 +1,4 @@ -from jinja2 import Markup +from markupsafe import Markup from pyramid.httpexceptions import HTTPFound from pyramid.view import view_config, view_defaults from sqlalchemy import func diff --git a/h/views/admin/search.py b/h/views/admin/search.py index cf6e644f76a..4889d56c67e 100644 --- a/h/views/admin/search.py +++ b/h/views/admin/search.py @@ -2,7 +2,7 @@ from pyramid.httpexceptions import HTTPFound from pyramid.view import view_config, view_defaults -from h import models +from h import models, tasks from h.security import Permission @@ -11,7 +11,7 @@ class NotFoundError(Exception): @view_config(context=NotFoundError) -def not_found(exc, request): +def not_found(exc, request): # pragma: no cover request.session.flash(str(exc), "error") return HTTPFound(location=request.route_url("admin.search")) @@ -20,6 +20,7 @@ def not_found(exc, request): class SearchAdminViews: def __init__(self, request): self.request = request + self.queue_service = request.find_service(name="queue_service") @view_config(request_method="GET", renderer="h:templates/admin/search.html.jinja2") def get(self): @@ -35,8 +36,11 @@ def reindex_date(self): start_time = isoparse(self.request.params["start"].strip()) end_time = isoparse(self.request.params["end"].strip()) - self.request.find_service(name="search_index").add_annotations_between_times( - start_time, end_time, tag="reindex_date" + tasks.job_queue.add_annotations_between_times.delay( + self.request.params["name"], + start_time, + end_time, + tag="reindex_date", ) return self._notify_reindexing_started( f"Began reindexing from {start_time} to {end_time}" @@ -58,8 +62,11 @@ def reindex_user(self): if not user: raise NotFoundError(f"User {username} not found") - self.request.find_service(name="search_index").add_users_annotations( - user.userid, tag="reindex_user", force=force + tasks.job_queue.add_annotations_from_user.delay( + self.request.params["name"], + user.userid, + tag="reindex_user", + force=force, ) return self._notify_reindexing_started( f"Began reindexing annotations by {user.userid}" @@ -79,8 +86,11 @@ def reindex_group(self): if not group: raise NotFoundError(f"Group {groupid} not found") - self.request.find_service(name="search_index").add_group_annotations( - groupid, tag="reindex_group", force=force + tasks.job_queue.add_annotations_from_group.delay( + self.request.params["name"], + groupid, + tag="reindex_group", + force=force, ) return self._notify_reindexing_started( f"Began reindexing annotations in group {groupid} ({group.name})" diff --git a/h/views/admin/users.py b/h/views/admin/users.py index e803b24cc12..1851099fe6c 100644 --- a/h/views/admin/users.py +++ b/h/views/admin/users.py @@ -1,4 +1,4 @@ -import jinja2 +from markupsafe import Markup from pyramid import httpexceptions from pyramid.view import view_config @@ -6,7 +6,7 @@ from h.accounts.events import ActivationEvent from h.i18n import TranslationString as _ from h.security import Permission -from h.services.rename_user import UserRenameError +from h.services.user_rename import UserRenameError class UserNotFoundError(Exception): @@ -42,6 +42,23 @@ def users_index(request): if user is None: user = models.User.get_by_email(request.db, username, authority) + if (user is not None) and user.deleted: + # Don't show users that're marked as deleted on admin pages. + # + # Users that're marked as deleted can't login or authenticate requests + # in any way. They're in the process of being purged by a background + # task and will soon be really deleted from the DB. + # + # Showing these users on admin pages is confusing because admins may + # have already deleted a user (so the user has been marked as deleted + # and is now going to be purged) and then think that the user has not + # been deleted successfully because they still show up on the admin + # pages. + # + # Also we don't want admins to be able to do things like rename users + # who're marked as deleted and in the process of being purged. + user = None + if user is not None: svc = request.find_service(name="annotation_stats") user_meta["annotations_count"] = svc.total_user_annotation_count(user.userid) @@ -70,7 +87,7 @@ def users_activate(request): request.session.flash( # pylint:disable=consider-using-f-string - jinja2.Markup(_("User {name} has been activated!".format(name=user.username))), + Markup(_("User {name} has been activated!".format(name=user.username))), "success", ) @@ -90,13 +107,13 @@ def users_activate(request): permission=Permission.AdminPage.LOW_RISK, require_csrf=True, ) -def users_rename(request): +def users_rename(request): # pragma: no cover user = _form_request_user(request) old_username = user.username new_username = request.params.get("new_username").strip() - svc = request.find_service(name="rename_user") + svc = request.find_service(name="user_rename") try: svc.rename(user, new_username) @@ -132,9 +149,9 @@ def users_rename(request): ) def users_delete(request): user = _form_request_user(request) - svc = request.find_service(name="delete_user") + svc = request.find_service(name="user_delete") - svc.delete(user) + svc.delete_user(user, requested_by=request.user, tag=request.matched_route.name) request.session.flash( f"Successfully deleted user {user.username} with authority {user.authority}" "success", @@ -145,7 +162,7 @@ def users_delete(request): @view_config(context=UserNotFoundError) def user_not_found(exc, request): - request.session.flash(jinja2.Markup(_(exc.message)), "error") + request.session.flash(Markup(_(str(exc))), "error") return httpexceptions.HTTPFound(location=request.route_path("admin.users")) diff --git a/h/views/api/__init__.py b/h/views/api/__init__.py index 07b79ec96b7..9c3aa6bf7ef 100644 --- a/h/views/api/__init__.py +++ b/h/views/api/__init__.py @@ -12,5 +12,5 @@ __all__ = ("API_VERSIONS", "API_VERSION_DEFAULT") -def includeme(config): +def includeme(config): # pragma: nocover config.scan(__name__) diff --git a/h/views/api/analytics.py b/h/views/api/analytics.py new file mode 100644 index 00000000000..c49007314cc --- /dev/null +++ b/h/views/api/analytics.py @@ -0,0 +1,23 @@ +from pyramid.httpexceptions import HTTPNoContent +from pyramid.request import Request + +from h.schemas.analytics import CreateEventSchema +from h.services.analytics import AnalyticsService +from h.views.api.config import api_config + + +@api_config( + versions=["v1", "v2"], + route_name="api.analytics.events", + request_method="POST", + link_name="analytics.events.create", + description="Create a new analytics event", +) +def create_event(request: Request): + """Create a new analytics event.""" + schema = CreateEventSchema() + analytics_service: AnalyticsService = request.find_service(name="analytics") + + analytics_service.create(schema.validate(request.json_body)) + + return HTTPNoContent() diff --git a/h/views/api/annotations.py b/h/views/api/annotations.py index 40bf730f359..d15dac63994 100644 --- a/h/views/api/annotations.py +++ b/h/views/api/annotations.py @@ -14,10 +14,10 @@ authorization system. You can find the mapping between annotation "permissions" objects and Pyramid ACLs in :mod:`h.traversal`. """ + from pyramid import i18n from h import search as search_lib -from h import storage from h.events import AnnotationEvent from h.presenters import AnnotationJSONLDPresenter from h.schemas.annotation import ( @@ -27,6 +27,7 @@ ) from h.schemas.util import validate_query_params from h.security import Permission +from h.services import AnnotationWriteService from h.views.api.config import api_config from h.views.api.exceptions import PayloadError @@ -78,7 +79,9 @@ def create(request): schema = CreateAnnotationSchema(request) appstruct = schema.validate(_json_payload(request)) - annotation = storage.create_annotation(request, appstruct) + annotation = request.find_service(AnnotationWriteService).create_annotation( + data=appstruct + ) _publish_annotation_event(request, annotation, "create") @@ -135,7 +138,9 @@ def update(context, request): ) appstruct = schema.validate(_json_payload(request)) - annotation = storage.update_annotation(request, context.annotation.id, appstruct) + annotation = request.find_service(AnnotationWriteService).update_annotation( + context.annotation, data=appstruct + ) _publish_annotation_event(request, annotation, "update") diff --git a/h/views/api/auth.py b/h/views/api/auth.py index d9e9ce5b0e2..a2df1f81eb5 100644 --- a/h/views/api/auth.py +++ b/h/views/api/auth.py @@ -1,5 +1,9 @@ import json import logging +import random +import re +import string +from datetime import datetime from functools import wraps from urllib.parse import parse_qs, urlparse @@ -8,7 +12,9 @@ from pyramid.view import view_config, view_defaults from h import models +from h.models import User from h.services.oauth import DEFAULT_SCOPES + from h.util.datetime import utc_iso8601 from h.views.api.config import api_config from h.views.api.exceptions import OAuthAuthorizeError, OAuthTokenError @@ -33,18 +39,20 @@ def inner(*args, **kwargs): return inner - @view_defaults(route_name="oauth_authorize") class OAuthAuthorizeController: def __init__(self, context, request): self.context = context self.request = request - + self.session = request.db self.user_svc = self.request.find_service(name="user") self.oauth = self.request.find_service(name="oauth_provider") @view_config( - request_method="GET", renderer="h:templates/oauth/authorize.html.jinja2" + request_method="GET", + # for tosdr + # renderer=None + renderer="h:templates/oauth/authorize.html.jinja2" ) def get(self): """ @@ -87,7 +95,7 @@ def get_web_message(self): @view_config( request_method="POST", - is_authenticated=True, + # is_authenticated=True, renderer="json", ) def post(self): @@ -102,8 +110,8 @@ def post(self): @view_config( request_method="POST", request_param="response_mode=web_message", - is_authenticated=True, - renderer="h:templates/oauth/authorize_web_message.html.jinja2", + # is_authenticated=True, + renderer="json", ) def post_web_message(self): """ @@ -115,8 +123,7 @@ def post_web_message(self): .. _draft-sakimura-oauth: https://tools.ietf.org/html/draft-sakimura-oauth-wmrm-00 """ - found = self._authorized_response() - return self._render_web_message_response(found.location) + return self._authorized_response() def _authorize(self): try: @@ -126,15 +133,9 @@ def _authorize(self): err.description or f"Error: {self.context.error}" ) from err - if self.request.authenticated_userid is None: - raise HTTPFound( - self.request.route_url( - "login", _query={"next": self.request.url, "for_oauth": True} - ) - ) client_id = credentials.get("client_id") - client = self.request.db.query(models.AuthClient).get(client_id) + client = self.request.db.get(models.AuthClient, client_id) # If the client is "trusted" -- which means its code is # owned/controlled by us -- then we don't ask the user to explicitly @@ -142,7 +143,7 @@ def _authorize(self): # logged-in user. if client.trusted: return self._authorized_response() - + state = credentials.get("state") user = self.user_svc.fetch(self.request.authenticated_userid) response_mode = credentials.get("request").response_mode @@ -156,21 +157,32 @@ def _authorize(self): "state": state, } - @handles_oauth_errors + # @handles_oauth_errors def _authorized_response(self): # We don't support scopes at the moment, but oauthlib does need a scope, # so we're explicitly overwriting whatever the client provides. scopes = DEFAULT_SCOPES - user = self.user_svc.fetch(self.request.authenticated_userid) + # TOSDR : find tosdr user based on h_key cookie + h_key = self.request.cookies.get('h_key') + user_tosdr = self.user_svc.fetch_from_tosdr(h_key) + username = user_tosdr.username + user = self.user_svc.fetch(username, authority=self.request.default_authority) + # TOSDR : create user in h if it does not exist + if h_key and not user: + clean_username = re.sub('[^a-zA-Z0-9\_\.]', '', username) + password = ''.join(random.choice(string.printable) for i in range(12)) + user = User(username=clean_username, email=user_tosdr.email, privacy_accepted=datetime.now(), comms_opt_in=False, password=password, authority=self.request.default_authority) + self.session.add(user) + credentials = {"user": user} - headers, _, _ = self.oauth.create_authorization_response( self.request.url, scopes=scopes, credentials=credentials ) try: - return HTTPFound(location=headers["Location"]) - except KeyError as err: + found = HTTPFound(location=headers["Location"]) + return self._render_web_message_response(found.location) + except KeyError as err: # pragma: no cover client_id = self.request.params.get("client_id") raise RuntimeError( f'created authorisation code for client "{client_id}" but got no redirect location' @@ -207,7 +219,8 @@ def post(self): ) if status == 200: - return json.loads(body) + response = json.loads(body) + return response raise exception_response(status, detail=body) @@ -270,7 +283,7 @@ def api_token_error(context, request): def _present_debug_token(token): data = { - "userid": token.userid, + "userid": token.user.userid, "expires_at": utc_iso8601(token.expires), "issued_at": utc_iso8601(token.created), "expired": token.expired, diff --git a/h/views/api/bulk/annotation.py b/h/views/api/bulk/annotation.py index a5898b4d83b..a621aff650e 100644 --- a/h/views/api/bulk/annotation.py +++ b/h/views/api/bulk/annotation.py @@ -6,7 +6,7 @@ from h.schemas.base import JSONSchema from h.security import Permission from h.services import BulkAnnotationService -from h.services.bulk_annotation import BadDateFilter, BadFieldSpec +from h.services.bulk_api import BadDateFilter, BulkAnnotation from h.views.api.bulk._ndjson import get_ndjson_response from h.views.api.config import api_config @@ -33,41 +33,31 @@ def bulk_annotation(request): # Once this has been applied, we know everything else is safe to use # without checking any further data = BulkAnnotationSchema().validate(request.json) - query_filter, fields = data["filter"], data["fields"] + query_filter = data["filter"] try: - annotation_rows = request.find_service(BulkAnnotationService).annotation_search( + annotations = request.find_service(BulkAnnotationService).annotation_search( # Use the authority from the authenticated client to ensure the user # is limited to items they have permission to request authority=request.identity.auth_client.authority, - fields=fields, - **query_filter, + username=query_filter["username"], + created=query_filter["created"], + limit=query_filter["limit"], ) - except BadFieldSpec as err: - # Emulate the format of the normal ValidationError's from a schema - raise ValidationError(f"fields: {err}") from err - except BadDateFilter as err: - # We happen to know this is the updated field, because there's no other + # We happen to know this is the created field, because there's no other # but, it could easily be something else in the future raise ValidationError(str(err)) from err - present_row = _get_present_row(fields) - return get_ndjson_response((present_row(row) for row in annotation_rows)) - - -def _get_present_row(fields): - # The schema enforces this, but we currently rely on it being hard coded - # so some belt and braces is in order. For example, the exact order matters - assert fields == ["author.username", "group.authority_provided_id"] - - def present_row(row): - username, authority_provided_id = row + return get_ndjson_response( + (_present_annotation(annotation) for annotation in annotations) + ) - return { - "author": {"username": username}, - "group": {"authority_provided_id": authority_provided_id}, - } - return present_row +def _present_annotation(annotation: BulkAnnotation) -> dict: + return { + "author": {"username": annotation.username}, + "group": {"authority_provided_id": annotation.authority_provided_id}, + "metadata": annotation.metadata, + } diff --git a/h/views/api/bulk/annotation_schema.json b/h/views/api/bulk/annotation_schema.json index 5b0a750e77c..4679ffea3f4 100644 --- a/h/views/api/bulk/annotation_schema.json +++ b/h/views/api/bulk/annotation_schema.json @@ -8,64 +8,35 @@ { "filter": { "limit": 2000, - "audience": { - "username": ["3a022b6c146dfd9df4ea8662178eac"] - }, - "updated": { + "username": "3a022b6c146dfd9df4ea8662178eac", + "created": { "gt": "2018-11-13T20:20:39+00:00", "lte": "2018-11-13T20:20:39+00:00" } - }, - "fields": ["author.username", "group.authority_provided_id"] + } } ], "properties": { - "fields": {"$ref": "#/$defs/fields"}, "filter": {"$ref": "#/$defs/filter"} }, - "required": ["filter", "fields"], - "additionalProperties": false, + "required": ["filter"], + "additionalProperties": true, "$defs": { - "fields": { - "title": "Fields", - "description": "A list of fields to include in the output", - - "type": "array", - "items": {"type": "string"}, - "enum": [["author.username", "group.authority_provided_id"]] - }, - "filter": { "title": "Filter query", - "description": "The fields to search for the annotations by", + "description": "The filters to search for the annotations by", "type": "object", "properties": { "limit": {"type": "integer", "minimum": 0, "maximum": 1000000}, - "audience": {"$ref": "#/$defs/userFilter"}, - "updated": {"$ref": "#/$defs/dateFilter"} + "username": {"type": "string", "pattern": "^[a-z0-9]{30}$"}, + "created": {"$ref": "#/$defs/dateFilter"} }, - "required": ["limit", "audience"], + "required": ["limit", "username", "created"], "additionalProperties": false }, - - "userFilter": { - "description": "A filter to specify the users you want", - - "type": "object", - "properties": { - "username": { - "type": "array", - "minItems": 1, - "items": {"type": "string", "pattern": "^[a-z0-9]{30}$"} - } - }, - "required": ["username"], - "additionalProperties": false - }, - "dateFilter": { "description": "A filter to apply on a date", diff --git a/h/views/api/bulk/group.py b/h/views/api/bulk/group.py new file mode 100644 index 00000000000..2a6a342fde1 --- /dev/null +++ b/h/views/api/bulk/group.py @@ -0,0 +1,44 @@ +import json + +from importlib_resources import files + +from h.schemas import ValidationError +from h.schemas.base import JSONSchema +from h.security import Permission +from h.services.bulk_api import BadDateFilter, BulkGroupService +from h.views.api.bulk._ndjson import get_ndjson_response +from h.views.api.config import api_config + + +class BulkGroupSchema(JSONSchema): + _SCHEMA_FILE = files("h.views.api.bulk") / "group_schema.json" + + schema_version = 7 + schema = json.loads(_SCHEMA_FILE.read_text(encoding="utf-8")) + + +@api_config( + versions=["v1", "v2"], + route_name="api.bulk.group", + request_method="POST", + link_name="bulk.group", + description="Retrieve a large number of groups in one go", + subtype="x-ndjson", + permission=Permission.API.BULK_ACTION, +) +def bulk_group(request): + data = BulkGroupSchema().validate(request.json) + query_filter = data["filter"] + + try: + groups = request.find_service(BulkGroupService).group_search( + groups=query_filter["groups"], + annotations_created=query_filter["annotations_created"], + ) + + except BadDateFilter as err: + raise ValidationError(str(err)) from err + + return get_ndjson_response( + [{"authority_provided_id": group.authority_provided_id} for group in groups] + ) diff --git a/h/views/api/bulk/group_schema.json b/h/views/api/bulk/group_schema.json new file mode 100644 index 00000000000..f84bea10467 --- /dev/null +++ b/h/views/api/bulk/group_schema.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema", + "type": "object", + "title": "Bulk Group Request", + "examples": [ + { + "filter": { + "groups": ["3a022b6c146dfd9df4ea8662178eac"], + "annotations_created": { + "gt": "2018-11-13T20:20:39+00:00", + "lte": "2018-11-13T20:20:39+00:00" + } + } + } + ], + "properties": { + "filter": {"$ref": "#/$defs/filter"} + }, + "required": ["filter"], + "additionalProperties": true, + "$defs": { + "filter": { + "title": "Filter query", + "description": "The filters to search for the annotations by", + + "type": "object", + "properties": { + "groups": {"$ref": "#/$defs/groupsFilter"}, + "annotations_created": {"$ref": "#/$defs/dateFilter"} + }, + "required": ["groups", "annotations_created"], + "additionalProperties": false + }, + + "groupsFilter": { + "type": "array", + "minItems": 1, + "items": {"type": "string"} + }, + "dateFilter": { + "description": "A filter to apply on a date", + + "type": "object", + "properties": { + "gt": {"type": "string", "format": "date-time"}, + "lte": {"type": "string", "format": "date-time"} + }, + "required": ["gt", "lte"], + "additionalProperties": false + } + } +} diff --git a/h/views/api/bulk/stats.py b/h/views/api/bulk/stats.py new file mode 100644 index 00000000000..95f7b53f686 --- /dev/null +++ b/h/views/api/bulk/stats.py @@ -0,0 +1,87 @@ +import json + +from importlib_resources import files +from pyramid.response import Response + +from h.schemas.base import JSONSchema +from h.security import Permission +from h.services.bulk_api import BulkLMSStatsService +from h.views.api.config import api_config + + +class AssignmentStatsSchema(JSONSchema): + _SCHEMA_FILE = files("h.views.api.bulk") / "stats_assignment.json" + schema_version = 7 + schema = json.loads(_SCHEMA_FILE.read_text(encoding="utf-8")) + + +class CourseStatsSchema(JSONSchema): + _SCHEMA_FILE = files("h.views.api.bulk") / "stats_course.json" + schema_version = 7 + schema = json.loads(_SCHEMA_FILE.read_text(encoding="utf-8")) + + +@api_config( + versions=["v1", "v2"], + route_name="api.bulk.stats.users", + request_method="POST", + description="Retrieve stats grouped by user", + link_name="bulk.stats.assignment", + subtype="x-ndjson", + permission=Permission.API.BULK_ACTION, +) +def get_counts_by_user(request): + data = AssignmentStatsSchema().validate(request.json) + query_filter = data["filter"] + + stats = request.find_service(BulkLMSStatsService).get_counts_by_user( + groups=query_filter["groups"], + assignment_id=query_filter["assignment_id"], + ) + + return Response( + json=[ + { + "display_name": row.display_name, + "userid": row.userid, + "annotations": row.annotations, + "replies": row.replies, + "last_activity": row.last_activity.isoformat(), + } + for row in stats + ], + status=200, + content_type="application/x-ndjson", + ) + + +@api_config( + versions=["v1", "v2"], + route_name="api.bulk.stats.assignments", + request_method="POST", + description="Retrieve stats grouped by assignment", + link_name="bulk.stats.course", + subtype="x-ndjson", + permission=Permission.API.BULK_ACTION, +) +def get_counts_by_assignment(request): + data = CourseStatsSchema().validate(request.json) + query_filter = data["filter"] + + stats = request.find_service(BulkLMSStatsService).get_counts_by_assignment( + groups=query_filter["groups"], + ) + + return Response( + json=[ + { + "assignment_id": row.assignment_id, + "annotations": row.annotations, + "replies": row.replies, + "last_activity": row.last_activity.isoformat(), + } + for row in stats + ], + status=200, + content_type="application/x-ndjson", + ) diff --git a/h/views/api/bulk/stats_assignment.json b/h/views/api/bulk/stats_assignment.json new file mode 100644 index 00000000000..70df699eaa7 --- /dev/null +++ b/h/views/api/bulk/stats_assignment.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema", + "type": "object", + "title": "Bulk assignment stats", + "properties": { + "filter": { + "$ref": "#/$defs/filter" + } + }, + "required": [ + "filter" + ], + "additionalProperties": true, + "$defs": { + "filter": { + "title": "Filter query", + "description": "The filters to search for the annotations by", + "type": "object", + "properties": { + "groups": { + "$ref": "#/$defs/groupsFilter" + }, + "assignment_id": { + "type": "string" + } + }, + "required": [ + "groups", + "assignment_id" + ], + "additionalProperties": false + }, + "groupsFilter": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + } + } +} diff --git a/h/views/api/bulk/stats_course.json b/h/views/api/bulk/stats_course.json new file mode 100644 index 00000000000..5d782f5eb16 --- /dev/null +++ b/h/views/api/bulk/stats_course.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema", + "type": "object", + "title": "Bulk course stats", + "properties": { + "filter": { + "$ref": "#/$defs/filter" + } + }, + "required": [ + "filter" + ], + "additionalProperties": true, + "$defs": { + "filter": { + "title": "Filter query", + "type": "object", + "properties": { + "groups": { + "$ref": "#/$defs/groupsFilter" + } + }, + "required": [ + "groups" + ], + "additionalProperties": false + }, + "groupsFilter": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + } + } +} diff --git a/h/views/api/config.py b/h/views/api/config.py index ac81a50ea98..eb3d50e5434 100644 --- a/h/views/api/config.py +++ b/h/views/api/config.py @@ -117,7 +117,7 @@ def callback(context, _name, view): **settings ) - def wrapper(wrapped): + def wrapper(wrapped): # pragma: no cover info = venusian.attach(wrapped, callback, category="pyramid") # Support use as a class method decorator. diff --git a/h/views/api/errors.py b/h/views/api/errors.py index 6d6a34196fb..26d445b9303 100644 --- a/h/views/api/errors.py +++ b/h/views/api/errors.py @@ -43,7 +43,7 @@ def api_notfound(context, request): @view_config( context=OAuthAuthorizeError, renderer="h:templates/oauth/error.html.jinja2" ) -def oauth_error(context, request): +def oauth_error(context, request): # pragma: no cover """Handle an expected/deliberately thrown OAuth exception.""" request.response.status_code = context.status_code return {"detail": context.detail} @@ -57,15 +57,14 @@ def api_error(context, request): @json_view(context=JSONAPIError, path_info="/api/bulk", decorator=cors_policy) -def bulk_api_error(context, request): +def bulk_api_error(context, request): # pragma: no cover """Handle JSONAPIErrors produced by the Bulk API.""" - request.response.status_code = context.http_status return context.as_dict() @json_view(context=Exception, path_info="/api/", decorator=cors_policy) -def json_error(context, request): +def json_error(context, request): # pragma: no cover """Handle an unexpected exception in an API view.""" handle_exception(request, exception=context) message = _( diff --git a/h/views/api/links.py b/h/views/api/links.py index 1448495ea1d..e37c68cf8b4 100644 --- a/h/views/api/links.py +++ b/h/views/api/links.py @@ -1,3 +1,4 @@ +import os from h.views.api.config import api_config from h.views.api.helpers.angular import AngularRouteTemplater @@ -18,6 +19,9 @@ def links(_context, request): tag_search_url = request.route_url("activity.search", _query={"q": 'tag:"__tag__"'}) tag_search_url = tag_search_url.replace("__tag__", ":tag") + settings = request.registry.settings + tosdr_url = settings.get("h.tosdr") + oauth_authorize_url = request.route_url("oauth_authorize") oauth_revoke_url = request.route_url("oauth_revoke") @@ -34,4 +38,5 @@ def links(_context, request): "signup": request.route_url("signup"), "user": templater.route_template("stream.user_query"), "websocket": websocket_url, + "tosdr": tosdr_url } diff --git a/h/views/api/moderation.py b/h/views/api/moderation.py index 2828b95b4f6..b830e5ac707 100644 --- a/h/views/api/moderation.py +++ b/h/views/api/moderation.py @@ -1,8 +1,8 @@ from pyramid.httpexceptions import HTTPNoContent from h import events -from h.models import AnnotationModeration from h.security import Permission +from h.services import AnnotationWriteService from h.views.api.config import api_config @@ -15,10 +15,7 @@ permission=Permission.Annotation.MODERATE, ) def create(context, request): - annotation = context.annotation - - if not annotation.is_hidden: - annotation.moderation = AnnotationModeration() + request.find_service(AnnotationWriteService).hide(context.annotation) event = events.AnnotationEvent(request, context.annotation.id, "update") request.notify_after_commit(event) @@ -35,7 +32,7 @@ def create(context, request): permission=Permission.Annotation.MODERATE, ) def delete(context, request): - context.annotation.moderation = None + request.find_service(AnnotationWriteService).unhide(context.annotation) event = events.AnnotationEvent(request, context.annotation.id, "update") request.notify_after_commit(event) diff --git a/h/views/badge.py b/h/views/badge.py index 8c538116734..43bd4736ec3 100644 --- a/h/views/badge.py +++ b/h/views/badge.py @@ -1,6 +1,7 @@ import re from pyramid import httpexceptions +from sqlalchemy import text from webob.multidict import MultiDict from h import search @@ -16,7 +17,7 @@ def _has_uri_ever_been_annotated(db, uri): # instead of `annotation.target_uri_normalized` because there is an existing # index on `uri_normalized`. query = "SELECT EXISTS(SELECT 1 FROM document_uri WHERE uri_normalized = :uri)" - result = db.execute(query, {"uri": normalize(uri)}).first() + result = db.execute(text(query), {"uri": normalize(uri)}).first() return result[0] is True diff --git a/h/views/client.py b/h/views/client.py index afce13e6074..7910e0acd06 100644 --- a/h/views/client.py +++ b/h/views/client.py @@ -63,9 +63,10 @@ def sidebar_app(request, extra=None): # The list of origins that the client will respond to cross-origin RPC # requests from. "rpcAllowedOrigins": settings.get("h.client_rpc_allowed_origins"), + "tosdr": settings.get("h.tosdr") } - if sentry_public_dsn: + if sentry_public_dsn: # pragma: no cover # `h.sentry_environment` primarily refers to h's Sentry environment, # but it also matches the client environment for the embed (dev, qa, prod). sentry_environment = settings.get("h.sentry_environment") @@ -78,7 +79,7 @@ def sidebar_app(request, extra=None): "client_url": _client_url(request), } - if extra is not None: + if extra is not None: # pragma: no cover ctx.update(extra) # Add CSP headers to prevent scripts or styles from unexpected locations @@ -94,9 +95,9 @@ def sidebar_app(request, extra=None): # math rendering using KaTeX relies on them. style_src = f"{client_origin} 'unsafe-inline'" - request.response.headers[ - "Content-Security-Policy" - ] = f"script-src {client_origin}; style-src {style_src}" + request.response.headers["Content-Security-Policy"] = ( + f"script-src {client_origin}; style-src {style_src}" + ) return ctx diff --git a/h/views/feeds.py b/h/views/feeds.py index d5a54a38a6c..6ecda24cb61 100644 --- a/h/views/feeds.py +++ b/h/views/feeds.py @@ -2,19 +2,13 @@ from pyramid.view import view_config from webob.multidict import MultiDict -from h import search from h.feeds import render_atom, render_rss -from h.storage import fetch_ordered_annotations +from h.search import Search +from h.services.annotation_read import AnnotationReadService _ = i18n.TranslationStringFactory(__package__) -def _annotations(request): - """Return the annotations from the search API.""" - result = search.Search(request).run(MultiDict(request.params)) - return fetch_ordered_annotations(request.db, result.annotation_ids) - - @view_config(route_name="stream_atom") def stream_atom(request): """Get an Atom feed of the /stream page.""" @@ -40,3 +34,12 @@ def stream_rss(request): description=request.registry.settings.get("h.feed.description") or _("The Web. Annotated"), ) + + +def _annotations(request): + """Return the annotations from the search API.""" + result = Search(request).run(MultiDict(request.params)) + + return request.find_service(AnnotationReadService).get_annotations_by_id( + ids=result.annotation_ids + ) diff --git a/h/views/home.py b/h/views/home.py index fd4a87ea629..4eb634a23eb 100644 --- a/h/views/home.py +++ b/h/views/home.py @@ -5,7 +5,7 @@ @view_config(route_name="via_redirect", request_method="GET") -def via_redirect(_context, request): +def via_redirect(_context, request): # pragma: no cover url = request.params.get("url") if url is None: diff --git a/h/views/main.py b/h/views/main.py index 98ed5b5668c..5743971e236 100644 --- a/h/views/main.py +++ b/h/views/main.py @@ -55,7 +55,7 @@ def annotation_page(context, request): @view_config(route_name="robots", http_cache=(86400, {"public": True})) -def robots(_context, request): +def robots(_context, request): # pragma: no cover return response.FileResponse( "h/static/robots.txt", request=request, content_type="text/plain" ) @@ -89,7 +89,7 @@ def stream(_context, request): @view_config(route_name="stream.tag_query") -def stream_tag_redirect(request): +def stream_tag_redirect(request): # pragma: no cover query = {"q": f"tag:{request.matchdict['tag']}"} location = request.route_url("stream", _query=query) raise httpexceptions.HTTPFound(location=location) diff --git a/h/views/status.py b/h/views/status.py index 657565c4971..aa612b5290c 100644 --- a/h/views/status.py +++ b/h/views/status.py @@ -1,6 +1,8 @@ import logging from pyramid.httpexceptions import HTTPInternalServerError +from sentry_sdk import capture_message +from sqlalchemy import text from h.util.view import json_view @@ -10,8 +12,19 @@ @json_view(route_name="status", http_cache=0) def status(request): try: - request.db.execute("SELECT 1") + request.db.execute(text("SELECT 1")) except Exception as err: log.exception(err) raise HTTPInternalServerError("Database connection failed") from err + + if "replica" in request.params: + try: + request.db_replica.execute(text("SELECT 1")) + except Exception as err: + log.exception(err) + raise HTTPInternalServerError("Replica database connection failed") from err + + if "sentry" in request.params: + capture_message("Test message from h's status view") + return {"status": "okay"} diff --git a/package.json b/package.json index 08b3fb61f39..c35f7baf5e6 100644 --- a/package.json +++ b/package.json @@ -2,59 +2,58 @@ "name": "h", "private": true, "version": "0.0.0", + "type": "module", "description": "The Internet, peer reviewed.", "scripts": { "build": "gulp build", - "checkformatting": "prettier --check *.mjs h/static/scripts", - "format": "prettier --list-different --write *.mjs h/static/scripts", + "checkformatting": "prettier --check *.js h/static/scripts", + "format": "prettier --list-different --write *.js h/static/scripts", "lint": "eslint h/static/scripts", "test": "gulp test" }, "dependencies": { - "@babel/core": "^7.21.0", - "@babel/preset-env": "^7.20.2", - "@hypothesis/frontend-build": "^1.2.0", - "@rollup/plugin-babel": "^6.0.3", - "@rollup/plugin-commonjs": "^24.0.1", - "@rollup/plugin-node-resolve": "^15.0.1", - "autoprefixer": "^10.4.13", + "@babel/core": "^7.24.5", + "@babel/preset-env": "^7.24.5", + "@hypothesis/frontend-build": "^3.0.0", + "@rollup/plugin-babel": "^6.0.4", + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-terser": "^0.4.4", + "autoprefixer": "^10.4.19", "bootstrap": "^4.6.2", "escape-html": "^1.0.3", - "gulp": "^4.0.0", - "gulp-changed": "^4.0.3", - "gulp-cli": "^2.3.0", + "gulp": "^5.0.0", + "gulp-changed": "^5.0.2", + "gulp-cli": "^3.0.0", "gulp-if": "^3.0.0", - "gulp-svgmin": "^4.0.1", - "jquery": "^3.6.3", + "gulp-svgmin": "^4.1.0", + "jquery": "^3.7.1", "normalize.css": "^8.0.0", "popper.js": "^1.16.1", - "postcss": "^8.4.21", + "postcss": "^8.4.38", "raven-js": "^3.7.0", - "rollup": "^2.79.1", - "rollup-plugin-terser": "^7.0.2", - "sass": "^1.58.3", + "rollup": "^4.17.2", + "sass": "^1.76.0", "scroll-into-view": "^1.16.2" }, "devDependencies": { "babel-plugin-mockable-imports": "^2.0.1", - "chai": "^4.3.7", - "diff": "^5.0.0", - "eslint": "^8.35.0", + "chai": "^5.1.0", + "diff": "^5.2.0", + "eslint": "^8.57.0", "eslint-config-hypothesis": "2.6", - "eslint-plugin-mocha": "^10.1.0", - "eslint-plugin-react": "^7.32.2", - "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-mocha": "^10.4.3", + "eslint-plugin-react": "^7.34.1", + "eslint-plugin-react-hooks": "^4.6.2", "fetch-mock": "^9.11.0", - "karma": "^6.4.1", - "karma-chai": "^0.1.0", - "karma-chrome-launcher": "^3.1.1", + "karma": "^6.4.3", + "karma-chrome-launcher": "^3.2.0", "karma-mocha": "^2.0.1", "karma-mocha-reporter": "^2.2.5", - "karma-sinon": "^1.0.5", "karma-source-map-support": "^1.4.0", - "mocha": "^10.2.0", - "prettier": "^2.8.4", - "sinon": "^15.0.1", + "mocha": "^10.4.0", + "prettier": "^3.2.5", + "sinon": "^17.0.1", "syn": "^0.2.2" }, "engines": { @@ -73,5 +72,6 @@ "prettier": { "arrowParens": "avoid", "singleQuote": true - } + }, + "packageManager": "yarn@3.6.1" } diff --git a/pyproject.toml b/pyproject.toml index 294fd1c4a73..47b84708481 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,79 @@ +[tool.pylint.main] +jobs = 0 # Use one process for CPU. + +load-plugins = [ + "pylint.extensions.bad_builtin", + "pylint.extensions.check_elif", + "pylint.extensions.docparams", + "pylint.extensions.mccabe", + "pylint.extensions.overlapping_exceptions", + "pylint.extensions.redefined_variable_type", +] + +# Fail if there are *any* messages from PyLint. +# The letters refer to PyLint's message categories, see +# https://pylint.pycqa.org/en/latest/messages/messages_introduction.html +fail-on = ["C", "E", "F", "I", "R", "W"] + +[tool.pylint.messages_control] +ignore-paths=[ +] +enable = [ + "bad-inline-option", + "deprecated-pragma", + "useless-suppression", + "use-symbolic-message-instead", + "use-implicit-booleaness-not-comparison-to-zero", + "use-implicit-booleaness-not-comparison-to-string", +] +disable = [ + # Docstrings are encouraged but we don't want to enforce that everything + # must have a docstring. + "missing-docstring", + + # We don't always want to have to put a `:return:` in a docstring. + "missing-return-doc", + + # We don't always want to have to put an `:rtype:` in a docstring. + "missing-return-type-doc", + + # We don't want to have to document the type of every parameter with a + # `:type:` in the docstring. + "missing-type-doc", + + # We use isort to sort and group our imports, so we don't need PyLint to + # check them for us. + "ungrouped-imports", + + # We use Black to format our code automatically, so we don't need PyLint to + # check formatting for us. + "line-too-long", + + # We use isort to sort out imports so we don't need PyLint to check import + # ordering for us. + "wrong-import-order", + + "too-few-public-methods", + + # Issues to disable this for false positives, disabling it globally in the meantime https://github.com/PyCQA/pylint/issues/214 + "duplicate-code", + + "missing-param-doc", + + # Temporarily ignored during pep8 -> pylint transition. This should be removed later. + "fixme", + +] + +good-names = [ + "i", "j", "k", "ex", "Run", "_", # PyLint's default good names. + "tm", "db", "ai", +] + +[tool.pylint.reports] +output-format = "colorized" +score = "no" + [tool.hdev] project_name = "h" project_type = "application" diff --git a/requirements/checkdocs.txt b/requirements/checkdocs.txt index 6c86981bde8..51a38fa5493 100644 --- a/requirements/checkdocs.txt +++ b/requirements/checkdocs.txt @@ -1,97 +1,111 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/checkdocs.in # -alabaster==0.7.12 +alabaster==0.7.16 # via sphinx -babel==2.10.3 +anyio==4.3.0 + # via + # starlette + # watchfiles +babel==2.14.0 # via sphinx -build==0.8.0 +build==1.0.3 # via pip-tools -certifi==2022.12.7 +certifi==2024.2.2 # via requests -charset-normalizer==2.1.0 +charset-normalizer==3.3.2 # via requests -click==8.1.3 - # via pip-tools -colorama==0.4.5 +click==8.1.7 + # via + # pip-tools + # uvicorn +colorama==0.4.6 # via sphinx-autobuild -docutils==0.18.1 +docutils==0.20.1 # via # sphinx # sphinx-rtd-theme -idna==3.3 - # via requests +h11==0.14.0 + # via uvicorn +idna==3.7 + # via + # anyio + # requests imagesize==1.4.1 # via sphinx -importlib-metadata==4.12.0 - # via - # pip-sync-faster - # sphinx -jinja2==3.1.2 +importlib-metadata==7.0.1 + # via pip-sync-faster +jinja2==3.1.4 # via sphinx -livereload==2.6.3 - # via sphinx-autobuild -markupsafe==2.1.1 +markupsafe==2.1.5 # via jinja2 -packaging==23.0 +packaging==24.0 # via # build # sphinx -pep517==0.13.0 - # via build pip-sync-faster==0.0.3 - # via -r requirements/checkdocs.in -pip-tools==6.12.3 + # via -r checkdocs.in +pip-tools==7.4.1 # via - # -r requirements/checkdocs.in + # -r checkdocs.in # pip-sync-faster -pygments==2.14.0 +pygments==2.17.2 # via sphinx -pytz==2022.1 - # via babel -requests==2.28.1 +pyproject-hooks==1.0.0 + # via + # build + # pip-tools +requests==2.32.0 # via sphinx -six==1.16.0 - # via livereload +sniffio==1.3.1 + # via anyio snowballstemmer==2.2.0 # via sphinx -sphinx==6.1.3 +sphinx==7.3.7 # via - # -r requirements/checkdocs.in + # -r checkdocs.in # sphinx-autobuild # sphinx-rtd-theme -sphinx-autobuild==2021.3.14 - # via -r requirements/checkdocs.in -sphinx-rtd-theme==1.2.0 - # via -r requirements/checkdocs.in -sphinxcontrib-applehelp==1.0.2 + # sphinxcontrib-applehelp + # sphinxcontrib-devhelp + # sphinxcontrib-htmlhelp + # sphinxcontrib-jquery + # sphinxcontrib-qthelp + # sphinxcontrib-serializinghtml +sphinx-autobuild==2024.4.16 + # via -r checkdocs.in +sphinx-rtd-theme==2.0.0 + # via -r checkdocs.in +sphinxcontrib-applehelp==1.0.7 # via sphinx -sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-devhelp==1.0.5 # via sphinx -sphinxcontrib-htmlhelp==2.0.0 +sphinxcontrib-htmlhelp==2.0.4 # via sphinx -sphinxcontrib-jquery==2.0.0 +sphinxcontrib-jquery==4.1 # via sphinx-rtd-theme sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-qthelp==1.0.6 # via sphinx -sphinxcontrib-serializinghtml==1.1.5 +sphinxcontrib-serializinghtml==1.1.9 # via sphinx -tomli==2.0.1 - # via - # build - # pep517 -tornado==6.2 - # via livereload -urllib3==1.26.11 +starlette==0.37.2 + # via sphinx-autobuild +urllib3==2.1.0 # via requests -wheel==0.38.1 +uvicorn==0.29.0 + # via sphinx-autobuild +watchfiles==0.21.0 + # via sphinx-autobuild +websockets==12.0 + # via sphinx-autobuild +wheel==0.42.0 # via pip-tools -zipp==3.8.1 +zipp==3.17.0 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/checkformatting.txt b/requirements/checkformatting.txt index f8605a9af91..70ac8cec888 100644 --- a/requirements/checkformatting.txt +++ b/requirements/checkformatting.txt @@ -1,48 +1,44 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/checkformatting.in # -black==23.1.0 +black==24.4.2 # via -r requirements/checkformatting.in -build==0.8.0 +build==1.0.3 # via pip-tools -click==8.1.3 +click==8.1.7 # via # black # pip-tools -importlib-metadata==4.12.0 +importlib-metadata==7.0.1 # via pip-sync-faster -isort==5.12.0 +isort==5.13.2 # via -r requirements/checkformatting.in -mypy-extensions==0.4.3 +mypy-extensions==1.0.0 # via black -packaging==23.0 +packaging==24.0 # via # black # build -pathspec==0.9.0 +pathspec==0.12.1 # via black -pep517==0.13.0 - # via build pip-sync-faster==0.0.3 # via -r requirements/checkformatting.in -pip-tools==6.12.3 +pip-tools==7.4.1 # via # -r requirements/checkformatting.in # pip-sync-faster -platformdirs==2.5.2 +platformdirs==4.1.0 # via black -tomli==2.0.1 +pyproject-hooks==1.0.0 # via - # black # build -typing-extensions==4.3.0 - # via black -wheel==0.38.1 + # pip-tools +wheel==0.42.0 # via pip-tools -zipp==3.8.1 +zipp==3.17.0 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/coverage.txt b/requirements/coverage.txt index 985edd4b6b3..965886ef52d 100644 --- a/requirements/coverage.txt +++ b/requirements/coverage.txt @@ -1,34 +1,32 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/coverage.in # -build==0.8.0 +build==1.0.3 # via pip-tools -click==8.1.3 +click==8.1.7 # via pip-tools -coverage==7.2.2 +coverage==7.5.2 # via -r requirements/coverage.in -importlib-metadata==4.12.0 +importlib-metadata==7.0.1 # via pip-sync-faster -packaging==23.0 - # via build -pep517==0.13.0 +packaging==24.0 # via build pip-sync-faster==0.0.3 # via -r requirements/coverage.in -pip-tools==6.12.3 +pip-tools==7.4.1 # via # -r requirements/coverage.in # pip-sync-faster -tomli==2.0.1 +pyproject-hooks==1.0.0 # via # build - # pep517 -wheel==0.38.1 + # pip-tools +wheel==0.42.0 # via pip-tools -zipp==3.8.1 +zipp==3.17.0 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/dev.in b/requirements/dev.in index 85b26e78637..bf2a48377e4 100644 --- a/requirements/dev.in +++ b/requirements/dev.in @@ -1,6 +1,6 @@ pip-tools pip-sync-faster -ipython +pyramid-ipython ipdb factory-boy --r requirements.txt +-r prod.txt diff --git a/requirements/dev.txt b/requirements/dev.txt index 07a58f9d07d..87056c8933b 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,241 +1,244 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/dev.in # -alembic==1.10.2 - # via -r requirements/requirements.txt -amqp==5.0.9 +alembic==1.13.1 + # via -r requirements/prod.txt +amqp==5.2.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # kombu -asttokens==2.0.5 +asttokens==2.4.1 # via stack-data -attrs==20.2.0 +attrs==23.2.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # jsonschema -backcall==0.2.0 - # via ipython -bcrypt==4.0.1 - # via -r requirements/requirements.txt -billiard==3.6.4.0 + # referencing +bcrypt==4.1.3 + # via -r requirements/prod.txt +billiard==4.2.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery -bleach==6.0.0 - # via -r requirements/requirements.txt -build==0.8.0 +bleach==6.1.0 + # via -r requirements/prod.txt +build==1.0.3 # via pip-tools -celery==5.2.7 - # via -r requirements/requirements.txt -certifi==2022.12.7 +celery==5.4.0 + # via -r requirements/prod.txt +certifi==2024.2.2 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # sentry-sdk -cffi==1.15.1 - # via -r requirements/requirements.txt -chameleon==3.8.1 +cffi==1.16.0 + # via -r requirements/prod.txt +chameleon==4.4.3 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # deform -click==8.1.3 +click==8.1.7 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery # click-didyoumean # click-plugins # click-repl # pip-tools -click-didyoumean==0.0.3 +click-didyoumean==0.3.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery click-plugins==1.1.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery -click-repl==0.2.0 +click-repl==0.3.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery -colander==1.8.2 +colander==2.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # deform data-tasks==0.0.3 - # via -r requirements/requirements.txt -decorator==5.0.7 + # via -r requirements/prod.txt +decorator==5.1.1 # via # ipdb # ipython deform==2.0.15 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt elasticsearch==6.8.2 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # elasticsearch-dsl elasticsearch-dsl==6.4.0 - # via -r requirements/requirements.txt -executing==0.8.2 + # via -r requirements/prod.txt +executing==2.0.1 # via stack-data -factory-boy==3.2.1 +factory-boy==3.3.0 # via -r requirements/dev.in -faker==17.4.0 +faker==22.2.0 # via factory-boy -gevent==22.10.2 - # via -r requirements/requirements.txt -greenlet==2.0.2 +gevent==24.2.1 + # via -r requirements/prod.txt +greenlet==3.0.3 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # gevent # sqlalchemy -gunicorn==20.1.0 - # via -r requirements/requirements.txt -h-api==1.0.2 - # via -r requirements/requirements.txt -h-assets==1.0.5 - # via -r requirements/requirements.txt +gunicorn==22.0.0 + # via -r requirements/prod.txt +h-api==1.1.0 + # via -r requirements/prod.txt +h-assets==1.0.6 + # via -r requirements/prod.txt h-matchers==1.2.15 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt h-pyramid-sentry==1.2.4 - # via -r requirements/requirements.txt -hupper==1.10.2 + # via -r requirements/prod.txt +hupper==1.12 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid -importlib-metadata==4.8.1 +importlib-metadata==7.0.1 # via - # -r requirements/requirements.txt - # alembic + # -r requirements/prod.txt # data-tasks - # markdown + # h-api + # h-assets # pip-sync-faster -importlib-resources==5.12.0 +importlib-resources==6.4.0 # via - # -r requirements/requirements.txt - # alembic + # -r requirements/prod.txt # data-tasks # h-api ipdb==0.13.13 # via -r requirements/dev.in -ipython==8.8.0 +ipython==8.20.0 # via - # -r requirements/dev.in # ipdb -ipython-genutils==0.2.0 - # via traitlets -iso8601==0.1.13 + # pyramid-ipython +iso8601==2.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # colander # deform -itsdangerous==2.1.2 - # via -r requirements/requirements.txt -jedi==0.18.0 +itsdangerous==2.2.0 + # via -r requirements/prod.txt +jedi==0.19.1 # via ipython -jinja2==2.11.3 +jinja2==3.1.4 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # data-tasks # pyramid-jinja2 -jsonschema==3.2.0 +jsonschema==4.22.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # h-api -kombu==5.2.4 +jsonschema-specifications==2023.12.1 + # via + # -r requirements/prod.txt + # jsonschema +kombu==5.3.7 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery -mako==1.2.2 +mako==1.3.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # alembic -markdown==3.4.2 - # via -r requirements/requirements.txt -markupsafe==1.1.1 +markdown==3.6 + # via -r requirements/prod.txt +markupsafe==2.1.5 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # jinja2 # mako # pyramid-jinja2 -matplotlib-inline==0.1.2 +matplotlib-inline==0.1.6 # via ipython -newrelic==8.7.1 - # via -r requirements/requirements.txt +newrelic==9.8.0 + # via -r requirements/prod.txt oauthlib==3.2.2 - # via -r requirements/requirements.txt -packaging==23.0 + # via -r requirements/prod.txt +packaging==24.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # build -parso==0.8.2 + # gunicorn + # zope-sqlalchemy +parso==0.8.3 # via jedi passlib==1.7.4 - # via -r requirements/requirements.txt -pastedeploy==2.1.0 + # via -r requirements/prod.txt +pastedeploy==3.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # plaster-pastedeploy -pep517==0.13.0 - # via build peppercorn==0.6 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # deform -pexpect==4.8.0 - # via ipython -pickleshare==0.7.5 +pexpect==4.9.0 # via ipython pip-sync-faster==0.0.3 # via -r requirements/dev.in -pip-tools==6.12.3 +pip-tools==7.4.1 # via # -r requirements/dev.in # pip-sync-faster -plaster==1.0 +plaster==1.1.2 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # plaster-pastedeploy # pyramid -plaster-pastedeploy==0.7 +plaster-pastedeploy==1.0.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid -prompt-toolkit==3.0.18 +prompt-toolkit==3.0.43 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # click-repl # ipython psycogreen==1.0.2 - # via -r requirements/requirements.txt -psycopg2==2.9.5 + # via -r requirements/prod.txt +psycopg2==2.9.9 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # data-tasks ptyprocess==0.7.0 # via pexpect -pure-eval==0.2.1 +pure-eval==0.2.2 # via stack-data -pycparser==2.20 +pycparser==2.21 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # cffi -pycryptodomex==3.17 - # via -r requirements/requirements.txt -pygments==2.9.0 +pycryptodomex==3.20.0 + # via -r requirements/prod.txt +pygments==2.17.2 # via ipython -pyjwt==2.6.0 - # via -r requirements/requirements.txt -pyparsing==3.0.9 - # via -r requirements/requirements.txt -pyramid==2.0 +pyjwt==2.8.0 + # via -r requirements/prod.txt +pyparsing==3.1.2 + # via -r requirements/prod.txt +pyproject-hooks==1.0.0 # via - # -r requirements/requirements.txt + # build + # pip-tools +pyramid==2.0.2 + # via + # -r requirements/prod.txt # h-assets # h-pyramid-sentry # pyramid-exclog + # pyramid-ipython # pyramid-jinja2 # pyramid-mailer # pyramid-retry @@ -243,157 +246,162 @@ pyramid==2.0 # pyramid-services # pyramid-tm pyramid-exclog==1.1 - # via -r requirements/requirements.txt -pyramid-jinja2==2.10 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt +pyramid-ipython==0.2 + # via -r requirements/dev.in +pyramid-jinja2==2.10.1 + # via -r requirements/prod.txt pyramid-mailer==0.15.1 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt pyramid-retry==2.1.1 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt pyramid-sanity==1.0.3 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt pyramid-services==2.2 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt pyramid-tm==2.5 - # via -r requirements/requirements.txt -pyrsistent==0.17.3 - # via - # -r requirements/requirements.txt - # jsonschema -python-dateutil==2.8.2 + # via -r requirements/prod.txt +python-dateutil==2.9.0.post0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt + # celery # elasticsearch-dsl # faker -python-slugify==8.0.1 - # via -r requirements/requirements.txt -pytz==2021.3 +python-slugify==8.0.4 + # via -r requirements/prod.txt +pytz==2024.1 + # via -r requirements/prod.txt +referencing==0.32.1 # via - # -r requirements/requirements.txt - # celery -repoze-sendmail==4.3 + # -r requirements/prod.txt + # h-api + # jsonschema + # jsonschema-specifications +repoze-sendmail==4.4.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid-mailer rfc3339-validator==0.1.4 - # via -r requirements/requirements.txt -sentry-sdk==0.17.6 + # via -r requirements/prod.txt +rpds-py==0.16.2 + # via + # -r requirements/prod.txt + # jsonschema + # referencing +sentry-sdk==2.3.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # h-pyramid-sentry -six==1.15.0 +six==1.16.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # asttokens # bleach - # click-repl # elasticsearch-dsl - # jsonschema # python-dateutil # rfc3339-validator -sqlalchemy==1.4.47 +sqlalchemy==2.0.25 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # alembic # data-tasks # zope-sqlalchemy -sqlparse==0.4.3 +sqlparse==0.5.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # data-tasks -stack-data==0.1.3 +stack-data==0.6.3 # via ipython supervisor==4.2.5 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt tabulate==0.9.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # data-tasks text-unidecode==1.3 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # python-slugify -tomli==2.0.1 - # via - # build - # ipdb - # pep517 -traitlets==5.0.5 +traitlets==5.14.1 # via # ipython # matplotlib-inline -transaction==3.1.0 +transaction==4.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid-mailer # pyramid-tm # repoze-sendmail # zope-sqlalchemy translationstring==1.4 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # colander # deform # pyramid -typing-extensions==4.5.0 +typing-extensions==4.9.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # alembic -urllib3==1.26.5 + # sqlalchemy +tzdata==2023.4 + # via + # -r requirements/prod.txt + # celery +urllib3==2.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # elasticsearch # sentry-sdk -venusian==3.0.0 +venusian==3.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid -vine==5.0.0 +vine==5.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # amqp # celery # kombu -wcwidth==0.2.5 +wcwidth==0.2.13 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # prompt-toolkit webencodings==0.5.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # bleach webob==1.8.7 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid -wheel==0.38.1 +wheel==0.42.0 # via pip-tools -wired==0.2.2 +wired==0.3 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid-services ws4py==0.5.1 - # via -r requirements/requirements.txt -wsaccel==0.6.4 - # via -r requirements/requirements.txt -zipp==3.4.1 + # via -r requirements/prod.txt +wsaccel==0.6.6 + # via -r requirements/prod.txt +zipp==3.17.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # importlib-metadata - # importlib-resources -zope-deprecation==4.1.2 +zope-deprecation==5.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # deform # pyramid # pyramid-jinja2 -zope-event==4.4 +zope-event==5.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # gevent -zope-interface==6.0 +zope-interface==6.4.post2 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # gevent # pyramid # pyramid-retry @@ -402,8 +410,8 @@ zope-interface==6.0 # transaction # wired # zope-sqlalchemy -zope-sqlalchemy==2.0 - # via -r requirements/requirements.txt +zope-sqlalchemy==3.1 + # via -r requirements/prod.txt # The following packages are considered to be unsafe in a requirements file: # pip diff --git a/requirements/dockercompose.in b/requirements/dockercompose.in deleted file mode 100644 index 4b8f9527be9..00000000000 --- a/requirements/dockercompose.in +++ /dev/null @@ -1,3 +0,0 @@ -pip-tools -pip-sync-faster -docker-compose diff --git a/requirements/dockercompose.txt b/requirements/dockercompose.txt deleted file mode 100644 index 4009a120153..00000000000 --- a/requirements/dockercompose.txt +++ /dev/null @@ -1,93 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# pip-compile requirements/dockercompose.in -# -attrs==20.3.0 - # via jsonschema -bcrypt==4.0.1 - # via paramiko -build==0.8.0 - # via pip-tools -certifi==2022.12.7 - # via requests -cffi==1.15.1 - # via - # cryptography - # pynacl -chardet==4.0.0 - # via requests -click==8.1.3 - # via pip-tools -cryptography==39.0.1 - # via paramiko -distro==1.5.0 - # via docker-compose -docker[ssh]==5.0.0 - # via docker-compose -docker-compose==1.29.2 - # via -r requirements/dockercompose.in -dockerpty==0.4.1 - # via docker-compose -docopt==0.6.2 - # via docker-compose -idna==2.10 - # via requests -importlib-metadata==4.12.0 - # via pip-sync-faster -jsonschema==3.2.0 - # via docker-compose -packaging==23.0 - # via build -paramiko==2.10.1 - # via docker -pep517==0.13.0 - # via build -pip-sync-faster==0.0.3 - # via -r requirements/dockercompose.in -pip-tools==6.12.3 - # via - # -r requirements/dockercompose.in - # pip-sync-faster -pycparser==2.20 - # via cffi -pynacl==1.4.0 - # via paramiko -pyrsistent==0.17.3 - # via jsonschema -python-dotenv==0.17.1 - # via docker-compose -pyyaml==5.4.1 - # via docker-compose -requests==2.25.1 - # via - # docker - # docker-compose -six==1.15.0 - # via - # dockerpty - # jsonschema - # paramiko - # pynacl - # websocket-client -texttable==1.6.3 - # via docker-compose -tomli==2.0.1 - # via - # build - # pep517 -urllib3==1.26.5 - # via requests -websocket-client==0.58.0 - # via - # docker - # docker-compose -wheel==0.38.1 - # via pip-tools -zipp==3.8.1 - # via importlib-metadata - -# The following packages are considered to be unsafe in a requirements file: -# pip -# setuptools diff --git a/requirements/docs.txt b/requirements/docs.txt index 1f6663b414a..245bd9f8bc4 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -1,97 +1,111 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/docs.in # -alabaster==0.7.12 +alabaster==0.7.16 # via sphinx -babel==2.9.1 +anyio==4.3.0 + # via + # starlette + # watchfiles +babel==2.14.0 # via sphinx -build==0.8.0 +build==1.0.3 # via pip-tools -certifi==2022.12.7 +certifi==2024.2.2 # via requests -chardet==4.0.0 +charset-normalizer==3.3.2 # via requests -click==8.1.3 - # via pip-tools -colorama==0.4.4 +click==8.1.7 + # via + # pip-tools + # uvicorn +colorama==0.4.6 # via sphinx-autobuild -docutils==0.18.1 +docutils==0.20.1 # via # sphinx # sphinx-rtd-theme -idna==2.10 - # via requests +h11==0.14.0 + # via uvicorn +idna==3.7 + # via + # anyio + # requests imagesize==1.4.1 # via sphinx -importlib-metadata==4.10.1 - # via - # pip-sync-faster - # sphinx -jinja2==3.1.2 +importlib-metadata==7.0.1 + # via pip-sync-faster +jinja2==3.1.4 # via sphinx -livereload==2.6.3 - # via sphinx-autobuild -markupsafe==2.1.2 +markupsafe==2.1.5 # via jinja2 -packaging==23.0 +packaging==24.0 # via # build # sphinx -pep517==0.13.0 - # via build pip-sync-faster==0.0.3 - # via -r requirements/docs.in -pip-tools==6.12.3 + # via -r docs.in +pip-tools==7.4.1 # via - # -r requirements/docs.in + # -r docs.in # pip-sync-faster -pygments==2.14.0 +pygments==2.17.2 # via sphinx -pytz==2021.1 - # via babel -requests==2.25.1 +pyproject-hooks==1.0.0 + # via + # build + # pip-tools +requests==2.32.0 # via sphinx -six==1.15.0 - # via livereload -snowballstemmer==2.1.0 +sniffio==1.3.1 + # via anyio +snowballstemmer==2.2.0 # via sphinx -sphinx==6.1.3 +sphinx==7.3.7 # via - # -r requirements/docs.in + # -r docs.in # sphinx-autobuild # sphinx-rtd-theme -sphinx-autobuild==2021.3.14 - # via -r requirements/docs.in -sphinx-rtd-theme==1.2.0 - # via -r requirements/docs.in -sphinxcontrib-applehelp==1.0.2 + # sphinxcontrib-applehelp + # sphinxcontrib-devhelp + # sphinxcontrib-htmlhelp + # sphinxcontrib-jquery + # sphinxcontrib-qthelp + # sphinxcontrib-serializinghtml +sphinx-autobuild==2024.4.16 + # via -r docs.in +sphinx-rtd-theme==2.0.0 + # via -r docs.in +sphinxcontrib-applehelp==1.0.7 # via sphinx -sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-devhelp==1.0.5 # via sphinx -sphinxcontrib-htmlhelp==2.0.0 +sphinxcontrib-htmlhelp==2.0.4 # via sphinx -sphinxcontrib-jquery==2.0.0 +sphinxcontrib-jquery==4.1 # via sphinx-rtd-theme sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-qthelp==1.0.6 # via sphinx -sphinxcontrib-serializinghtml==1.1.5 +sphinxcontrib-serializinghtml==1.1.9 # via sphinx -tomli==2.0.1 - # via - # build - # pep517 -tornado==6.1 - # via livereload -urllib3==1.26.5 +starlette==0.37.2 + # via sphinx-autobuild +urllib3==2.1.0 # via requests -wheel==0.38.1 +uvicorn==0.29.0 + # via sphinx-autobuild +watchfiles==0.21.0 + # via sphinx-autobuild +websockets==12.0 + # via sphinx-autobuild +wheel==0.42.0 # via pip-tools -zipp==3.7.0 +zipp==3.17.0 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/format.txt b/requirements/format.txt index e69d161f701..bb424edd5b0 100644 --- a/requirements/format.txt +++ b/requirements/format.txt @@ -1,48 +1,44 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/format.in # -black==23.1.0 +black==24.4.2 # via -r requirements/format.in -build==0.8.0 +build==1.0.3 # via pip-tools -click==8.1.3 +click==8.1.7 # via # black # pip-tools -importlib-metadata==4.12.0 +importlib-metadata==7.0.1 # via pip-sync-faster -isort==5.12.0 +isort==5.13.2 # via -r requirements/format.in -mypy-extensions==0.4.3 +mypy-extensions==1.0.0 # via black -packaging==23.0 +packaging==24.0 # via # black # build -pathspec==0.9.0 +pathspec==0.12.1 # via black -pep517==0.13.0 - # via build pip-sync-faster==0.0.3 # via -r requirements/format.in -pip-tools==6.12.3 +pip-tools==7.4.1 # via # -r requirements/format.in # pip-sync-faster -platformdirs==2.2.0 +platformdirs==4.1.0 # via black -tomli==2.0.0 +pyproject-hooks==1.0.0 # via - # black # build -typing-extensions==3.10.0.1 - # via black -wheel==0.38.1 + # pip-tools +wheel==0.42.0 # via pip-tools -zipp==3.8.1 +zipp==3.17.0 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/functests.in b/requirements/functests.in index 88b83150f28..6f770755bcd 100644 --- a/requirements/functests.in +++ b/requirements/functests.in @@ -4,4 +4,5 @@ pytest factory-boy webtest pytest-reverse --r requirements.txt +h-testkit +-r prod.txt diff --git a/requirements/functests.txt b/requirements/functests.txt index 32533c1bdce..a8e0df042af 100644 --- a/requirements/functests.txt +++ b/requirements/functests.txt @@ -1,213 +1,220 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/functests.in # -alembic==1.10.2 - # via -r requirements/requirements.txt -amqp==5.0.9 +alembic==1.13.1 + # via -r requirements/prod.txt +amqp==5.2.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # kombu -attrs==20.2.0 +attrs==23.2.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # jsonschema - # pytest -bcrypt==4.0.1 - # via -r requirements/requirements.txt -beautifulsoup4==4.9.3 + # referencing +bcrypt==4.1.3 + # via -r requirements/prod.txt +beautifulsoup4==4.12.2 # via webtest -billiard==3.6.4.0 +billiard==4.2.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery -bleach==6.0.0 - # via -r requirements/requirements.txt -build==0.8.0 +bleach==6.1.0 + # via -r requirements/prod.txt +build==1.0.3 # via pip-tools -celery==5.2.7 - # via -r requirements/requirements.txt -certifi==2022.12.7 +celery==5.4.0 + # via -r requirements/prod.txt +certifi==2024.2.2 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # sentry-sdk -cffi==1.15.1 - # via -r requirements/requirements.txt -chameleon==3.8.1 +cffi==1.16.0 + # via -r requirements/prod.txt +chameleon==4.4.3 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # deform -click==8.1.3 +click==8.1.7 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery # click-didyoumean # click-plugins # click-repl # pip-tools -click-didyoumean==0.0.3 +click-didyoumean==0.3.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery click-plugins==1.1.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery -click-repl==0.2.0 +click-repl==0.3.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery -colander==1.8.2 +colander==2.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # deform data-tasks==0.0.3 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt deform==2.0.15 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt elasticsearch==6.8.2 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # elasticsearch-dsl elasticsearch-dsl==6.4.0 - # via -r requirements/requirements.txt -exceptiongroup==1.1.0 - # via pytest -factory-boy==3.2.1 + # via -r requirements/prod.txt +factory-boy==3.3.0 # via -r requirements/functests.in -faker==17.4.0 +faker==22.2.0 # via factory-boy -gevent==22.10.2 - # via -r requirements/requirements.txt -greenlet==2.0.2 +gevent==24.2.1 + # via -r requirements/prod.txt +greenlet==3.0.3 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # gevent # sqlalchemy -gunicorn==20.1.0 - # via -r requirements/requirements.txt -h-api==1.0.2 - # via -r requirements/requirements.txt -h-assets==1.0.5 - # via -r requirements/requirements.txt +gunicorn==22.0.0 + # via -r requirements/prod.txt +h-api==1.1.0 + # via -r requirements/prod.txt +h-assets==1.0.6 + # via -r requirements/prod.txt h-matchers==1.2.15 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt h-pyramid-sentry==1.2.4 - # via -r requirements/requirements.txt -hupper==1.10.2 + # via -r requirements/prod.txt +h-testkit==1.0.1 + # via -r requirements/functests.in +hupper==1.12 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid -importlib-metadata==4.8.1 +importlib-metadata==7.0.1 # via - # -r requirements/requirements.txt - # alembic + # -r requirements/prod.txt # data-tasks - # markdown + # h-api + # h-assets # pip-sync-faster -importlib-resources==5.12.0 +importlib-resources==6.4.0 # via - # -r requirements/requirements.txt - # alembic + # -r requirements/prod.txt # data-tasks # h-api -iniconfig==1.1.1 +iniconfig==2.0.0 # via pytest -iso8601==0.1.13 +iso8601==2.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # colander # deform -itsdangerous==2.1.2 - # via -r requirements/requirements.txt -jinja2==2.11.3 +itsdangerous==2.2.0 + # via -r requirements/prod.txt +jinja2==3.1.4 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # data-tasks # pyramid-jinja2 -jsonschema==3.2.0 +jsonschema==4.22.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # h-api -kombu==5.2.4 +jsonschema-specifications==2023.12.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt + # jsonschema +kombu==5.3.7 + # via + # -r requirements/prod.txt # celery -mako==1.2.2 +mako==1.3.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # alembic -markdown==3.4.2 - # via -r requirements/requirements.txt -markupsafe==1.1.1 +markdown==3.6 + # via -r requirements/prod.txt +markupsafe==2.1.5 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # jinja2 # mako # pyramid-jinja2 -newrelic==8.7.1 - # via -r requirements/requirements.txt +newrelic==9.8.0 + # via -r requirements/prod.txt oauthlib==3.2.2 - # via -r requirements/requirements.txt -packaging==23.0 + # via -r requirements/prod.txt +packaging==24.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # build + # gunicorn # pytest + # zope-sqlalchemy passlib==1.7.4 - # via -r requirements/requirements.txt -pastedeploy==2.1.0 + # via -r requirements/prod.txt +pastedeploy==3.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # plaster-pastedeploy -pep517==0.13.0 - # via build peppercorn==0.6 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # deform pip-sync-faster==0.0.3 # via -r requirements/functests.in -pip-tools==6.12.3 +pip-tools==7.4.1 # via # -r requirements/functests.in # pip-sync-faster -plaster==1.0 +plaster==1.1.2 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # plaster-pastedeploy # pyramid -plaster-pastedeploy==0.7 +plaster-pastedeploy==1.0.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid -pluggy==0.13.1 +pluggy==1.5.0 # via pytest -prompt-toolkit==3.0.18 +prompt-toolkit==3.0.43 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # click-repl psycogreen==1.0.2 - # via -r requirements/requirements.txt -psycopg2==2.9.5 + # via -r requirements/prod.txt +psycopg2==2.9.9 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # data-tasks -pycparser==2.20 +pycparser==2.21 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # cffi -pycryptodomex==3.17 - # via -r requirements/requirements.txt -pyjwt==2.6.0 - # via -r requirements/requirements.txt -pyparsing==3.0.9 - # via -r requirements/requirements.txt -pyramid==2.0 - # via - # -r requirements/requirements.txt +pycryptodomex==3.20.0 + # via -r requirements/prod.txt +pyjwt==2.8.0 + # via -r requirements/prod.txt +pyparsing==3.1.2 + # via -r requirements/prod.txt +pyproject-hooks==1.0.0 + # via + # build + # pip-tools +pyramid==2.0.2 + # via + # -r requirements/prod.txt # h-assets # h-pyramid-sentry # pyramid-exclog @@ -218,163 +225,166 @@ pyramid==2.0 # pyramid-services # pyramid-tm pyramid-exclog==1.1 - # via -r requirements/requirements.txt -pyramid-jinja2==2.10 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt +pyramid-jinja2==2.10.1 + # via -r requirements/prod.txt pyramid-mailer==0.15.1 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt pyramid-retry==2.1.1 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt pyramid-sanity==1.0.3 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt pyramid-services==2.2 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt pyramid-tm==2.5 - # via -r requirements/requirements.txt -pyrsistent==0.17.3 - # via - # -r requirements/requirements.txt - # jsonschema -pytest==7.2.2 + # via -r requirements/prod.txt +pytest==8.2.1 # via # -r requirements/functests.in # pytest-reverse -pytest-reverse==1.5.0 +pytest-reverse==1.7.0 # via -r requirements/functests.in -python-dateutil==2.8.2 +python-dateutil==2.9.0.post0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt + # celery # elasticsearch-dsl # faker -python-slugify==8.0.1 - # via -r requirements/requirements.txt -pytz==2021.3 +python-slugify==8.0.4 + # via -r requirements/prod.txt +pytz==2024.1 + # via -r requirements/prod.txt +referencing==0.32.1 # via - # -r requirements/requirements.txt - # celery -repoze-sendmail==4.3 + # -r requirements/prod.txt + # h-api + # jsonschema + # jsonschema-specifications +repoze-sendmail==4.4.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid-mailer rfc3339-validator==0.1.4 - # via -r requirements/requirements.txt -sentry-sdk==0.17.6 + # via -r requirements/prod.txt +rpds-py==0.16.2 + # via + # -r requirements/prod.txt + # jsonschema + # referencing +sentry-sdk==2.3.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # h-pyramid-sentry -six==1.15.0 +six==1.16.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # bleach - # click-repl # elasticsearch-dsl - # jsonschema # python-dateutil # rfc3339-validator -soupsieve==2.2.1 +soupsieve==2.5 # via beautifulsoup4 -sqlalchemy==1.4.47 +sqlalchemy==2.0.25 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # alembic # data-tasks # zope-sqlalchemy -sqlparse==0.4.3 +sqlparse==0.5.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # data-tasks supervisor==4.2.5 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt tabulate==0.9.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # data-tasks text-unidecode==1.3 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # python-slugify -tomli==2.0.0 - # via - # build - # pep517 - # pytest -transaction==3.1.0 +transaction==4.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid-mailer # pyramid-tm # repoze-sendmail # zope-sqlalchemy translationstring==1.4 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # colander # deform # pyramid -typing-extensions==4.5.0 +typing-extensions==4.9.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # alembic -urllib3==1.26.5 + # sqlalchemy +tzdata==2023.4 + # via + # -r requirements/prod.txt + # celery +urllib3==2.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # elasticsearch # sentry-sdk -venusian==3.0.0 +venusian==3.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid -vine==5.0.0 +vine==5.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # amqp # celery # kombu waitress==2.1.2 # via webtest -wcwidth==0.2.5 +wcwidth==0.2.13 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # prompt-toolkit webencodings==0.5.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # bleach webob==1.8.7 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid # webtest webtest==3.0.0 # via -r requirements/functests.in -wheel==0.38.1 +wheel==0.42.0 # via pip-tools -wired==0.2.2 +wired==0.3 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid-services ws4py==0.5.1 - # via -r requirements/requirements.txt -wsaccel==0.6.4 - # via -r requirements/requirements.txt -zipp==3.4.1 + # via -r requirements/prod.txt +wsaccel==0.6.6 + # via -r requirements/prod.txt +zipp==3.17.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # importlib-metadata - # importlib-resources -zope-deprecation==4.1.2 +zope-deprecation==5.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # deform # pyramid # pyramid-jinja2 -zope-event==4.4 +zope-event==5.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # gevent -zope-interface==6.0 +zope-interface==6.4.post2 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # gevent # pyramid # pyramid-retry @@ -383,8 +393,8 @@ zope-interface==6.0 # transaction # wired # zope-sqlalchemy -zope-sqlalchemy==2.0 - # via -r requirements/requirements.txt +zope-sqlalchemy==3.1 + # via -r requirements/prod.txt # The following packages are considered to be unsafe in a requirements file: # pip diff --git a/requirements/lint.txt b/requirements/lint.txt index e6bfa62aa50..e9210cdc382 100644 --- a/requirements/lint.txt +++ b/requirements/lint.txt @@ -1,68 +1,68 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/lint.in # -alembic==1.10.2 +alembic==1.13.1 # via # -r requirements/functests.txt # -r requirements/tests.txt -amqp==5.0.9 +amqp==5.2.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # kombu -astroid==2.15.0 +astroid==3.1.0 # via pylint -attrs==20.2.0 +attrs==23.2.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # hypothesis # jsonschema - # pytest -bcrypt==4.0.1 + # referencing +bcrypt==4.1.3 # via # -r requirements/functests.txt # -r requirements/tests.txt -beautifulsoup4==4.9.3 +beautifulsoup4==4.12.2 # via # -r requirements/functests.txt # webtest -billiard==3.6.4.0 +billiard==4.2.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # celery -bleach==6.0.0 +bleach==6.1.0 # via # -r requirements/functests.txt # -r requirements/tests.txt -build==0.8.0 +build==1.0.3 # via # -r requirements/functests.txt # -r requirements/tests.txt # pip-tools -celery==5.2.7 +celery==5.4.0 # via # -r requirements/functests.txt # -r requirements/tests.txt -certifi==2022.12.7 +certifi==2024.2.2 # via # -r requirements/functests.txt # -r requirements/tests.txt # sentry-sdk -cffi==1.15.1 +cffi==1.16.0 # via # -r requirements/functests.txt # -r requirements/tests.txt -chameleon==3.8.1 +chameleon==4.4.3 # via # -r requirements/functests.txt # -r requirements/tests.txt # deform -click==8.1.3 +click==8.1.7 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -71,7 +71,7 @@ click==8.1.3 # click-plugins # click-repl # pip-tools -click-didyoumean==0.0.3 +click-didyoumean==0.3.0 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -81,18 +81,20 @@ click-plugins==1.1.1 # -r requirements/functests.txt # -r requirements/tests.txt # celery -click-repl==0.2.0 +click-repl==0.3.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # celery -colander==1.8.2 +colander==2.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # deform -coverage==7.2.2 - # via -r requirements/tests.txt +coverage[toml]==7.5.2 + # via + # -r requirements/tests.txt + # pytest-cov data-tasks==0.0.3 # via # -r requirements/functests.txt @@ -101,7 +103,7 @@ deform==2.0.15 # via # -r requirements/functests.txt # -r requirements/tests.txt -dill==0.3.4 +dill==0.3.7 # via pylint elasticsearch==6.8.2 # via @@ -112,40 +114,40 @@ elasticsearch-dsl==6.4.0 # via # -r requirements/functests.txt # -r requirements/tests.txt -exceptiongroup==1.1.0 +execnet==2.1.1 # via - # -r requirements/functests.txt # -r requirements/tests.txt - # hypothesis - # pytest -factory-boy==3.2.1 + # pytest-xdist +factory-boy==3.3.0 # via # -r requirements/functests.txt # -r requirements/tests.txt -faker==17.4.0 +faker==22.2.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # factory-boy -gevent==22.10.2 +freezegun==1.5.1 + # via -r requirements/tests.txt +gevent==24.2.1 # via # -r requirements/functests.txt # -r requirements/tests.txt -greenlet==2.0.2 +greenlet==3.0.3 # via # -r requirements/functests.txt # -r requirements/tests.txt # gevent # sqlalchemy -gunicorn==20.1.0 +gunicorn==22.0.0 # via # -r requirements/functests.txt # -r requirements/tests.txt -h-api==1.0.2 +h-api==1.1.0 # via # -r requirements/functests.txt # -r requirements/tests.txt -h-assets==1.0.5 +h-assets==1.0.6 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -157,82 +159,88 @@ h-pyramid-sentry==1.2.4 # via # -r requirements/functests.txt # -r requirements/tests.txt -hupper==1.10.2 +h-testkit==1.0.1 + # via + # -r requirements/functests.txt + # -r requirements/tests.txt +hupper==1.12 # via # -r requirements/functests.txt # -r requirements/tests.txt # pyramid -hypothesis==6.70.0 +hypothesis==6.102.6 # via -r requirements/tests.txt -importlib-metadata==4.8.1 +importlib-metadata==7.0.1 # via # -r requirements/functests.txt # -r requirements/tests.txt - # alembic # data-tasks - # markdown + # h-api + # h-assets # pip-sync-faster -importlib-resources==5.12.0 +importlib-resources==6.4.0 # via # -r requirements/functests.txt # -r requirements/tests.txt - # alembic # data-tasks # h-api -iniconfig==1.1.1 +iniconfig==2.0.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # pytest -iso8601==0.1.13 +iso8601==2.1.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # colander # deform -isort==5.12.0 +isort==5.13.2 # via pylint -itsdangerous==2.1.2 +itsdangerous==2.2.0 # via # -r requirements/functests.txt # -r requirements/tests.txt -jinja2==2.11.3 +jinja2==3.1.4 # via # -r requirements/functests.txt # -r requirements/tests.txt # data-tasks # pyramid-jinja2 -jsonschema==3.2.0 +jsonschema==4.22.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # h-api -kombu==5.2.4 +jsonschema-specifications==2023.12.1 + # via + # -r requirements/functests.txt + # -r requirements/tests.txt + # jsonschema +kombu==5.3.7 # via # -r requirements/functests.txt # -r requirements/tests.txt # celery -lazy-object-proxy==1.6.0 - # via astroid -mako==1.2.2 +mako==1.3.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # alembic -markdown==3.4.2 +markdown==3.6 # via # -r requirements/functests.txt # -r requirements/tests.txt -markupsafe==1.1.1 +markupsafe==2.1.5 # via # -r requirements/functests.txt # -r requirements/tests.txt # jinja2 # mako # pyramid-jinja2 -mccabe==0.6.1 +mccabe==0.7.0 # via pylint -newrelic==8.7.1 +newrelic==9.8.0 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -240,26 +248,23 @@ oauthlib==3.2.2 # via # -r requirements/functests.txt # -r requirements/tests.txt -packaging==23.0 +packaging==24.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # build + # gunicorn # pytest + # zope-sqlalchemy passlib==1.7.4 # via # -r requirements/functests.txt # -r requirements/tests.txt -pastedeploy==2.1.0 +pastedeploy==3.1.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # plaster-pastedeploy -pep517==0.13.0 - # via - # -r requirements/functests.txt - # -r requirements/tests.txt - # build peppercorn==0.6 # via # -r requirements/functests.txt @@ -270,68 +275,78 @@ pip-sync-faster==0.0.3 # -r requirements/functests.txt # -r requirements/lint.in # -r requirements/tests.txt -pip-tools==6.12.3 +pip-tools==7.4.1 # via # -r requirements/functests.txt # -r requirements/lint.in # -r requirements/tests.txt # pip-sync-faster -plaster==1.0 +plaster==1.1.2 # via # -r requirements/functests.txt # -r requirements/tests.txt # plaster-pastedeploy # pyramid -plaster-pastedeploy==0.7 +plaster-pastedeploy==1.0.1 # via # -r requirements/functests.txt # -r requirements/tests.txt # pyramid -platformdirs==2.2.0 +platformdirs==4.1.0 # via pylint -pluggy==0.13.1 +pluggy==1.5.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # pytest -prompt-toolkit==3.0.18 +prompt-toolkit==3.0.43 # via # -r requirements/functests.txt # -r requirements/tests.txt # click-repl +psutil==5.9.7 + # via + # -r requirements/tests.txt + # pytest-xdist psycogreen==1.0.2 # via # -r requirements/functests.txt # -r requirements/tests.txt -psycopg2==2.9.5 +psycopg2==2.9.9 # via # -r requirements/functests.txt # -r requirements/tests.txt # data-tasks -pycodestyle==2.10.0 +pycodestyle==2.11.1 # via -r requirements/lint.in -pycparser==2.20 +pycparser==2.21 # via # -r requirements/functests.txt # -r requirements/tests.txt # cffi -pycryptodomex==3.17 +pycryptodomex==3.20.0 # via # -r requirements/functests.txt # -r requirements/tests.txt pydocstyle==6.3.0 # via -r requirements/lint.in -pyjwt==2.6.0 +pyjwt==2.8.0 # via # -r requirements/functests.txt # -r requirements/tests.txt -pylint==2.17.1 +pylint==3.1.0 # via -r requirements/lint.in -pyparsing==3.0.9 +pyparsing==3.1.2 # via # -r requirements/functests.txt # -r requirements/tests.txt -pyramid==2.0 +pyproject-hooks==1.0.0 + # via + # -r requirements/functests.txt + # -r requirements/tests.txt + # build + # pip-tools +pyramid==2.0.2 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -348,7 +363,7 @@ pyramid-exclog==1.1 # via # -r requirements/functests.txt # -r requirements/tests.txt -pyramid-jinja2==2.10 +pyramid-jinja2==2.10.1 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -372,34 +387,46 @@ pyramid-tm==2.5 # via # -r requirements/functests.txt # -r requirements/tests.txt -pyrsistent==0.17.3 - # via - # -r requirements/functests.txt - # -r requirements/tests.txt - # jsonschema -pytest==7.2.2 +pytest==8.2.1 # via # -r requirements/functests.txt # -r requirements/tests.txt + # pytest-cov + # pytest-mock # pytest-reverse -pytest-reverse==1.5.0 + # pytest-xdist +pytest-cov==5.0.0 + # via -r requirements/tests.txt +pytest-mock==3.14.0 + # via -r requirements/tests.txt +pytest-reverse==1.7.0 # via -r requirements/functests.txt -python-dateutil==2.8.2 +pytest-xdist[psutil]==3.6.1 + # via -r requirements/tests.txt +python-dateutil==2.9.0.post0 # via # -r requirements/functests.txt # -r requirements/tests.txt + # celery # elasticsearch-dsl # faker -python-slugify==8.0.1 + # freezegun +python-slugify==8.0.4 # via # -r requirements/functests.txt # -r requirements/tests.txt -pytz==2021.3 +pytz==2024.1 # via # -r requirements/functests.txt # -r requirements/tests.txt - # celery -repoze-sendmail==4.3 +referencing==0.32.1 + # via + # -r requirements/functests.txt + # -r requirements/tests.txt + # h-api + # jsonschema + # jsonschema-specifications +repoze-sendmail==4.4.1 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -408,39 +435,43 @@ rfc3339-validator==0.1.4 # via # -r requirements/functests.txt # -r requirements/tests.txt -sentry-sdk==0.17.6 +rpds-py==0.16.2 + # via + # -r requirements/functests.txt + # -r requirements/tests.txt + # jsonschema + # referencing +sentry-sdk==2.3.1 # via # -r requirements/functests.txt # -r requirements/tests.txt # h-pyramid-sentry -six==1.15.0 +six==1.16.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # bleach - # click-repl # elasticsearch-dsl - # jsonschema # python-dateutil # rfc3339-validator snowballstemmer==2.2.0 # via pydocstyle -sortedcontainers==2.3.0 +sortedcontainers==2.4.0 # via # -r requirements/tests.txt # hypothesis -soupsieve==2.2.1 +soupsieve==2.5 # via # -r requirements/functests.txt # beautifulsoup4 -sqlalchemy==1.4.47 +sqlalchemy==2.0.25 # via # -r requirements/functests.txt # -r requirements/tests.txt # alembic # data-tasks # zope-sqlalchemy -sqlparse==0.4.3 +sqlparse==0.5.0 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -459,17 +490,9 @@ text-unidecode==1.3 # -r requirements/functests.txt # -r requirements/tests.txt # python-slugify -tomli==2.0.0 - # via - # -r requirements/functests.txt - # -r requirements/tests.txt - # build - # pep517 - # pylint - # pytest -tomlkit==0.11.0 +tomlkit==0.12.3 # via pylint -transaction==3.1.0 +transaction==4.0 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -484,25 +507,29 @@ translationstring==1.4 # colander # deform # pyramid -typing-extensions==4.5.0 +typing-extensions==4.9.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # alembic - # astroid - # pylint -urllib3==1.26.5 + # sqlalchemy +tzdata==2023.4 + # via + # -r requirements/functests.txt + # -r requirements/tests.txt + # celery +urllib3==2.1.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # elasticsearch # sentry-sdk -venusian==3.0.0 +venusian==3.1.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # pyramid -vine==5.0.0 +vine==5.1.0 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -513,7 +540,7 @@ waitress==2.1.2 # via # -r requirements/functests.txt # webtest -wcwidth==0.2.5 +wcwidth==0.2.13 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -531,45 +558,42 @@ webob==1.8.7 # webtest webtest==3.0.0 # via -r requirements/functests.txt -wheel==0.38.1 +wheel==0.42.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # pip-tools -wired==0.2.2 +wired==0.3 # via # -r requirements/functests.txt # -r requirements/tests.txt # pyramid-services -wrapt==1.12.1 - # via astroid ws4py==0.5.1 # via # -r requirements/functests.txt # -r requirements/tests.txt -wsaccel==0.6.4 +wsaccel==0.6.6 # via # -r requirements/functests.txt # -r requirements/tests.txt -zipp==3.4.1 +zipp==3.17.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # importlib-metadata - # importlib-resources -zope-deprecation==4.1.2 +zope-deprecation==5.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # deform # pyramid # pyramid-jinja2 -zope-event==4.4 +zope-event==5.0 # via # -r requirements/functests.txt # -r requirements/tests.txt # gevent -zope-interface==6.0 +zope-interface==6.4.post2 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -581,7 +605,7 @@ zope-interface==6.0 # transaction # wired # zope-sqlalchemy -zope-sqlalchemy==2.0 +zope-sqlalchemy==3.1 # via # -r requirements/functests.txt # -r requirements/tests.txt diff --git a/requirements/requirements.in b/requirements/prod.in similarity index 94% rename from requirements/requirements.in rename to requirements/prod.in index 43e4e60747d..d0eaf8fdc08 100644 --- a/requirements/requirements.in +++ b/requirements/prod.in @@ -1,4 +1,5 @@ # Hypothesis packages +sentry-sdk h-pyramid-sentry h-matchers h-api @@ -8,7 +9,7 @@ pyramid-sanity # 3rd-party packages PyJWT -SQLAlchemy >= 1.1.4 +SQLAlchemy alembic bcrypt bleach @@ -36,6 +37,8 @@ pycryptodomex pyparsing >= 2.1.5 pyramid pyramid-exclog +markupsafe +jinja2 pyramid-jinja2 pyramid-services pyramid-mailer @@ -43,6 +46,7 @@ pyramid-retry pyramid-tm python-dateutil python-slugify < 8.1.0 +pytz rfc3339-validator # Required for date-time format checking in jsonschema supervisor >= 4.0.0 sqlparse diff --git a/requirements/prod.txt b/requirements/prod.txt new file mode 100644 index 00000000000..fa045e9b761 --- /dev/null +++ b/requirements/prod.txt @@ -0,0 +1,295 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile requirements/prod.in +# +alembic==1.13.1 + # via -r requirements/prod.in +amqp==5.2.0 + # via kombu +attrs==23.2.0 + # via + # jsonschema + # referencing +bcrypt==4.1.3 + # via -r requirements/prod.in +billiard==4.2.0 + # via celery +bleach==6.1.0 + # via -r requirements/prod.in +celery==5.4.0 + # via -r requirements/prod.in +certifi==2024.2.2 + # via + # -r requirements/prod.in + # sentry-sdk +cffi==1.16.0 + # via -r requirements/prod.in +chameleon==4.4.3 + # via deform +click==8.1.7 + # via + # -r requirements/prod.in + # celery + # click-didyoumean + # click-plugins + # click-repl +click-didyoumean==0.3.0 + # via celery +click-plugins==1.1.1 + # via celery +click-repl==0.3.0 + # via celery +colander==2.0 + # via deform +data-tasks==0.0.3 + # via -r requirements/prod.in +deform==2.0.15 + # via -r requirements/prod.in +elasticsearch==6.8.2 + # via + # -r requirements/prod.in + # elasticsearch-dsl +elasticsearch-dsl==6.4.0 + # via -r requirements/prod.in +gevent==24.2.1 + # via -r requirements/prod.in +greenlet==3.0.3 + # via + # gevent + # sqlalchemy +gunicorn==22.0.0 + # via -r requirements/prod.in +h-api==1.1.0 + # via -r requirements/prod.in +h-assets==1.0.6 + # via -r requirements/prod.in +h-matchers==1.2.15 + # via -r requirements/prod.in +h-pyramid-sentry==1.2.4 + # via -r requirements/prod.in +hupper==1.12 + # via pyramid +importlib-metadata==7.0.1 + # via + # data-tasks + # h-api + # h-assets +importlib-resources==6.4.0 + # via + # -r requirements/prod.in + # data-tasks + # h-api +iso8601==2.1.0 + # via + # colander + # deform +itsdangerous==2.2.0 + # via -r requirements/prod.in +jinja2==3.1.4 + # via + # -r requirements/prod.in + # data-tasks + # pyramid-jinja2 +jsonschema==4.22.0 + # via + # -r requirements/prod.in + # h-api +jsonschema-specifications==2023.12.1 + # via jsonschema +kombu==5.3.7 + # via + # -r requirements/prod.in + # celery +mako==1.3.0 + # via alembic +markdown==3.6 + # via -r requirements/prod.in +markupsafe==2.1.5 + # via + # -r requirements/prod.in + # jinja2 + # mako + # pyramid-jinja2 +newrelic==9.8.0 + # via -r requirements/prod.in +oauthlib==3.2.2 + # via -r requirements/prod.in +packaging==24.0 + # via + # -r requirements/prod.in + # gunicorn + # zope-sqlalchemy +passlib==1.7.4 + # via -r requirements/prod.in +pastedeploy==3.1.0 + # via plaster-pastedeploy +peppercorn==0.6 + # via deform +plaster==1.1.2 + # via + # plaster-pastedeploy + # pyramid +plaster-pastedeploy==1.0.1 + # via pyramid +prompt-toolkit==3.0.43 + # via click-repl +psycogreen==1.0.2 + # via -r requirements/prod.in +psycopg2==2.9.9 + # via + # -r requirements/prod.in + # data-tasks +pycparser==2.21 + # via cffi +pycryptodomex==3.20.0 + # via -r requirements/prod.in +pyjwt==2.8.0 + # via -r requirements/prod.in +pyparsing==3.1.2 + # via -r requirements/prod.in +pyramid==2.0.2 + # via + # -r requirements/prod.in + # h-assets + # h-pyramid-sentry + # pyramid-exclog + # pyramid-jinja2 + # pyramid-mailer + # pyramid-retry + # pyramid-sanity + # pyramid-services + # pyramid-tm +pyramid-exclog==1.1 + # via -r requirements/prod.in +pyramid-jinja2==2.10.1 + # via -r requirements/prod.in +pyramid-mailer==0.15.1 + # via -r requirements/prod.in +pyramid-retry==2.1.1 + # via -r requirements/prod.in +pyramid-sanity==1.0.3 + # via -r requirements/prod.in +pyramid-services==2.2 + # via -r requirements/prod.in +pyramid-tm==2.5 + # via -r requirements/prod.in +python-dateutil==2.9.0.post0 + # via + # -r requirements/prod.in + # celery + # elasticsearch-dsl +python-slugify==8.0.4 + # via -r requirements/prod.in +pytz==2024.1 + # via -r requirements/prod.in +referencing==0.32.1 + # via + # h-api + # jsonschema + # jsonschema-specifications +repoze-sendmail==4.4.1 + # via pyramid-mailer +rfc3339-validator==0.1.4 + # via -r requirements/prod.in +rpds-py==0.16.2 + # via + # jsonschema + # referencing +sentry-sdk==2.3.1 + # via + # -r requirements/prod.in + # h-pyramid-sentry +six==1.16.0 + # via + # bleach + # elasticsearch-dsl + # python-dateutil + # rfc3339-validator +sqlalchemy==2.0.25 + # via + # -r requirements/prod.in + # alembic + # data-tasks + # zope-sqlalchemy +sqlparse==0.5.0 + # via + # -r requirements/prod.in + # data-tasks +supervisor==4.2.5 + # via -r requirements/prod.in +tabulate==0.9.0 + # via + # -r requirements/prod.in + # data-tasks +text-unidecode==1.3 + # via python-slugify +transaction==4.0 + # via + # -r requirements/prod.in + # pyramid-mailer + # pyramid-tm + # repoze-sendmail + # zope-sqlalchemy +translationstring==1.4 + # via + # colander + # deform + # pyramid +typing-extensions==4.9.0 + # via + # alembic + # sqlalchemy +tzdata==2023.4 + # via celery +urllib3==2.1.0 + # via + # elasticsearch + # sentry-sdk +venusian==3.1.0 + # via + # -r requirements/prod.in + # pyramid +vine==5.1.0 + # via + # amqp + # celery + # kombu +wcwidth==0.2.13 + # via prompt-toolkit +webencodings==0.5.1 + # via bleach +webob==1.8.7 + # via pyramid +wired==0.3 + # via pyramid-services +ws4py==0.5.1 + # via -r requirements/prod.in +wsaccel==0.6.6 + # via -r requirements/prod.in +zipp==3.17.0 + # via importlib-metadata +zope-deprecation==5.0 + # via + # deform + # pyramid + # pyramid-jinja2 +zope-event==5.0 + # via gevent +zope-interface==6.4.post2 + # via + # -r requirements/prod.in + # gevent + # pyramid + # pyramid-retry + # pyramid-services + # repoze-sendmail + # transaction + # wired + # zope-sqlalchemy +zope-sqlalchemy==3.1 + # via -r requirements/prod.in + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/requirements/requirements.txt b/requirements/requirements.txt deleted file mode 100644 index 8cda2e4779c..00000000000 --- a/requirements/requirements.txt +++ /dev/null @@ -1,277 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# pip-compile requirements/requirements.in -# -alembic==1.10.2 - # via -r requirements/requirements.in -amqp==5.0.9 - # via kombu -attrs==20.2.0 - # via jsonschema -bcrypt==4.0.1 - # via -r requirements/requirements.in -billiard==3.6.4.0 - # via celery -bleach==6.0.0 - # via -r requirements/requirements.in -celery==5.2.7 - # via -r requirements/requirements.in -certifi==2022.12.7 - # via - # -r requirements/requirements.in - # sentry-sdk -cffi==1.15.1 - # via -r requirements/requirements.in -chameleon==3.8.1 - # via deform -click==8.1.3 - # via - # -r requirements/requirements.in - # celery - # click-didyoumean - # click-plugins - # click-repl -click-didyoumean==0.0.3 - # via celery -click-plugins==1.1.1 - # via celery -click-repl==0.2.0 - # via celery -colander==1.8.2 - # via deform -data-tasks==0.0.3 - # via -r requirements/requirements.in -deform==2.0.15 - # via -r requirements/requirements.in -elasticsearch==6.8.2 - # via - # -r requirements/requirements.in - # elasticsearch-dsl -elasticsearch-dsl==6.4.0 - # via -r requirements/requirements.in -gevent==22.10.2 - # via -r requirements/requirements.in -greenlet==2.0.2 - # via - # gevent - # sqlalchemy -gunicorn==20.1.0 - # via -r requirements/requirements.in -h-api==1.0.2 - # via -r requirements/requirements.in -h-assets==1.0.5 - # via -r requirements/requirements.in -h-matchers==1.2.15 - # via -r requirements/requirements.in -h-pyramid-sentry==1.2.4 - # via -r requirements/requirements.in -hupper==1.10.2 - # via pyramid -importlib-metadata==4.8.1 - # via - # alembic - # data-tasks - # markdown -importlib-resources==5.12.0 - # via - # -r requirements/requirements.in - # alembic - # data-tasks - # h-api -iso8601==0.1.13 - # via - # colander - # deform -itsdangerous==2.1.2 - # via -r requirements/requirements.in -jinja2==2.11.3 - # via - # data-tasks - # pyramid-jinja2 -jsonschema==3.2.0 - # via - # -r requirements/requirements.in - # h-api -kombu==5.2.4 - # via - # -r requirements/requirements.in - # celery -mako==1.2.2 - # via alembic -markdown==3.4.2 - # via -r requirements/requirements.in -markupsafe==1.1.1 - # via - # jinja2 - # mako - # pyramid-jinja2 -newrelic==8.7.1 - # via -r requirements/requirements.in -oauthlib==3.2.2 - # via -r requirements/requirements.in -packaging==23.0 - # via -r requirements/requirements.in -passlib==1.7.4 - # via -r requirements/requirements.in -pastedeploy==2.1.0 - # via plaster-pastedeploy -peppercorn==0.6 - # via deform -plaster==1.0 - # via - # plaster-pastedeploy - # pyramid -plaster-pastedeploy==0.7 - # via pyramid -prompt-toolkit==3.0.18 - # via click-repl -psycogreen==1.0.2 - # via -r requirements/requirements.in -psycopg2==2.9.5 - # via - # -r requirements/requirements.in - # data-tasks -pycparser==2.20 - # via cffi -pycryptodomex==3.17 - # via -r requirements/requirements.in -pyjwt==2.6.0 - # via -r requirements/requirements.in -pyparsing==3.0.9 - # via -r requirements/requirements.in -pyramid==2.0 - # via - # -r requirements/requirements.in - # h-assets - # h-pyramid-sentry - # pyramid-exclog - # pyramid-jinja2 - # pyramid-mailer - # pyramid-retry - # pyramid-sanity - # pyramid-services - # pyramid-tm -pyramid-exclog==1.1 - # via -r requirements/requirements.in -pyramid-jinja2==2.10 - # via -r requirements/requirements.in -pyramid-mailer==0.15.1 - # via -r requirements/requirements.in -pyramid-retry==2.1.1 - # via -r requirements/requirements.in -pyramid-sanity==1.0.3 - # via -r requirements/requirements.in -pyramid-services==2.2 - # via -r requirements/requirements.in -pyramid-tm==2.5 - # via -r requirements/requirements.in -pyrsistent==0.17.3 - # via jsonschema -python-dateutil==2.8.2 - # via - # -r requirements/requirements.in - # elasticsearch-dsl -python-slugify==8.0.1 - # via -r requirements/requirements.in -pytz==2021.3 - # via celery -repoze-sendmail==4.3 - # via pyramid-mailer -rfc3339-validator==0.1.4 - # via -r requirements/requirements.in -sentry-sdk==0.17.6 - # via h-pyramid-sentry -six==1.15.0 - # via - # bleach - # click-repl - # elasticsearch-dsl - # jsonschema - # python-dateutil - # rfc3339-validator -sqlalchemy==1.4.47 - # via - # -r requirements/requirements.in - # alembic - # data-tasks - # zope-sqlalchemy -sqlparse==0.4.3 - # via - # -r requirements/requirements.in - # data-tasks -supervisor==4.2.5 - # via -r requirements/requirements.in -tabulate==0.9.0 - # via - # -r requirements/requirements.in - # data-tasks -text-unidecode==1.3 - # via python-slugify -transaction==3.1.0 - # via - # -r requirements/requirements.in - # pyramid-mailer - # pyramid-tm - # repoze-sendmail - # zope-sqlalchemy -translationstring==1.4 - # via - # colander - # deform - # pyramid -typing-extensions==4.5.0 - # via alembic -urllib3==1.26.5 - # via - # elasticsearch - # sentry-sdk -venusian==3.0.0 - # via - # -r requirements/requirements.in - # pyramid -vine==5.0.0 - # via - # amqp - # celery - # kombu -wcwidth==0.2.5 - # via prompt-toolkit -webencodings==0.5.1 - # via bleach -webob==1.8.7 - # via pyramid -wired==0.2.2 - # via pyramid-services -ws4py==0.5.1 - # via -r requirements/requirements.in -wsaccel==0.6.4 - # via -r requirements/requirements.in -zipp==3.4.1 - # via - # importlib-metadata - # importlib-resources -zope-deprecation==4.1.2 - # via - # deform - # pyramid - # pyramid-jinja2 -zope-event==4.4 - # via gevent -zope-interface==6.0 - # via - # -r requirements/requirements.in - # gevent - # pyramid - # pyramid-retry - # pyramid-services - # repoze-sendmail - # transaction - # wired - # zope-sqlalchemy -zope-sqlalchemy==2.0 - # via -r requirements/requirements.in - -# The following packages are considered to be unsafe in a requirements file: -# setuptools diff --git a/requirements/tests.in b/requirements/tests.in index 2564b41629c..3606a26161e 100644 --- a/requirements/tests.in +++ b/requirements/tests.in @@ -2,6 +2,11 @@ pip-tools pip-sync-faster coverage pytest +pytest-cov +pytest-xdist[psutil] +pytest-mock +freezegun factory-boy hypothesis --r requirements.txt +h-testkit +-r prod.txt diff --git a/requirements/tests.txt b/requirements/tests.txt index f382a866fc4..afbbae6946a 100644 --- a/requirements/tests.txt +++ b/requirements/tests.txt @@ -1,218 +1,231 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/tests.in # -alembic==1.10.2 - # via -r requirements/requirements.txt -amqp==5.0.9 +alembic==1.13.1 + # via -r requirements/prod.txt +amqp==5.2.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # kombu -attrs==20.2.0 +attrs==23.2.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # hypothesis # jsonschema - # pytest -bcrypt==4.0.1 - # via -r requirements/requirements.txt -billiard==3.6.4.0 + # referencing +bcrypt==4.1.3 + # via -r requirements/prod.txt +billiard==4.2.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery -bleach==6.0.0 - # via -r requirements/requirements.txt -build==0.8.0 +bleach==6.1.0 + # via -r requirements/prod.txt +build==1.0.3 # via pip-tools -celery==5.2.7 - # via -r requirements/requirements.txt -certifi==2022.12.7 +celery==5.4.0 + # via -r requirements/prod.txt +certifi==2024.2.2 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # sentry-sdk -cffi==1.15.1 - # via -r requirements/requirements.txt -chameleon==3.8.1 +cffi==1.16.0 + # via -r requirements/prod.txt +chameleon==4.4.3 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # deform -click==8.1.3 +click==8.1.7 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery # click-didyoumean # click-plugins # click-repl # pip-tools -click-didyoumean==0.0.3 +click-didyoumean==0.3.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery click-plugins==1.1.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery -click-repl==0.2.0 +click-repl==0.3.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery -colander==1.8.2 +colander==2.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # deform -coverage==7.2.2 - # via -r requirements/tests.in +coverage[toml]==7.5.2 + # via + # -r requirements/tests.in + # pytest-cov data-tasks==0.0.3 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt deform==2.0.15 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt elasticsearch==6.8.2 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # elasticsearch-dsl elasticsearch-dsl==6.4.0 - # via -r requirements/requirements.txt -exceptiongroup==1.1.0 - # via - # hypothesis - # pytest -factory-boy==3.2.1 + # via -r requirements/prod.txt +execnet==2.1.1 + # via pytest-xdist +factory-boy==3.3.0 # via -r requirements/tests.in -faker==17.4.0 +faker==22.2.0 # via factory-boy -gevent==22.10.2 - # via -r requirements/requirements.txt -greenlet==2.0.2 +freezegun==1.5.1 + # via -r requirements/tests.in +gevent==24.2.1 + # via -r requirements/prod.txt +greenlet==3.0.3 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # gevent # sqlalchemy -gunicorn==20.1.0 - # via -r requirements/requirements.txt -h-api==1.0.2 - # via -r requirements/requirements.txt -h-assets==1.0.5 - # via -r requirements/requirements.txt +gunicorn==22.0.0 + # via -r requirements/prod.txt +h-api==1.1.0 + # via -r requirements/prod.txt +h-assets==1.0.6 + # via -r requirements/prod.txt h-matchers==1.2.15 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt h-pyramid-sentry==1.2.4 - # via -r requirements/requirements.txt -hupper==1.10.2 + # via -r requirements/prod.txt +h-testkit==1.0.1 + # via -r requirements/tests.in +hupper==1.12 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid -hypothesis==6.70.0 +hypothesis==6.102.6 # via -r requirements/tests.in -importlib-metadata==4.8.1 +importlib-metadata==7.0.1 # via - # -r requirements/requirements.txt - # alembic + # -r requirements/prod.txt # data-tasks - # markdown + # h-api + # h-assets # pip-sync-faster -importlib-resources==5.12.0 +importlib-resources==6.4.0 # via - # -r requirements/requirements.txt - # alembic + # -r requirements/prod.txt # data-tasks # h-api -iniconfig==1.1.1 +iniconfig==2.0.0 # via pytest -iso8601==0.1.13 +iso8601==2.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # colander # deform -itsdangerous==2.1.2 - # via -r requirements/requirements.txt -jinja2==2.11.3 +itsdangerous==2.2.0 + # via -r requirements/prod.txt +jinja2==3.1.4 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # data-tasks # pyramid-jinja2 -jsonschema==3.2.0 +jsonschema==4.22.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # h-api -kombu==5.2.4 +jsonschema-specifications==2023.12.1 + # via + # -r requirements/prod.txt + # jsonschema +kombu==5.3.7 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # celery -mako==1.2.2 +mako==1.3.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # alembic -markdown==3.4.2 - # via -r requirements/requirements.txt -markupsafe==1.1.1 +markdown==3.6 + # via -r requirements/prod.txt +markupsafe==2.1.5 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # jinja2 # mako # pyramid-jinja2 -newrelic==8.7.1 - # via -r requirements/requirements.txt +newrelic==9.8.0 + # via -r requirements/prod.txt oauthlib==3.2.2 - # via -r requirements/requirements.txt -packaging==23.0 + # via -r requirements/prod.txt +packaging==24.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # build + # gunicorn # pytest + # zope-sqlalchemy passlib==1.7.4 - # via -r requirements/requirements.txt -pastedeploy==2.1.0 + # via -r requirements/prod.txt +pastedeploy==3.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # plaster-pastedeploy -pep517==0.13.0 - # via build peppercorn==0.6 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # deform pip-sync-faster==0.0.3 # via -r requirements/tests.in -pip-tools==6.12.3 +pip-tools==7.4.1 # via # -r requirements/tests.in # pip-sync-faster -plaster==1.0 +plaster==1.1.2 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # plaster-pastedeploy # pyramid -plaster-pastedeploy==0.7 +plaster-pastedeploy==1.0.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid -pluggy==0.13.1 +pluggy==1.5.0 # via pytest -prompt-toolkit==3.0.18 +prompt-toolkit==3.0.43 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # click-repl +psutil==5.9.7 + # via pytest-xdist psycogreen==1.0.2 - # via -r requirements/requirements.txt -psycopg2==2.9.5 + # via -r requirements/prod.txt +psycopg2==2.9.9 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # data-tasks -pycparser==2.20 +pycparser==2.21 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # cffi -pycryptodomex==3.17 - # via -r requirements/requirements.txt -pyjwt==2.6.0 - # via -r requirements/requirements.txt -pyparsing==3.0.9 - # via -r requirements/requirements.txt -pyramid==2.0 - # via - # -r requirements/requirements.txt +pycryptodomex==3.20.0 + # via -r requirements/prod.txt +pyjwt==2.8.0 + # via -r requirements/prod.txt +pyparsing==3.1.2 + # via -r requirements/prod.txt +pyproject-hooks==1.0.0 + # via + # build + # pip-tools +pyramid==2.0.2 + # via + # -r requirements/prod.txt # h-assets # h-pyramid-sentry # pyramid-exclog @@ -223,154 +236,168 @@ pyramid==2.0 # pyramid-services # pyramid-tm pyramid-exclog==1.1 - # via -r requirements/requirements.txt -pyramid-jinja2==2.10 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt +pyramid-jinja2==2.10.1 + # via -r requirements/prod.txt pyramid-mailer==0.15.1 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt pyramid-retry==2.1.1 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt pyramid-sanity==1.0.3 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt pyramid-services==2.2 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt pyramid-tm==2.5 - # via -r requirements/requirements.txt -pyrsistent==0.17.3 + # via -r requirements/prod.txt +pytest==8.2.1 # via - # -r requirements/requirements.txt - # jsonschema -pytest==7.2.2 + # -r requirements/tests.in + # pytest-cov + # pytest-mock + # pytest-xdist +pytest-cov==5.0.0 + # via -r requirements/tests.in +pytest-mock==3.14.0 # via -r requirements/tests.in -python-dateutil==2.8.2 +pytest-xdist[psutil]==3.6.1 + # via -r requirements/tests.in +python-dateutil==2.9.0.post0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt + # celery # elasticsearch-dsl # faker -python-slugify==8.0.1 - # via -r requirements/requirements.txt -pytz==2021.3 - # via - # -r requirements/requirements.txt - # celery -repoze-sendmail==4.3 + # freezegun +python-slugify==8.0.4 + # via -r requirements/prod.txt +pytz==2024.1 + # via -r requirements/prod.txt +referencing==0.32.1 + # via + # -r requirements/prod.txt + # h-api + # jsonschema + # jsonschema-specifications +repoze-sendmail==4.4.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid-mailer rfc3339-validator==0.1.4 - # via -r requirements/requirements.txt -sentry-sdk==0.17.6 + # via -r requirements/prod.txt +rpds-py==0.16.2 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt + # jsonschema + # referencing +sentry-sdk==2.3.1 + # via + # -r requirements/prod.txt # h-pyramid-sentry -six==1.15.0 +six==1.16.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # bleach - # click-repl # elasticsearch-dsl - # jsonschema # python-dateutil # rfc3339-validator -sortedcontainers==2.3.0 +sortedcontainers==2.4.0 # via hypothesis -sqlalchemy==1.4.47 +sqlalchemy==2.0.25 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # alembic # data-tasks # zope-sqlalchemy -sqlparse==0.4.3 +sqlparse==0.5.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # data-tasks supervisor==4.2.5 - # via -r requirements/requirements.txt + # via -r requirements/prod.txt tabulate==0.9.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # data-tasks text-unidecode==1.3 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # python-slugify -tomli==2.0.0 +transaction==4.0 # via - # build - # pep517 - # pytest -transaction==3.1.0 - # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid-mailer # pyramid-tm # repoze-sendmail # zope-sqlalchemy translationstring==1.4 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # colander # deform # pyramid -typing-extensions==4.5.0 +typing-extensions==4.9.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # alembic -urllib3==1.26.5 + # sqlalchemy +tzdata==2023.4 + # via + # -r requirements/prod.txt + # celery +urllib3==2.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # elasticsearch # sentry-sdk -venusian==3.0.0 +venusian==3.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid -vine==5.0.0 +vine==5.1.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # amqp # celery # kombu -wcwidth==0.2.5 +wcwidth==0.2.13 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # prompt-toolkit webencodings==0.5.1 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # bleach webob==1.8.7 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid -wheel==0.38.1 +wheel==0.42.0 # via pip-tools -wired==0.2.2 +wired==0.3 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # pyramid-services ws4py==0.5.1 - # via -r requirements/requirements.txt -wsaccel==0.6.4 - # via -r requirements/requirements.txt -zipp==3.4.1 + # via -r requirements/prod.txt +wsaccel==0.6.6 + # via -r requirements/prod.txt +zipp==3.17.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # importlib-metadata - # importlib-resources -zope-deprecation==4.1.2 +zope-deprecation==5.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # deform # pyramid # pyramid-jinja2 -zope-event==4.4 +zope-event==5.0 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # gevent -zope-interface==6.0 +zope-interface==6.4.post2 # via - # -r requirements/requirements.txt + # -r requirements/prod.txt # gevent # pyramid # pyramid-retry @@ -379,8 +406,8 @@ zope-interface==6.0 # transaction # wired # zope-sqlalchemy -zope-sqlalchemy==2.0 - # via -r requirements/requirements.txt +zope-sqlalchemy==3.1 + # via -r requirements/prod.txt # The following packages are considered to be unsafe in a requirements file: # pip diff --git a/rollup-tests.config.mjs b/rollup-tests.config.js similarity index 100% rename from rollup-tests.config.mjs rename to rollup-tests.config.js diff --git a/rollup.config.mjs b/rollup.config.js similarity index 96% rename from rollup.config.mjs rename to rollup.config.js index a4c4b3620fa..45117d2fb66 100644 --- a/rollup.config.mjs +++ b/rollup.config.js @@ -1,7 +1,7 @@ import { babel } from '@rollup/plugin-babel'; import commonjs from '@rollup/plugin-commonjs'; import { nodeResolve } from '@rollup/plugin-node-resolve'; -import { terser } from 'rollup-plugin-terser'; +import terser from '@rollup/plugin-terser'; const isProd = process.env.NODE_ENV === 'production'; const prodPlugins = []; diff --git a/setup.cfg b/setup.cfg index f401f1cb628..29bb44c20a5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -4,10 +4,10 @@ max-line-length = 160 ignore = \ # Rules that flake8 ignores by default (we have to put these in our `ignore` # setting otherwise they would be un-ignored). - E121,E123,E126,E226,E24,E704,W503 \ + E121,E123,E126,E226,E24,E704,W503, # "whitespace before ':'" conflicts with the Black code formatter. - E203 + E203, [pycodestyle] ignore = @@ -18,8 +18,9 @@ ignore = E501, # Line too long, W503, # Line break before binary operator, - # Bare except. PyLint finds these for us so we don't need pycodestyle to. - E722, + # Rules already checked by pylint + E711,E712, E722, + [pydocstyle] ignore = diff --git a/tests/.pylintrc b/tests/.pylintrc deleted file mode 100644 index 0b6cf90a65a..00000000000 --- a/tests/.pylintrc +++ /dev/null @@ -1,104 +0,0 @@ -[MASTER] -# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the -# number of processors available to use. -jobs=0 - -load-plugins=pylint.extensions.bad_builtin, - pylint.extensions.check_elif, - pylint.extensions.comparetozero, - pylint.extensions.docparams, - pylint.extensions.emptystring, - pylint.extensions.overlapping_exceptions, - pylint.extensions.redefined_variable_type, - -# Fail if there are *any* messages from PyLint. -# The letters refer to PyLint's message categories, see -# https://pylint.pycqa.org/en/latest/messages/messages_introduction.html -fail-on=C,E,F,I,R,W - -[MESSAGES CONTROL] -enable= - bad-inline-option, - deprecated-pragma, - useless-suppression, - use-symbolic-message-instead, -disable= - # Docstrings are encouraged but we don't want to enforce that everything - # must have a docstring. - missing-docstring, - - # We don't always want to have to put a `:return:` in a docstring. - missing-return-doc, - # We don't always want to have to put an `:rtype:` in a docstring. - missing-return-type-doc, - - # We don't want to have to document the type of every parameter with a - # `:type:` in the docstring. - missing-type-doc, - - # We use isort to sort and group our imports, so we don't need PyLint to - # check them for us. - ungrouped-imports, - - # We use Black to format our code automatically, so we don't need PyLint to - # check formatting for us. - line-too-long, - - # Because of how pytest fixtures work it's frequently necessary for - # parameters to redefine outer names. - redefined-outer-name, - - # Lots of test methods don't use self, but we still want to group our tests - # into classes. - too-few-public-methods, - too-many-public-methods, - - too-many-arguments, - - # not-callable is mis-firing on all pytest.mark.parametrize usages, so - # disable it for now. This can be re-enabled once a new pytest version - # including https://github.com/pytest-dev/pytest/pull/7565 has been - # released. - not-callable, - - # Issues to disable this for false positives, disabling it globally in the meantime https://github.com/PyCQA/pylint/issues/214 - duplicate-code, - - # Ignored during pep8 -> pylint transition - fixme, - no-member, # Intermittent failures with the same input - - # Ignored until https://github.com/PyCQA/pylint/issues/3804 is closed - comparison-with-callable, - -# Just disable PyLint's name style checking for the tests, because we -# frequently use lots of argument names that don't conform. -# For example we frequently create pytest fixtures that aren't named in -# snake_case, such as a fixture that returns a mock of the FooBar class would -# be named FooBar in CamelCase. -argument-naming-style=any -class-naming-style=any -function-naming-style=any -method-naming-style=any -variable-naming-style=any - -good-names= - # PyLint's default good names. - i,j,k,ex,Run,_, - - # The standard name used for the pyramid_tm transaction manager. - tm, - - # request.db. - db, - - pytestmark, - - # Name used for mocks of the standard os module. - os, - -[REPORTS] -output-format=colorized -# Deactivate the evaluation score: we don't care about it, we just enforce that -# there are zero PyLint messages. -score=no diff --git a/tests/common/factories/__init__.py b/tests/common/factories/__init__.py index 53b5beb4a20..75c5fd62995 100644 --- a/tests/common/factories/__init__.py +++ b/tests/common/factories/__init__.py @@ -2,20 +2,24 @@ from tests.common.factories.activation import Activation from tests.common.factories.annotation import Annotation +from tests.common.factories.annotation_metadata import AnnotationMetadata from tests.common.factories.annotation_moderation import AnnotationModeration +from tests.common.factories.annotation_slim import AnnotationSlim from tests.common.factories.auth_client import AuthClient, ConfidentialAuthClient from tests.common.factories.auth_ticket import AuthTicket from tests.common.factories.authz_code import AuthzCode from tests.common.factories.base import set_session from tests.common.factories.document import Document, DocumentMeta, DocumentURI from tests.common.factories.feature import Feature +from tests.common.factories.feature_cohort import FeatureCohort from tests.common.factories.flag import Flag from tests.common.factories.group import Group, OpenGroup, RestrictedGroup from tests.common.factories.group_scope import GroupScope -from tests.common.factories.job import Job, SyncAnnotationJob +from tests.common.factories.job import ExpungeUserJob, Job, SyncAnnotationJob from tests.common.factories.organization import Organization from tests.common.factories.setting import Setting from tests.common.factories.subscriptions import Subscriptions from tests.common.factories.token import DeveloperToken, OAuth2Token from tests.common.factories.user import User +from tests.common.factories.user_deletion import UserDeletion from tests.common.factories.user_identity import UserIdentity diff --git a/tests/common/factories/annotation.py b/tests/common/factories/annotation.py index d6693fa0226..48cd3abf5c5 100644 --- a/tests/common/factories/annotation.py +++ b/tests/common/factories/annotation.py @@ -130,7 +130,7 @@ def make_id(self, create, extracted, **kwargs): # pylint:disable=unused-argumen return # Ids in the DB are in hex, but in the code they should be URL safe - self.id = URLSafeUUID().process_result_value( # pylint:disable=attribute-defined-outside-init,invalid-name + self.id = URLSafeUUID().process_result_value( # pylint:disable=attribute-defined-outside-init uuid.uuid4().hex, None ) diff --git a/tests/common/factories/annotation_metadata.py b/tests/common/factories/annotation_metadata.py new file mode 100644 index 00000000000..7ae184e2ea6 --- /dev/null +++ b/tests/common/factories/annotation_metadata.py @@ -0,0 +1,12 @@ +import factory + +from h import models +from tests.common.factories.annotation_slim import AnnotationSlim +from tests.common.factories.base import ModelFactory + + +class AnnotationMetadata(ModelFactory): + class Meta: + model = models.AnnotationMetadata + + annotation_slim = factory.SubFactory(AnnotationSlim) diff --git a/tests/common/factories/annotation_slim.py b/tests/common/factories/annotation_slim.py new file mode 100644 index 00000000000..830f2ad2b86 --- /dev/null +++ b/tests/common/factories/annotation_slim.py @@ -0,0 +1,19 @@ +import factory + +from h import models + +from .annotation import Annotation +from .base import ModelFactory +from .document import Document +from .group import Group +from .user import User + + +class AnnotationSlim(ModelFactory): + class Meta: + model = models.AnnotationSlim + + annotation = factory.SubFactory(Annotation) + user = factory.SubFactory(User) + group = factory.SubFactory(Group) + document = factory.SubFactory(Document) diff --git a/tests/common/factories/feature_cohort.py b/tests/common/factories/feature_cohort.py new file mode 100644 index 00000000000..df431aa33c9 --- /dev/null +++ b/tests/common/factories/feature_cohort.py @@ -0,0 +1,22 @@ +from factory import Sequence, post_generation + +from h import models + +from .base import ModelFactory + + +class FeatureCohort(ModelFactory): + class Meta: + model = models.FeatureCohort + + name = Sequence(lambda n: f"featurecohort_{n}") + + @post_generation + def members(self, _create, extracted, **_kwargs): + if extracted: + self.members.extend(extracted) + + @post_generation + def features(self, _create, extracted, **_kwargs): + if extracted: + self.features.extend(extracted) diff --git a/tests/common/factories/group.py b/tests/common/factories/group.py index 70489dd17d5..4d72a744955 100644 --- a/tests/common/factories/group.py +++ b/tests/common/factories/group.py @@ -20,7 +20,7 @@ class Meta: joinable_by = JoinableBy.authority readable_by = ReadableBy.members writeable_by = WriteableBy.members - members = factory.LazyAttribute(lambda obj: [obj.creator]) + members = factory.LazyFunction(list) authority_provided_id = Faker("hexify", text="^" * 30) enforce_scope = True @@ -33,6 +33,17 @@ def scopes( # pylint: disable=method-hidden,unused-argument self.scopes = scopes or [] + @factory.post_generation + def add_creator_as_member( # pylint:disable=no-self-argument + obj, _create, _extracted, **_kwargs + ): + if ( + obj.creator + and obj.creator + not in obj.members # pylint:disable=unsupported-membership-test + ): + obj.members.insert(0, obj.creator) # pylint:disable=no-member + class OpenGroup(Group): name = factory.Sequence(lambda n: f"Open Group {n}") @@ -42,6 +53,14 @@ class OpenGroup(Group): writeable_by = WriteableBy.authority members = [] + @factory.post_generation + def add_creator_as_member( # pylint:disable=no-self-argument + _obj, _create, _extracted, **_kwargs + ): + # Open groups don't have members, so don't add group.creator to + # group.members for open groups. + pass + class RestrictedGroup(Group): name = factory.Sequence(lambda n: f"Restricted Group {n}") diff --git a/tests/common/factories/job.py b/tests/common/factories/job.py index 3c07ee25539..a8c30e93693 100644 --- a/tests/common/factories/job.py +++ b/tests/common/factories/job.py @@ -7,6 +7,7 @@ from .annotation import Annotation from .base import ModelFactory +from .user import User class Job(ModelFactory): @@ -48,3 +49,13 @@ class Meta: "force": o.force, } ) + + +class ExpungeUserJob(Job): + class Meta: + exclude = "user" + + user = SubFactory(User) + + name = "expunge_user" + kwargs = LazyAttribute(lambda o: {"userid": o.user.userid}) diff --git a/tests/common/factories/token.py b/tests/common/factories/token.py index 02bfd314647..3238922b926 100644 --- a/tests/common/factories/token.py +++ b/tests/common/factories/token.py @@ -7,7 +7,8 @@ from h.services.oauth import ACCESS_TOKEN_PREFIX, REFRESH_TOKEN_PREFIX from .auth_client import AuthClient -from .base import FAKER, ModelFactory +from .base import ModelFactory +from .user import User class DeveloperToken(ModelFactory): @@ -15,11 +16,7 @@ class Meta: model = models.Token sqlalchemy_session_persistence = "flush" - userid = factory.LazyAttribute( - lambda _: ( - "acct:" + FAKER.user_name() + "@example.com" # pylint:disable=no-member - ) - ) + user = factory.SubFactory(User) value = factory.LazyAttribute( lambda _: (DEVELOPER_TOKEN_PREFIX + security.token_urlsafe()) ) @@ -30,11 +27,7 @@ class Meta: model = models.Token sqlalchemy_session_persistence = "flush" - userid = factory.LazyAttribute( - lambda _: ( - "acct:" + FAKER.user_name() + "@example.com" # pylint:disable=no-member - ) - ) + user = factory.SubFactory(User) value = factory.LazyAttribute( lambda _: (ACCESS_TOKEN_PREFIX + security.token_urlsafe()) ) diff --git a/tests/common/factories/user.py b/tests/common/factories/user.py index 3cd326b5e8a..8b503ad3729 100644 --- a/tests/common/factories/user.py +++ b/tests/common/factories/user.py @@ -50,3 +50,4 @@ class Params: email = factory.LazyAttribute(unique_email) display_name = factory.Faker("name") registered_date = factory.Faker("date_time_this_decade") + deleted = False diff --git a/tests/common/factories/user_deletion.py b/tests/common/factories/user_deletion.py new file mode 100644 index 00000000000..5afa267dfac --- /dev/null +++ b/tests/common/factories/user_deletion.py @@ -0,0 +1,19 @@ +from factory import Faker, LazyAttribute + +from h import models + +from .base import ModelFactory + + +class UserDeletion(ModelFactory): + class Meta: + model = models.UserDeletion + exclude = ("username", "requesting_username") + + username = Faker("user_name") + userid = LazyAttribute(lambda o: f"acct:{o.username}@example.com") + requesting_username = Faker("user_name") + requested_by = LazyAttribute(lambda o: f"acct:{o.requesting_username}@example.com") + tag = "factory" + registered_date = Faker("date_time") + num_annotations = Faker("random_int") diff --git a/tests/common/fixtures/elasticsearch.py b/tests/common/fixtures/elasticsearch.py index e24af8f9d84..57f3be7e08a 100644 --- a/tests/common/fixtures/elasticsearch.py +++ b/tests/common/fixtures/elasticsearch.py @@ -49,7 +49,7 @@ def mock_es_client(es_client): ) -@pytest.fixture(scope="session", autouse=True) +@pytest.fixture(scope="session") def init_elasticsearch(request): """ Initialize the elasticsearch cluster. diff --git a/tests/common/fixtures/services.py b/tests/common/fixtures/services.py index 2300e3109dc..6f180fbc9f3 100644 --- a/tests/common/fixtures/services.py +++ b/tests/common/fixtures/services.py @@ -2,29 +2,41 @@ import pytest -from h.services import BulkAnnotationService +from h.services.analytics import AnalyticsService from h.services.annotation_delete import AnnotationDeleteService from h.services.annotation_json import AnnotationJSONService +from h.services.annotation_metadata import AnnotationMetadataService from h.services.annotation_moderation import AnnotationModerationService +from h.services.annotation_read import AnnotationReadService +from h.services.annotation_sync import AnnotationSyncService +from h.services.annotation_write import AnnotationWriteService from h.services.auth_cookie import AuthCookieService from h.services.auth_token import AuthTokenService -from h.services.delete_group import DeleteGroupService +from h.services.bulk_api import ( + BulkAnnotationService, + BulkGroupService, + BulkLMSStatsService, +) +from h.services.developer_token import DeveloperTokenService from h.services.flag import FlagService from h.services.group import GroupService from h.services.group_create import GroupCreateService +from h.services.group_delete import GroupDeleteService from h.services.group_links import GroupLinksService from h.services.group_list import GroupListService from h.services.group_members import GroupMembersService from h.services.group_update import GroupUpdateService +from h.services.job_queue import JobQueueService from h.services.links import LinksService from h.services.list_organizations import ListOrganizationsService from h.services.nipsa import NipsaService from h.services.oauth.service import OAuthProviderService from h.services.organization import OrganizationService from h.services.search_index import SearchIndexService -from h.services.search_index._queue import Queue from h.services.subscription import SubscriptionService +from h.services.url_migration import URLMigrationService from h.services.user import UserService +from h.services.user_delete import UserDeleteService from h.services.user_password import UserPasswordService from h.services.user_signup import UserSignupService from h.services.user_unique import UserUniqueService @@ -32,16 +44,24 @@ __all__ = ( "mock_service", + "analytics_service", "annotation_delete_service", "annotation_json_service", + "annotation_metadata_service", + "annotation_read_service", + "annotation_sync_service", + "annotation_write_service", "auth_cookie_service", "auth_token_service", "bulk_annotation_service", - "delete_group_service", + "bulk_group_service", + "bulk_stats_service", + "developer_token_service", "links_service", "list_organizations_service", "flag_service", "group_create_service", + "group_delete_service", "group_links_service", "group_list_service", "group_members_service", @@ -52,7 +72,10 @@ "oauth_provider_service", "organization_service", "search_index", + "queue_service", "subscription_service", + "url_migration_service", + "user_delete_service", "user_password_service", "user_service", "user_password_service", @@ -78,6 +101,11 @@ def mock_service(service_class, name=None, iface=None, spec_set=True, **kwargs): return mock_service +@pytest.fixture +def analytics_service(mock_service): + return mock_service(AnalyticsService, name="analytics") + + @pytest.fixture def annotation_delete_service(mock_service): return mock_service(AnnotationDeleteService, name="annotation_delete") @@ -88,9 +116,31 @@ def annotation_json_service(mock_service): return mock_service(AnnotationJSONService, name="annotation_json") +@pytest.fixture +def annotation_read_service(mock_service): + return mock_service(AnnotationReadService) + + +@pytest.fixture +def annotation_sync_service(mock_service): + return mock_service(AnnotationSyncService) + + +@pytest.fixture +def annotation_write_service(mock_service): + return mock_service(AnnotationWriteService) + + +@pytest.fixture +def annotation_metadata_service(mock_service): + return mock_service(AnnotationMetadataService) + + @pytest.fixture def auth_cookie_service(mock_service): - return mock_service(AuthCookieService) + auth_cookie_service = mock_service(AuthCookieService) + auth_cookie_service.verify_cookie.return_value.deleted = False + return auth_cookie_service @pytest.fixture @@ -104,8 +154,18 @@ def bulk_annotation_service(mock_service): @pytest.fixture -def delete_group_service(mock_service): - return mock_service(DeleteGroupService, name="delete_group") +def bulk_group_service(mock_service): + return mock_service(BulkGroupService) + + +@pytest.fixture +def bulk_stats_service(mock_service): + return mock_service(BulkLMSStatsService) + + +@pytest.fixture +def developer_token_service(mock_service): + return mock_service(DeveloperTokenService, name="developer_token") @pytest.fixture @@ -136,6 +196,11 @@ def group_create_service(mock_service): return mock_service(GroupCreateService, name="group_create") +@pytest.fixture +def group_delete_service(mock_service): + return mock_service(GroupDeleteService, name="group_delete") + + @pytest.fixture def group_links_service(mock_service): return mock_service(GroupLinksService, name="group_links") @@ -186,12 +251,12 @@ def organization_service(mock_service): @pytest.fixture def search_index(mock_service): - return mock_service( - SearchIndexService, - "search_index", - spec_set=False, - _queue=create_autospec(Queue, spec_set=True, instance=True), - ) + return mock_service(SearchIndexService, "search_index", spec_set=False) + + +@pytest.fixture +def queue_service(mock_service): + return mock_service(JobQueueService, name="queue_service") @pytest.fixture @@ -199,6 +264,16 @@ def subscription_service(mock_service): return mock_service(SubscriptionService) +@pytest.fixture +def url_migration_service(mock_service): + return mock_service(URLMigrationService, name="url_migration") + + +@pytest.fixture +def user_delete_service(mock_service): + return mock_service(UserDeleteService, name="user_delete") + + @pytest.fixture def user_password_service(mock_service): return mock_service(UserPasswordService, name="user_password") @@ -206,7 +281,9 @@ def user_password_service(mock_service): @pytest.fixture def user_service(mock_service): - return mock_service(UserService, name="user") + user_service = mock_service(UserService, name="user") + user_service.fetch.return_value.deleted = False + return user_service @pytest.fixture diff --git a/tests/common/matchers.py b/tests/common/matchers.py index 1e7f31b4c42..9bbe809dd9c 100644 --- a/tests/common/matchers.py +++ b/tests/common/matchers.py @@ -4,6 +4,7 @@ Implements some matching objects in the style of h_matchers library for comparing with other objects in tests. """ + from h_matchers.matcher.core import Matcher from pyramid.httpexceptions import HTTPFound, HTTPSeeOther diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000000..90ff0f9735f --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,49 @@ +from os import environ + +import pytest +from sqlalchemy import create_engine, text +from sqlalchemy.orm import sessionmaker + + +@pytest.fixture(scope="session") +def db_engine(): + return create_engine(environ["DATABASE_URL"]) + + +@pytest.fixture(scope="session") +def db_sessionfactory(): + return sessionmaker() + + +@pytest.fixture +def db_session(db_engine, db_sessionfactory): + """ + Return the SQLAlchemy database session. + + This returns a session that is wrapped in an external transaction that is + rolled back after each test, so tests can't make database changes that + affect later tests. Even if the test (or the code under test) calls + session.commit() this won't touch the external transaction. + + Recipe adapted from: + + https://docs.sqlalchemy.org/en/20/orm/session_transaction.html#joining-a-session-into-an-external-transaction-such-as-for-test-suites + """ + connection = db_engine.connect() + transaction = connection.begin() + session = db_sessionfactory( + bind=connection, join_transaction_mode="create_savepoint" + ) + + try: + yield session + finally: + session.close() + transaction.rollback() + connection.close() + + +@pytest.fixture +def db_session_replica(db_session): + db_session.execute(text("SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY;")) + yield db_session diff --git a/tests/functional/api/annotations_test.py b/tests/functional/api/annotations_test.py index ff1275b06e9..d38d34695f7 100644 --- a/tests/functional/api/annotations_test.py +++ b/tests/functional/api/annotations_test.py @@ -272,7 +272,7 @@ def user_annotation(db_session, user, factories): @pytest.fixture def user_with_token(user, db_session, factories): - token = factories.DeveloperToken(userid=user.userid) + token = factories.DeveloperToken(user=user) db_session.add(token) db_session.commit() return (user, token) diff --git a/tests/functional/api/bulk/action_test.py b/tests/functional/api/bulk/action_test.py index f1f28a3ffe5..235c16f2a52 100644 --- a/tests/functional/api/bulk/action_test.py +++ b/tests/functional/api/bulk/action_test.py @@ -7,6 +7,8 @@ from h.models import Group, GroupMembership, User +pytestmark = pytest.mark.usefixtures("init_elasticsearch") + @pytest.mark.usefixtures("with_clean_db") class TestBulk: diff --git a/tests/functional/api/bulk/annotation_test.py b/tests/functional/api/bulk/annotation_test.py index e2a00c65699..90599cfb6f9 100644 --- a/tests/functional/api/bulk/annotation_test.py +++ b/tests/functional/api/bulk/annotation_test.py @@ -25,20 +25,23 @@ def test_it_accepts_a_valid_request(self, make_request, factories): authority_provided_id="1234567890", members=[user], ) - factories.Annotation( - userid=user.userid, + annotation_slim = factories.AnnotationSlim( + user=user, group=group, shared=True, deleted=False, - updated="2018-11-13T20:20:39", + created="2018-11-13T20:20:39", + ) + factories.AnnotationMetadata( + annotation_slim=annotation_slim, data={"some": "value"} ) response = make_request( { "filter": { "limit": 20, - "audience": {"username": [user.username]}, - "updated": { + "username": user.username, + "created": { "gt": "2018-11-12T20:20:39+00:00", "lte": "2018-11-13T20:20:39+00:00", }, @@ -60,6 +63,7 @@ def test_it_accepts_a_valid_request(self, make_request, factories): { "group": {"authority_provided_id": group.authority_provided_id}, "author": {"username": user.username}, + "metadata": {"some": "value"}, } ] diff --git a/tests/functional/api/conftest.py b/tests/functional/api/conftest.py index 61cd1eefc57..a75dd03e0be 100644 --- a/tests/functional/api/conftest.py +++ b/tests/functional/api/conftest.py @@ -37,7 +37,7 @@ def _make_headers(authority): @pytest.fixture def token_auth_header(db_session, factories, user): - token = factories.DeveloperToken(userid=user.userid) + token = factories.DeveloperToken(user=user) db_session.add(token) db_session.commit() diff --git a/tests/functional/api/errors_test.py b/tests/functional/api/errors_test.py index 7479c292190..74f6720c9c6 100644 --- a/tests/functional/api/errors_test.py +++ b/tests/functional/api/errors_test.py @@ -152,7 +152,7 @@ def append_header(headers=None): @pytest.fixture def user_with_token(db_session, factories): user = factories.User() - token = factories.DeveloperToken(userid=user.userid) + token = factories.DeveloperToken(user=user) db_session.commit() return (user, token) diff --git a/tests/functional/api/flags_test.py b/tests/functional/api/flags_test.py index 84f8e30d17a..f86923b804c 100644 --- a/tests/functional/api/flags_test.py +++ b/tests/functional/api/flags_test.py @@ -78,7 +78,7 @@ def user(db_session, factories): @pytest.fixture def user_with_token(user, db_session, factories): - token = factories.DeveloperToken(userid=user.userid) + token = factories.DeveloperToken(user=user) db_session.add(token) db_session.commit() return (user, token) diff --git a/tests/functional/api/groups/create_test.py b/tests/functional/api/groups/create_test.py index c14cc989cf8..4e14b6ff74f 100644 --- a/tests/functional/api/groups/create_test.py +++ b/tests/functional/api/groups/create_test.py @@ -152,7 +152,7 @@ def auth_client_header(auth_client): @pytest.fixture def user_with_token(db_session, factories): user = factories.User() - token = factories.DeveloperToken(userid=user.userid) + token = factories.DeveloperToken(user=user) db_session.add(token) db_session.commit() return (user, token) diff --git a/tests/functional/api/groups/members_test.py b/tests/functional/api/groups/members_test.py index b13f1e8d134..9baf7f0160f 100644 --- a/tests/functional/api/groups/members_test.py +++ b/tests/functional/api/groups/members_test.py @@ -258,7 +258,7 @@ def group_member(group, db_session, factories): @pytest.fixture def group_member_with_token(group_member, db_session, factories): - token = factories.DeveloperToken(userid=group_member.userid) + token = factories.DeveloperToken(user=group_member) db_session.add(token) db_session.commit() return (group_member, token) @@ -267,7 +267,7 @@ def group_member_with_token(group_member, db_session, factories): @pytest.fixture def user_with_token(db_session, factories): user = factories.User() - token = factories.DeveloperToken(userid=user.userid) + token = factories.DeveloperToken(user=user) db_session.add(token) db_session.commit() return (user, token) diff --git a/tests/functional/api/groups/read_test.py b/tests/functional/api/groups/read_test.py index 9dfa8ed0723..9d255ba5549 100644 --- a/tests/functional/api/groups/read_test.py +++ b/tests/functional/api/groups/read_test.py @@ -176,7 +176,7 @@ def auth_client_header(auth_client): @pytest.fixture def user_with_token(db_session, factories): user = factories.User() - token = factories.DeveloperToken(userid=user.userid) + token = factories.DeveloperToken(user=user) db_session.add(token) db_session.commit() return (user, token) diff --git a/tests/functional/api/groups/update_test.py b/tests/functional/api/groups/update_test.py index b86699ba5b5..b2ef8958763 100644 --- a/tests/functional/api/groups/update_test.py +++ b/tests/functional/api/groups/update_test.py @@ -229,7 +229,7 @@ def first_party_group(db_session, factories, first_party_user): @pytest.fixture def user_with_token(db_session, factories, first_party_user): - token = factories.DeveloperToken(userid=first_party_user.userid) + token = factories.DeveloperToken(user=first_party_user) db_session.add(token) db_session.commit() return (first_party_user, token) diff --git a/tests/functional/api/groups/upsert_test.py b/tests/functional/api/groups/upsert_test.py index ad0f7c6a0b6..4add397bb31 100644 --- a/tests/functional/api/groups/upsert_test.py +++ b/tests/functional/api/groups/upsert_test.py @@ -254,7 +254,7 @@ def first_party_group(db_session, factories, first_party_user): @pytest.fixture def user_with_token(db_session, factories, first_party_user): - token = factories.DeveloperToken(userid=first_party_user.userid) + token = factories.DeveloperToken(user=first_party_user) db_session.add(token) db_session.commit() return (first_party_user, token) diff --git a/tests/functional/api/moderation_test.py b/tests/functional/api/moderation_test.py index 5804971f9cb..7bc9183bfdb 100644 --- a/tests/functional/api/moderation_test.py +++ b/tests/functional/api/moderation_test.py @@ -108,6 +108,13 @@ def user(db_session, factories): return user +@pytest.fixture +def other_user(db_session, factories): + user = factories.User() + db_session.commit() + return user + + @pytest.fixture def group(user, db_session, factories): group = factories.Group(creator=user) @@ -123,18 +130,18 @@ def world_annotation(user, db_session, factories): @pytest.fixture -def group_annotation(group, db_session, factories): +def group_annotation(group, db_session, factories, other_user): ann = factories.Annotation( - userid="acct:someone@example.com", groupid=group.pubid, shared=True + userid=other_user.userid, groupid=group.pubid, shared=True ) db_session.commit() return ann @pytest.fixture -def private_group_annotation(group, db_session, factories): +def private_group_annotation(group, db_session, factories, other_user): ann = factories.Annotation( - userid="acct:someone@example.com", groupid=group.pubid, shared=False + userid=other_user.userid, groupid=group.pubid, shared=False ) db_session.commit() return ann @@ -142,7 +149,7 @@ def private_group_annotation(group, db_session, factories): @pytest.fixture def user_with_token(user, db_session, factories): - token = factories.DeveloperToken(userid=user.userid) + token = factories.DeveloperToken(user=user) db_session.add(token) db_session.commit() return (user, token) diff --git a/tests/functional/api/profile_test.py b/tests/functional/api/profile_test.py index c03a965233d..9a42d1c0a12 100644 --- a/tests/functional/api/profile_test.py +++ b/tests/functional/api/profile_test.py @@ -155,7 +155,7 @@ def user(groups, db_session, factories): @pytest.fixture def user_with_token(user, db_session, factories): - token = factories.DeveloperToken(userid=user.userid) + token = factories.DeveloperToken(user=user) db_session.add(token) db_session.commit() return (user, token) @@ -184,6 +184,6 @@ def open_group(auth_client, db_session, factories): @pytest.fixture def third_party_user_with_token(third_party_user, db_session, factories): - token = factories.DeveloperToken(userid=third_party_user.userid) + token = factories.DeveloperToken(user=third_party_user) db_session.commit() return (third_party_user, token) diff --git a/tests/functional/bin/run_data_task_test.py b/tests/functional/bin/run_data_task_test.py index fffff26854e..c3efc443b34 100644 --- a/tests/functional/bin/run_data_task_test.py +++ b/tests/functional/bin/run_data_task_test.py @@ -29,7 +29,7 @@ def test_reporting_tasks(self, environ): sys.executable, "bin/run_data_task.py", "--config-file", - "conf/development-app.ini", + "conf/development.ini", "--task", task_name, ], diff --git a/tests/functional/conftest.py b/tests/functional/conftest.py index 43c09341ec0..c95f3b5aa45 100644 --- a/tests/functional/conftest.py +++ b/tests/functional/conftest.py @@ -2,6 +2,7 @@ import os import pytest +from sqlalchemy import text from webtest import TestApp from h import db @@ -24,9 +25,7 @@ "h.sentry_dsn_frontend": "TEST_SENTRY_DSN_FRONTEND", "pyramid.debug_all": False, "secret_key": "notasecret", - "sqlalchemy.url": os.environ.get( - "TEST_DATABASE_URL", "postgresql://postgres@localhost/htest" - ), + "sqlalchemy.url": os.environ["DATABASE_URL"], } TEST_ENVIRONMENT = { @@ -58,28 +57,20 @@ def with_clean_db(db_engine): with contextlib.closing(db_engine.connect()) as conn: tx = conn.begin() tnames = ", ".join('"' + t.name + '"' for t in tables) - conn.execute(f"TRUNCATE {tnames};") + conn.execute(text(f"TRUNCATE {tnames};")) tx.commit() # We need to re-init the DB as it creates the default test group and # possibly more in future? - db.init(db_engine, authority=TEST_SETTINGS["h.authority"]) - - -@pytest.fixture(scope="session") -def db_engine(): - db_engine = db.make_engine(TEST_SETTINGS) - db.init(db_engine, authority=TEST_SETTINGS["h.authority"], should_create=True) - - yield db_engine - - db_engine.dispose() + db.pre_create(db_engine) + db.Base.metadata.create_all(db_engine) + db.post_create(db_engine) @pytest.fixture -def db_session(db_engine): +def db_session(db_engine, db_sessionfactory): """Get a standalone database session for preparing database state.""" - session = db.Session(bind=db_engine) + session = db_sessionfactory(bind=db_engine) yield session session.close() @@ -91,12 +82,6 @@ def factories(db_session): factories_common.set_session(None) -@pytest.fixture(scope="session", autouse=True) -def init_db(db_engine): - authority = TEST_SETTINGS["h.authority"] - db.init(db_engine, should_drop=True, should_create=True, authority=authority) - - @pytest.fixture(scope="session") def pyramid_app(): return create_app(None, **TEST_SETTINGS) diff --git a/tests/functional/feeds_test.py b/tests/functional/feeds_test.py index 3389b6da423..41762320d27 100644 --- a/tests/functional/feeds_test.py +++ b/tests/functional/feeds_test.py @@ -1,3 +1,8 @@ +import pytest + +pytestmark = pytest.mark.usefixtures("init_elasticsearch") + + def test_atom_feed(app): app.get("/stream.atom") diff --git a/tests/functional/h/views/activity_test.py b/tests/functional/h/views/activity_test.py index 3c06a5fe046..7c5da8163df 100644 --- a/tests/functional/h/views/activity_test.py +++ b/tests/functional/h/views/activity_test.py @@ -1,5 +1,7 @@ import pytest +pytestmark = pytest.mark.usefixtures("init_elasticsearch") + class TestGroupSearchController: @pytest.mark.usefixtures("with_logged_in_user") diff --git a/tests/functional/h/views/group_test.py b/tests/functional/h/views/group_test.py index a9bfc6f9d81..5c504412b2c 100644 --- a/tests/functional/h/views/group_test.py +++ b/tests/functional/h/views/group_test.py @@ -1,6 +1,8 @@ import pytest from pytest import param +pytestmark = pytest.mark.usefixtures("init_elasticsearch") + class TestGroupCreateController: @pytest.mark.usefixtures("with_logged_in_user") diff --git a/tests/functional/moderation_test.py b/tests/functional/moderation_test.py index 46e9d00f6d8..fa17a350733 100644 --- a/tests/functional/moderation_test.py +++ b/tests/functional/moderation_test.py @@ -39,6 +39,6 @@ def moderator(db_session, factories): @pytest.fixture def moderator_with_token(moderator, db_session, factories): - token = factories.DeveloperToken(userid=moderator.userid) + token = factories.DeveloperToken(user=moderator) db_session.commit() return (moderator, token) diff --git a/tests/functional/search_test.py b/tests/functional/search_test.py index 5722c3f05a2..687b0dd5fba 100644 --- a/tests/functional/search_test.py +++ b/tests/functional/search_test.py @@ -1,5 +1,9 @@ """Functional tests for the /search page, without JavaScript.""" +import pytest + +pytestmark = pytest.mark.usefixtures("init_elasticsearch") + def test_search_input_text_is_submitted_as_q_without_javascript(app): res = app.get("/search") diff --git a/tests/h/cli/commands/init_test.py b/tests/h/cli/commands/init_test.py deleted file mode 100644 index 805591bb4e7..00000000000 --- a/tests/h/cli/commands/init_test.py +++ /dev/null @@ -1,91 +0,0 @@ -from unittest import mock - -import pytest - -from h.cli.commands import init as init_cli - - -@pytest.mark.usefixtures("alembic_config", "alembic_stamp", "db", "search") -class TestInitCommand: - def test_initialises_database( - self, cli, cliconfig, db, db_engine, pyramid_settings - ): - db.make_engine.return_value = db_engine - pyramid_settings["h.authority"] = "foobar.org" - - result = cli.invoke(init_cli.init, obj=cliconfig) - - db.make_engine.assert_called_once_with(pyramid_settings) - db.init.assert_called_once_with( - db_engine, should_create=True, authority="foobar.org" - ) - assert not result.exit_code - - def test_skips_database_init_if_alembic_managed( - self, request, cli, cliconfig, db, db_engine - ): - db.make_engine.return_value = db_engine - db_engine.execute("CREATE TABLE alembic_version (version_num VARCHAR(32));") - - @request.addfinalizer - def _cleanup(): - db_engine.execute("DROP TABLE alembic_version;") - - result = cli.invoke(init_cli.init, obj=cliconfig) - - assert not db.init.called - assert not result.exit_code - - def test_stamps_alembic_version( - self, - alembic_config, - alembic_stamp, - cli, - cliconfig, - db, - db_engine, - pyramid_settings, - ): - db.make_engine.return_value = db_engine - Config = alembic_config.Config - pyramid_settings["h.authority"] = "foobar.org" - - result = cli.invoke(init_cli.init, obj=cliconfig) - - Config.assert_called_once_with("conf/alembic.ini") - alembic_stamp.assert_called_once_with(Config.return_value, "head") - assert not result.exit_code - - def test_initialises_search(self, cli, cliconfig, search, pyramid_settings): - pyramid_settings["es.check_icu_plugin"] = False - es_client = search.get_client.return_value - result = cli.invoke(init_cli.init, obj=cliconfig) - - search.get_client.assert_called_once_with(pyramid_settings) - search.init.assert_any_call(es_client, pyramid_settings["es.check_icu_plugin"]) - assert not result.exit_code - - -@pytest.fixture -def cliconfig(pyramid_request): - return {"bootstrap": mock.Mock(return_value=pyramid_request)} - - -@pytest.fixture -def db(patch): - return patch("h.cli.commands.init.db") - - -@pytest.fixture -def search(patch): - return patch("h.cli.commands.init.search") - - -@pytest.fixture -def alembic_config(patch): - return patch("h.cli.commands.init.alembic.config") - - -@pytest.fixture -def alembic_stamp(patch): - return patch("h.cli.commands.init.alembic.command.stamp") diff --git a/tests/h/cli/commands/shell_test.py b/tests/h/cli/commands/shell_test.py deleted file mode 100644 index 6d14289a853..00000000000 --- a/tests/h/cli/commands/shell_test.py +++ /dev/null @@ -1,124 +0,0 @@ -import sys -from unittest import mock - -import pytest - -from h.cli.commands import shell - - -class TestAutoDetect: - def test_bpython(self, monkeypatch): - monkeypatch.setitem(sys.modules, "bpython", mock.sentinel.bpython) - assert shell.autodetect() == "bpython" - - def test_bpython_over_ipython(self, monkeypatch): - monkeypatch.setitem(sys.modules, "bpython", mock.sentinel.bpython) - monkeypatch.setitem(sys.modules, "IPython", mock.sentinel.bpython) - assert shell.autodetect() == "bpython" - - def test_ipython(self, monkeypatch): - monkeypatch.setitem(sys.modules, "IPython", mock.sentinel.bpython) - assert shell.autodetect() == "ipython" - - def test_plain(self): - assert shell.autodetect() == "plain" - - -@pytest.mark.usefixtures("banner") -class TestShells: - def test_bpython(self, monkeypatch): - fake_bpython = mock.Mock(spec_set=["embed"]) - monkeypatch.setitem(sys.modules, "bpython", fake_bpython) - - shell.bpython(foo="bar", baz="qux") - - fake_bpython.embed.assert_called_once_with( - {"foo": "bar", "baz": "qux"}, banner="custom banner!" - ) - - def test_ipython(self, monkeypatch): - fake_ipython = mock.Mock(spec_set=["start_ipython"]) - monkeypatch.setitem(sys.modules, "IPython", fake_ipython) - fake_traitlets = mock.Mock(spec_set=["config"]) - fake_traitlets_config = mock.Mock(spec_set=["get_config"]) - monkeypatch.setitem(sys.modules, "traitlets", fake_traitlets) - monkeypatch.setitem(sys.modules, "traitlets.config", fake_traitlets_config) - - shell.ipython(foo="bar", baz="qux") - - _, kwargs = fake_ipython.start_ipython.call_args - - assert kwargs["argv"] == [] - assert kwargs["user_ns"] == {"foo": "bar", "baz": "qux"} - assert kwargs["config"].TerminalInteractiveShell.banner2 == "custom banner!" - - def test_plain(self, monkeypatch): - fake_code = mock.Mock(spec_set=["interact"]) - monkeypatch.setitem(sys.modules, "code", fake_code) - - shell.plain(foo="bar", baz="qux") - - fake_code.interact.assert_called_once_with( - banner="custom banner!", local={"foo": "bar", "baz": "qux"} - ) - - @pytest.fixture - def banner(self, monkeypatch): - monkeypatch.setattr(shell, "BANNER", "custom banner!") - - -@pytest.mark.usefixtures("code", "models") -class TestShellCommand: - def test_runs_bootstrap(self, cli): - config = {"bootstrap": mock.Mock(spec_set=[])} - - cli.invoke(shell.shell, obj=config) - - config["bootstrap"].assert_called_once_with() - - def test_can_select_shell_manually(self, cli, monkeypatch): - config = {"bootstrap": mock.Mock(spec_set=[])} - fake_bpython = mock.Mock(spec_set=["embed"]) - monkeypatch.setitem(sys.modules, "bpython", fake_bpython) - - cli.invoke(shell.shell, ["--type", "bpython"], obj=config) - - assert fake_bpython.embed.called - - def test_passes_useful_locals(self, cli, code, models): - bootstrap = mock.Mock(spec_set=[]) - request = bootstrap.return_value - config = {"bootstrap": bootstrap} - - cli.invoke(shell.shell, obj=config) - - _, kwargs = code.interact.call_args - locals_ = kwargs["local"] - - assert locals_ == { - "m": models, - "models": models, - "registry": request.registry, - "request": request, - "session": request.db, - } - - def test_error_if_shell_not_found(self, cli): - config = {"bootstrap": mock.Mock(spec_set=[])} - - result = cli.invoke(shell.shell, ["--type", "bpython"], obj=config) - - assert result.exit_code - - @pytest.fixture - def code(self, monkeypatch): - code = mock.Mock(spec_set=["interact"]) - monkeypatch.setitem(sys.modules, "code", code) - return code - - @pytest.fixture - def models(self, monkeypatch): - h = mock.Mock(spec_set=["models"]) - h.models = mock.sentinel.models - monkeypatch.setitem(sys.modules, "h", h) - return h.models diff --git a/tests/h/cli/commands/user_test.py b/tests/h/cli/commands/user_test.py deleted file mode 100644 index 8feddde6601..00000000000 --- a/tests/h/cli/commands/user_test.py +++ /dev/null @@ -1,327 +0,0 @@ -from unittest import mock - -import pytest -from passlib.context import CryptContext - -from h import models -from h.cli.commands import user as user_cli -from h.services.annotation_delete import AnnotationDeleteService -from h.services.delete_user import DeleteUserService -from h.services.user_password import UserPasswordService - - -class TestAddCommand: - def test_it_adds_user_with_default_authority(self, cli, cliconfig, signup_service): - result = cli.invoke( - user_cli.add, - [ - "--username", - "admin", - "--email", - "admin@localhost", - "--password", - "admin", - ], - obj=cliconfig, - ) - - assert not result.exit_code - - signup_service.signup.assert_called_with( - username="admin", - email="admin@localhost", - password="admin", - require_activation=False, - ) - - def test_it_adds_user_with_specific_authority(self, cli, cliconfig, signup_service): - result = cli.invoke( - user_cli.add, - [ - "--username", - "admin", - "--email", - "admin@localhost", - "--password", - "admin", - "--authority", - "publisher.org", - ], - obj=cliconfig, - ) - - assert not result.exit_code - - signup_service.signup.assert_called_with( - username="admin", - email="admin@localhost", - password="admin", - authority="publisher.org", - require_activation=False, - ) - - -class TestAdminCommand: - def test_it_adds_admin(self, cli, cliconfig, non_admin_user, db_session): - result = cli.invoke( - user_cli.admin, ["--on", non_admin_user.username], obj=cliconfig - ) - - assert not result.exit_code - - user = db_session.query(models.User).get(non_admin_user.id) - assert user.admin - - def test_it_adds_admin_by_default(self, cli, cliconfig, non_admin_user, db_session): - result = cli.invoke(user_cli.admin, [non_admin_user.username], obj=cliconfig) - - assert not result.exit_code - - user = db_session.query(models.User).get(non_admin_user.id) - assert user.admin - - def test_it_adds_admin_with_specific_authority( - self, cli, cliconfig, non_admin_user, db_session - ): - non_admin_user.authority = "partner.org" - db_session.flush() - - result = cli.invoke( - user_cli.admin, - ["--authority", "partner.org", non_admin_user.username], - obj=cliconfig, - ) - - assert not result.exit_code - - user = db_session.query(models.User).get(non_admin_user.id) - assert user.admin - - def test_it_removes_admin(self, cli, cliconfig, admin_user, db_session): - result = cli.invoke( - user_cli.admin, ["--off", admin_user.username], obj=cliconfig - ) - - assert not result.exit_code - - user = db_session.query(models.User).get(admin_user.id) - assert not user.admin - - def test_it_removes_admin_with_specific_authority( - self, cli, cliconfig, admin_user, db_session - ): - admin_user.authority = "partner.org" - - result = cli.invoke( - user_cli.admin, - ["--off", "--authority", "partner.org", admin_user.username], - obj=cliconfig, - ) - - assert not result.exit_code - - user = db_session.query(models.User).get(admin_user.id) - assert not user.admin - - def test_it_errors_when_user_could_not_be_found( - self, cli, cliconfig, non_admin_user, db_session - ): - result = cli.invoke( - user_cli.admin, [f"bogus_{non_admin_user.username}"], obj=cliconfig - ) - - assert result.exit_code == 1 - user = db_session.query(models.User).get(non_admin_user.id) - assert not user.admin - - def test_it_errors_when_user_with_specific_authority_could_not_be_found( - self, cli, cliconfig, non_admin_user, db_session - ): - result = cli.invoke( - user_cli.admin, - ["--authority", "foo.com", non_admin_user.username], - obj=cliconfig, - ) - - assert result.exit_code == 1 - user = db_session.query(models.User).get(non_admin_user.id) - assert not user.admin - - @pytest.fixture - def admin_user(self, db_session, factories): - return self._user(db_session, factories, True) - - @pytest.fixture - def non_admin_user(self, db_session, factories): - return self._user(db_session, factories, False) - - def _user(self, db_session, factories, admin): - user = factories.User(admin=admin) - db_session.flush() - return user - - -class TestPasswordCommand: - def test_it_changes_password( - self, cli, cliconfig, user, db_session, password_service - ): - result = cli.invoke( - user_cli.password, [user.username, "--password", "newpass"], obj=cliconfig - ) - - assert not result.exit_code - - user = db_session.query(models.User).get(user.id) - assert password_service.check_password(user, "newpass") - - def test_it_changes_password_with_specific_authority( - self, cli, cliconfig, user, db_session, password_service - ): - user.authority = "partner.org" - db_session.flush() - - result = cli.invoke( - user_cli.password, - ["--authority", "partner.org", user.username, "--password", "newpass"], - obj=cliconfig, - ) - - assert not result.exit_code - - user = db_session.query(models.User).get(user.id) - assert password_service.check_password(user, "newpass") - - def test_it_errors_when_user_could_not_be_found( - self, cli, cliconfig, user, db_session, password_service - ): - result = cli.invoke( - user_cli.password, - [f"bogus_{user.username}", "--password", "newpass"], - obj=cliconfig, - ) - - assert result.exit_code == 1 - - user = db_session.query(models.User).get(user.id) - assert not password_service.check_password(user, "newpass") - - def test_it_errors_when_user_with_specific_authority_could_not_be_found( - self, cli, cliconfig, user, db_session, password_service - ): - result = cli.invoke( - user_cli.password, - ["--authority", "foo.com", user.username, "--password", "newpass"], - obj=cliconfig, - ) - - assert result.exit_code == 1 - - user = db_session.query(models.User).get(user.id) - assert not password_service.check_password(user, "newpass") - - @pytest.fixture - def user(self, db_session, factories): - user = factories.User() - db_session.flush() - return user - - -class TestDeleteUserCommand: - def test_it_deletes_user(self, cli, cliconfig, user, db_session): - result = cli.invoke(user_cli.delete, [user.username], obj=cliconfig) - - assert not result.exit_code - assert not db_session.query(models.User).filter_by(id=user.id).count() - - def test_it_deletes_user_with_specific_authority( - self, cli, cliconfig, user, db_session - ): - user.authority = "partner.org" - db_session.flush() - - result = cli.invoke( - user_cli.delete, - ["--authority", "partner.org", user.username], - obj=cliconfig, - ) - - assert not result.exit_code - assert not db_session.query(models.User).filter_by(id=user.id).count() - - def test_it_errors_when_user_could_not_be_found( - self, cli, cliconfig, user, db_session - ): - result = cli.invoke(user_cli.delete, [f"bogus_{user.username}"], obj=cliconfig) - - assert result.exit_code == 1 - assert db_session.query(models.User).filter_by(id=user.id).count() == 1 - - def test_it_errors_when_user_with_specific_authority_could_not_be_found( - self, cli, cliconfig, user, db_session - ): - result = cli.invoke( - user_cli.delete, ["--authority", "foo.com", user.username], obj=cliconfig - ) - - assert result.exit_code == 1 - assert db_session.query(models.User).filter_by(id=user.id).count() == 1 - - @pytest.fixture - def user(self, db_session, factories): - user = factories.User() - db_session.flush() - return user - - -@pytest.fixture -def signup_service(): - signup_service = mock.Mock(spec_set=["signup"]) - return signup_service - - -@pytest.fixture -def hasher(): - # Use a much faster hasher for testing purposes. DO NOT use as few as - # 5 rounds of bcrypt in production code under ANY CIRCUMSTANCES. - return CryptContext( - schemes=["bcrypt"], - bcrypt__ident="2b", - bcrypt__min_rounds=5, - bcrypt__max_rounds=5, - ) - - -@pytest.fixture -def password_service(hasher): - password_service = UserPasswordService() - password_service.hasher = hasher - return password_service - - -@pytest.fixture -def delete_user_service(pyramid_request, annotation_delete_service): - return DeleteUserService(pyramid_request, annotation_delete_service) - - -@pytest.fixture -def annotation_delete_service(pyramid_config): # pylint:disable=unused-argument - service = mock.create_autospec( - AnnotationDeleteService, spec_set=True, instance=True - ) - return service - - -@pytest.fixture -def pyramid_config( - pyramid_config, signup_service, password_service, delete_user_service -): - pyramid_config.register_service(signup_service, name="user_signup") - pyramid_config.register_service(password_service, name="user_password") - pyramid_config.register_service(delete_user_service, name="delete_user") - return pyramid_config - - -@pytest.fixture -def cliconfig(pyramid_config, pyramid_request): # pylint:disable=unused-argument - pyramid_request.tm = mock.Mock() - return {"bootstrap": mock.Mock(return_value=pyramid_request)} diff --git a/tests/h/indexer/reindexer_test.py b/tests/h/indexer/reindexer_test.py deleted file mode 100644 index b216f953065..00000000000 --- a/tests/h/indexer/reindexer_test.py +++ /dev/null @@ -1,173 +0,0 @@ -from unittest import mock - -import pytest - -from h.indexer.reindexer import reindex - - -@pytest.mark.usefixtures( - "BatchIndexer", - "configure_index", - "delete_index", - "nipsa_service", - "get_aliased_index", - "update_aliased_index", - "settings_service", -) -class TestReindex: - def test_sets_op_type_to_create( - self, pyramid_request, mock_es_client, BatchIndexer - ): - reindex(mock.sentinel.session, mock_es_client, pyramid_request) - - _, kwargs = BatchIndexer.call_args - assert kwargs["op_type"] == "create" - - def test_indexes_annotations(self, pyramid_request, mock_es_client, batchindexer): - """Should call .index() on the batch indexer instance.""" - reindex(mock.sentinel.session, mock_es_client, pyramid_request) - - batchindexer.index.assert_called_once_with() - - def test_retries_failed_annotations( - self, pyramid_request, mock_es_client, batchindexer - ): - """Should call .index() a second time with any failed annotation IDs.""" - batchindexer.index.return_value = ["abc123", "def456"] - - reindex(mock.sentinel.session, mock_es_client, pyramid_request) - - assert batchindexer.index.mock_calls == [ - mock.call(), - mock.call(["abc123", "def456"]), - ] - - def test_creates_new_index(self, pyramid_request, mock_es_client, configure_index): - """Creates a new target index.""" - reindex(mock.sentinel.session, mock_es_client, pyramid_request) - - configure_index.assert_called_once_with(mock_es_client) - - def test_passes_new_index_to_indexer( - self, pyramid_request, mock_es_client, configure_index, BatchIndexer - ): - """Pass the name of the new index as target_index to indexer.""" - configure_index.return_value = "hypothesis-abcd1234" - - reindex(mock.sentinel.session, mock_es_client, pyramid_request) - - _, kwargs = BatchIndexer.call_args - assert kwargs["target_index"] == "hypothesis-abcd1234" - - def test_updates_alias_when_reindexed( - self, pyramid_request, mock_es_client, configure_index, update_aliased_index - ): - """Call update_aliased_index on the client with the new index name.""" - configure_index.return_value = "hypothesis-abcd1234" - - reindex(mock.sentinel.session, mock_es_client, pyramid_request) - - update_aliased_index.assert_called_once_with( - mock_es_client, "hypothesis-abcd1234" - ) - - def test_does_not_update_alias_if_indexing_fails( - self, pyramid_request, mock_es_client, batchindexer, update_aliased_index - ): - """Don't call update_aliased_index if index() fails...""" - batchindexer.index.side_effect = RuntimeError("fail") - - try: - reindex(mock.sentinel.session, mock_es_client, pyramid_request) - except RuntimeError: - pass - - assert not update_aliased_index.called - - def test_raises_if_index_not_aliased(self, mock_es_client, get_aliased_index): - get_aliased_index.return_value = None - - with pytest.raises(RuntimeError): - reindex(mock.sentinel.session, mock_es_client, mock.sentinel.request) - - def test_stores_new_index_name_in_settings( - self, pyramid_request, mock_es_client, settings_service, configure_index - ): - configure_index.return_value = "hypothesis-abcd1234" - - reindex(mock.sentinel.session, mock_es_client, pyramid_request) - - settings_service.put.assert_called_once_with( - "reindex.new_index", "hypothesis-abcd1234" - ) - - def test_deletes_index_name_setting( - self, pyramid_request, mock_es_client, settings_service - ): - reindex(mock.sentinel.session, mock_es_client, pyramid_request) - - settings_service.delete.assert_called_once_with("reindex.new_index") - - def test_deletes_index_name_setting_when_exception_raised( - self, pyramid_request, mock_es_client, settings_service, batchindexer - ): - batchindexer.index.side_effect = RuntimeError("boom!") - - with pytest.raises(RuntimeError): - reindex(mock.sentinel.session, mock_es_client, pyramid_request) - - settings_service.delete.assert_called_once_with("reindex.new_index") - - def test_deletes_old_index( - self, pyramid_request, mock_es_client, delete_index, get_aliased_index - ): - get_aliased_index.return_value = "original_index" - - reindex(mock.sentinel.session, mock_es_client, pyramid_request) - - delete_index.assert_called_once_with(mock_es_client, "original_index") - - def test_populates_nipsa_cache( - self, pyramid_request, mock_es_client, nipsa_service - ): - reindex(mock.sentinel.session, mock_es_client, pyramid_request) - nipsa_service.fetch_all_flagged_userids.assert_called_once_with() - - @pytest.fixture - def BatchIndexer(self, patch): - return patch("h.indexer.reindexer.BatchIndexer") - - @pytest.fixture - def configure_index(self, patch): - return patch("h.indexer.reindexer.configure_index") - - @pytest.fixture - def get_aliased_index(self, patch): - func = patch("h.indexer.reindexer.get_aliased_index") - func.return_value = "foobar" - return func - - @pytest.fixture - def delete_index(self, patch): - return patch("h.indexer.reindexer.delete_index") - - @pytest.fixture - def update_aliased_index(self, patch): - return patch("h.indexer.reindexer.update_aliased_index") - - @pytest.fixture - def batchindexer(self, BatchIndexer): - indexer = BatchIndexer.return_value - indexer.index.return_value = [] - return indexer - - @pytest.fixture - def settings_service(self, pyramid_config): - service = mock.Mock() - pyramid_config.register_service(service, name="settings") - return service - - @pytest.fixture - def pyramid_request(self, pyramid_request): - pyramid_request.tm = mock.Mock() - return pyramid_request diff --git a/tests/h/models/activation_test.py b/tests/h/models/activation_test.py deleted file mode 100644 index 6ae4a9cf681..00000000000 --- a/tests/h/models/activation_test.py +++ /dev/null @@ -1,12 +0,0 @@ -import re - -from h.models import Activation - - -def test_activation_has_asciinumeric_code(db_session): - act = Activation() - - db_session.add(act) - db_session.flush() - - assert re.match(r"[A-Za-z0-9]{12}", act.code) diff --git a/tests/h/models/blocklist_test.py b/tests/h/models/blocklist_test.py deleted file mode 100644 index c51accab075..00000000000 --- a/tests/h/models/blocklist_test.py +++ /dev/null @@ -1,20 +0,0 @@ -from h import models - - -def test_is_blocked(db_session): - db_session.add(models.Blocklist(uri="http://example.com")) - db_session.add(models.Blocklist(uri="http://example.com/bar")) - db_session.flush() - - assert models.Blocklist.is_blocked(db_session, "http://example.com") - assert models.Blocklist.is_blocked(db_session, "http://example.com/bar") - assert not models.Blocklist.is_blocked(db_session, "http://example.com/foo") - - -def test_is_blocked_with_wildcards(db_session): - db_session.add(models.Blocklist(uri="%//example.com%")) - db_session.flush() - - assert models.Blocklist.is_blocked(db_session, "http://example.com/") - assert models.Blocklist.is_blocked(db_session, "http://example.com/bar") - assert models.Blocklist.is_blocked(db_session, "http://example.com/foo") diff --git a/tests/h/notification/reply_test.py b/tests/h/notification/reply_test.py deleted file mode 100644 index 942a0c0eea2..00000000000 --- a/tests/h/notification/reply_test.py +++ /dev/null @@ -1,161 +0,0 @@ -import pytest - -from h.models import Annotation, Document, DocumentMeta, Subscriptions -from h.notification.reply import Notification, get_notification - -FIXTURE_DATA = { - "reply": { - "id": "OECV3AmDEeaAtTt8rjCjIg", - "groupid": "__world__", - "shared": True, - "userid": "acct:elephant@safari.net", - }, - "parent": { - "id": "SucHcAmDEeaAtf_ZeH-rhA", - "groupid": "__world__", - "shared": True, - "userid": "acct:giraffe@safari.net", - }, -} - - -class TestGetNotification: - def test_returns_correct_params_when_subscribed( - self, parent, pyramid_request, reply, user_service, subscription_service - ): - result = get_notification(pyramid_request, reply, "create") - - subscription_service.get_subscription.assert_called_once_with( - user_id=parent.userid, type_=Subscriptions.Type.REPLY - ) - - assert isinstance(result, Notification) - assert result.reply == reply - assert result.parent == parent - assert result.reply_user == user_service.fetch(reply.userid) - assert result.parent_user == user_service.fetch(parent.userid) - assert result.document == reply.document - - def test_returns_none_when_action_is_not_create(self, pyramid_request, reply): - assert get_notification(pyramid_request, reply, "update") is None - assert get_notification(pyramid_request, reply, "delete") is None - assert get_notification(pyramid_request, reply, "frobnicate") is None - - def test_returns_none_when_annotation_is_not_reply(self, pyramid_request, reply): - reply.references = None - - assert get_notification(pyramid_request, reply, "create") is None - - def test_returns_none_when_parent_does_not_exist( - self, annotations, parent, pyramid_request, reply - ): - del annotations[parent.id] - - assert get_notification(pyramid_request, reply, "create") is None - - def test_returns_none_when_parent_user_does_not_exist( - self, factories, pyramid_request, reply, user_service - ): - users = {"acct:elephant@safari.net": factories.User()} - user_service.fetch.side_effect = users.get - - assert get_notification(pyramid_request, reply, "create") is None - - def test_returns_none_when_parent_user_has_no_email_address( - self, factories, pyramid_request, reply, user_service - ): - users = { - "acct:giraffe@safari.net": factories.User(email=None), - "acct:elephant@safari.net": factories.User(), - } - user_service.fetch.side_effect = users.get - - assert get_notification(pyramid_request, reply, "create") is None - - def test_returns_none_when_reply_user_does_not_exist( - self, factories, pyramid_request, reply, user_service - ): - """ - Don't send a reply if somehow the replying user ceased to exist. - - It's not clear when or why this would ever happen, but we can't - construct the reply email without the user who replied existing. We log - a warning if this happens. - """ - users = {"acct:giraffe@safari.net": factories.User()} - user_service.fetch.side_effect = users.get - - assert get_notification(pyramid_request, reply, "create") is None - - def test_returns_none_when_reply_by_same_user(self, parent, pyramid_request, reply): - parent.userid = "acct:elephant@safari.net" - - assert get_notification(pyramid_request, reply, "create") is None - - def test_returns_none_when_parent_user_cannot_read_reply( - self, pyramid_request, reply - ): - reply.shared = False - - assert get_notification(pyramid_request, reply, "create") is None - - def test_returns_none_when_subscription_inactive( - self, pyramid_request, reply, subscription_service - ): - subscription_service.get_subscription.return_value.active = False - - assert get_notification(pyramid_request, reply, "create") is None - - @pytest.fixture - def annotations(self): - return {} - - @pytest.fixture - def parent(self, annotations): - parent = Annotation(**FIXTURE_DATA["parent"]) - annotations[parent.id] = parent - return parent - - @pytest.fixture - def reply(self, annotations, db_session, parent): - # We need to create a document object to provide the title, and - # ensure it is associated with the annotation through the - # annotation's `target_uri` - doc = Document.find_or_create_by_uris( - db_session, claimant_uri="http://example.net/foo", uris=[] - ).one() - doc.meta.append( - DocumentMeta( - type="title", value=["Some document"], claimant="http://example.com/foo" - ) - ) - reply = Annotation(**FIXTURE_DATA["reply"]) - reply.target_uri = "http://example.net/foo" - reply.references = [parent.id] - reply.document = doc - db_session.add(reply) - db_session.flush() - annotations[reply.id] = reply - return reply - - @pytest.fixture(autouse=True) - def fetch_annotation(self, patch, annotations): - fetch_annotation = patch("h.notification.reply.storage.fetch_annotation") - fetch_annotation.side_effect = lambda _, id: annotations.get(id) - return fetch_annotation - - @pytest.fixture(autouse=True) - def subscription_service(self, subscription_service, factories): - subscription_service.get_subscription.return_value = factories.Subscriptions( - active=True, type=Subscriptions.Type.REPLY.value - ) - return subscription_service - - @pytest.fixture(autouse=True) - def user_service(self, user_service, factories): - users = { - "acct:giraffe@safari.net": factories.User(), - "acct:elephant@safari.net": factories.User(), - } - user_service.fetch.side_effect = users.get - return user_service diff --git a/tests/h/services/annotation_delete_test.py b/tests/h/services/annotation_delete_test.py deleted file mode 100644 index 873f6ee60fa..00000000000 --- a/tests/h/services/annotation_delete_test.py +++ /dev/null @@ -1,62 +0,0 @@ -from unittest import mock - -import pytest - -from h.events import AnnotationEvent -from h.services.annotation_delete import annotation_delete_service_factory - - -class TestAnnotationDeleteService: - def test_it_marks_the_annotation_as_deleted(self, svc, annotation): - ann = annotation() - svc.delete(ann) - - assert ann.deleted - - def test_it_updates_the_updated_field(self, svc, annotation, datetime): - ann = annotation() - svc.delete(ann) - - assert ann.updated == datetime.utcnow.return_value - - def test_it_publishes_a_delete_event(self, svc, pyramid_request, annotation): - ann = annotation() - svc.delete(ann) - - expected_event = AnnotationEvent(pyramid_request, ann.id, "delete") - actual_event = pyramid_request.notify_after_commit.call_args[0][0] - assert ( - expected_event.request, - expected_event.annotation_id, - expected_event.action, - ) == (actual_event.request, actual_event.annotation_id, actual_event.action) - - def test_it_deletes_all_annotations(self, svc, annotation): - svc.delete = mock.create_autospec(svc.delete, spec_set=True) - - anns = [annotation(), annotation()] - svc.delete_annotations(anns) - - assert svc.delete.mock_calls == [mock.call(anns[0]), mock.call(anns[1])] - - -@pytest.fixture -def annotation(factories): - return lambda factories=factories: factories.Annotation() - - -@pytest.fixture -def svc(db_session, pyramid_request): - pyramid_request.db = db_session - return annotation_delete_service_factory({}, pyramid_request) - - -@pytest.fixture -def pyramid_request(pyramid_request): - pyramid_request.notify_after_commit = mock.Mock() - return pyramid_request - - -@pytest.fixture -def datetime(patch): - return patch("h.services.annotation_delete.datetime") diff --git a/tests/h/services/bulk_annotation_test.py b/tests/h/services/bulk_annotation_test.py deleted file mode 100644 index 4d36e7bbe2d..00000000000 --- a/tests/h/services/bulk_annotation_test.py +++ /dev/null @@ -1,195 +0,0 @@ -from unittest.mock import sentinel - -import pytest -from _pytest.mark import param -from h_matchers import Any -from sqlalchemy import select - -from h.models import Annotation -from h.services.bulk_annotation import ( - BadDateFilter, - BadFieldSpec, - BulkAnnotationService, - date_match, -) - - -class TestDateMatch: - @pytest.mark.parametrize( - "spec,expected", - ( - param({"gt": "2001-01-01"}, ["2"], id="gt"), - param({"gte": "2001-01-01"}, ["1", "2"], id="gte"), - param({"lt": "2001-01-01"}, ["0"], id="lt"), - param({"lte": "2001-01-01"}, ["0", "1"], id="lte"), - param({"eq": "2001-01-01"}, ["1"], id="eq"), - param({"ne": "2001-01-01"}, ["0", "2"], id="ne"), - param({"gt": "2000-01-01", "lt": "2002-01-01"}, ["1"], id="combo"), - ), - ) - def test_it(self, db_session, factories, spec, expected): - factories.Annotation(text="0", created="2000-01-01") - factories.Annotation(text="1", created="2001-01-01") - factories.Annotation(text="2", created="2002-01-01") - - annotations = ( - db_session.execute( - select(Annotation).where(date_match(Annotation.created, spec)) - ) - .scalars() - .all() - ) - - assert [anno.text for anno in annotations] == Any.list.containing( - expected - ).only() - - @pytest.mark.parametrize( - "bad_spec", - ( - param({}, id="empty"), - param({"bad_op": "2002-01-01"}, id="bad_op"), - ), - ) - def test_it_raises_for_bad_spec(self, bad_spec): - with pytest.raises(BadDateFilter): - date_match(sentinel.column, bad_spec) - - -class TestBulkAnnotationService: - AUTHORITY = "my.authority" - - @pytest.mark.parametrize( - "key,value,visible", - ( - (None, None, True), - ("shared", False, False), - ("deleted", True, False), - ("nipsad", True, False), - ("moderated", True, False), - ("updated", "2020-01-01", False), - ("updated", "2020-01-02", True), - ("updated", "2022-01-01", True), - ("updated", "2022-01-02", False), - ), - ) - def test_it_with_single_annotation(self, svc, factories, key, value, visible): - values = { - "shared": True, - "deleted": False, - "nipsad": False, - "moderated": False, - "updated": "2021-01-01", - } - if key: - values[key] = value - - viewer = factories.User(authority=self.AUTHORITY) - author = factories.User(authority=self.AUTHORITY, nipsa=values["nipsad"]) - anno = factories.Annotation( - userid=author.userid, - group=factories.Group(members=[author, viewer]), - shared=values["shared"], - deleted=values["deleted"], - updated=values["updated"], - ) - if values["moderated"]: - factories.AnnotationModeration(annotation=anno) - - annotations = svc.annotation_search( - authority=self.AUTHORITY, - audience={"username": [viewer.username]}, - updated={"gt": "2020-01-01", "lte": "2022-01-01"}, - ) - - if visible: - assert annotations == [anno] - else: - assert not annotations - - def test_it_with_more_complex_grouping(self, svc, factories): - *viewers, author = factories.User.create_batch(3, authority=self.AUTHORITY) - - annotations = [ - factories.Annotation( - userid=author.userid, - group=factories.Group(members=group_members), - shared=True, - deleted=False, - ) - for group_members in ( - # The first two annotations should match, because they are in - # groups the viewers are in - [author, viewers[0]], - [author, viewers[1]], - # This one is just noise and shouldn't match - [author], - ) - ] - - matched_annos = svc.annotation_search( - authority=self.AUTHORITY, - audience={"username": [viewer.username for viewer in viewers]}, - updated={"gt": "2020-01-01", "lte": "2099-01-01"}, - ) - - # Only the first two annotations should match - assert matched_annos == Any.list.containing(annotations[:2]).only() - - @pytest.mark.parametrize( - "fields,expected", - ( - (["author.username"], ("USERNAME",)), - (["group.authority_provided_id"], ("AUTHORITY_PROVIDED_ID",)), - ( - ["author.username", "group.authority_provided_id"], - ("USERNAME", "AUTHORITY_PROVIDED_ID"), - ), - ( - ["group.authority_provided_id", "author.username"], - ("AUTHORITY_PROVIDED_ID", "USERNAME"), - ), - ), - ) - def test_it_with_fields(self, svc, factories, fields, expected): - viewer = factories.User(authority=self.AUTHORITY) - author = factories.User(authority=self.AUTHORITY, username="USERNAME") - group = factories.Group( - members=[viewer, author], authority_provided_id="AUTHORITY_PROVIDED_ID" - ) - factories.Annotation( - userid=author.userid, - group=group, - shared=True, - deleted=False, - updated="2021-01-01", - ) - - results = svc.annotation_search( - authority=self.AUTHORITY, - audience={"username": [viewer.username]}, - updated={"gt": "2020-01-01", "lte": "2099-01-01"}, - fields=fields, - ) - - assert results == [expected] - - @pytest.mark.parametrize( - "bad_fields", - ( - param([], id="empty_list"), - param(["not.a_field"], id="bad_value"), - ), - ) - def test_it_with_bad_fields(self, svc, bad_fields): - with pytest.raises(BadFieldSpec): - svc.annotation_search( - authority=self.AUTHORITY, - audience={"username": ["something"]}, - updated={"gt": "2020-01-01", "lte": "2099-01-01"}, - fields=bad_fields, - ) - - @pytest.fixture - def svc(self, db_session): - return BulkAnnotationService(db_session) diff --git a/tests/h/services/delete_user_test.py b/tests/h/services/delete_user_test.py deleted file mode 100644 index f2cf22e4a34..00000000000 --- a/tests/h/services/delete_user_test.py +++ /dev/null @@ -1,112 +0,0 @@ -from unittest import mock - -import pytest -import sqlalchemy - -from h.models import Annotation, Document -from h.services.annotation_delete import AnnotationDeleteService -from h.services.delete_user import delete_user_service_factory - - -@pytest.mark.usefixtures("annotation_delete_service") -class TestDeleteUserService: - def test_delete_disassociate_group_memberships(self, factories, svc): - user = factories.User() - - svc.delete(user) - - assert user.groups == [] - - def test_delete_deletes_annotations( - self, factories, svc, annotation_delete_service - ): - user = factories.User(username="bob") - anns = [ - factories.Annotation(userid=user.userid), - factories.Annotation(userid=user.userid), - ] - - svc.delete(user) - - annotation_delete_service.delete.assert_has_calls( - [mock.call(anns[0]), mock.call(anns[1])], any_order=True - ) - - def test_delete_deletes_user(self, db_session, factories, svc): - user = factories.User() - - svc.delete(user) - - assert user in db_session.deleted - - def test_delete_user_removes_groups_if_no_collaborators( - self, db_session, group_with_two_users, pyramid_request, svc - ): - pyramid_request.db = db_session - (group, creator, _, _, member_ann) = group_with_two_users - db_session.delete(member_ann) - - svc.delete(creator) - - assert sqlalchemy.inspect(group).was_deleted - - def test_creator_is_none_if_groups_have_collaborators( - self, db_session, group_with_two_users, pyramid_request, svc - ): - pyramid_request.db = db_session - (group, creator, _, _, _) = group_with_two_users - - svc.delete(creator) - - assert group.creator is None - - def test_delete_user_removes_only_groups_created_by_user( - self, db_session, group_with_two_users, pyramid_request, svc - ): - pyramid_request.db = db_session - (group, _, member, _, _) = group_with_two_users - - svc.delete(member) - - assert group not in db_session.deleted - - @pytest.fixture - def svc(self, db_session, pyramid_request): - pyramid_request.db = db_session - return delete_user_service_factory({}, pyramid_request) - - -@pytest.fixture -def pyramid_request(pyramid_request): - pyramid_request.notify_after_commit = mock.Mock() - return pyramid_request - - -@pytest.fixture -def group_with_two_users(db_session, factories): - """Create a group with two members and an annotation created by each.""" - creator = factories.User() - member = factories.User() - - group = factories.Group( - authority=creator.authority, creator=creator, members=[creator, member] - ) - - doc = Document(web_uri="https://example.org") - creator_ann = Annotation(userid=creator.userid, groupid=group.pubid, document=doc) - member_ann = Annotation(userid=member.userid, groupid=group.pubid, document=doc) - - db_session.add(creator_ann) - db_session.add(member_ann) - db_session.flush() - - return (group, creator, member, creator_ann, member_ann) - - -@pytest.fixture -def annotation_delete_service(pyramid_config): - service = mock.create_autospec( - AnnotationDeleteService, spec_set=True, instance=True - ) - pyramid_config.register_service(service, name="annotation_delete") - return service diff --git a/tests/h/services/developer_token_test.py b/tests/h/services/developer_token_test.py deleted file mode 100644 index fc87afb5482..00000000000 --- a/tests/h/services/developer_token_test.py +++ /dev/null @@ -1,67 +0,0 @@ -import pytest - -from h import models -from h.services.developer_token import ( - DeveloperTokenService, - developer_token_service_factory, -) - - -class TestDeveloperTokenService: - def test_fetch_returns_developer_token_for_userid( - self, svc, developer_token, userid - ): - assert svc.fetch(userid) == developer_token - - def test_fetch_returns_none_for_missing_developer_token(self, svc, userid): - assert svc.fetch(userid) is None - - def test_create_creates_new_developer_token_for_userid( - self, svc, db_session, userid - ): - assert not db_session.query(models.Token).count() - svc.create(userid) - assert db_session.query(models.Token).count() == 1 - - def test_create_returns_new_developer_token_for_userid(self, svc, userid, patch): - token_urlsafe = patch("h.services.developer_token.security.token_urlsafe") - token_urlsafe.return_value = "secure-token" - - token = svc.create(userid) - - assert token.userid == userid - assert token.value == "6879-secure-token" - assert token.expires is None - assert token.authclient is None - assert token.refresh_token is None - - def test_regenerate_sets_a_new_token_value(self, svc, developer_token): - old_userid = developer_token.userid - old_value = developer_token.value - - svc.regenerate(developer_token) - - assert old_userid == developer_token.userid - assert old_value != developer_token.value - - @pytest.fixture - def svc(self, pyramid_request): - return developer_token_service_factory(None, pyramid_request) - - @pytest.fixture - def developer_token(self, factories, userid): - return factories.DeveloperToken(userid=userid) - - @pytest.fixture - def userid(self): - return "acct:john@doe.org" - - -class TestDeveloperTokenServiceFactory: - def test_it_returns_developer_token_service(self, pyramid_request): - svc = developer_token_service_factory(None, pyramid_request) - assert isinstance(svc, DeveloperTokenService) - - def test_it_provides_request_db_as_session(self, pyramid_request): - svc = developer_token_service_factory(None, pyramid_request) - assert svc.session == pyramid_request.db diff --git a/tests/h/services/search_index/_queue_test.py b/tests/h/services/search_index/_queue_test.py deleted file mode 100644 index 3afabfda266..00000000000 --- a/tests/h/services/search_index/_queue_test.py +++ /dev/null @@ -1,450 +0,0 @@ -import datetime as datetime_ -import uuid -from unittest import mock -from unittest.mock import patch, sentinel - -import pytest -from h_matchers import Any -from sqlalchemy.sql.elements import BinaryExpression - -from h.db.types import URLSafeUUID -from h.models import Annotation, Job -from h.search.index import BatchIndexer -from h.services.search_index import SearchIndexService -from h.services.search_index._queue import Queue - -ONE_WEEK = datetime_.timedelta(weeks=1) -ONE_WEEK_IN_SECONDS = int(ONE_WEEK.total_seconds()) -MINUS_5_MIN = datetime_.timedelta(minutes=-5) -MINUS_5_MIN_IN_SECS = int(MINUS_5_MIN.total_seconds()) - - -class TestQueue: - def test_add_where(self, queue, factories, db_session, now): - matching = [ - factories.Annotation(shared=True), - factories.Annotation(shared=True), - ] - # Add some noise - factories.Annotation(shared=False) - - queue.add_where( - where=[Annotation.shared.is_(True)], - tag="test_tag", - priority=1234, - schedule_in=ONE_WEEK_IN_SECONDS, - ) - - assert ( - db_session.query(Job).all() - == Any.list.containing( - [ - Any.instance_of(Job).with_attrs( - { - "enqueued_at": Any.instance_of(datetime_.datetime), - "scheduled_at": now + ONE_WEEK, - "tag": "test_tag", - "priority": 1234, - "kwargs": { - "annotation_id": self.database_id(annotation), - "force": False, - }, - } - ) - for annotation in matching - ] - ).only() - ) - - @pytest.mark.parametrize( - "force,expected_force", - ( - (True, True), - (1, True), - (False, False), - ("", False), - ), - ) - def test_add_where_with_force( - self, queue, db_session, factories, force, expected_force - ): - annotation = factories.Annotation() - - queue.add_where([Annotation.id == annotation.id], "test_tag", 1, force=force) - - assert db_session.query(Job).one().kwargs["force"] == expected_force - - def test_add_by_id(self, queue, add_where): - queue.add_by_id( - sentinel.annotation_id, - sentinel.tag, - schedule_in=sentinel.schedule_in, - force=sentinel.force, - ) - - add_where.assert_called_once_with( - [Any.instance_of(BinaryExpression)], - sentinel.tag, - Queue.Priority.SINGLE_ITEM, - sentinel.force, - sentinel.schedule_in, - ) - - where = add_where.call_args[0][0] - assert where[0].compare(Annotation.id == sentinel.annotation_id) - - def test_add_annotations_between_times(self, queue, add_where): - queue.add_between_times( - sentinel.start_time, sentinel.end_time, sentinel.tag, force=sentinel.force - ) - - add_where.assert_called_once_with( - [Any.instance_of(BinaryExpression)] * 2, - sentinel.tag, - Queue.Priority.BETWEEN_TIMES, - sentinel.force, - ) - - where = add_where.call_args[0][0] - assert where[0].compare(Annotation.updated >= sentinel.start_time) - assert where[1].compare(Annotation.updated <= sentinel.end_time) - - def test_add_users_annotations(self, queue, add_where): - queue.add_by_user( - sentinel.userid, - sentinel.tag, - force=sentinel.force, - schedule_in=sentinel.schedule_in, - ) - - add_where.assert_called_once_with( - [Any.instance_of(BinaryExpression)], - sentinel.tag, - Queue.Priority.SINGLE_USER, - sentinel.force, - sentinel.schedule_in, - ) - - where = add_where.call_args[0][0] - assert where[0].compare(Annotation.userid == sentinel.userid) - - def test_add_group_annotations(self, queue, add_where): - queue.add_by_group( - sentinel.groupid, - sentinel.tag, - force=sentinel.force, - schedule_in=sentinel.schedule_in, - ) - - add_where.assert_called_once_with( - [Any.instance_of(BinaryExpression)], - sentinel.tag, - Queue.Priority.SINGLE_GROUP, - sentinel.force, - sentinel.schedule_in, - ) - - where = add_where.call_args[0][0] - assert where[0].compare(Annotation.groupid == sentinel.groupid) - - def database_id(self, annotation): - """Return `annotation.id` in the internal format used within the database.""" - return str(uuid.UUID(URLSafeUUID.url_safe_to_hex(annotation.id))) - - @pytest.fixture() - def add_where(self, queue): - with patch.object(queue, "add_where") as add_where: - yield add_where - - -class TestSync: - def test_it_does_nothing_if_the_queue_is_empty(self, batch_indexer, queue): - counts = queue.sync(1) - - assert counts == {} - batch_indexer.index.assert_not_called() - - def test_it_ignores_jobs_that_arent_scheduled_yet( - self, batch_indexer, factories, now, queue - ): - factories.SyncAnnotationJob(scheduled_at=now + datetime_.timedelta(hours=1)) - - counts = queue.sync(1) - - assert counts == {} - batch_indexer.index.assert_not_called() - - def test_it_ignores_jobs_beyond_limit(self, batch_indexer, factories, queue): - limit = 1 - factories.SyncAnnotationJob.create_batch(size=limit + 1) - - queue.sync(limit) - - assert len(batch_indexer.index.call_args[0][0]) == limit - - def test_it_ignores_jobs_that_are_expired( - self, batch_indexer, db_session, factories, now, queue - ): - job = factories.SyncAnnotationJob(expires_at=now - datetime_.timedelta(hours=1)) - - counts = queue.sync(1) - - assert counts == {} - batch_indexer.index.assert_not_called() - assert job in db_session.query(Job) - - def test_if_the_job_has_force_True_it_indexes_the_annotation_and_deletes_the_job( - self, batch_indexer, db_session, factories, queue - ): - job = factories.SyncAnnotationJob(force=True) - - counts = queue.sync(1) - - assert counts == { - Queue.Result.SYNCED_FORCED.format(tag="test_tag"): 1, - Queue.Result.SYNCED_TAG_TOTAL.format(tag="test_tag"): 1, - Queue.Result.SYNCED_TOTAL: 1, - Queue.Result.COMPLETED_FORCED.format(tag="test_tag"): 1, - Queue.Result.COMPLETED_TAG_TOTAL.format(tag="test_tag"): 1, - Queue.Result.COMPLETED_TOTAL: 1, - } - assert job not in db_session.query(Job) - batch_indexer.index.assert_called_once_with([self.url_safe_id(job)]) - - def test_if_the_annotation_isnt_in_the_DB_it_deletes_the_job_from_the_queue( - self, db_session, factories, queue - ): - # We have to actually create an annotation and save it to the DB in - # order to get a valid annotation ID. Then we delete the annotation - # from the DB again because we actually don't want the annotation to be - # in the DB in this test. - annotation = factories.Annotation() - job = factories.SyncAnnotationJob(annotation=annotation) - db_session.delete(annotation) - - counts = queue.sync(1) - - assert counts == { - Queue.Result.COMPLETED_DELETED.format(tag="test_tag"): 1, - Queue.Result.COMPLETED_TAG_TOTAL.format(tag="test_tag"): 1, - Queue.Result.COMPLETED_TOTAL: 1, - } - assert job not in db_session.query(Job) - - def test_if_the_annotation_is_marked_as_deleted_in_the_DB_it_deletes_the_job_from_the_queue( - self, db_session, factories, queue - ): - annotation = factories.Annotation() - job = factories.SyncAnnotationJob(annotation=annotation) - annotation.deleted = True - - counts = queue.sync(1) - - assert counts == { - Queue.Result.COMPLETED_DELETED.format(tag="test_tag"): 1, - Queue.Result.COMPLETED_TAG_TOTAL.format(tag="test_tag"): 1, - Queue.Result.COMPLETED_TOTAL: 1, - } - assert job not in db_session.query(Job) - - def test_if_the_annotation_is_missing_from_Elastic_it_indexes_it( - self, batch_indexer, factories, queue - ): - job = factories.SyncAnnotationJob() - - counts = queue.sync(1) - - assert counts == { - Queue.Result.SYNCED_MISSING.format(tag="test_tag"): 1, - Queue.Result.SYNCED_TAG_TOTAL.format(tag="test_tag"): 1, - Queue.Result.SYNCED_TOTAL: 1, - } - batch_indexer.index.assert_called_once_with([self.url_safe_id(job)]) - - def test_if_the_annotation_is_already_in_Elastic_it_removes_the_job_from_the_queue( - self, batch_indexer, db_session, factories, index, queue - ): - annotation = factories.Annotation() - index(annotation) - job = factories.SyncAnnotationJob(annotation=annotation) - - counts = queue.sync(1) - - assert counts == { - Queue.Result.COMPLETED_UP_TO_DATE.format(tag="test_tag"): 1, - Queue.Result.COMPLETED_TAG_TOTAL.format(tag="test_tag"): 1, - Queue.Result.COMPLETED_TOTAL: 1, - } - assert job not in db_session.query(Job) - batch_indexer.index.assert_not_called() - - def test_if_the_annotation_has_a_different_updated_time_in_Elastic_it_indexes_it( - self, batch_indexer, factories, index, now, queue - ): - annotation = factories.Annotation() - index(annotation) - factories.SyncAnnotationJob(annotation=annotation) - # Simulate the annotation having been updated in the DB after it was - # indexed. - annotation.updated = now - - counts = queue.sync(1) - - assert counts == { - Queue.Result.SYNCED_DIFFERENT.format(tag="test_tag"): 1, - Queue.Result.SYNCED_TAG_TOTAL.format(tag="test_tag"): 1, - Queue.Result.SYNCED_TOTAL: 1, - } - batch_indexer.index.assert_called_once_with([annotation.id]) - - def test_if_the_annotation_has_a_different_userid_in_Elastic_it_indexes_it( - self, batch_indexer, factories, index, queue - ): - annotation = factories.Annotation() - index(annotation) - factories.SyncAnnotationJob(annotation=annotation) - # Simulate the user having been renamed in the DB. - annotation.userid = "new_userid" - - counts = queue.sync(1) - - assert counts == { - Queue.Result.SYNCED_DIFFERENT.format(tag="test_tag"): 1, - Queue.Result.SYNCED_TAG_TOTAL.format(tag="test_tag"): 1, - Queue.Result.SYNCED_TOTAL: 1, - } - batch_indexer.index.assert_called_once_with([annotation.id]) - - def test_if_there_are_multiple_jobs_with_the_same_annotation_id( - self, batch_indexer, factories, queue - ): - annotation = factories.Annotation() - jobs = factories.SyncAnnotationJob.create_batch(size=2, annotation=annotation) - - counts = queue.sync(len(jobs)) - - assert counts == { - Queue.Result.SYNCED_MISSING.format(tag="test_tag"): 1, - Queue.Result.SYNCED_TAG_TOTAL.format(tag="test_tag"): 1, - Queue.Result.SYNCED_TOTAL: 1, - } - # It only syncs the annotation to Elasticsearch once, even though it - # processed two separate jobs (for the same annotation). - batch_indexer.index.assert_called_once_with([annotation.id]) - - def test_deleting_multiple_jobs_with_the_same_annotation_id( - self, batch_indexer, db_session, factories, index, queue - ): - annotation = factories.Annotation() - index(annotation) - jobs = factories.SyncAnnotationJob.create_batch(size=2, annotation=annotation) - - counts = queue.sync(len(jobs)) - - assert counts == { - Queue.Result.COMPLETED_UP_TO_DATE.format(tag="test_tag"): 2, - Queue.Result.COMPLETED_TAG_TOTAL.format(tag="test_tag"): 2, - Queue.Result.COMPLETED_TOTAL: 2, - } - for job in jobs: - assert job not in db_session.query(Job) - batch_indexer.index.assert_not_called() - - def test_metrics(self, factories, index, now, queue): - def add_job(indexed=True, updated=False, deleted=False, **kwargs): - annotation = factories.Annotation() - factories.SyncAnnotationJob(annotation=annotation, **kwargs) - - if indexed: - index(annotation) - - if updated: - annotation.updated = now + ONE_WEEK - - if deleted: - annotation.deleted = True - - add_job() - add_job(indexed=False) - add_job(updated=True) - add_job(deleted=True) - add_job(tag="tag_2", force=True) - - counts = queue.sync(5) - - assert counts == { - "Synced/Total": 3, - "Completed/Total": 3, - "Synced/test_tag/Total": 2, - "Completed/test_tag/Total": 2, - "Synced/test_tag/Different_in_Elastic": 1, - "Synced/test_tag/Missing_from_Elastic": 1, - "Synced/tag_2/Forced": 1, - "Synced/tag_2/Total": 1, - "Completed/tag_2/Forced": 1, - "Completed/tag_2/Total": 1, - "Completed/test_tag/Up_to_date_in_Elastic": 1, - "Completed/test_tag/Deleted_from_db": 1, - } - - def url_safe_id(self, job): - """Return the URL-safe version of the given job's annotation ID.""" - return URLSafeUUID.hex_to_url_safe(job.kwargs["annotation_id"]) - - @pytest.fixture - def search_index( - self, es_client, pyramid_request, moderation_service, nipsa_service - ): # pylint:disable=unused-argument - return SearchIndexService( - pyramid_request, - es_client, - session=pyramid_request.db, - settings={}, - queue=queue, - ) - - @pytest.fixture - def index(self, es_client, search_index): - """Declare a method that indexes the given annotation into Elasticsearch.""" - - def index(annotation): - search_index.add_annotation(annotation) - es_client.conn.indices.refresh(index=es_client.index) - - return index - - @pytest.fixture(autouse=True) - def noise_annotations(self, factories, index): - # Create some noise annotations in the DB. Some of them also in - # Elasticsearch, some not. None of these should ever be touched by the - # sync() method in these tests. - annotations = factories.Annotation.create_batch(size=2) - index(annotations[0]) - - @pytest.fixture(autouse=True) - def noise_jobs(self, factories): - # Create some noise jobs in the DB. None of these should ever be - # touched by the sync() method in these tests. - factories.Job() - - -@pytest.fixture -def batch_indexer(): - return mock.create_autospec(BatchIndexer, spec_set=True, instance=True) - - -@pytest.fixture(autouse=True) -def datetime(patch, now): - datetime = patch("h.services.search_index._queue.datetime") - datetime.utcnow.return_value = now - return datetime - - -@pytest.fixture -def now(): - return datetime_.datetime.utcnow() - - -@pytest.fixture -def queue(batch_indexer, db_session, es_client): - return Queue(db_session, es_client, batch_indexer) diff --git a/tests/h/services/search_index/service_factory_test.py b/tests/h/services/search_index/service_factory_test.py deleted file mode 100644 index 4209986babd..00000000000 --- a/tests/h/services/search_index/service_factory_test.py +++ /dev/null @@ -1,55 +0,0 @@ -from unittest.mock import sentinel - -import pytest - -from h.services.search_index.service_factory import factory - - -class TestFactory: - def test_it( - self, pyramid_request, SearchIndexService, settings, BatchIndexer, Queue - ): - result = factory(sentinel.context, pyramid_request) - - BatchIndexer.assert_called_once_with( - pyramid_request.db, pyramid_request.es, pyramid_request - ) - Queue.assert_called_once_with( - db=pyramid_request.db, - es=pyramid_request.es, - batch_indexer=BatchIndexer.return_value, - ) - SearchIndexService.assert_called_once_with( - request=pyramid_request, - es_client=pyramid_request.es, - session=pyramid_request.db, - settings=settings, - queue=Queue.return_value, - ) - assert result == SearchIndexService.return_value - - @pytest.fixture - def settings(self, pyramid_config): - settings = sentinel.settings - pyramid_config.register_service(settings, name="settings") - return settings - - @pytest.fixture - def pyramid_request(self, pyramid_request): - pyramid_request.es = sentinel.es - return pyramid_request - - -@pytest.fixture(autouse=True) -def BatchIndexer(patch): - return patch("h.services.search_index.service_factory.BatchIndexer") - - -@pytest.fixture(autouse=True) -def Queue(patch): - return patch("h.services.search_index.service_factory.Queue") - - -@pytest.fixture(autouse=True) -def SearchIndexService(patch): - return patch("h.services.search_index.service_factory.SearchIndexService") diff --git a/tests/h/storage_test.py b/tests/h/storage_test.py deleted file mode 100644 index 115b2e2b478..00000000000 --- a/tests/h/storage_test.py +++ /dev/null @@ -1,493 +0,0 @@ -from datetime import datetime as datetime_ -from datetime import timedelta -from unittest.mock import create_autospec, sentinel - -import pytest -import sqlalchemy as sa -from h_matchers import Any - -from h import storage -from h.models.annotation import Annotation -from h.models.document import Document, DocumentURI -from h.schemas import ValidationError -from h.security import Permission -from h.traversal.group import GroupContext - -pytestmark = pytest.mark.usefixtures("search_index") - - -class TestFetchAnnotation: - def test_it_fetches_and_returns_the_annotation(self, db_session, factories): - annotation = factories.Annotation() - - actual = storage.fetch_annotation(db_session, annotation.id) - assert annotation == actual - - def test_it_does_not_crash_if_id_is_invalid(self, db_session): - assert storage.fetch_annotation(db_session, "foo") is None - - -class TestFetchOrderedAnnotations: - def test_it_returns_annotations_for_ids_in_the_same_order( - self, db_session, factories - ): - ann_1 = factories.Annotation(userid="luke") - ann_2 = factories.Annotation(userid="luke") - - assert [ann_2, ann_1] == storage.fetch_ordered_annotations( - db_session, [ann_2.id, ann_1.id] - ) - assert [ann_1, ann_2] == storage.fetch_ordered_annotations( - db_session, [ann_1.id, ann_2.id] - ) - - def test_it_allows_to_change_the_query(self, db_session, factories): - ann_1 = factories.Annotation(userid="luke") - ann_2 = factories.Annotation(userid="maria") - - def only_maria(query): - return query.filter(Annotation.userid == "maria") - - assert [ann_2] == storage.fetch_ordered_annotations( - db_session, [ann_2.id, ann_1.id], query_processor=only_maria - ) - - def test_it_handles_empty_ids(self): - results = storage.fetch_ordered_annotations(sentinel.db_session, ids=[]) - - assert results == [] - - -class TestExpandURI: - @pytest.mark.parametrize( - "normalized,expected_uris", - ( - (False, ["http://example.com/"]), - (True, ["httpx://example.com"]), - ), - ) - def test_expand_uri_no_document(self, db_session, normalized, expected_uris): - uris = storage.expand_uri( - db_session, "http://example.com/", normalized=normalized - ) - - assert uris == expected_uris - - @pytest.mark.parametrize( - "normalized,expected_uris", - ( - (False, ["http://example.com/"]), - (True, ["httpx://example.com"]), - ), - ) - def test_expand_uri_document_doesnt_expand_canonical_uris( - self, db_session, normalized, expected_uris - ): - document = Document( - document_uris=[ - DocumentURI( - uri="http://example.com/", - type="rel-canonical", - claimant="http://example.com", - ), - DocumentURI( - uri="http://noise.example.com/", claimant="http://example.com" - ), - ] - ) - db_session.add(document) - db_session.flush() - - uris = storage.expand_uri( - db_session, "http://example.com/", normalized=normalized - ) - - assert uris == expected_uris - - @pytest.mark.parametrize( - "normalized,expected_uris", - ( - (False, ["http://example.com/", "http://alt.example.com/"]), - (True, ["httpx://example.com", "httpx://alt.example.com"]), - ), - ) - def test_expand_uri_document_uris(self, db_session, normalized, expected_uris): - document = Document( - document_uris=[ - DocumentURI(uri="http://example.com/", claimant="http://example.com"), - DocumentURI( - uri="http://alt.example.com/", claimant="http://example.com" - ), - ] - ) - db_session.add(document) - db_session.flush() - - uris = storage.expand_uri( - db_session, "http://alt.example.com/", normalized=normalized - ) - - assert uris == expected_uris - - -class TestCreateAnnotation: - def test_it(self, pyramid_request, annotation_data, datetime): - annotation = storage.create_annotation(pyramid_request, annotation_data) - - for param, value in annotation_data.items(): - assert getattr(annotation, param) == value - - assert annotation.created == datetime.utcnow.return_value - assert annotation.updated == datetime.utcnow.return_value - - assert sa.inspect(annotation).persistent # We saved it to the DB - - def test_it_validates_the_group_scope( - self, pyramid_request, annotation_data, group, _validate_group_scope - ): - storage.create_annotation(pyramid_request, annotation_data) - - _validate_group_scope.assert_called_once_with( - group, annotation_data["target_uri"] - ) - - def test_it_adds_document_metadata( - self, pyramid_request, annotation_data, update_document_metadata, datetime - ): - annotation_data["document"] = { - "document_meta_dicts": sentinel.document_meta_dicts, - "document_uri_dicts": sentinel.document_uri_dicts, - } - - annotation = storage.create_annotation(pyramid_request, annotation_data) - - update_document_metadata.assert_called_once_with( - pyramid_request.db, - annotation_data["target_uri"], - sentinel.document_meta_dicts, - sentinel.document_uri_dicts, - created=datetime.utcnow.return_value, - updated=datetime.utcnow.return_value, - ) - assert annotation.document == update_document_metadata.return_value - - def test_it_queues_the_search_index( - self, pyramid_request, annotation_data, search_index - ): - annotation = storage.create_annotation(pyramid_request, annotation_data) - - search_index._queue.add_by_id.assert_called_once_with( # pylint:disable=protected-access - annotation.id, tag="storage.create_annotation", schedule_in=60 - ) - - def test_it_sets_the_group_to_match_the_parent_for_replies( - self, pyramid_request, annotation_data, factories, other_group - ): - parent_annotation = factories.Annotation(group=other_group) - annotation_data["references"] = [parent_annotation.id] - - annotation = storage.create_annotation(pyramid_request, annotation_data) - - assert annotation.groupid - assert annotation.group == parent_annotation.group - - def test_it_raises_if_parent_annotation_does_not_exist( - self, pyramid_request, annotation_data - ): - annotation_data["references"] = ["MISSING_ID"] - - with pytest.raises(ValidationError): - storage.create_annotation(pyramid_request, annotation_data) - - def test_it_raises_if_the_group_doesnt_exist( - self, pyramid_request, annotation_data - ): - annotation_data["groupid"] = "MISSING_ID" - - with pytest.raises(ValidationError): - storage.create_annotation(pyramid_request, annotation_data) - - def test_it_raises_if_write_permission_is_missing( - self, pyramid_request, annotation_data, has_permission - ): - has_permission.return_value = False - - with pytest.raises(ValidationError): - storage.create_annotation(pyramid_request, annotation_data) - - has_permission.assert_called_once_with( - Permission.Group.WRITE, context=Any.instance_of(GroupContext) - ) - - def test_it_does_not_crash_if_target_selectors_is_empty( - self, pyramid_request, annotation_data - ): - # Page notes have [] for target_selectors. - annotation_data["target_selectors"] = [] - - storage.create_annotation(pyramid_request, annotation_data) - - @pytest.mark.xfail(reason="This test passed before due to over fixturing") - def test_it_does_not_crash_if_no_text_or_tags( - self, pyramid_request, annotation_data - ): - # Highlights have no text or tags. - annotation_data["text"] = annotation_data["tags"] = "" - - # ValueError: Attribute 'tags' does not accept objects of type - # So what should this be? None? - storage.create_annotation(pyramid_request, annotation_data) - - @pytest.fixture - def other_group(self, factories): - # Set an authority_provided_id so our group_id is not None - return factories.OpenGroup(authority_provided_id="other_group_auth_id") - - @pytest.fixture - def has_permission(self, pyramid_request): - pyramid_request.has_permission = create_autospec(pyramid_request.has_permission) - return pyramid_request.has_permission - - -class TestUpdateAnnotation: - def test_it(self, pyramid_request, annotation, annotation_data, datetime): - result = storage.update_annotation( - pyramid_request, annotation.id, annotation_data - ) - - assert result == annotation - - for param, value in annotation_data.items(): - assert getattr(result, param) == value - - assert result.created != datetime.utcnow.return_value - assert result.updated == datetime.utcnow.return_value - - def test_update_timestamps_disabled( - self, pyramid_request, annotation, annotation_data, datetime - ): - orig_updated = annotation.updated - - result = storage.update_annotation( - pyramid_request, annotation.id, annotation_data, update_timestamp=False - ) - - assert orig_updated != datetime.utcnow.return_value - assert result.updated == orig_updated - - def test_it_validates_the_group_scope( - self, pyramid_request, annotation, _validate_group_scope - ): - storage.update_annotation( - pyramid_request, annotation.id, {"target_uri": "sentinel.target_uri"} - ) - - _validate_group_scope.assert_called_once_with( - annotation.group, "sentinel.target_uri" - ) - - def test_it_doesnt_validates_the_group_scope_if_target_uri_missing( - self, pyramid_request, annotation, _validate_group_scope - ): - storage.update_annotation(pyramid_request, annotation.id, {}) - - _validate_group_scope.assert_not_called() - - def test_it_updates_extras(self, pyramid_request, annotation): - annotation.extra = {"old_key": "old_value"} - pyramid_request.db.flush() - - result = storage.update_annotation( - pyramid_request, annotation.id, {"extra": {"new_key": "new_value"}} - ) - - assert result.extra == {"new_key": "new_value", "old_key": "old_value"} - - def test_it_updates_document_metadata( - self, pyramid_request, annotation, update_document_metadata, datetime - ): - result = storage.update_annotation( - pyramid_request, - annotation.id, - { - "document": { - "document_meta_dicts": sentinel.document_meta_dicts, - "document_uri_dicts": sentinel.document_uri_dicts, - } - }, - ) - - update_document_metadata.assert_called_once_with( - pyramid_request.db, - annotation.target_uri, - sentinel.document_meta_dicts, - sentinel.document_uri_dicts, - updated=datetime.utcnow.return_value, - ) - assert result.document == update_document_metadata.return_value - - def test_it_updates_document_if_uri_changed( - self, pyramid_request, annotation, update_document_metadata - ): - result = storage.update_annotation( - pyramid_request, annotation.id, {"target_uri": "https://new-url.com"} - ) - - update_document_metadata.assert_called_once_with( - pyramid_request.db, annotation.target_uri, {}, {}, updated=Any() - ) - assert result.document == update_document_metadata.return_value - - def test_it_does_not_update_document_if_no_document_or_uri_change( - self, pyramid_request, annotation, update_document_metadata - ): - storage.update_annotation(pyramid_request, annotation.id, {}) - - update_document_metadata.assert_not_called() - - def test_it_uses_the_updated_group_not_the_old_one( - self, pyramid_request, annotation, group - ): - assert annotation.groupid != group.pubid - assert annotation.group != group - - result = storage.update_annotation( - pyramid_request, annotation.id, {"groupid": group.pubid} - ) - - assert result.groupid == group.pubid - assert result.group == group - - def test_it_raises_if_missing_group(self, pyramid_request, annotation): - with pytest.raises(ValidationError): - storage.update_annotation( - pyramid_request, annotation.id, {"groupid": "MISSING_ID"} - ) - - def test_it_queues_the_annotation_for_syncing_to_Elasticsearch( - self, annotation, pyramid_request, search_index - ): - storage.update_annotation(pyramid_request, annotation.id, {}) - - search_index._queue.add_by_id.assert_called_once_with( # pylint:disable=protected-access - annotation.id, tag="storage.update_annotation", schedule_in=60, force=False - ) - - def test_it_uses_custom_reindex_tag( - self, annotation, pyramid_request, search_index - ): - storage.update_annotation( - pyramid_request, annotation.id, {}, reindex_tag="h.services.SomeService" - ) - - search_index._queue.add_by_id.assert_called_once_with( # pylint:disable=protected-access - annotation.id, tag="h.services.SomeService", schedule_in=60, force=False - ) - - def test_it_forces_reindexing_if_update_timestamp_is_false( - self, annotation, pyramid_request, search_index - ): - storage.update_annotation( - pyramid_request, annotation.id, {}, update_timestamp=False - ) - - search_index._queue.add_by_id.assert_called_once_with( # pylint:disable=protected-access - annotation.id, tag=Any(), schedule_in=60, force=True - ) - - @pytest.fixture - def annotation(self, factories): - return factories.Annotation() - - -class TestValidateGroupScope: - def test_it_allows_matching_scopes(self, scoped_group): - storage._validate_group_scope( # pylint:disable=protected-access - scoped_group, "http://inscope.example.com" - ) - - def test_it_allows_mismatching_scopes_if_a_group_has_no_scopes( - self, scoped_group, url_in_scope - ): - scoped_group.scopes = [] - - storage._validate_group_scope( # pylint:disable=protected-access - scoped_group, "http://not-inscope.example.com" - ) - - url_in_scope.assert_not_called() - - def test_it_allows_mismatching_scopes_if_enforce_is_False( - self, scoped_group, url_in_scope - ): - scoped_group.enforce_scope = False - - storage._validate_group_scope( # pylint:disable=protected-access - scoped_group, "http://not-inscope.example.com" - ) - - url_in_scope.assert_not_called() - - def test_it_catches_mismatching_scopes(self, scoped_group, url_in_scope): - url_in_scope.return_value = False - - with pytest.raises(ValidationError): - storage._validate_group_scope( # pylint:disable=protected-access - scoped_group, "http://not-inscope.example.com" - ) - - @pytest.fixture - def scoped_group(self, factories): - return factories.OpenGroup( - enforce_scope=True, - scopes=[factories.GroupScope(scope="http://inscope.example.com")], - ) - - @pytest.fixture - def url_in_scope(self, patch): - return patch("h.storage.url_in_scope") - - -@pytest.fixture -def group(factories): - # Set an authority_provided_id so our group_id is not None - return factories.OpenGroup(authority_provided_id="group_auth_id") - - -@pytest.fixture -def user(factories): - return factories.User() - - -@pytest.fixture -def annotation_data(user, group): - return { - "userid": user.userid, - "text": "text", - "tags": ["one", "two"], - "shared": False, - "target_uri": "http://www.example.com/example.html", - "groupid": group.pubid, - "references": [], - "target_selectors": ["selector_one", "selector_two"], - "document": {"document_uri_dicts": [], "document_meta_dicts": []}, - } - - -@pytest.fixture -def datetime(patch): - datetime = patch("h.storage.datetime") - datetime.utcnow.return_value = datetime_.utcnow() + timedelta(hours=1) - return datetime - - -@pytest.fixture -def _validate_group_scope(patch): - return patch("h.storage._validate_group_scope") - - -@pytest.fixture -def update_document_metadata(patch, factories): - update_document_metadata = patch("h.storage.update_document_metadata") - update_document_metadata.return_value = factories.Document() - return update_document_metadata diff --git a/tests/h/util/query_test.py b/tests/h/util/query_test.py deleted file mode 100644 index 8373d6215ed..00000000000 --- a/tests/h/util/query_test.py +++ /dev/null @@ -1,90 +0,0 @@ -import string - -import pytest -import sqlalchemy as sa - -from h.util.query import column_windows - -ASCII_LOWERCASE = string.ascii_lowercase - -meta = sa.MetaData() - -test_cw = sa.Table( - "test_column_windows", - meta, - sa.Column("id", sa.Integer, autoincrement=True, primary_key=True), - sa.Column("name", sa.UnicodeText, nullable=False), - sa.Column("enabled", sa.Boolean, nullable=False), -) - - -@pytest.mark.usefixtures("cw_table") -class TestColumnWindows: - @pytest.mark.parametrize( - "windowsize,expected", - [ - (100, ["abcdefghijklmnopqrstuvwxyz"]), - (26, ["abcdefghijklmnopqrstuvwxyz"]), - (13, ["abcdefghijklm", "nopqrstuvwxyz"]), - (10, ["abcdefghij", "klmnopqrst", "uvwxyz"]), - (5, ["abcde", "fghij", "klmno", "pqrst", "uvwxy", "z"]), - (1, list(ASCII_LOWERCASE)), - ], - ) - def test_basic_windowing(self, db_session, windowsize, expected): - """Check that windowing returns the correct batches of rows.""" - testdata = [{"name": char, "enabled": True} for char in ASCII_LOWERCASE] - db_session.execute(test_cw.insert().values(testdata)) - - windows = column_windows(db_session, test_cw.c.name, windowsize=windowsize) - - assert window_query_results(db_session, windows) == expected - - @pytest.mark.parametrize( - "windowsize,expected", - [ - (100, ["abcdefghijklm"]), - (13, ["abcdefghijklm"]), - (10, ["abcdefghij", "klm"]), - (3, ["abc", "def", "ghi", "jkl", "m"]), - (1, list(ASCII_LOWERCASE[:13])), - ], - ) - def test_filtered_windowing(self, db_session, windowsize, expected): - """Check that windowing respects the where clause.""" - testdata = [] - enabled = ASCII_LOWERCASE[:13] - disabled = ASCII_LOWERCASE[13:] - testdata.extend([{"name": char, "enabled": True} for char in enabled]) - testdata.extend([{"name": char, "enabled": False} for char in disabled]) - db_session.execute(test_cw.insert().values(testdata)) - - filter_ = test_cw.c.enabled - windows = column_windows( - db_session, test_cw.c.name, windowsize=windowsize, where=filter_ - ) - - assert window_query_results(db_session, windows, filter_) == expected - - -def window_query_results(session, windows, filter_=None): - """ - Fetch results using the passed windows and optional filter. - - Returns a list of strings which represent the rows returned by each - window. - """ - results = [] - for window in windows: - part = session.query(test_cw.c.name).filter(window) - if filter_ is not None: - part = part.filter(filter_) - results.append("".join(row.name for row in part)) - return results - - -@pytest.fixture -def cw_table(db_engine): - test_cw.create(db_engine) - yield - test_cw.drop(db_engine) diff --git a/tests/h/util/session_tracker_test.py b/tests/h/util/session_tracker_test.py deleted file mode 100644 index 856e7f158cd..00000000000 --- a/tests/h/util/session_tracker_test.py +++ /dev/null @@ -1,108 +0,0 @@ -from uuid import uuid4 - -import pytest -from sqlalchemy.orm.util import identity_key - -from h.db.types import URLSafeUUID -from h.models import Annotation, Document -from h.util.session_tracker import ObjectState, Tracker - - -def generate_ann_id(): - """Generate a random annotation identifier in the encoded form used by the API.""" - return URLSafeUUID.hex_to_url_safe(str(uuid4())) - - -class TestTracker: - @pytest.mark.usefixtures("session") - def test_uncommitted_changes_returns_unflushed_changes( - self, tracker, expected_changes - ): - added_entry, changed_entry, deleted_entry = expected_changes - - changes = tracker.uncommitted_changes() - - assert added_entry in changes - assert changed_entry in changes - assert deleted_entry in changes - - def test_uncommitted_changes_returns_flushed_changes( - self, tracker, session, expected_changes - ): - added_entry, changed_entry, deleted_entry = expected_changes - - session.flush() - changes = tracker.uncommitted_changes() - - assert added_entry in changes - assert changed_entry in changes - assert deleted_entry in changes - - def test_uncommitted_changes_does_not_return_committed_changes( - self, tracker, session - ): - session.commit() - assert tracker.uncommitted_changes() == [] - - def test_uncommitted_changes_does_not_return_rolled_back_changes( - self, tracker, session - ): - session.rollback() - assert tracker.uncommitted_changes() == [] - - @pytest.fixture - def expected_changes(self, added_ann_id, changed_ann_id, deleted_ann_id): - added_entry = (identity_key(Annotation, (added_ann_id,)), ObjectState.ADDED) - changed_entry = ( - identity_key(Annotation, (changed_ann_id,)), - ObjectState.CHANGED, - ) - deleted_entry = ( - identity_key(Annotation, (deleted_ann_id,)), - ObjectState.DELETED, - ) - - return (added_entry, changed_entry, deleted_entry) - - @pytest.fixture - def added_ann_id(self): - return generate_ann_id() - - @pytest.fixture - def changed_ann_id(self): - return generate_ann_id() - - @pytest.fixture - def deleted_ann_id(self): - return generate_ann_id() - - @pytest.fixture - def session(self, db_session, added_ann_id, changed_ann_id, deleted_ann_id): - # Populate the DB session with different types of change relative to the - # last-committed state. We could use any model object for this purpose - # but annotations are the primary object in the system. - - doc = Document(web_uri="https://example.org") - changed = Annotation( - id=changed_ann_id, userid="foo", groupid="wibble", document=doc - ) - deleted = Annotation( - id=deleted_ann_id, userid="foo", groupid="wibble", document=doc - ) - db_session.add(changed) - db_session.add(deleted) - db_session.commit() - - changed.text = "changed text" - db_session.delete(deleted) - - added = Annotation( - id=added_ann_id, userid="foo", groupid="wibble", document=doc - ) - db_session.add(added) - - return db_session - - @pytest.fixture - def tracker(self, db_session): - return Tracker(db_session) diff --git a/tests/h/views/api/decorators/__init__.py b/tests/h/views/api/decorators/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/h/views/api/helpers/__init__.py b/tests/h/views/api/helpers/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/h/views/api/moderation_test.py b/tests/h/views/api/moderation_test.py deleted file mode 100644 index c81a453007c..00000000000 --- a/tests/h/views/api/moderation_test.py +++ /dev/null @@ -1,97 +0,0 @@ -from unittest import mock - -import pytest -from pyramid.httpexceptions import HTTPNoContent - -from h.models import AnnotationModeration -from h.traversal import AnnotationContext -from h.views.api import moderation as views - - -class TestCreate: - def test_it_hides_the_annotation( - self, pyramid_request, annotation, annotation_context - ): - annotation.moderation = None - - views.create(annotation_context, pyramid_request) - - assert annotation.is_hidden - - def test_it_does_not_modify_an_already_hidden_annotation( - self, pyramid_request, annotation, annotation_context - ): - moderation = AnnotationModeration() - annotation.moderation = moderation - - views.create(annotation_context, pyramid_request) - - assert annotation.is_hidden - # It's the same one not a new one - assert annotation.moderation == moderation - - def test_it_publishes_update_event( - self, pyramid_request, annotation_context, events - ): - views.create(annotation_context, pyramid_request) - - events.AnnotationEvent.assert_called_once_with( - pyramid_request, annotation_context.annotation.id, "update" - ) - - pyramid_request.notify_after_commit.assert_called_once_with( - events.AnnotationEvent.return_value - ) - - def test_it_renders_no_content(self, pyramid_request, annotation_context): - response = views.create(annotation_context, pyramid_request) - assert isinstance(response, HTTPNoContent) - - -class TestDelete: - def test_it_unhides_the_annotation( - self, pyramid_request, annotation, annotation_context - ): - annotation.moderation = AnnotationModeration() - - views.delete(annotation_context, pyramid_request) - - assert not annotation.is_hidden - - def test_it_publishes_update_event( - self, pyramid_request, annotation_context, events - ): - views.delete(annotation_context, pyramid_request) - - events.AnnotationEvent.assert_called_once_with( - pyramid_request, annotation_context.annotation.id, "update" - ) - - pyramid_request.notify_after_commit.assert_called_once_with( - events.AnnotationEvent.return_value - ) - - def test_it_renders_no_content(self, pyramid_request, annotation_context): - response = views.delete(annotation_context, pyramid_request) - assert isinstance(response, HTTPNoContent) - - -@pytest.fixture -def annotation(factories): - return factories.Annotation() - - -@pytest.fixture -def annotation_context(annotation): - return AnnotationContext(annotation) - - -@pytest.fixture -def events(patch): - return patch("h.views.api.moderation.events") - - -@pytest.fixture -def pyramid_request(pyramid_request): - pyramid_request.notify_after_commit = mock.Mock() - return pyramid_request diff --git a/tests/h/views/feeds_test.py b/tests/h/views/feeds_test.py deleted file mode 100644 index 7bb02a20396..00000000000 --- a/tests/h/views/feeds_test.py +++ /dev/null @@ -1,103 +0,0 @@ -from unittest import mock - -import pytest - -from h.search.core import SearchResult -from h.views.feeds import stream_atom, stream_rss - - -@pytest.mark.usefixtures( - "fetch_ordered_annotations", "render_atom", "search_run", "routes" -) -class TestStreamAtom: - def test_renders_atom(self, pyramid_request, render_atom): - stream_atom(pyramid_request) - - render_atom.assert_called_once_with( - request=pyramid_request, - annotations=mock.sentinel.fetched_annotations, - atom_url="http://example.com/thestream.atom", - html_url="http://example.com/thestream", - title="Some feed", - subtitle="It contains stuff", - ) - - def test_returns_rendered_atom(self, pyramid_request, render_atom): - result = stream_atom(pyramid_request) - - assert result == render_atom.return_value - - -@pytest.mark.usefixtures( - "fetch_ordered_annotations", "render_rss", "search_run", "routes" -) -class TestStreamRSS: - def test_renders_rss(self, pyramid_request, render_rss): - stream_rss(pyramid_request) - - render_rss.assert_called_once_with( - request=pyramid_request, - annotations=mock.sentinel.fetched_annotations, - rss_url="http://example.com/thestream.rss", - html_url="http://example.com/thestream", - title="Some feed", - description="Stuff and things", - ) - - def test_returns_rendered_rss(self, pyramid_request, render_rss): - result = stream_rss(pyramid_request) - - assert result == render_rss.return_value - - -@pytest.fixture -def fetch_ordered_annotations(patch): - fetch_ordered_annotations = patch("h.views.feeds.fetch_ordered_annotations") - fetch_ordered_annotations.return_value = mock.sentinel.fetched_annotations - return fetch_ordered_annotations - - -@pytest.fixture -def pyramid_settings(pyramid_settings): - settings = {} - settings.update(pyramid_settings) - settings.update( - { - "h.feed.title": "Some feed", - "h.feed.subtitle": "It contains stuff", - "h.feed.description": "Stuff and things", - } - ) - return settings - - -@pytest.fixture -def render_atom(patch): - return patch("h.views.feeds.render_atom") - - -@pytest.fixture -def render_rss(patch): - return patch("h.views.feeds.render_rss") - - -@pytest.fixture -def routes(pyramid_config): - pyramid_config.add_route("stream_atom", "/thestream.atom") - pyramid_config.add_route("stream_rss", "/thestream.rss") - pyramid_config.add_route("stream", "/thestream") - - -@pytest.fixture -def search(patch): - return patch("h.views.feeds.search") - - -@pytest.fixture -def search_run(search): - result = SearchResult( - total=123, annotation_ids=["foo", "bar"], reply_ids=[], aggregations={} - ) - search_run = search.Search.return_value.run - search_run.return_value = result - return search_run diff --git a/tests/h/views/status_test.py b/tests/h/views/status_test.py deleted file mode 100644 index c42add978d4..00000000000 --- a/tests/h/views/status_test.py +++ /dev/null @@ -1,27 +0,0 @@ -from unittest import mock - -import pytest -from pyramid.httpexceptions import HTTPInternalServerError - -from h.views.status import status - - -@pytest.mark.usefixtures("db") -class TestStatus: - def test_it_returns_okay_on_success(self, pyramid_request): - result = status(pyramid_request) - assert result - - def test_it_fails_when_database_unreachable(self, pyramid_request, db): - db.execute.side_effect = Exception("explode!") - - with pytest.raises(HTTPInternalServerError) as exc: - status(pyramid_request) - - assert "Database connection failed" in str(exc.value) - - @pytest.fixture - def db(self, pyramid_request): - db = mock.Mock() - pyramid_request.db = db - return db diff --git a/tests/pyproject.toml b/tests/pyproject.toml new file mode 100644 index 00000000000..f7adc35ddbb --- /dev/null +++ b/tests/pyproject.toml @@ -0,0 +1,95 @@ +[tool.pylint.main] +jobs = 0 # Use one process for CPU. + +load-plugins = [ + "pylint.extensions.bad_builtin", + "pylint.extensions.check_elif", + "pylint.extensions.docparams", + "pylint.extensions.mccabe", + "pylint.extensions.overlapping_exceptions", + "pylint.extensions.redefined_variable_type", +] + +# Fail if there are *any* messages from PyLint. +# The letters refer to PyLint's message categories, see +# https://pylint.pycqa.org/en/latest/messages/messages_introduction.html +fail-on = ["C", "E", "F", "I", "R", "W"] + +[tool.pylint.messages_control] +ignore-paths = [ +] +enable = [ + "bad-inline-option", + "deprecated-pragma", + "useless-suppression", + "use-symbolic-message-instead", + "use-implicit-booleaness-not-comparison-to-zero", + "use-implicit-booleaness-not-comparison-to-string", +] +disable = [ + # Docstrings are encouraged but we don't want to enforce that everything + # must have a docstring. + "missing-docstring", + + # We don't always want to have to put a `:return:` in a docstring. + "missing-return-doc", + + # We don't always want to have to put an `:rtype:` in a docstring. + "missing-return-type-doc", + + # We don't want to have to document the type of every parameter with a + # `:type:` in the docstring. + "missing-type-doc", + + # We use isort to sort and group our imports, so we don't need PyLint to + # check them for us. + "ungrouped-imports", + + # We use Black to format our code automatically, so we don't need PyLint to + # check formatting for us. + "line-too-long", + + # Because of how pytest fixtures work it's frequently necessary for + # parameters to redefine outer names. + "redefined-outer-name", + + # Lots of test methods don't use self, but we still want to group our tests + # into classes. + "too-few-public-methods", + "too-many-public-methods", + + "too-many-arguments", + + # not-callable is mis-firing on all pytest.mark.parametrize usages, so + # disable it for now. This can be re-enabled once a new pytest version + # including https://github.com/pytest-dev/pytest/pull/7565 has been + # released. + "not-callable", + + # Issues to disable this for false positives, disabling it globally in the meantime https://github.com/PyCQA/pylint/issues/214 + "duplicate-code", + + # Temporarily ignored during pep8 -> pylint transition. This should be removed later. + "fixme", +] + +# Just disable PyLint's name style checking for the tests, because we +# frequently use lots of argument names that don't conform. +# For example we frequently create pytest fixtures that aren't named in +# snake_case, such as a fixture that returns a mock of the FooBar class would +# be named FooBar in CamelCase. +argument-naming-style = "any" +class-naming-style = "any" +function-naming-style = "any" +method-naming-style = "any" +variable-naming-style = "any" + +good-names = [ + "i", "j", "k", "ex", "Run", "_", # PyLint's default good names. + "pytestmark", + "os", # Name used for mocks of the standard os module. +] + +[tool.pylint.reports] +output-format = "colorized" +score = "no" diff --git a/h/services/job_queue/__init__.py b/tests/unit/__init__.py similarity index 100% rename from h/services/job_queue/__init__.py rename to tests/unit/__init__.py diff --git a/tests/h/__init__.py b/tests/unit/h/__init__.py similarity index 100% rename from tests/h/__init__.py rename to tests/unit/h/__init__.py diff --git a/tests/h/accounts/__init__.py b/tests/unit/h/accounts/__init__.py similarity index 100% rename from tests/h/accounts/__init__.py rename to tests/unit/h/accounts/__init__.py diff --git a/tests/h/accounts/__init___test.py b/tests/unit/h/accounts/__init___test.py similarity index 100% rename from tests/h/accounts/__init___test.py rename to tests/unit/h/accounts/__init___test.py diff --git a/tests/h/accounts/schemas_test.py b/tests/unit/h/accounts/schemas_test.py similarity index 85% rename from tests/h/accounts/schemas_test.py rename to tests/unit/h/accounts/schemas_test.py index 5e4a428508e..119a24a73dc 100644 --- a/tests/h/accounts/schemas_test.py +++ b/tests/unit/h/accounts/schemas_test.py @@ -1,3 +1,4 @@ +from datetime import datetime, timedelta from unittest.mock import Mock import colander @@ -6,6 +7,7 @@ from h.accounts import schemas from h.services.user_password import UserPasswordService +from h.util.user import format_userid pytestmark = pytest.mark.usefixtures("pyramid_config") @@ -72,35 +74,29 @@ def test_it_is_valid_when_authorized_users_email( schemas.unique_email(dummy_node, "elliot@bar.com") -@pytest.mark.usefixtures("user_model") class TestRegisterSchema: def test_it_is_invalid_when_password_too_short(self, pyramid_request): schema = schemas.RegisterSchema().bind(request=pyramid_request) with pytest.raises(colander.Invalid) as exc: schema.deserialize({"password": "a"}) - assert exc.value.asdict()["password"] == ("Must be 2 characters or more.") + assert exc.value.asdict()["password"] == ("Must be 8 characters or more.") - def test_it_is_invalid_when_username_too_short(self, pyramid_request, user_model): + def test_it_is_invalid_when_username_too_short(self, pyramid_request): schema = schemas.RegisterSchema().bind(request=pyramid_request) - user_model.get_by_username.return_value = None with pytest.raises(colander.Invalid) as exc: schema.deserialize({"username": "a"}) assert exc.value.asdict()["username"] == ("Must be 3 characters or more.") - def test_it_is_invalid_when_username_too_long(self, pyramid_request, user_model): + def test_it_is_invalid_when_username_too_long(self, pyramid_request): schema = schemas.RegisterSchema().bind(request=pyramid_request) - user_model.get_by_username.return_value = None with pytest.raises(colander.Invalid) as exc: schema.deserialize({"username": "a" * 500}) assert exc.value.asdict()["username"] == ("Must be 30 characters or less.") - def test_it_is_invalid_with_invalid_characters_in_username( - self, pyramid_request, user_model - ): - user_model.get_by_username.return_value = None + def test_it_is_invalid_with_invalid_characters_in_username(self, pyramid_request): schema = schemas.RegisterSchema().bind(request=pyramid_request) with pytest.raises(colander.Invalid) as exc: @@ -128,24 +124,51 @@ def test_it_is_invalid_when_privacy_accepted_missing(self, pyramid_request): assert exc.value.asdict()["privacy_accepted"] == "Required" - def test_it_validates_with_valid_payload(self, pyramid_csrf_request, user_model): - user_model.get_by_username.return_value = None - user_model.get_by_email.return_value = None + def test_it_is_invalid_when_user_recently_deleted( + self, factories, pyramid_request, valid_params + ): + """If an account with the same username was recently deleted it should be invalid.""" + schema = schemas.RegisterSchema().bind(request=pyramid_request) + factories.UserDeletion( + userid=format_userid( + username=valid_params["username"], + authority=pyramid_request.default_authority, + ) + ) + + with pytest.raises(colander.Invalid) as exc: + schema.deserialize(valid_params) + assert exc.value.asdict() == {"username": "This username is already taken."} + + def test_it_validates_with_valid_payload( + self, pyramid_csrf_request, valid_params, factories + ): schema = schemas.RegisterSchema().bind(request=pyramid_csrf_request) - params = { + # A user with the same username was deleted over a month ago. + # This should not prevent registration. + factories.UserDeletion( + userid=format_userid( + valid_params["username"], pyramid_csrf_request.default_authority + ), + requested_at=datetime.now() - timedelta(days=32), + ) + + result = schema.deserialize(valid_params) + + assert result == dict( + valid_params, privacy_accepted=True, comms_opt_in=None, csrf_token=None + ) + + @pytest.fixture + def valid_params(self): + return { "username": "filbert", "email": "foo@bar.com", "password": "sdlkfjlk3j3iuei", "privacy_accepted": "true", } - result = schema.deserialize(params) - - assert result == dict( - params, privacy_accepted=True, comms_opt_in=None, csrf_token=None - ) - @pytest.mark.usefixtures("models", "user_password_service") class TestEmailChangeSchema: @@ -273,8 +296,8 @@ def test_it_is_invalid_if_passwords_dont_match(self, pyramid_csrf_request): with pytest.raises(colander.Invalid) as exc: schema.deserialize( { - "new_password": "wibble", - "new_password_confirm": "wibble!", + "new_password": "foo-bar-baz", + "new_password_confirm": "foo-bar-buzz", "password": "flibble", } ) @@ -292,8 +315,8 @@ def test_it_is_invalid_if_current_password_is_wrong( with pytest.raises(colander.Invalid) as exc: schema.deserialize( { - "new_password": "wibble", - "new_password_confirm": "wibble", + "new_password": "foo-bar-baz", + "new_password_confirm": "foo-bar-baz", "password": "flibble", } ) diff --git a/tests/h/accounts/util_test.py b/tests/unit/h/accounts/util_test.py similarity index 100% rename from tests/h/accounts/util_test.py rename to tests/unit/h/accounts/util_test.py diff --git a/tests/h/activity/__init__.py b/tests/unit/h/activity/__init__.py similarity index 100% rename from tests/h/activity/__init__.py rename to tests/unit/h/activity/__init__.py diff --git a/tests/h/activity/bucketing_test.py b/tests/unit/h/activity/bucketing_test.py similarity index 99% rename from tests/h/activity/bucketing_test.py rename to tests/unit/h/activity/bucketing_test.py index fd262d6b683..9225ccb25e0 100644 --- a/tests/h/activity/bucketing_test.py +++ b/tests/unit/h/activity/bucketing_test.py @@ -24,9 +24,9 @@ def __eq__(self, timeframe): and self.document_buckets == timeframe.document_buckets ) - def __repr__(self): - # pragma: no cover - return f'{self.__class__} "{self.label}" with {len(self.document_buckets)} document buckets' + # pragma: nocover + def __repr__(self): # pragma: nocover + return f'{self.__class__} "{self.label}" with {len(self.document_buckets)} document buckets' # pragma: nocover @pytest.mark.usefixtures("factories") diff --git a/tests/h/activity/query_test.py b/tests/unit/h/activity/query_test.py similarity index 93% rename from tests/h/activity/query_test.py rename to tests/unit/h/activity/query_test.py index c13f21b2f0a..bcfc3057d21 100644 --- a/tests/h/activity/query_test.py +++ b/tests/unit/h/activity/query_test.py @@ -5,7 +5,8 @@ from pyramid.httpexceptions import HTTPFound from webob.multidict import MultiDict -from h.activity.query import check_url, execute, extract, fetch_annotations +from h.activity.query import check_url, execute, extract +from h.models import Annotation class TestExtract: @@ -190,7 +191,7 @@ def unparse(self): @pytest.mark.usefixtures( - "fetch_annotations", + "annotation_read_service", "_fetch_groups", "bucketing", "presenters", @@ -353,20 +354,22 @@ def test_it_returns_the_search_result_if_there_are_no_matches( assert result.timeframes == [] def test_it_fetches_the_annotations_from_the_database( - self, fetch_annotations, pyramid_request, search + self, annotation_read_service, pyramid_request, search ): execute(pyramid_request, MultiDict(), self.PAGE_SIZE) - fetch_annotations.assert_called_once_with( - pyramid_request.db, search.run.return_value.annotation_ids + annotation_read_service.get_annotations_by_id.assert_called_once_with( + ids=search.run.return_value.annotation_ids, eager_load=[Annotation.document] ) def test_it_buckets_the_annotations( - self, fetch_annotations, bucketing, pyramid_request + self, annotation_read_service, bucketing, pyramid_request ): result = execute(pyramid_request, MultiDict(), self.PAGE_SIZE) - bucketing.bucket.assert_called_once_with(fetch_annotations.return_value) + bucketing.bucket.assert_called_once_with( + annotation_read_service.get_annotations_by_id.return_value + ) assert result.timeframes == bucketing.bucket.return_value def test_it_fetches_the_groups_from_the_database( @@ -386,12 +389,12 @@ def test_it_returns_each_annotation_presented(self, annotations, pyramid_request for bucket in timeframe.document_buckets.values(): presented_annotations.extend(bucket.presented_annotations) - for annotation in annotations: - for presented_annotation in presented_annotations: - if presented_annotation["annotation"].annotation == annotation: - break - else: - assert False + assert set(annotations).intersection( + { + presented_anno["annotation"].annotation + for presented_anno in presented_annotations + } + ) def test_it_returns_each_annotations_group(self, _fetch_groups, pyramid_request): result = execute(pyramid_request, MultiDict(), self.PAGE_SIZE) @@ -401,12 +404,8 @@ def test_it_returns_each_annotations_group(self, _fetch_groups, pyramid_request) for bucket in timeframe.document_buckets.values(): presented_annotations.extend(bucket.presented_annotations) - for group in _fetch_groups.return_value: - for presented_annotation in presented_annotations: - if presented_annotation["group"] == group: - break - else: - assert False + expected_groups = [anno["group"] for anno in presented_annotations] + assert _fetch_groups.return_value == expected_groups def test_it_returns_each_annotations_incontext_link(self, links, pyramid_request): def incontext_link(request, annotation): @@ -460,10 +459,6 @@ def test_it_returns_the_aggregations(self, pyramid_request): assert result.aggregations == mock.sentinel.aggregations - @pytest.fixture - def fetch_annotations(self, patch): - return patch("h.activity.query.fetch_annotations") - @pytest.fixture def _fetch_groups(self, group_pubids, patch): _fetch_groups = patch("h.activity.query._fetch_groups") @@ -478,7 +473,6 @@ def annotations(self, factories, group_pubids): Return a single flat list of all 20 annotations that will be distributed among the timeframes and document buckets that our mock bucketing.bucket() will return. - """ return [ factories.Annotation.build(id="annotation_" + str(i), groupid=group_pubid) @@ -525,7 +519,6 @@ def document_buckets(self, annotations): Return a single flat list of all 7 document buckets that will be distributed among the timeframes that our mock bucketing.bucket() will return. - """ def document_bucket(annotations): @@ -552,7 +545,6 @@ def group_pubids(self): Return a single flat list of all 20 pubids of the groups of the annotations that our mock bucket() will return. - """ return ["group_" + str(i) for i in range(20)] @@ -607,16 +599,6 @@ def pyramid_request(self, pyramid_request): return pyramid_request -class TestFetchAnnotations: - def test_it_returns_annotations_by_ids(self, db_session, factories): - annotations = factories.Annotation.create_batch(3) - ids = [a.id for a in annotations] - - result = fetch_annotations(db_session, ids) - - assert annotations == result - - @pytest.fixture def pyramid_request(pyramid_request): class DummyRoute: diff --git a/tests/h/admin/__init__.py b/tests/unit/h/admin/__init__.py similarity index 100% rename from tests/h/admin/__init__.py rename to tests/unit/h/admin/__init__.py diff --git a/tests/h/app_test.py b/tests/unit/h/app_test.py similarity index 86% rename from tests/h/app_test.py rename to tests/unit/h/app_test.py index 798768333ae..812f7ae65de 100644 --- a/tests/h/app_test.py +++ b/tests/unit/h/app_test.py @@ -24,6 +24,7 @@ def test_it_configures_pyramid_sentry_plugin(self, pyramid_config): def pyramid_config(self, pyramid_config): # Mock out jinja2 related stuff pyramid_config.get_jinja2_environment = mock.create_autospec( + # pragma: nocover spec=lambda: JinjaEnvironment() # pylint: disable=unnecessary-lambda ) @@ -34,9 +35,13 @@ def pyramid_config(self, pyramid_config): auto_reload=True, ) - pyramid_config.add_jinja2_extension = mock.create_autospec(lambda name: True) + pyramid_config.add_jinja2_extension = mock.create_autospec( + lambda name: True + ) # pragma: nocover # Prevent us from really loading the includes - pyramid_config.include = mock.create_autospec(lambda name: True) + pyramid_config.include = mock.create_autospec( + lambda name: True + ) # pragma: nocover return pyramid_config diff --git a/tests/h/badge/__init__.py b/tests/unit/h/badge/__init__.py similarity index 100% rename from tests/h/badge/__init__.py rename to tests/unit/h/badge/__init__.py diff --git a/tests/h/celery_test.py b/tests/unit/h/celery_test.py similarity index 100% rename from tests/h/celery_test.py rename to tests/unit/h/celery_test.py diff --git a/tests/h/cli/__init__.py b/tests/unit/h/cli/__init__.py similarity index 100% rename from tests/h/cli/__init__.py rename to tests/unit/h/cli/__init__.py diff --git a/tests/h/cli/commands/__init__.py b/tests/unit/h/cli/commands/__init__.py similarity index 100% rename from tests/h/cli/commands/__init__.py rename to tests/unit/h/cli/commands/__init__.py diff --git a/tests/h/cli/commands/annotation_id_test.py b/tests/unit/h/cli/commands/annotation_id_test.py similarity index 100% rename from tests/h/cli/commands/annotation_id_test.py rename to tests/unit/h/cli/commands/annotation_id_test.py diff --git a/tests/h/cli/commands/authclient_test.py b/tests/unit/h/cli/commands/authclient_test.py similarity index 72% rename from tests/h/cli/commands/authclient_test.py rename to tests/unit/h/cli/commands/authclient_test.py index 6282edcadfb..93e42585367 100644 --- a/tests/h/cli/commands/authclient_test.py +++ b/tests/unit/h/cli/commands/authclient_test.py @@ -48,6 +48,34 @@ def test_it_prints_the_id_and_secret_for_confidential_client( ) assert expected_id_and_secret in output + def test_it_creates_an_authclient_with_grant_type(self, cli, cliconfig, db_session): + result = cli.invoke( + authclient_cli.add, + [ + "--name", + "AuthCode", + "--authority", + "example.org", + "--type", + "public", + "--grant-type", + "authorization_code", + "--redirect-uri", + "http://localhost:5000/app.html", + ], + obj=cliconfig, + ) + + assert not result.exit_code + + authclient = ( + db_session.query(models.AuthClient) + .filter(models.AuthClient.authority == "example.org") + .first() + ) + assert authclient.grant_type.value == "authorization_code" + assert authclient.redirect_uri == "http://localhost:5000/app.html" + def _add_authclient(self, cli, cliconfig, db_session, type_): result = cli.invoke( authclient_cli.add, diff --git a/tests/h/cli/commands/normalize_uris_test.py b/tests/unit/h/cli/commands/normalize_uris_test.py similarity index 91% rename from tests/h/cli/commands/normalize_uris_test.py rename to tests/unit/h/cli/commands/normalize_uris_test.py index 6c230b4e51c..5f208b8cfb5 100644 --- a/tests/h/cli/commands/normalize_uris_test.py +++ b/tests/unit/h/cli/commands/normalize_uris_test.py @@ -28,6 +28,7 @@ def test_it_normalizes_document_uris_uri(req): normalize_uris.normalize_document_uris(req) + # pylint:disable=comparison-with-callable,useless-suppression assert docuri_1.uri_normalized == "httpx://example.org" assert docuri_2.uri_normalized == "httpx://example.org" @@ -53,8 +54,14 @@ def test_it_normalizes_document_uris_claimant(req): normalize_uris.normalize_document_uris(req) - assert docuri_1.claimant_normalized == "httpx://example.org" - assert docuri_2.claimant_normalized == "httpx://example.org" + assert ( + docuri_1.claimant_normalized # pylint:disable=comparison-with-callable + == "httpx://example.org" + ) + assert ( + docuri_2.claimant_normalized # pylint:disable=comparison-with-callable + == "httpx://example.org" + ) def test_it_deletes_duplicate_document_uri_objects(req): @@ -123,8 +130,14 @@ def test_it_normalizes_document_meta_claimant(req): normalize_uris.normalize_document_meta(req) - assert docmeta_1.claimant_normalized == "httpx://example.org" - assert docmeta_2.claimant_normalized == "httpx://example.net" + assert ( + docmeta_1.claimant_normalized # pylint:disable=comparison-with-callable + == "httpx://example.org" + ) + assert ( + docmeta_2.claimant_normalized # pylint:disable=comparison-with-callable + == "httpx://example.net" + ) def test_it_deletes_duplicate_document_meta_objects(req): diff --git a/tests/h/cli/commands/search_test.py b/tests/unit/h/cli/commands/search_test.py similarity index 60% rename from tests/h/cli/commands/search_test.py rename to tests/unit/h/cli/commands/search_test.py index d09d2bed8b6..49f6b140077 100644 --- a/tests/h/cli/commands/search_test.py +++ b/tests/unit/h/cli/commands/search_test.py @@ -1,29 +1,13 @@ -import os from unittest import mock import pytest from h.cli.commands import search - -class TestReindexCommand: - @pytest.mark.usefixtures("reindex") - def test_it_raises_timeout(self, cli, cliconfig): - cli.invoke(search.reindex, [], obj=cliconfig) - assert os.getenv("ELASTICSEARCH_CLIENT_TIMEOUT") == "30" - - def test_calls_reindex(self, cli, cliconfig, pyramid_request, reindex): - result = cli.invoke(search.reindex, [], obj=cliconfig) - - assert not result.exit_code - reindex.assert_called_once_with( - pyramid_request.db, pyramid_request.es, pyramid_request - ) - - @pytest.fixture - def reindex(self, patch): - index = patch("h.cli.commands.search.indexer") - return index.reindex +pytestmark = [ + pytest.mark.xdist_group("elasticsearch"), + pytest.mark.usefixtures("init_elasticsearch"), +] class TestUpdateSettingsCommand: diff --git a/tests/unit/h/cli/commands/user_test.py b/tests/unit/h/cli/commands/user_test.py new file mode 100644 index 00000000000..62edc0af5ef --- /dev/null +++ b/tests/unit/h/cli/commands/user_test.py @@ -0,0 +1,207 @@ +from unittest import mock + +import pytest + +from h.cli.commands import user as user_cli +from h.models import User + + +class TestAddCommand: + def test_it_adds_user_with_default_authority(self, invoke_cli, user_signup_service): + result = invoke_cli( + user_cli.add, + [ + "--username", + "admin", + "--email", + "admin@localhost", + "--password", + "admin", + ], + ) + + assert not result.exit_code + + user_signup_service.signup.assert_called_with( + username="admin", + email="admin@localhost", + password="admin", + require_activation=False, + ) + + def test_it_adds_user_with_specific_authority( + self, invoke_cli, user_signup_service + ): + result = invoke_cli( + user_cli.add, + [ + "--username", + "admin", + "--email", + "admin@localhost", + "--password", + "admin", + "--authority", + "publisher.org", + ], + ) + + assert not result.exit_code + + user_signup_service.signup.assert_called_with( + username="admin", + email="admin@localhost", + password="admin", + authority="publisher.org", + require_activation=False, + ) + + +class TestAdminCommand: + def test_it_adds_admin(self, invoke_cli, non_admin_user, db_session): + result = invoke_cli(user_cli.admin, ["--on", non_admin_user.username]) + + assert not result.exit_code + + user = db_session.get(User, non_admin_user.id) + assert user.admin + + def test_it_adds_admin_by_default(self, invoke_cli, non_admin_user, db_session): + result = invoke_cli(user_cli.admin, [non_admin_user.username]) + + assert not result.exit_code + + user = db_session.get(User, non_admin_user.id) + assert user.admin + + def test_it_adds_admin_with_specific_authority( + self, invoke_cli, non_admin_user, db_session + ): + non_admin_user.authority = "partner.org" + db_session.flush() + + result = invoke_cli( + user_cli.admin, ["--authority", "partner.org", non_admin_user.username] + ) + + assert not result.exit_code + + user = db_session.get(User, non_admin_user.id) + assert user.admin + + def test_it_removes_admin(self, invoke_cli, admin_user, db_session): + result = invoke_cli(user_cli.admin, ["--off", admin_user.username]) + + assert not result.exit_code + + user = db_session.get(User, admin_user.id) + assert not user.admin + + def test_it_removes_admin_with_specific_authority( + self, invoke_cli, admin_user, db_session + ): + admin_user.authority = "partner.org" + + result = invoke_cli( + user_cli.admin, ["--off", "--authority", "partner.org", admin_user.username] + ) + + assert not result.exit_code + + user = db_session.get(User, admin_user.id) + assert not user.admin + + def test_it_errors_when_user_could_not_be_found( + self, invoke_cli, non_admin_user, db_session + ): + result = invoke_cli(user_cli.admin, [f"bogus_{non_admin_user.username}"]) + + assert result.exit_code == 1 + user = db_session.get(User, non_admin_user.id) + assert not user.admin + + def test_it_errors_when_user_with_specific_authority_could_not_be_found( + self, invoke_cli, non_admin_user, db_session + ): + result = invoke_cli( + user_cli.admin, ["--authority", "foo.com", non_admin_user.username] + ) + + assert result.exit_code == 1 + user = db_session.get(User, non_admin_user.id) + assert not user.admin + + @pytest.fixture + def admin_user(self, factories): + return factories.User(admin=True) + + @pytest.fixture + def non_admin_user(self, factories): + return factories.User(admin=False) + + +class TestPasswordCommand: + def test_it_changes_password( + self, invoke_cli, user, db_session, user_password_service + ): + result = invoke_cli(user_cli.password, [user.username, "--password", "newpass"]) + + assert not result.exit_code + + user = db_session.get(User, user.id) + user_password_service.update_password.assert_called_once_with(user, "newpass") + + def test_it_changes_password_with_specific_authority( + self, invoke_cli, user, db_session, user_password_service + ): + user.authority = "partner.org" + db_session.flush() + + result = invoke_cli( + user_cli.password, + ["--authority", "partner.org", user.username, "--password", "newpass"], + ) + + assert not result.exit_code + + user = db_session.get(User, user.id) + user_password_service.update_password.assert_called_once_with(user, "newpass") + + def test_it_errors_when_user_could_not_be_found( + self, invoke_cli, user_password_service + ): + result = invoke_cli( + user_cli.password, ["bogus_username", "--password", "newpass"] + ) + + assert result.exit_code == 1 + + user_password_service.update_password.assert_not_called() + + def test_it_errors_when_user_with_specific_authority_could_not_be_found( + self, invoke_cli, user, user_password_service + ): + result = invoke_cli( + user_cli.password, + ["--authority", "foo.com", user.username, "--password", "newpass"], + ) + + assert result.exit_code == 1 + + user_password_service.update_password.assert_not_called() + + @pytest.fixture + def user(self, factories): + return factories.User() + + +@pytest.fixture +def invoke_cli(cli, pyramid_request): + pyramid_request.tm = mock.Mock() + + def invoke_cli(method, args): + return cli.invoke( + method, args, obj={"bootstrap": mock.Mock(return_value=pyramid_request)} + ) + + return invoke_cli diff --git a/tests/h/config_test.py b/tests/unit/h/config_test.py similarity index 100% rename from tests/h/config_test.py rename to tests/unit/h/config_test.py diff --git a/tests/h/conftest.py b/tests/unit/h/conftest.py similarity index 66% rename from tests/h/conftest.py rename to tests/unit/h/conftest.py index 3a4eb47f3be..dbcf873f2b9 100644 --- a/tests/h/conftest.py +++ b/tests/unit/h/conftest.py @@ -5,26 +5,17 @@ import click.testing import deform import pytest -import sqlalchemy from pyramid import testing from pyramid.request import apply_request_extensions -from sqlalchemy.orm import sessionmaker from webob.multidict import MultiDict -from h import db from h.models import Organization -from h.settings import database_url +from h.models.auth_client import GrantType +from h.security import Identity from tests.common import factories as common_factories from tests.common.fixtures.elasticsearch import * # pylint:disable=wildcard-import,unused-wildcard-import from tests.common.fixtures.services import * # pylint:disable=wildcard-import,unused-wildcard-import -TEST_AUTHORITY = "example.com" -TEST_DATABASE_URL = database_url( - os.environ.get("TEST_DATABASE_URL", "postgresql://postgres@localhost/htest") -) - -Session = sessionmaker() - class DummyFeature: """ @@ -46,19 +37,6 @@ def all(self): return self.flags -class DummySession: - def __init__(self): - self.added = [] - self.deleted = [] - self.flushed = False - - def add(self, obj): - self.added.append(obj) - - def flush(self): - self.flushed = True - - # A fake version of colander.Invalid class FakeInvalid: def __init__(self, errors): @@ -82,14 +60,6 @@ def cli(): yield runner -@pytest.fixture(scope="session") -def db_engine(): - """Set up the database connection and create tables.""" - engine = sqlalchemy.create_engine(TEST_DATABASE_URL) - db.init(engine, should_create=True, should_drop=True, authority=TEST_AUTHORITY) - return engine - - @pytest.fixture def default_organization(db_session): # This looks a bit odd, but as part of our DB initialization we always add @@ -99,40 +69,6 @@ def default_organization(db_session): ) -@pytest.fixture -def db_session(db_engine): - """ - Prepare the SQLAlchemy session object. - - We enable fast repeatable database tests by setting up the database only - once per session (see :func:`db_engine`) and then wrapping each test - function in a transaction that is rolled back. - - Additionally, we set a SAVEPOINT before entering the test, and if we - detect that the test has committed (i.e. released the savepoint) we - immediately open another. This has the effect of preventing test code from - committing the outer transaction. - """ - conn = db_engine.connect() - trans = conn.begin() - session = Session(bind=conn) - session.begin_nested() - - @sqlalchemy.event.listens_for(session, "after_transaction_end") - def restart_savepoint(session, transaction): - if ( # pylint:disable=protected-access - transaction.nested and not transaction._parent.nested - ): - session.begin_nested() - - try: - yield session - finally: - session.close() - trans.rollback() - conn.close() - - @pytest.fixture def factories(db_session): common_factories.set_session(db_session) @@ -145,11 +81,6 @@ def fake_feature(): return DummyFeature() -@pytest.fixture -def fake_db_session(): - return DummySession() - - @pytest.fixture def form_validating_to(): def form_validating_to(appstruct): @@ -176,7 +107,7 @@ def invalid_form(errors=None): @pytest.fixture def matchers(): # pylint: disable=redefined-outer-name, import-outside-toplevel - from ..common import matchers + from tests.common import matchers return matchers @@ -208,10 +139,12 @@ def pyramid_config(pyramid_settings, pyramid_request): @pytest.fixture -def pyramid_request(db_session, fake_feature, pyramid_settings): +def pyramid_request(db_session, db_session_replica, fake_feature, pyramid_settings): """Return pyramid request object.""" - request = testing.DummyRequest(db=db_session, feature=fake_feature) - request.default_authority = TEST_AUTHORITY + request = testing.DummyRequest( + db=db_session, db_replica=db_session_replica, feature=fake_feature + ) + request.default_authority = "example.com" request.create_form = mock.Mock() request.matched_route = mock.Mock() request.registry.settings = pyramid_settings @@ -233,4 +166,16 @@ def pyramid_csrf_request(pyramid_request): @pytest.fixture def pyramid_settings(): """Return the default app settings.""" - return {"sqlalchemy.url": TEST_DATABASE_URL} + return {"sqlalchemy.url": os.environ["DATABASE_URL"]} + + +@pytest.fixture +def auth_client(factories): + return factories.ConfidentialAuthClient(grant_type=GrantType.client_credentials) + + +@pytest.fixture +def with_auth_client(auth_client, pyramid_config): + pyramid_config.testing_securitypolicy( + identity=Identity.from_models(auth_client=auth_client) + ) diff --git a/tests/h/db/__init__.py b/tests/unit/h/db/__init__.py similarity index 100% rename from tests/h/db/__init__.py rename to tests/unit/h/db/__init__.py diff --git a/tests/h/db/types_test.py b/tests/unit/h/db/types_test.py similarity index 100% rename from tests/h/db/types_test.py rename to tests/unit/h/db/types_test.py diff --git a/tests/h/emails/__init__.py b/tests/unit/h/emails/__init__.py similarity index 100% rename from tests/h/emails/__init__.py rename to tests/unit/h/emails/__init__.py diff --git a/tests/h/emails/flag_notification_test.py b/tests/unit/h/emails/flag_notification_test.py similarity index 100% rename from tests/h/emails/flag_notification_test.py rename to tests/unit/h/emails/flag_notification_test.py diff --git a/tests/h/emails/reply_notification_test.py b/tests/unit/h/emails/reply_notification_test.py similarity index 100% rename from tests/h/emails/reply_notification_test.py rename to tests/unit/h/emails/reply_notification_test.py diff --git a/tests/h/emails/reset_password_test.py b/tests/unit/h/emails/reset_password_test.py similarity index 100% rename from tests/h/emails/reset_password_test.py rename to tests/unit/h/emails/reset_password_test.py diff --git a/tests/h/emails/signup_test.py b/tests/unit/h/emails/signup_test.py similarity index 100% rename from tests/h/emails/signup_test.py rename to tests/unit/h/emails/signup_test.py diff --git a/tests/h/emails/test_test.py b/tests/unit/h/emails/test_test.py similarity index 100% rename from tests/h/emails/test_test.py rename to tests/unit/h/emails/test_test.py diff --git a/tests/h/eventqueue_test.py b/tests/unit/h/eventqueue_test.py similarity index 97% rename from tests/h/eventqueue_test.py rename to tests/unit/h/eventqueue_test.py index 7c6e8060006..4ae47c08bc1 100644 --- a/tests/h/eventqueue_test.py +++ b/tests/unit/h/eventqueue_test.py @@ -91,10 +91,6 @@ def test_response_callback_publishes_events(self, publish_all, pyramid_request): queue.response_callback(pyramid_request, None) assert publish_all.called - @pytest.fixture - def log(self, patch): - return patch("h.eventqueue.log") - @pytest.fixture def publish_all(self, patch): return patch("h.eventqueue.EventQueue.publish_all") diff --git a/tests/h/events_test.py b/tests/unit/h/events_test.py similarity index 100% rename from tests/h/events_test.py rename to tests/unit/h/events_test.py diff --git a/tests/h/feeds/__init__.py b/tests/unit/h/feeds/__init__.py similarity index 100% rename from tests/h/feeds/__init__.py rename to tests/unit/h/feeds/__init__.py diff --git a/tests/h/feeds/atom_test.py b/tests/unit/h/feeds/atom_test.py similarity index 91% rename from tests/h/feeds/atom_test.py rename to tests/unit/h/feeds/atom_test.py index 87b8988418e..86720eb0ea8 100644 --- a/tests/h/feeds/atom_test.py +++ b/tests/unit/h/feeds/atom_test.py @@ -1,25 +1,11 @@ -"""Unit tests for h/atom.py.""" from datetime import datetime, timedelta from unittest import mock import pytest -from h import models from h.feeds import atom -def _annotation(**kwargs): - args = { - "userid": "acct:janebloggs@hypothes.is", - "created": datetime.utcnow(), - "updated": datetime.utcnow(), - "target_selectors": [], - "document": models.Document(), - } - args.update(kwargs) - return models.Annotation(**args) - - def test_feed_id(): feed = atom.feed_from_annotations([], "atom_url", mock.Mock()) @@ -105,15 +91,22 @@ def test_entry_id(util, factories): assert feed["entries"][0]["id"] == util.tag_uri_for_annotation.return_value -def test_entry_author(factories): +@pytest.mark.parametrize( + "userid,name", + ( + ("acct:username@hypothes.is", "username"), + ("malformed", "malformed"), + ), +) +def test_entry_author(factories, userid, name): """The authors of entries should come from the annotation usernames.""" - annotation = factories.Annotation(userid="acct:nobu@hypothes.is") + annotation = factories.Annotation(userid=userid) feed = atom.feed_from_annotations( [annotation], "atom_url", lambda _: "annotation url" ) - assert feed["entries"][0]["author"]["name"] == "nobu" + assert feed["entries"][0]["author"]["name"] == name def test_entry_title(factories): diff --git a/tests/h/feeds/render_test.py b/tests/unit/h/feeds/render_test.py similarity index 100% rename from tests/h/feeds/render_test.py rename to tests/unit/h/feeds/render_test.py diff --git a/tests/h/feeds/rss_test.py b/tests/unit/h/feeds/rss_test.py similarity index 94% rename from tests/h/feeds/rss_test.py rename to tests/unit/h/feeds/rss_test.py index 807672027f1..8d09c095c85 100644 --- a/tests/h/feeds/rss_test.py +++ b/tests/unit/h/feeds/rss_test.py @@ -1,6 +1,8 @@ import datetime from unittest import mock +import pytest + from h import models from h.feeds import rss @@ -28,15 +30,22 @@ def _annotation(**kwargs): return models.Annotation(**args) -def test_feed_from_annotations_item_author(): +@pytest.mark.parametrize( + "userid,name", + ( + ("acct:username@hypothes.is", "username"), + ("malformed", "malformed"), + ), +) +def test_feed_from_annotations_item_author(userid, name): """Feed items should include the annotation's author.""" - annotation = _annotation() + annotation = _annotation(userid=userid) feed = rss.feed_from_annotations( [annotation], _annotation_url(), mock.Mock(), "", "", "" ) - assert feed["entries"][0]["author"] == {"name": "janebloggs"} + assert feed["entries"][0]["author"]["name"] == name def test_feed_annotations_pubDate(): diff --git a/tests/h/feeds/util_test.py b/tests/unit/h/feeds/util_test.py similarity index 100% rename from tests/h/feeds/util_test.py rename to tests/unit/h/feeds/util_test.py diff --git a/tests/h/form_test.py b/tests/unit/h/form_test.py similarity index 100% rename from tests/h/form_test.py rename to tests/unit/h/form_test.py diff --git a/tests/h/groups/__init__.py b/tests/unit/h/groups/__init__.py similarity index 100% rename from tests/h/groups/__init__.py rename to tests/unit/h/groups/__init__.py diff --git a/tests/h/indexer/__init__.py b/tests/unit/h/indexer/__init__.py similarity index 100% rename from tests/h/indexer/__init__.py rename to tests/unit/h/indexer/__init__.py diff --git a/tests/h/jinja2_extensions/__init__.py b/tests/unit/h/jinja2_extensions/__init__.py similarity index 100% rename from tests/h/jinja2_extensions/__init__.py rename to tests/unit/h/jinja2_extensions/__init__.py diff --git a/tests/h/jinja2_extensions/__init___test.py b/tests/unit/h/jinja2_extensions/__init___test.py similarity index 100% rename from tests/h/jinja2_extensions/__init___test.py rename to tests/unit/h/jinja2_extensions/__init___test.py diff --git a/tests/h/jinja2_extensions/back_link_label_test.py b/tests/unit/h/jinja2_extensions/back_link_label_test.py similarity index 100% rename from tests/h/jinja2_extensions/back_link_label_test.py rename to tests/unit/h/jinja2_extensions/back_link_label_test.py diff --git a/tests/h/jinja2_extensions/filter_test.py b/tests/unit/h/jinja2_extensions/filter_test.py similarity index 100% rename from tests/h/jinja2_extensions/filter_test.py rename to tests/unit/h/jinja2_extensions/filter_test.py diff --git a/tests/h/jinja2_extensions/navbar_data_admin_test.py b/tests/unit/h/jinja2_extensions/navbar_data_admin_test.py similarity index 100% rename from tests/h/jinja2_extensions/navbar_data_admin_test.py rename to tests/unit/h/jinja2_extensions/navbar_data_admin_test.py diff --git a/tests/h/jinja2_extensions/navbar_data_test.py b/tests/unit/h/jinja2_extensions/navbar_data_test.py similarity index 88% rename from tests/h/jinja2_extensions/navbar_data_test.py rename to tests/unit/h/jinja2_extensions/navbar_data_test.py index f89f6f53137..73a8c6773fe 100644 --- a/tests/h/jinja2_extensions/navbar_data_test.py +++ b/tests/unit/h/jinja2_extensions/navbar_data_test.py @@ -50,6 +50,25 @@ def test_it(self, pyramid_request, user): "username_url": f"http://example.com/users/{user.username}", } + def test_it_with_a_group_with_no_creator( + self, pyramid_request, user, factories, group_list_service + ): + user.groups = group_list_service.associated_groups.return_value = [ + factories.Group(creator=None) + ] + pyramid_request.user = user + + result = navbar_data(pyramid_request) + + assert result["groups_suggestions"] == [ + { + "name": group.name, + "pubid": group.pubid, + "relationship": None, + } + for group in user.groups + ] + def test_it_with_no_user(self, pyramid_request, group_list_service): pyramid_request.user = None group_list_service.associated_groups.return_value = [] diff --git a/tests/h/jinja2_extensions/svg_icon_test.py b/tests/unit/h/jinja2_extensions/svg_icon_test.py similarity index 100% rename from tests/h/jinja2_extensions/svg_icon_test.py rename to tests/unit/h/jinja2_extensions/svg_icon_test.py diff --git a/tests/h/links_test.py b/tests/unit/h/links_test.py similarity index 100% rename from tests/h/links_test.py rename to tests/unit/h/links_test.py diff --git a/tests/h/models/__init__.py b/tests/unit/h/models/__init__.py similarity index 100% rename from tests/h/models/__init__.py rename to tests/unit/h/models/__init__.py diff --git a/tests/unit/h/models/activation_test.py b/tests/unit/h/models/activation_test.py new file mode 100644 index 00000000000..f3b5f7db51d --- /dev/null +++ b/tests/unit/h/models/activation_test.py @@ -0,0 +1,24 @@ +import re + +import pytest + +from h.models.activation import Activation + + +class TestActivation: + def test_code(self, activation): + assert re.match(r"[A-Za-z0-9]{12}", activation.code) + + def test_get_by_code(self, activation, db_session): + result = Activation.get_by_code(db_session, code=activation.code) + + assert result == activation + + @pytest.fixture + def activation(self, db_session): + activation = Activation() + + db_session.add(activation) + db_session.flush() + + return activation diff --git a/tests/unit/h/models/annotation_moderation_test.py b/tests/unit/h/models/annotation_moderation_test.py new file mode 100644 index 00000000000..2295fb8fb05 --- /dev/null +++ b/tests/unit/h/models/annotation_moderation_test.py @@ -0,0 +1,8 @@ +from h.models.annotation_moderation import AnnotationModeration + + +class TestAnnotationModeration: + def test___repr__(self): + moderation = AnnotationModeration(annotation_id=123) + + assert repr(moderation) == "" diff --git a/tests/h/models/annotation_test.py b/tests/unit/h/models/annotation_test.py similarity index 94% rename from tests/h/models/annotation_test.py rename to tests/unit/h/models/annotation_test.py index 508b3a8f7d0..f7c20539396 100644 --- a/tests/h/models/annotation_test.py +++ b/tests/unit/h/models/annotation_test.py @@ -131,7 +131,7 @@ def test_setting_extras_inline_is_persisted(db_session, factories): # dict. Without this commit() this test would never fail. db_session.commit() - annotation = db_session.query(Annotation).get(annotation.id) + annotation = db_session.get(Annotation, annotation.id) assert annotation.extra == {"foo": "bar"} @@ -148,7 +148,7 @@ def test_deleting_extras_inline_is_persisted(db_session, factories): del annotation.extra["foo"] db_session.commit() - annotation = db_session.query(Annotation).get(annotation.id) + annotation = db_session.get(Annotation, annotation.id) assert "foo" not in annotation.extra @@ -165,7 +165,7 @@ def test_appending_tags_inline_is_persisted(db_session, factories): annotation.tags.append("bar") db_session.commit() - annotation = db_session.query(Annotation).get(annotation.id) + annotation = db_session.get(Annotation, annotation.id) assert "bar" in annotation.tags @@ -176,7 +176,7 @@ def test_deleting_tags_inline_is_persisted(db_session, factories): del annotation.tags[0] db_session.commit() - annotation = db_session.query(Annotation).get(annotation.id) + annotation = db_session.get(Annotation, annotation.id) assert "foo" not in annotation.tags @@ -250,6 +250,12 @@ def test_uuid(factories): assert annotation.uuid == UUID(URLSafeUUID.url_safe_to_hex(annotation.id)) +def test_repr(factories): + annotation = factories.Annotation() + + assert repr(annotation) == f"" + + @pytest.fixture def markdown_render(patch): return patch("h.models.annotation.markdown_render") diff --git a/tests/h/models/auth_client_test.py b/tests/unit/h/models/auth_client_test.py similarity index 90% rename from tests/h/models/auth_client_test.py rename to tests/unit/h/models/auth_client_test.py index 412058c21ce..fc6450b46ed 100644 --- a/tests/h/models/auth_client_test.py +++ b/tests/unit/h/models/auth_client_test.py @@ -31,6 +31,11 @@ def test_allows_empty_redirect_uri_for_other_grant( db_session.add(client) db_session.flush() + def test___repr__(self): + client = AuthClient(id=123) + + assert repr(client) == "AuthClient(id=123)" + @pytest.fixture def client(self, db_session): client = AuthClient(authority="example.com") diff --git a/tests/unit/h/models/blocklist_test.py b/tests/unit/h/models/blocklist_test.py new file mode 100644 index 00000000000..e3c41657133 --- /dev/null +++ b/tests/unit/h/models/blocklist_test.py @@ -0,0 +1,26 @@ +import pytest + +from h.models.blocklist import Blocklist + + +class TestBlocklist: + @pytest.mark.parametrize( + "block_uri,uri,is_blocked", + ( + ("http://example.com", "http://example.com", True), + ("http://example.com/path", "http://example.com/path", True), + (None, "http://example.com", False), + ("%//example.com%", "http://example.com", True), + ("%//example.com%", "http://example.com/path", True), + ), + ) + def test_is_blocked(self, db_session, block_uri, uri, is_blocked): + if block_uri: + db_session.add(Blocklist(uri=block_uri)) + + assert Blocklist.is_blocked(db_session, uri) == is_blocked + + def test___repr__(self): + blocklist = Blocklist(uri="http://example.com") + + assert repr(blocklist) == "http://example.com" diff --git a/tests/h/models/document/__init__.py b/tests/unit/h/models/document/__init__.py similarity index 100% rename from tests/h/models/document/__init__.py rename to tests/unit/h/models/document/__init__.py diff --git a/tests/h/models/document/_document_test.py b/tests/unit/h/models/document/_document_test.py similarity index 100% rename from tests/h/models/document/_document_test.py rename to tests/unit/h/models/document/_document_test.py diff --git a/tests/h/models/document/_meta_test.py b/tests/unit/h/models/document/_meta_test.py similarity index 98% rename from tests/h/models/document/_meta_test.py rename to tests/unit/h/models/document/_meta_test.py index db2692f3fcd..c486a302b3e 100644 --- a/tests/h/models/document/_meta_test.py +++ b/tests/unit/h/models/document/_meta_test.py @@ -71,7 +71,7 @@ def test_it_denormalizes_title_to_document_when_falsy( create_or_update_document_meta(session=db_session, **meta_attrs) - document = db_session.query(Document).get(document.id) + document = db_session.get(Document, document.id) assert document.title == final_title def test_it_logs_a_warning_with_existing_meta_on_a_different_doc( diff --git a/tests/h/models/document/_uri_test.py b/tests/unit/h/models/document/_uri_test.py similarity index 91% rename from tests/h/models/document/_uri_test.py rename to tests/unit/h/models/document/_uri_test.py index 17ad06026bd..3a70a08edae 100644 --- a/tests/h/models/document/_uri_test.py +++ b/tests/unit/h/models/document/_uri_test.py @@ -14,7 +14,10 @@ class TestDocumentURI: def test_it_normalizes_the_uri(self): document_uri = DocumentURI(uri="http://example.com/") - assert document_uri.uri_normalized == "httpx://example.com" + assert ( + document_uri.uri_normalized # pylint:disable=comparison-with-callable + == "httpx://example.com" + ) def test_type_defaults_to_empty_string(self, db_session, document_uri, factories): document_uri = factories.DocumentURI(type=None) @@ -40,6 +43,15 @@ def test_you_cannot_set_content_type_to_null(self, db_session, document_uri): with pytest.raises(sa.exc.IntegrityError): db_session.flush() + def test_unique_constraint_can_take_long_values(self, db_session): + document_uri = DocumentURI( + uri="http://example.com/" * 10000, + claimant="https://example.com" * 10000, + document=Document(), + ) + db_session.add(document_uri) + db_session.commit() + def test_you_cannot_add_duplicate_document_uris(self, db_session): # You can't add DocumentURI's with the same claimant, uri, type and # content_type, even if they have different documents. @@ -118,7 +130,7 @@ def test_it_skips_denormalizing_http_uris_to_document( create_or_update_document_uri(session=db_session, **doc_uri_attrs) - document_ = db_session.query(Document).get(document.id) + document_ = db_session.get(Document, document.id) assert document_.web_uri == "http://example.com/first_uri.html" def test_it_logs_a_warning_if_document_ids_differ( diff --git a/tests/h/models/feature_test.py b/tests/unit/h/models/feature_test.py similarity index 65% rename from tests/h/models/feature_test.py rename to tests/unit/h/models/feature_test.py index be6c7f33db0..3fc2818e457 100644 --- a/tests/h/models/feature_test.py +++ b/tests/unit/h/models/feature_test.py @@ -5,7 +5,7 @@ from h.models import Feature -@pytest.mark.usefixtures("features_override", "features_pending_removal_override") +@pytest.mark.usefixtures("features_override") class TestFeature: def test_description_returns_hardcoded_description(self): feat = Feature(name="notification") @@ -20,12 +20,11 @@ def test_all_creates_annotations_that_dont_exist(self, db_session): def test_all_only_returns_current_flags(self, db_session): """The .all() method should only return named current feature flags.""" - new, pending, old = [ + new, old = [ Feature(name="notification"), - Feature(name="abouttoberemoved"), Feature(name="somethingelse"), ] - db_session.add_all([new, pending, old]) + db_session.add_all([new, old]) db_session.flush() features = Feature.all(db_session) @@ -37,21 +36,20 @@ def test_remove_old_flag_removes_old_flags(self, db_session): """ The remove_old_flags function should remove unknown flags. - New flags and flags pending removal should be left alone, but completely + New flags should be left alone, but completely unknown flags should be removed. """ - new, pending, old = [ + new, old = [ Feature(name="notification"), - Feature(name="abouttoberemoved"), Feature(name="somethingelse"), ] - db_session.add_all([new, pending, old]) + db_session.add_all([new, old]) db_session.flush() Feature.remove_old_flags(db_session) remaining = {f.name for f in db_session.query(Feature).all()} - assert remaining == {"abouttoberemoved", "notification"} + assert remaining == {"notification"} @pytest.fixture def features_override(self, request): @@ -63,14 +61,3 @@ def features_override(self, request): ) patcher.start() request.addfinalizer(patcher.stop) - - @pytest.fixture - def features_pending_removal_override(self, request): - # And configure 'abouttoberemoved' as a feature pending removal... - patcher = mock.patch.dict( - "h.models.feature.FEATURES_PENDING_REMOVAL", - {"abouttoberemoved": "A test flag that's about to be removed."}, - clear=True, - ) - patcher.start() - request.addfinalizer(patcher.stop) diff --git a/tests/unit/h/models/flag_test.py b/tests/unit/h/models/flag_test.py new file mode 100644 index 00000000000..44e58091ef3 --- /dev/null +++ b/tests/unit/h/models/flag_test.py @@ -0,0 +1,8 @@ +from h.models.flag import Flag + + +class TestFlag: + def test___repr__(self): + flag = Flag(annotation_id=123, user_id=456) + + assert repr(flag) == "" diff --git a/tests/h/models/group_scope_test.py b/tests/unit/h/models/group_scope_test.py similarity index 100% rename from tests/h/models/group_scope_test.py rename to tests/unit/h/models/group_scope_test.py diff --git a/tests/h/models/group_test.py b/tests/unit/h/models/group_test.py similarity index 98% rename from tests/h/models/group_test.py rename to tests/unit/h/models/group_test.py index 3709722a6a6..4f79aba4ceb 100644 --- a/tests/h/models/group_test.py +++ b/tests/unit/h/models/group_test.py @@ -156,7 +156,7 @@ def test_type_raises_for_unknown_type_of_group(factories): def test_you_cannot_set_type(factories): group = factories.Group() - with pytest.raises(AttributeError, match="can't set attribute"): + with pytest.raises(AttributeError, match="object has no setter"): group.type = "open" diff --git a/tests/unit/h/models/helpers_test.py b/tests/unit/h/models/helpers_test.py new file mode 100644 index 00000000000..2a42fc473ae --- /dev/null +++ b/tests/unit/h/models/helpers_test.py @@ -0,0 +1,9 @@ +from unittest.mock import Mock + +from h.models import helpers + + +def test_repr_(): + obj = Mock(foo="FOO", bar="BAR") + + assert helpers.repr_(obj, ["foo", "bar"]) == "Mock(foo='FOO', bar='BAR')" diff --git a/tests/unit/h/models/job_test.py b/tests/unit/h/models/job_test.py new file mode 100644 index 00000000000..a4948dfd2e1 --- /dev/null +++ b/tests/unit/h/models/job_test.py @@ -0,0 +1,29 @@ +import pytest + + +def test___repr__(factories, helpers): + job = factories.Job() + repr_ = repr(job) + + helpers.repr_.assert_called_once_with( + job, + [ + "id", + "name", + "enqueued_at", + "scheduled_at", + "expires_at", + "priority", + "tag", + "kwargs", + ], + ) + assert repr_ == helpers.repr_.return_value + + +@pytest.fixture(autouse=True) +def helpers(mocker): + helpers = mocker.patch("h.models.job.helpers") + # __repr__() needs to return a string or repr() raises. + helpers.repr_.return_value = "test_string_representation" + return helpers diff --git a/tests/h/models/organization_test.py b/tests/unit/h/models/organization_test.py similarity index 100% rename from tests/h/models/organization_test.py rename to tests/unit/h/models/organization_test.py diff --git a/tests/unit/h/models/subscriptions_test.py b/tests/unit/h/models/subscriptions_test.py new file mode 100644 index 00000000000..17b82893a23 --- /dev/null +++ b/tests/unit/h/models/subscriptions_test.py @@ -0,0 +1,13 @@ +from h.models.subscriptions import Subscriptions + + +class TestSubscriptions: + def test___repr__(self): + subscription = Subscriptions( + uri="http://example.com", type=Subscriptions.Type.REPLY, active=True + ) + + assert ( + repr(subscription) + == "" + ) diff --git a/tests/h/models/token_test.py b/tests/unit/h/models/token_test.py similarity index 94% rename from tests/h/models/token_test.py rename to tests/unit/h/models/token_test.py index b3f09f323c9..56575d51b61 100644 --- a/tests/h/models/token_test.py +++ b/tests/unit/h/models/token_test.py @@ -46,7 +46,3 @@ def test_refresh_token_expired_is_true_if_in_past(self): token = Token(refresh_token_expires=refresh_token_expires) assert token.refresh_token_expired is True - - -def one_hour_from_now(): - return datetime.datetime.now() + datetime.timedelta(hours=1) diff --git a/tests/unit/h/models/user_deletion_test.py b/tests/unit/h/models/user_deletion_test.py new file mode 100644 index 00000000000..e580a589bfd --- /dev/null +++ b/tests/unit/h/models/user_deletion_test.py @@ -0,0 +1,28 @@ +import pytest + + +def test___repr__(factories, helpers): + user_deletion = factories.UserDeletion() + repr_ = repr(user_deletion) + + helpers.repr_.assert_called_once_with( + user_deletion, + [ + "id", + "userid", + "requested_at", + "requested_by", + "tag", + "registered_date", + "num_annotations", + ], + ) + assert repr_ == helpers.repr_.return_value + + +@pytest.fixture(autouse=True) +def helpers(mocker): + helpers = mocker.patch("h.models.user_deletion.helpers") + # __repr__() needs to return a string or repr() raises. + helpers.repr_.return_value = "test_string_representation" + return helpers diff --git a/tests/h/models/user_identity_test.py b/tests/unit/h/models/user_identity_test.py similarity index 78% rename from tests/h/models/user_identity_test.py rename to tests/unit/h/models/user_identity_test.py index d269e511cea..d702321d1d8 100644 --- a/tests/h/models/user_identity_test.py +++ b/tests/unit/h/models/user_identity_test.py @@ -44,8 +44,7 @@ def test_provider_cant_be_null(self, db_session, user): db_session.add(models.UserIdentity(provider_unique_id="1", user=user)) with pytest.raises( - sqlalchemy.exc.IntegrityError, - match='null value in column "provider" violates not-null constraint', + sqlalchemy.exc.IntegrityError, match='null value in column "provider"' ): db_session.flush() @@ -54,7 +53,7 @@ def test_provider_id_cant_be_null(self, db_session, user): with pytest.raises( sqlalchemy.exc.IntegrityError, - match='null value in column "provider_unique_id" violates not-null constraint', + match='null value in column "provider_unique_id"', ): db_session.flush() @@ -62,8 +61,7 @@ def test_user_cant_be_null(self, db_session): db_session.add(models.UserIdentity(provider="provider", provider_unique_id="1")) with pytest.raises( - sqlalchemy.exc.IntegrityError, - match='null value in column "user_id" violates not-null constraint', + sqlalchemy.exc.IntegrityError, match='null value in column "user_id"' ): db_session.flush() @@ -123,43 +121,24 @@ def test_different_users_can_have_the_same_provider_id_from_different_providers( db_session.flush() - def test_removing_a_user_identity_from_a_user_deletes_the_user_identity_from_the_db( - self, db_session, user - ): - # Add a couple of noise UserIdentity's. These should not be removed - # from the DB. - models.UserIdentity(provider="provider", provider_unique_id="1", user=user) - models.UserIdentity(provider="provider", provider_unique_id="2", user=user) - # The UserIdentity that we are going to remove. - user_identity = models.UserIdentity( - provider="provider", provider_unique_id="3", user=user - ) - - user.identities.remove(user_identity) - - assert user_identity not in db_session.query(models.UserIdentity).all() - + @pytest.mark.usefixtures("user_identities") def test_deleting_a_user_identity_removes_it_from_its_user(self, db_session, user): - # Add a couple of noise UserIdentity's. These should not be removed - # from user.identities. - models.UserIdentity(provider="provider", provider_unique_id="1", user=user) - models.UserIdentity(provider="provider", provider_unique_id="2", user=user) # The UserIdentity that we are going to remove. user_identity = models.UserIdentity( provider="provider", provider_unique_id="3", user=user ) + db_session.add(user_identity) db_session.commit() db_session.delete(user_identity) db_session.refresh(user) # Make sure user.identities is up to date. + + assert user_identity not in db_session.query(models.UserIdentity).all() assert user_identity not in user.identities + @pytest.mark.usefixtures("user_identities") def test_deleting_a_user_deletes_all_its_user_identities(self, db_session, user): - models.UserIdentity(provider="provider", provider_unique_id="1", user=user) - models.UserIdentity(provider="provider", provider_unique_id="2", user=user) - db_session.commit() - db_session.delete(user) assert not db_session.query(models.UserIdentity).count() @@ -176,3 +155,17 @@ def test_repr(self): @pytest.fixture def user(self, factories): return factories.User() + + @pytest.fixture + def user_identities(self, db_session, user): + db_session.add_all( + [ + models.UserIdentity( + provider="provider", provider_unique_id="1", user=user + ), + models.UserIdentity( + provider="provider", provider_unique_id="2", user=user + ), + ] + ) + db_session.commit() diff --git a/tests/h/models/user_test.py b/tests/unit/h/models/user_test.py similarity index 65% rename from tests/h/models/user_test.py rename to tests/unit/h/models/user_test.py index e6041f87e70..519be1fa436 100644 --- a/tests/h/models/user_test.py +++ b/tests/unit/h/models/user_test.py @@ -4,8 +4,8 @@ from sqlalchemy import exc from sqlalchemy.sql.elements import BinaryExpression -from h import models -from h.models.user import UserIDComparator +from h.models import Activation +from h.models.user import User, UserIDComparator class TestUserIDComparator: @@ -30,24 +30,18 @@ def comparator(self): class TestUserModelDataConstraints: """Unit tests for :py:module:`h.models.User` data integrity constraints.""" - def test_cannot_create_dot_variant_of_user(self, db_session): - fred = models.User( - authority="example.com", username="fredbloggs", email="fred@example.com" + def test_cannot_create_dot_variant_of_user(self, db_session, fred): + db_session.add( + User(authority=fred.authority, username="fred.bloggs", email=fred.email) ) - fred2 = models.User( - authority="example.com", username="fred.bloggs", email="fred@example.org" - ) - - db_session.add(fred) - db_session.add(fred2) with pytest.raises(exc.IntegrityError): db_session.flush() def test_cannot_create_case_variant_of_user(self, db_session): - bob = models.User( + bob = User( authority="example.com", username="BobJones", email="bob@example.com" ) - bob2 = models.User( + bob2 = User( authority="example.com", username="bobjones", email="bob@example.org" ) @@ -56,56 +50,51 @@ def test_cannot_create_case_variant_of_user(self, db_session): with pytest.raises(exc.IntegrityError): db_session.flush() - def test_filtering_by_username_matches_dot_variant_of_user(self, db_session): - fred = models.User( - authority="example.com", username="fredbloggs", email="fred@example.com" - ) - db_session.add(fred) - db_session.flush() - - result = db_session.query(models.User).filter_by(username="fred.bloggs").one() + def test_filtering_by_username_matches_dot_variant_of_user(self, db_session, fred): + result = db_session.query(User).filter_by(username="fred.bloggs").one() assert result == fred - def test_filtering_by_username_matches_case_variant_of_user(self, db_session): - fred = models.User( - authority="example.com", username="fredbloggs", email="fred@example.com" + def test_filtering_by_username_matches_dot_variant_of_user_using_in( + self, db_session, fred + ): + result = ( + db_session.query(User) + .filter(User.username.in_(["Fred.bloggs"])) # pylint:disable=no-member + .one() ) - db_session.add(fred) - db_session.flush() - - result = db_session.query(models.User).filter_by(username="FredBloggs").one() assert result == fred - def test_userid_derived_from_username_and_authority(self): - fred = models.User( - authority="example.net", username="fredbloggs", email="fred@example.com" - ) + def test_filtering_by_username_matches_case_variant_of_user(self, db_session, fred): + result = db_session.query(User).filter_by(username="FredBloggs").one() - assert fred.userid == "acct:fredbloggs@example.net" + assert result == fred + + def test_userid_derived_from_username_and_authority(self, fred): + assert fred.userid == "acct:fredbloggs@example.com" def test_cannot_create_user_with_too_short_username(self): with pytest.raises(ValueError): - models.User(username="aa") + User(username="aa") def test_cannot_create_user_with_too_long_username(self): with pytest.raises(ValueError): - models.User(username="1234567890123456789012345678901") + User(username="1234567890123456789012345678901") def test_cannot_create_user_with_invalid_chars(self): with pytest.raises(ValueError): - models.User(username="foo-bar") + User(username="foo-bar") def test_cannot_create_user_with_too_long_email(self): with pytest.raises(ValueError): - models.User(email="bob@b" + "o" * 100 + "b.com") + User(email="bob@b" + "o" * 100 + "b.com") def test_can_create_user_with_null_email(self): - models.User(email=None) + User(email=None) def test_can_change_email_to_null(self): - user = models.User(email="bob@bob.com") + user = User(email="bob@bob.com") user.email = None @@ -131,17 +120,9 @@ def test_can_create_two_users_with_same_null_email_and_authority( class TestUserModelUserId: - def test_userid_equals_query(self, db_session): - fred = models.User( - authority="example.net", username="fredbloggs", email="fred@example.com" - ) - db_session.add(fred) - db_session.flush() - + def test_userid_equals_query(self, db_session, fred): result = ( - db_session.query(models.User) - .filter_by(userid="acct:fredbloggs@example.net") - .one() + db_session.query(User).filter_by(userid="acct:fredbloggs@example.com").one() ) assert result == fred @@ -150,30 +131,23 @@ def test_userid_equals_query_with_invalid_userid(self, db_session): # This is to ensure that we don't expose the InvalidUserId that could # potentially be thrown by split_user. - result = ( - db_session.query(models.User) - .filter_by(userid="fredbloggsexample.net") - .all() - ) + result = db_session.query(User).filter_by(userid="fredbloggsexample.com").all() assert result == [] - def test_userid_in_query(self, db_session): - fred = models.User( - authority="example.net", username="fredbloggs", email="fred@example.net" - ) - alice = models.User( + def test_userid_in_query(self, db_session, fred): + alice = User( authority="foobar.com", username="alicewrites", email="alice@foobar.com" ) - db_session.add_all([fred, alice]) + db_session.add(alice) db_session.flush() result = ( - db_session.query(models.User) + db_session.query(User) .filter( - models.User.userid.in_( # pylint:disable=no-member + User.userid.in_( # pylint:disable=no-member [ - "acct:fredbloggs@example.net", + "acct:fredbloggs@example.com", "acct:alicewrites@foobar.com", "acct:missing@bla.org", ] @@ -186,21 +160,14 @@ def test_userid_in_query(self, db_session): assert fred in result assert alice in result - def test_userid_in_query_with_invalid_userid_mixed_in(self, db_session): + def test_userid_in_query_with_invalid_userid_mixed_in(self, db_session, fred): # This is to ensure that we don't expose the InvalidUserId that could # potentially be thrown by split_user. - - fred = models.User( - authority="example.net", username="fredbloggs", email="fred@example.com" - ) - db_session.add(fred) - db_session.flush() - result = ( - db_session.query(models.User) + db_session.query(User) .filter( # pylint:disable=no-member - models.User.userid.in_(["acct:fredbloggs@example.net", "invalid"]) + User.userid.in_(["acct:fredbloggs@example.com", "invalid"]) ) .all() ) @@ -213,11 +180,9 @@ def test_userid_in_query_with_only_invalid_userid(self, db_session): # potentially be thrown by split_user. result = ( - db_session.query(models.User) + db_session.query(User) .filter( - models.User.userid.in_( # pylint:disable=no-member - ["fredbloggsexample.net"] - ) + User.userid.in_(["fredbloggsexample.net"]) # pylint:disable=no-member ) .all() ) @@ -244,17 +209,15 @@ def test_activate_updates_activation_date(self, user): def test_privacy_accepted_defaults_to_None(self): # nullable - assert getattr(models.User(), "privacy_accepted") is None + assert getattr(User(), "privacy_accepted") is None def test_repr(self, user): assert repr(user) == "" @pytest.fixture def user(self, db_session): - user = models.User( - authority="example.com", username="kiki", email="kiki@kiki.com" - ) - user.activation = models.Activation() + user = User(authority="example.com", username="kiki", email="kiki@kiki.com") + user.activation = Activation() db_session.add(user) db_session.flush() @@ -264,7 +227,7 @@ def user(self, db_session): class TestUserGetByEmail: def test_it_returns_a_user(self, db_session, users): user = users["meredith"] - actual = models.User.get_by_email(db_session, user.email, user.authority) + actual = User.get_by_email(db_session, user.email, user.authority) assert actual == user @pytest.mark.usefixtures("users") @@ -272,24 +235,24 @@ def test_it_filters_by_email(self, db_session): authority = "example.com" email = "bogus@msn.com" - actual = models.User.get_by_email(db_session, email, authority) + actual = User.get_by_email(db_session, email, authority) assert actual is None def test_it_filters_email_case_insensitive(self, db_session, users): user = users["emily"] mixed_email = "eMiLy@mSn.com" - actual = models.User.get_by_email(db_session, mixed_email, user.authority) + actual = User.get_by_email(db_session, mixed_email, user.authority) assert actual == user def test_it_filters_by_authority(self, db_session, users): user = users["norma"] - actual = models.User.get_by_email(db_session, user.email, "example.com") + actual = User.get_by_email(db_session, user.email, "example.com") assert actual is None def test_you_cannot_get_users_with_no_emails(self, db_session): - assert not models.User.get_by_email(db_session, None, "example.com") + assert not User.get_by_email(db_session, None, "example.com") @pytest.fixture def users(self, db_session, factories): @@ -313,14 +276,14 @@ class TestUserGetByActivation: def test_it(self, db_session, factories): activated_user = factories.User(activation=factories.Activation()) - user = models.User.get_by_activation(db_session, activated_user.activation) + user = User.get_by_activation(db_session, activated_user.activation) assert user == activated_user def test_it_with_no_matches(self, db_session, factories): activation = factories.Activation() - user = models.User.get_by_activation(db_session, activation) + user = User.get_by_activation(db_session, activation) assert user is None @@ -329,20 +292,20 @@ class TestUserGetByUsername: def test_it_returns_a_user(self, db_session, users): user = users["meredith"] - actual = models.User.get_by_username(db_session, user.username, user.authority) + actual = User.get_by_username(db_session, user.username, user.authority) assert actual == user def test_it_filters_by_username(self, db_session): authority = "example.com" username = "bogus" - actual = models.User.get_by_username(db_session, username, authority) + actual = User.get_by_username(db_session, username, authority) assert actual is None def test_it_filters_by_authority(self, db_session, users): user = users["norma"] - actual = models.User.get_by_username(db_session, user.username, "example.com") + actual = User.get_by_username(db_session, user.username, "example.com") assert actual is None @pytest.fixture @@ -354,3 +317,12 @@ def users(self, db_session, factories): } db_session.flush() return users + + +@pytest.fixture +def fred(db_session): + fred = User(authority="example.com", username="fredbloggs", email="fred@email.com") + + db_session.add(fred) + db_session.flush() + return fred diff --git a/tests/h/notification/__init__.py b/tests/unit/h/notification/__init__.py similarity index 100% rename from tests/h/notification/__init__.py rename to tests/unit/h/notification/__init__.py diff --git a/tests/unit/h/notification/reply_test.py b/tests/unit/h/notification/reply_test.py new file mode 100644 index 00000000000..c44d6fcea7c --- /dev/null +++ b/tests/unit/h/notification/reply_test.py @@ -0,0 +1,142 @@ +from unittest.mock import call + +import pytest + +from h.models import Subscriptions +from h.notification.reply import Notification, get_notification + + +class TestGetNotification: + def test_it( + self, + annotation, + parent, + annotation_user, + parent_user, + pyramid_request, + user_service, + subscription_service, + annotation_read_service, + ): + result = get_notification(pyramid_request, annotation, "create") + + annotation_read_service.get_annotation_by_id.assert_called_once_with( + annotation.parent_id + ) + user_service.fetch.assert_has_calls( + [call(parent.userid), call(annotation.userid)] + ) + subscription_service.get_subscription.assert_called_once_with( + user_id=parent.userid, type_=Subscriptions.Type.REPLY + ) + + assert isinstance(result, Notification) + assert result.reply == annotation + assert result.parent == parent + assert result.reply_user == annotation_user + assert result.parent_user == parent_user + assert result.document == annotation.document + + def test_it_returns_none_when_action_is_not_create( + self, pyramid_request, annotation + ): + assert get_notification(pyramid_request, annotation, "NOT_CREATE") is None + + def test_it_returns_none_when_annotation_is_not_reply( + self, pyramid_request, annotation + ): + annotation.references = None + + assert get_notification(pyramid_request, annotation, "create") is None + + def test_it_returns_none_when_parent_does_not_exist( + self, + pyramid_request, + annotation, + annotation_read_service, + ): + annotation_read_service.get_annotation_by_id.return_value = None + + assert get_notification(pyramid_request, annotation, "create") is None + + def test_it_returns_none_when_parent_user_does_not_exist( + self, pyramid_request, annotation, user_service, factories + ): + user_service.fetch.side_effect = (None, factories.User()) + + assert get_notification(pyramid_request, annotation, "create") is None + + def test_it_returns_none_when_reply_user_does_not_exist( + self, pyramid_request, annotation, user_service, factories + ): + user_service.fetch.side_effect = (factories.User(), None) + + assert get_notification(pyramid_request, annotation, "create") is None + + def test_it_returns_none_when_parent_user_has_no_email_address( + self, pyramid_request, annotation, parent_user + ): + parent_user.email = None + assert get_notification(pyramid_request, annotation, "create") is None + + def test_it_returns_none_when_reply_by_same_user( + self, pyramid_request, annotation, user_service, factories + ): + single_user = factories.User() + user_service.fetch.side_effect = (single_user, single_user) + + assert get_notification(pyramid_request, annotation, "create") is None + + def test_it_returns_none_when_parent_user_cannot_read_reply( + self, pyramid_request, annotation + ): + annotation.shared = False + + assert get_notification(pyramid_request, annotation, "create") is None + + def test_it_returns_none_when_subscription_inactive( + self, pyramid_request, annotation, subscription_service + ): + subscription_service.get_subscription.return_value.active = False + + assert get_notification(pyramid_request, annotation, "create") is None + + # This would all be a lot more pleasant if we had some SQLAlchemy + # relationships between these very important items + @pytest.fixture + def annotation_user(self, factories, db_session): + annotation_user = factories.User() + db_session.flush() + return annotation_user + + @pytest.fixture + def annotation(self, factories, annotation_user, parent): + return factories.Annotation( + userid=annotation_user.userid, shared=True, references=[parent.id] + ) + + @pytest.fixture + def parent_user(self, factories, db_session): + parent_user = factories.User() + db_session.flush() + return parent_user + + @pytest.fixture + def parent(self, factories, db_session, parent_user, annotation_read_service): + parent = factories.Annotation(userid=parent_user.userid) + db_session.flush() + + annotation_read_service.get_annotation_by_id.return_value = parent + return parent + + @pytest.fixture(autouse=True) + def user_service(self, user_service, parent_user, annotation_user): + user_service.fetch.side_effect = (parent_user, annotation_user) + return user_service + + @pytest.fixture(autouse=True) + def subscription_service(self, subscription_service, factories): + subscription_service.get_subscription.return_value = factories.Subscriptions( + active=True + ) + return subscription_service diff --git a/tests/h/paginator_test.py b/tests/unit/h/paginator_test.py similarity index 100% rename from tests/h/paginator_test.py rename to tests/unit/h/paginator_test.py diff --git a/tests/h/presenters/__init__.py b/tests/unit/h/presenters/__init__.py similarity index 100% rename from tests/h/presenters/__init__.py rename to tests/unit/h/presenters/__init__.py diff --git a/tests/h/presenters/annotation_html_test.py b/tests/unit/h/presenters/annotation_html_test.py similarity index 99% rename from tests/h/presenters/annotation_html_test.py rename to tests/unit/h/presenters/annotation_html_test.py index d3abbe45ae3..e31e7a2ad52 100644 --- a/tests/h/presenters/annotation_html_test.py +++ b/tests/unit/h/presenters/annotation_html_test.py @@ -1,7 +1,7 @@ import datetime import pytest -from jinja2 import Markup +from markupsafe import Markup from h.presenters.annotation_html import AnnotationHTMLPresenter diff --git a/tests/h/presenters/annotation_jsonld_test.py b/tests/unit/h/presenters/annotation_jsonld_test.py similarity index 100% rename from tests/h/presenters/annotation_jsonld_test.py rename to tests/unit/h/presenters/annotation_jsonld_test.py diff --git a/tests/h/presenters/annotation_searchindex_test.py b/tests/unit/h/presenters/annotation_searchindex_test.py similarity index 53% rename from tests/h/presenters/annotation_searchindex_test.py rename to tests/unit/h/presenters/annotation_searchindex_test.py index 56ce37d4422..79ed90c4add 100644 --- a/tests/h/presenters/annotation_searchindex_test.py +++ b/tests/unit/h/presenters/annotation_searchindex_test.py @@ -1,73 +1,67 @@ -import datetime -from unittest import mock - import pytest +from h_matchers import Any from h.presenters.annotation_searchindex import AnnotationSearchIndexPresenter +from h.util.datetime import utc_iso8601 pytestmark = pytest.mark.usefixtures("moderation_service") @pytest.mark.usefixtures("nipsa_service") class TestAnnotationSearchIndexPresenter: - def test_asdict(self, DocumentSearchIndexPresenter, pyramid_request): - annotation = mock.MagicMock( - id="xyz123", - created=datetime.datetime(2016, 2, 24, 18, 3, 25, 768), - updated=datetime.datetime(2016, 2, 29, 10, 24, 5, 564), - userid="acct:luke@hypothes.is", - text="It is magical!", - tags=["magic"], - groupid="__world__", - shared=True, - references=["referenced-id-1", "referenced-id-2"], - thread_ids=["thread-id-1", "thread-id-2"], - extra={"extra-1": "foo", "extra-2": "bar"}, + def test_asdict(self, DocumentSearchIndexPresenter, pyramid_request, factories): + annotation = factories.Annotation( + references=[ + reference.id for reference in factories.Annotation.create_batch(2) + ] ) - DocumentSearchIndexPresenter.return_value.asdict.return_value = {"foo": "bar"} + replies = factories.Annotation.create_batch(2, references=[annotation.id]) annotation_dict = AnnotationSearchIndexPresenter( annotation, pyramid_request ).asdict() assert annotation_dict == { - "authority": "hypothes.is", - "id": "xyz123", - "created": "2016-02-24T18:03:25.000768+00:00", - "updated": "2016-02-29T10:24:05.000564+00:00", - "user": "acct:luke@hypothes.is", - "user_raw": "acct:luke@hypothes.is", + "authority": annotation.authority, + "id": annotation.id, + "created": utc_iso8601(annotation.created), + "updated": utc_iso8601(annotation.updated), + "user": annotation.userid, + "user_raw": annotation.userid, "uri": annotation.target_uri, - "text": "It is magical!", - "tags": ["magic"], - "tags_raw": ["magic"], - "group": "__world__", - "shared": True, - "target": annotation.target, - "document": {"foo": "bar"}, - "references": ["referenced-id-1", "referenced-id-2"], - "thread_ids": ["thread-id-1", "thread-id-2"], + "text": annotation.text, + "tags": annotation.tags, + "tags_raw": annotation.tags, + "group": annotation.groupid, + "shared": annotation.shared, + "target": [ + {"scope": [annotation.target_uri_normalized], **annotation.target[0]} + ], + "document": DocumentSearchIndexPresenter.return_value.asdict.return_value, + "references": annotation.references, + "thread_ids": Any.list.containing([reply.id for reply in replies]).only(), "hidden": False, } @pytest.mark.parametrize("is_moderated", [True, False]) @pytest.mark.parametrize("replies_moderated", [True, False]) def test_it_marks_annotation_hidden_correctly( - self, pyramid_request, moderation_service, is_moderated, replies_moderated + self, + pyramid_request, + moderation_service, + is_moderated, + replies_moderated, + factories, ): - # Annotation reply ids are referred to as thread_ids in our code base. - reply_ids = ["thread-id-1", "thread-id-2"] - - annotation = mock.MagicMock( - userid="acct:luke@hypothes.is", thread_ids=reply_ids - ) + annotation = factories.Annotation() + replies = factories.Annotation.create_batch(2, references=[annotation.id]) # Configure moderation return value moderated_ids = [] if is_moderated: moderated_ids.append(annotation.id) if replies_moderated: - moderated_ids.extend(reply_ids) + moderated_ids.extend([reply.id for reply in replies]) moderation_service.all_hidden.return_value = moderated_ids annotation_dict = AnnotationSearchIndexPresenter( @@ -78,7 +72,7 @@ def test_it_marks_annotation_hidden_correctly( assert annotation_dict["hidden"] == bool(is_moderated and replies_moderated) @pytest.mark.parametrize("is_nipsaed", [True, False]) - def test_it_marks_annotation_nipsaed_correctly( + def test_it_marks_annotation_nipsad_correctly( self, pyramid_request, nipsa_service, is_nipsaed, factories ): annotation = factories.Annotation.build() diff --git a/tests/h/presenters/document_html_test.py b/tests/unit/h/presenters/document_html_test.py similarity index 92% rename from tests/h/presenters/document_html_test.py rename to tests/unit/h/presenters/document_html_test.py index 38fbafc97ee..d107546155d 100644 --- a/tests/h/presenters/document_html_test.py +++ b/tests/unit/h/presenters/document_html_test.py @@ -1,7 +1,7 @@ from unittest import mock -import jinja2 import pytest +from markupsafe import Markup, escape from h.presenters.document_html import DocumentHTMLPresenter @@ -26,7 +26,7 @@ def test_filename_returns_Markup(self): document_uris=[mock.Mock(uri="file:///home/seanh/MyFile.pdf")] ) - assert isinstance(presenter.filename, jinja2.Markup) + assert isinstance(presenter.filename, Markup) def test_filename_with_FILE_uri(self): presenter = self.presenter( @@ -65,7 +65,7 @@ def test_href_returns_empty_string_for_document_with_no_web_uri(self): def test_href_returns_Markup(self): web_uri = "http://www.example.com/example.html" - assert isinstance(self.presenter(web_uri=web_uri).href, jinja2.Markup) + assert isinstance(self.presenter(web_uri=web_uri).href, Markup) link_text_fixtures = pytest.mark.usefixtures("title") @@ -105,12 +105,12 @@ def test_link_text_with_https_title(self, title): @link_text_fixtures def test_link_text_returns_Markup_if_title_returns_Markup(self, title): for title_ in ( - jinja2.Markup("Example Document"), - jinja2.Markup("http://www.example.com/example.html"), - jinja2.Markup("https://www.example.com/example.html"), + Markup("Example Document"), + Markup("http://www.example.com/example.html"), + Markup("https://www.example.com/example.html"), ): title.return_value = title_ - assert isinstance(self.presenter().link_text, jinja2.Markup) + assert isinstance(self.presenter().link_text, Markup) hostname_or_filename_fixtures = pytest.mark.usefixtures("uri", "filename") @@ -122,9 +122,9 @@ def test_hostname_or_filename_returns_filename_for_files(self, filename): @hostname_or_filename_fixtures def test_hostname_or_filename_returns_Markup_if_filename_does(self, filename): - filename.return_value = jinja2.Markup("MyFile.pdf") + filename.return_value = Markup("MyFile.pdf") - assert isinstance(self.presenter().hostname_or_filename, jinja2.Markup) + assert isinstance(self.presenter().hostname_or_filename, Markup) @hostname_or_filename_fixtures def test_hostname_or_filename_unquotes_filenames(self, filename): @@ -142,9 +142,9 @@ def test_hostname_or_filename_returns_hostname_for_non_files(self, uri, filename @hostname_or_filename_fixtures def test_hostname_or_filename_returns_Markup_when_uri_does(self, uri, filename): filename.return_value = "" - uri.return_value = jinja2.Markup("http://www.example.com/example.html") + uri.return_value = Markup("http://www.example.com/example.html") - assert isinstance(self.presenter().hostname_or_filename, jinja2.Markup) + assert isinstance(self.presenter().hostname_or_filename, Markup) @hostname_or_filename_fixtures def test_hostname_or_filename_with_empty_string_for_uri(self, uri, filename): @@ -178,10 +178,10 @@ def test_title_escapes_html_in_document_titles(self): title = self.presenter(title=spam_link).title - assert jinja2.escape(spam_link) in title + assert escape(spam_link) in title for char in ["<", ">", '"', "'"]: assert char not in title - assert isinstance(title, jinja2.Markup) + assert isinstance(title, Markup) @title_fixtures def test_title_with_file_uri(self, filename): @@ -193,9 +193,9 @@ def test_title_with_file_uri(self, filename): @title_fixtures def test_title_returns_Markup_when_filename_returns_Markup(self, filename): - filename.return_value = jinja2.Markup("MyFile.pdf") + filename.return_value = Markup("MyFile.pdf") - assert isinstance(self.presenter(title=None).title, jinja2.Markup) + assert isinstance(self.presenter(title=None).title, Markup) @title_fixtures def test_title_unquotes_uris(self, uri, filename): @@ -207,9 +207,9 @@ def test_title_unquotes_uris(self, uri, filename): @title_fixtures def test_title_returns_Markup_when_uri_returns_Markup(self, uri, filename): filename.return_value = "" # This is not a file:// URI. - uri.return_value = jinja2.Markup("http://example.com/example.html") + uri.return_value = Markup("http://example.com/example.html") - assert isinstance(self.presenter(title=None).title, jinja2.Markup) + assert isinstance(self.presenter(title=None).title, Markup) @title_fixtures def test_title_when_document_has_None_for_title(self, uri, filename): diff --git a/tests/h/presenters/document_json_test.py b/tests/unit/h/presenters/document_json_test.py similarity index 100% rename from tests/h/presenters/document_json_test.py rename to tests/unit/h/presenters/document_json_test.py diff --git a/tests/h/presenters/document_searchindex_test.py b/tests/unit/h/presenters/document_searchindex_test.py similarity index 100% rename from tests/h/presenters/document_searchindex_test.py rename to tests/unit/h/presenters/document_searchindex_test.py diff --git a/tests/h/presenters/group_json_test.py b/tests/unit/h/presenters/group_json_test.py similarity index 97% rename from tests/h/presenters/group_json_test.py rename to tests/unit/h/presenters/group_json_test.py index 86724618630..98d83130f04 100644 --- a/tests/h/presenters/group_json_test.py +++ b/tests/unit/h/presenters/group_json_test.py @@ -5,6 +5,11 @@ from h.presenters.group_json import GroupJSONPresenter, GroupsJSONPresenter +pytestmark = [ + pytest.mark.xdist_group("elasticsearch"), + pytest.mark.usefixtures("init_elasticsearch"), +] + @pytest.mark.usefixtures("group_links_service") class TestGroupJSONPresenter: diff --git a/tests/h/presenters/organization_json_test.py b/tests/unit/h/presenters/organization_json_test.py similarity index 100% rename from tests/h/presenters/organization_json_test.py rename to tests/unit/h/presenters/organization_json_test.py diff --git a/tests/h/presenters/user_json_test.py b/tests/unit/h/presenters/user_json_test.py similarity index 100% rename from tests/h/presenters/user_json_test.py rename to tests/unit/h/presenters/user_json_test.py diff --git a/tests/h/realtime_test.py b/tests/unit/h/realtime_test.py similarity index 100% rename from tests/h/realtime_test.py rename to tests/unit/h/realtime_test.py diff --git a/tests/h/renderers_test.py b/tests/unit/h/renderers_test.py similarity index 100% rename from tests/h/renderers_test.py rename to tests/unit/h/renderers_test.py diff --git a/tests/h/routes_test.py b/tests/unit/h/routes_test.py similarity index 95% rename from tests/h/routes_test.py rename to tests/unit/h/routes_test.py index 630a50785c0..ee5b38a959a 100644 --- a/tests/h/routes_test.py +++ b/tests/unit/h/routes_test.py @@ -124,6 +124,17 @@ def test_includeme(): ), call("api.bulk.action", "/api/bulk", request_method="POST"), call("api.bulk.annotation", "/api/bulk/annotation", request_method="POST"), + call("api.bulk.group", "/api/bulk/group", request_method="POST"), + call( + "api.bulk.stats.users", + "/api/bulk/stats/users", + request_method="POST", + ), + call( + "api.bulk.stats.assignments", + "/api/bulk/stats/assignments", + request_method="POST", + ), call("api.groups", "/api/groups", factory="h.traversal.GroupRoot"), call( "api.group_upsert", @@ -173,6 +184,7 @@ def test_includeme(): call("token", "/api/token"), call("oauth_authorize", "/oauth/authorize"), call("oauth_revoke", "/oauth/revoke"), + call("api.analytics.events", "/api/analytics/events"), call("sidebar_app", "/app.html"), call("notebook_app", "/notebook"), call("profile_app", "/user-profile"), diff --git a/tests/h/schemas/__init__.py b/tests/unit/h/schemas/__init__.py similarity index 100% rename from tests/h/schemas/__init__.py rename to tests/unit/h/schemas/__init__.py diff --git a/tests/unit/h/schemas/analytics_test.py b/tests/unit/h/schemas/analytics_test.py new file mode 100644 index 00000000000..ac72d2293cb --- /dev/null +++ b/tests/unit/h/schemas/analytics_test.py @@ -0,0 +1,28 @@ +import pytest + +from h.schemas import ValidationError +from h.schemas.analytics import CreateEventSchema + + +class TestCreateEventSchema: + @pytest.mark.parametrize( + "payload,expected_error", + [ + ({}, "'event' is a required property"), + ({"foo": "bar"}, "'event' is a required property"), + ( + {"event": "invalid"}, + "event: 'invalid' is not one of \\['client.realtime.apply_updates'\\]", + ), + ], + ) + def test_error_for_invalid_data(self, payload: dict, expected_error: str): + schema = CreateEventSchema() + with pytest.raises(ValidationError, match=expected_error): + schema.validate(payload) + + def test_valid_data_is_returned(self): + schema = CreateEventSchema() + result = schema.validate({"event": "client.realtime.apply_updates"}) + + assert result == {"event": "client.realtime.apply_updates"} diff --git a/tests/h/schemas/annotation_test.py b/tests/unit/h/schemas/annotation_test.py similarity index 94% rename from tests/h/schemas/annotation_test.py rename to tests/unit/h/schemas/annotation_test.py index c9489497a02..2e8c9f2c6bc 100644 --- a/tests/h/schemas/annotation_test.py +++ b/tests/unit/h/schemas/annotation_test.py @@ -65,7 +65,7 @@ def test_it_does_not_raise_for_full_valid_data(self, pyramid_request, validate): "references": ["foo", "bar"], "tags": ["foo", "bar"], "target": [ - {"selector": [{"type": "foo"}]}, + {"selector": [{"type": "foo", "suffix": "selector suffix"}]}, {"selector": [{"type": "bar"}]}, ], "text": "foo", @@ -122,6 +122,14 @@ def test_it_does_not_raise_for_full_valid_data(self, pyramid_request, validate): {"document": {"link": [{"href": False}]}}, "document.link.0.href: False is not of type 'string'", ), + ( + { + "document": { + "link": [{"href": f"https://example.com?{'LONG'*3000}"}] + } + }, + f"document.link.0.href: 'https://example.com?{'LONG'*3000}' is too long", + ), ( {"document": {"link": [{"href": "http://example.com", "type": False}]}}, "document.link.0.type: False is not of type 'string'", @@ -143,6 +151,7 @@ def test_it_does_not_raise_for_full_valid_data(self, pyramid_request, validate): ), ({"references": False}, "references: False is not of type 'array'"), ({"references": [False]}, "references.0: False is not of type 'string'"), + ({"tags": ["tag" * 1000]}, f"tags.0: '{'tag' * 1000}' is too long"), ({"tags": False}, "tags: False is not of type 'array'"), ({"tags": [False]}, "tags.0: False is not of type 'string'"), ({"target": False}, "target: False is not of type 'array'"), @@ -249,6 +258,43 @@ def test_it_replaces_target_with_target_selectors(self, pyramid_request, validat {"type": "BarSelector"}, ] + @pytest.mark.parametrize( + "payload,expected", + [ + ( + { + "target": [ + { + "selector": [ + {"type": "FooSelector", "suffix": "Invalid \ud835"} + ], + } + ] + }, + "suffix: 'suffix' must be valid unicode", + ), + ( + { + "target": [ + { + "selector": [ + {"type": "FooSelector", "prefix": "Invalid \ud835"} + ], + } + ] + }, + "prefix: 'prefix' must be valid unicode", + ), + ], + ) + def test_it_validates_invalid_unicode( + self, pyramid_request, validate, payload, expected + ): + with pytest.raises(ValidationError) as exc: + validate(pyramid_request, payload) + + assert str(exc.value) == expected + def test_it_extracts_document_uris_from_the_document( self, pyramid_request, document_claims, validate ): diff --git a/tests/h/schemas/api/__init__.py b/tests/unit/h/schemas/api/__init__.py similarity index 100% rename from tests/h/schemas/api/__init__.py rename to tests/unit/h/schemas/api/__init__.py diff --git a/tests/h/schemas/api/group_test.py b/tests/unit/h/schemas/api/group_test.py similarity index 96% rename from tests/h/schemas/api/group_test.py rename to tests/unit/h/schemas/api/group_test.py index 6fc14df16ba..ad69998d77a 100644 --- a/tests/h/schemas/api/group_test.py +++ b/tests/unit/h/schemas/api/group_test.py @@ -122,14 +122,6 @@ def test_validate_raises_ValidationError_groupid_authority_mismatch( {"name": "Shambles", "groupid": "group:valid_id@invalidauthority.com"} ) - @pytest.fixture - def appstruct(self): - return { - "groupid": "group:valid_id@thirdparty.com", - "name": "DingDong!", - "description": "OH, hello there", - } - @pytest.fixture def schema(self): schema = GroupAPISchema( diff --git a/tests/h/schemas/api/user_test.py b/tests/unit/h/schemas/api/user_test.py similarity index 98% rename from tests/h/schemas/api/user_test.py rename to tests/unit/h/schemas/api/user_test.py index c3c15294519..9d44267c2b0 100644 --- a/tests/h/schemas/api/user_test.py +++ b/tests/unit/h/schemas/api/user_test.py @@ -117,8 +117,9 @@ def test_it_allows_valid_identities(self, schema, payload): def test_it_raises_when_email_missing_and_identities_empty(self, schema, payload): del payload["email"] payload["identities"] = [] - - with pytest.raises(ValidationError, match=".*identities.*too short.*"): + with pytest.raises( + ValidationError, match="identities: \\[\\] should be non-empty" + ): schema.validate(payload) def test_it_raises_when_identities_not_an_array(self, schema, payload): diff --git a/tests/unit/h/schemas/auth_client_test.py b/tests/unit/h/schemas/auth_client_test.py new file mode 100644 index 00000000000..9ab7505b116 --- /dev/null +++ b/tests/unit/h/schemas/auth_client_test.py @@ -0,0 +1,46 @@ +import colander +import pytest + +from h.schemas.auth_client import CreateAuthClientSchema + +pytestmark = pytest.mark.usefixtures("pyramid_config") + + +class TestCreateAuthClientSchema: + def test_it_allows_valid_authcode_data(self, authcode_data, bound_schema): + bound_schema.deserialize(authcode_data) + + def test_it_allows_valid_clientcredentials_data( + self, client_credentials_data, bound_schema + ): + bound_schema.deserialize(client_credentials_data) + + def test_it_raises_if_redirect_url_missing(self, authcode_data, bound_schema): + authcode_data["redirect_url"] = None + + with pytest.raises( + colander.Invalid, match='Required when grant type is "authorization_code"' + ): + bound_schema.deserialize(authcode_data) + + @pytest.fixture + def authcode_data(self): + return { + "name": "Test client", + "authority": "example.com", + "grant_type": "authorization_code", + "trusted": False, + "redirect_url": "https://test-client.com/oauth-redirect", + } + + @pytest.fixture + def client_credentials_data(self): + return { + "name": "Test client", + "authority": "example.com", + "grant_type": "client_credentials", + } + + @pytest.fixture + def bound_schema(self, pyramid_csrf_request): + return CreateAuthClientSchema().bind(request=pyramid_csrf_request) diff --git a/tests/h/schemas/base_test.py b/tests/unit/h/schemas/base_test.py similarity index 94% rename from tests/h/schemas/base_test.py rename to tests/unit/h/schemas/base_test.py index f39dc8f1cdc..01ecdbf08d8 100644 --- a/tests/h/schemas/base_test.py +++ b/tests/unit/h/schemas/base_test.py @@ -48,6 +48,13 @@ def test_ok_with_good_csrf_from_header(self, pyramid_csrf_request): class TestJSONSchema: + def test_it_raises_for_unsupported_schema_versions(self): + class BadSchema(JSONSchema): + schema_version = 95 + + with pytest.raises(ValueError): + BadSchema() + def test_it_returns_data_when_valid(self): data = {"foo": "baz", "bar": 123} diff --git a/tests/h/schemas/forms/__init__.py b/tests/unit/h/schemas/forms/__init__.py similarity index 100% rename from tests/h/schemas/forms/__init__.py rename to tests/unit/h/schemas/forms/__init__.py diff --git a/tests/h/schemas/forms/accounts/__init__.py b/tests/unit/h/schemas/forms/accounts/__init__.py similarity index 100% rename from tests/h/schemas/forms/accounts/__init__.py rename to tests/unit/h/schemas/forms/accounts/__init__.py diff --git a/tests/h/schemas/forms/accounts/edit_profile_test.py b/tests/unit/h/schemas/forms/accounts/edit_profile_test.py similarity index 100% rename from tests/h/schemas/forms/accounts/edit_profile_test.py rename to tests/unit/h/schemas/forms/accounts/edit_profile_test.py diff --git a/tests/h/schemas/forms/accounts/forgot_password_test.py b/tests/unit/h/schemas/forms/accounts/forgot_password_test.py similarity index 100% rename from tests/h/schemas/forms/accounts/forgot_password_test.py rename to tests/unit/h/schemas/forms/accounts/forgot_password_test.py diff --git a/tests/h/schemas/forms/accounts/login_test.py b/tests/unit/h/schemas/forms/accounts/login_test.py similarity index 100% rename from tests/h/schemas/forms/accounts/login_test.py rename to tests/unit/h/schemas/forms/accounts/login_test.py diff --git a/tests/h/schemas/forms/accounts/reset_password_test.py b/tests/unit/h/schemas/forms/accounts/reset_password_test.py similarity index 92% rename from tests/h/schemas/forms/accounts/reset_password_test.py rename to tests/unit/h/schemas/forms/accounts/reset_password_test.py index bca51012cb3..9135e5e5ccf 100644 --- a/tests/h/schemas/forms/accounts/reset_password_test.py +++ b/tests/unit/h/schemas/forms/accounts/reset_password_test.py @@ -12,9 +12,9 @@ @pytest.mark.usefixtures("pyramid_config") class TestResetPasswordSchemaDeserialize: def test_it_is_valid_with_a_long_password(self, schema): - # Yeah... our minimum password length is 2 chars. See + # Yeah... our minimum password length is 8 chars. See # `h.schema.forms.accounts.util` - schema.deserialize({"user": "*any*", "password": "aa"}) + schema.deserialize({"user": "*any*", "password": "new-password"}) @pytest.mark.parametrize("password", ("", "a")) def test_it_is_invalid_with_password_too_short(self, schema, password): @@ -25,7 +25,7 @@ def test_it_is_invalid_with_password_too_short(self, schema, password): def test_it_is_invalid_with_a_null_user(self, schema): with pytest.raises(colander.Invalid) as exc: - schema.deserialize({"user": colander.null, "password": "*any*"}) + schema.deserialize({"user": colander.null, "password": "new-password"}) assert "user" in exc.value.asdict() @@ -33,7 +33,7 @@ def test_it_is_invalid_with_a_missing_user(self, schema, models): models.User.get_by_username.return_value = None with pytest.raises(colander.Invalid) as exc: - schema.deserialize({"user": "encoded_token", "password": "*any*"}) + schema.deserialize({"user": "encoded_token", "password": "new-password"}) assert "user" in exc.value.asdict() @@ -41,7 +41,7 @@ def test_it_is_invalid_with_invalid_user_token(self, schema, serializer): serializer.loads.side_effect = BadData("Invalid token") with pytest.raises(colander.Invalid) as exc: - schema.deserialize({"user": "INVALID_TOKEN", "password": "*any*"}) + schema.deserialize({"user": "INVALID_TOKEN", "password": "new-password"}) assert "user" in exc.value.asdict() assert "Wrong reset code." in exc.value.asdict()["user"] @@ -50,7 +50,7 @@ def test_it_is_invalid_with_expired_token(self, schema, serializer): serializer.loads.side_effect = SignatureExpired("Token has expired") with pytest.raises(colander.Invalid) as exc: - schema.deserialize({"user": "encoded_token", "password": "*any*"}) + schema.deserialize({"user": "encoded_token", "password": "new-password"}) serializer.loads.assert_called_once_with( "encoded_token", max_age=72 * 3600, return_timestamp=True @@ -74,7 +74,9 @@ def test_it_returns_user_when_valid( ): user.password_updated = password_updated - appstruct = schema.deserialize({"user": "encoded_token", "password": "secret"}) + appstruct = schema.deserialize( + {"user": "encoded_token", "password": "new-password"} + ) models.User.get_by_username.assert_called_once_with( pyramid_csrf_request.db, @@ -89,7 +91,7 @@ def test_it_is_invalid_if_user_has_already_reset_their_password(self, schema, us user.password_updated = datetime.now() + timedelta(days=1) with pytest.raises(colander.Invalid) as exc: - schema.deserialize({"user": "EXPIRED_TOKEN", "password": "*any*"}) + schema.deserialize({"user": "EXPIRED_TOKEN", "password": "new-password"}) assert "user" in exc.value.asdict() assert "This reset code has already been used." in exc.value.asdict()["user"] diff --git a/tests/h/schemas/forms/admin/__init__.py b/tests/unit/h/schemas/forms/admin/__init__.py similarity index 100% rename from tests/h/schemas/forms/admin/__init__.py rename to tests/unit/h/schemas/forms/admin/__init__.py diff --git a/tests/h/schemas/forms/admin/group_test.py b/tests/unit/h/schemas/forms/admin/group_test.py similarity index 100% rename from tests/h/schemas/forms/admin/group_test.py rename to tests/unit/h/schemas/forms/admin/group_test.py diff --git a/tests/h/schemas/forms/admin/organization_test.py b/tests/unit/h/schemas/forms/admin/organization_test.py similarity index 84% rename from tests/h/schemas/forms/admin/organization_test.py rename to tests/unit/h/schemas/forms/admin/organization_test.py index 9e2d4e98440..abddc3b668c 100644 --- a/tests/h/schemas/forms/admin/organization_test.py +++ b/tests/unit/h/schemas/forms/admin/organization_test.py @@ -8,13 +8,19 @@ class TestOrganizationSchema: - def test_it_allows_valid_data(self, org_data, bound_schema): + @pytest.mark.parametrize( + "logo", + ("foo", 'foo'), + ) + def test_it_allows_valid_data(self, org_data, bound_schema, logo): + org_data["logo"] = logo + bound_schema.deserialize(org_data) def test_it_raises_if_logo_is_too_long(self, org_data, bound_schema): - org_data[ - "logo" - ] = f'{"a" * Organization.LOGO_MAX_CHARS}b' + org_data["logo"] = ( + f'{"a" * Organization.LOGO_MAX_CHARS}b' + ) with pytest.raises( colander.Invalid, diff --git a/tests/h/schemas/forms/group_test.py b/tests/unit/h/schemas/forms/group_test.py similarity index 100% rename from tests/h/schemas/forms/group_test.py rename to tests/unit/h/schemas/forms/group_test.py diff --git a/tests/h/schemas/util_test.py b/tests/unit/h/schemas/util_test.py similarity index 100% rename from tests/h/schemas/util_test.py rename to tests/unit/h/schemas/util_test.py diff --git a/tests/h/schemas/validators_test.py b/tests/unit/h/schemas/validators_test.py similarity index 100% rename from tests/h/schemas/validators_test.py rename to tests/unit/h/schemas/validators_test.py diff --git a/tests/h/search/__init__.py b/tests/unit/h/search/__init__.py similarity index 100% rename from tests/h/search/__init__.py rename to tests/unit/h/search/__init__.py diff --git a/tests/h/search/client_test.py b/tests/unit/h/search/client_test.py similarity index 95% rename from tests/h/search/client_test.py rename to tests/unit/h/search/client_test.py index 71687433e20..2ab4674781c 100644 --- a/tests/h/search/client_test.py +++ b/tests/unit/h/search/client_test.py @@ -7,6 +7,11 @@ from h.search.client import Client, get_client +pytestmark = [ + pytest.mark.xdist_group("elasticsearch"), + pytest.mark.usefixtures("init_elasticsearch"), +] + class TestClient: def test_close(self, client, conn): diff --git a/tests/h/search/config_test.py b/tests/unit/h/search/config_test.py similarity index 98% rename from tests/h/search/config_test.py rename to tests/unit/h/search/config_test.py index b597179c9fb..72f3dbe410a 100644 --- a/tests/h/search/config_test.py +++ b/tests/unit/h/search/config_test.py @@ -19,6 +19,11 @@ update_index_settings, ) +pytestmark = [ + pytest.mark.xdist_group("elasticsearch"), + pytest.mark.usefixtures("init_elasticsearch"), +] + def test_strip_scheme_char_filter(): f = ANALYSIS_SETTINGS["char_filter"]["strip_scheme"] diff --git a/tests/h/search/conftest.py b/tests/unit/h/search/conftest.py similarity index 86% rename from tests/h/search/conftest.py rename to tests/unit/h/search/conftest.py index f8c5243e542..b55fb615a07 100644 --- a/tests/h/search/conftest.py +++ b/tests/unit/h/search/conftest.py @@ -4,7 +4,6 @@ from h.services.group import GroupService from h.services.search_index import SearchIndexService -from h.services.search_index._queue import Queue @pytest.fixture @@ -47,14 +46,16 @@ def _index(*annotations): @pytest.fixture def search_index( # pylint:disable=unused-argument - es_client, pyramid_request, moderation_service + es_client, + pyramid_request, + moderation_service, + annotation_read_service, ): return SearchIndexService( pyramid_request, - es_client, - session=pyramid_request.db, + es=es_client, settings={}, - queue=mock.create_autospec(Queue, spec_set=True, instance=True), + annotation_read_service=annotation_read_service, ) diff --git a/tests/h/search/core_test.py b/tests/unit/h/search/core_test.py similarity index 99% rename from tests/h/search/core_test.py rename to tests/unit/h/search/core_test.py index 688239f36a4..086679bfb90 100644 --- a/tests/h/search/core_test.py +++ b/tests/unit/h/search/core_test.py @@ -13,6 +13,11 @@ from h import search +pytestmark = [ + pytest.mark.xdist_group("elasticsearch"), + pytest.mark.usefixtures("init_elasticsearch"), +] + @pytest.mark.usefixtures("group_service", "nipsa_service") class TestSearch: diff --git a/tests/h/search/index_test.py b/tests/unit/h/search/index_test.py similarity index 77% rename from tests/h/search/index_test.py rename to tests/unit/h/search/index_test.py index 91d7d91117e..1b7d461f4c8 100644 --- a/tests/h/search/index_test.py +++ b/tests/unit/h/search/index_test.py @@ -1,26 +1,19 @@ import logging -from unittest import mock from unittest.mock import sentinel -import elasticsearch import pytest +from elasticsearch.exceptions import NotFoundError from h.search.index import BatchIndexer +pytestmark = [ + pytest.mark.xdist_group("elasticsearch"), + pytest.mark.usefixtures("init_elasticsearch"), +] + @pytest.mark.usefixtures("nipsa_service") class TestBatchIndexer: - def test_it_indexes_all_annotations( - self, batch_indexer, factories, get_indexed_ann - ): - annotations = factories.Annotation.create_batch(3) - ids = [a.id for a in annotations] - - batch_indexer.index() - - for _id in ids: - assert get_indexed_ann(_id) is not None - @pytest.mark.parametrize("target_index", (None, "custom_index")) def test_it_accepts_different_indexes(self, target_index, es_client): indexer = BatchIndexer( @@ -50,7 +43,7 @@ def test_it_indexes_specific_annotations( assert get_indexed_ann(_id) is not None for _id in ids_not_to_index: - with pytest.raises(elasticsearch.exceptions.NotFoundError): + with pytest.raises(NotFoundError): get_indexed_ann(_id) def test_it_does_not_index_deleted_annotations( @@ -60,11 +53,11 @@ def test_it_does_not_index_deleted_annotations( # create deleted annotations ann_del = factories.Annotation(deleted=True) - batch_indexer.index() + batch_indexer.index([ann.id, ann_del.id]) assert get_indexed_ann(ann.id) is not None - with pytest.raises(elasticsearch.exceptions.NotFoundError): + with pytest.raises(NotFoundError): get_indexed_ann(ann_del.id) def test_it_logs_indexing_status(self, caplog, batch_indexer, factories): @@ -88,7 +81,7 @@ def test_it_correctly_indexes_fields_for_bulk_actions( ): annotations = factories.Annotation.create_batch(2, groupid="group_a") - batch_indexer.index() + batch_indexer.index([annotation.id for annotation in annotations]) for ann in annotations: result = get_indexed_ann(ann.id) @@ -97,29 +90,29 @@ def test_it_correctly_indexes_fields_for_bulk_actions( assert result.get("user") == ann.userid assert result.get("uri") == ann.target_uri - def test_it_returns_errored_annotation_ids(self, batch_indexer, factories): + def test_it_returns_errored_annotation_ids( + self, batch_indexer, factories, es_helpers + ): annotations = factories.Annotation.create_batch(3) expected_errored_ids = {annotations[0].id, annotations[2].id} - elasticsearch.helpers.streaming_bulk = mock.Mock() - elasticsearch.helpers.streaming_bulk.return_value = [ + es_helpers.streaming_bulk.return_value = [ (False, {"index": {"error": "some error", "_id": annotations[0].id}}), (True, {}), (False, {"index": {"error": "some error", "_id": annotations[2].id}}), ] - errored = batch_indexer.index() + errored = batch_indexer.index([annotation.id for annotation in annotations]) assert errored == expected_errored_ids def test_it_does_not_error_if_annotations_already_indexed( - self, db_session, es_client, factories, pyramid_request + self, db_session, es_client, factories, pyramid_request, es_helpers ): annotations = factories.Annotation.create_batch(3) expected_errored_ids = {annotations[1].id} - elasticsearch.helpers.streaming_bulk = mock.Mock() - elasticsearch.helpers.streaming_bulk.return_value = [ + es_helpers.streaming_bulk.return_value = [ (True, {}), (False, {"create": {"error": "some error", "_id": annotations[1].id}}), ( @@ -135,10 +128,19 @@ def test_it_does_not_error_if_annotations_already_indexed( errored = BatchIndexer( db_session, es_client, pyramid_request, es_client.index, "create" - ).index() + ).index([annotation.id for annotation in annotations]) assert errored == expected_errored_ids + def test_delete(self, batch_indexer, factories, get_indexed_ann): + annotations = factories.Annotation.create_batch(2) + batch_indexer.index([annotation.id for annotation in annotations]) + + batch_indexer.delete([annotation.id for annotation in annotations]) + + for annotation in annotations: + assert get_indexed_ann(annotation.id) == {"doc": {"deleted": True}} + @pytest.fixture def batch_indexer( # pylint:disable=unused-argument @@ -160,3 +162,8 @@ def _get(annotation_id): )["_source"] return _get + + +@pytest.fixture +def es_helpers(patch): + return patch("h.search.index.es_helpers") diff --git a/tests/h/search/parser_test.py b/tests/unit/h/search/parser_test.py similarity index 98% rename from tests/h/search/parser_test.py rename to tests/unit/h/search/parser_test.py index d9a1625553b..15a27017e47 100644 --- a/tests/h/search/parser_test.py +++ b/tests/unit/h/search/parser_test.py @@ -5,6 +5,11 @@ from h.search import parser +pytestmark = [ + pytest.mark.xdist_group("elasticsearch"), + pytest.mark.usefixtures("init_elasticsearch"), +] + @pytest.mark.parametrize( "query_in,query_out", diff --git a/tests/h/search/query_test.py b/tests/unit/h/search/query_test.py similarity index 91% rename from tests/h/search/query_test.py rename to tests/unit/h/search/query_test.py index 155a242b980..20d78cf6f10 100644 --- a/tests/h/search/query_test.py +++ b/tests/unit/h/search/query_test.py @@ -1,4 +1,3 @@ -# pylint: disable=too-many-lines import datetime import elasticsearch_dsl @@ -15,7 +14,10 @@ OFFSET_MAX = query.OFFSET_MAX -pytestmark = pytest.mark.usefixtures("nipsa_service") +pytestmark = [ + pytest.mark.xdist_group("elasticsearch"), + pytest.mark.usefixtures("init_elasticsearch", "nipsa_service"), +] class TestLimiter: @@ -924,91 +926,57 @@ def test_matches_replies_of_replies_to_an_annotation(self, Annotation, search): class TestTagsAggregation: - def test_it_returns_annotation_counts_by_tag(self, Annotation, search): + @pytest.mark.parametrize( + "limit,expected", + ( + [ + 2, + [ + {"count": 2, "tag": "tag_a"}, + {"count": 1, "tag": "tag_b"}, + ], + ], + [1, [{"count": 2, "tag": "tag_a"}]], + ), + ) + def test_it_returns_annotation_counts_by_tag( + self, Annotation, search, limit, expected + ): for _ in range(2): Annotation(tags=["tag_a"]) Annotation(tags=["tag_b"]) - search.append_aggregation(query.TagsAggregation()) + search.append_aggregation(query.TagsAggregation(limit=limit)) result = search.run(webob.multidict.MultiDict({})) - tag_results = result.aggregations["tags"] - count_for_tag_a = next(r for r in tag_results if r["tag"] == "tag_a")["count"] - count_for_tag_b = next(r for r in tag_results if r["tag"] == "tag_b")["count"] - - assert len(tag_results) == 2 - assert count_for_tag_a == 2 - assert count_for_tag_b == 1 - - def test_it_limits_number_of_annotation_counts_by_tag_returned( - self, Annotation, search - ): - bucket_limit = 2 - - Annotation(tags=["tag_a"]) - for _ in range(3): - Annotation(tags=["tag_b"]) - for _ in range(2): - Annotation(tags=["tag_c"]) - - search.append_aggregation(query.TagsAggregation(bucket_limit)) - result = search.run(webob.multidict.MultiDict({})) - - tag_results = result.aggregations["tags"] - count_for_tag_b = next(r for r in tag_results if r["tag"] == "tag_b")["count"] - count_for_tag_c = next(r for r in tag_results if r["tag"] == "tag_c")["count"] - - assert len(tag_results) == bucket_limit - assert count_for_tag_b == 3 - assert count_for_tag_c == 2 + assert result.aggregations["tags"] == expected class TestUsersAggregation: - def test_it_returns_annotation_counts_by_user(self, Annotation, search): - for _ in range(2): - Annotation(userid="acct:pa@example.com") - Annotation(userid="acct:pb@example.com") - - search.append_aggregation(query.UsersAggregation()) - result = search.run(webob.multidict.MultiDict({})) - - users_results = result.aggregations["users"] - count_pa = next(r for r in users_results if r["user"] == "acct:pa@example.com")[ - "count" - ] - count_pb = next(r for r in users_results if r["user"] == "acct:pb@example.com")[ - "count" - ] - - assert len(users_results) == 2 - assert count_pa == 2 - assert count_pb == 1 - - def test_it_limits_number_of_annotation_counts_by_user_returned( - self, Annotation, search + @pytest.mark.parametrize( + "limit,expected", + ( + [ + 2, + [ + {"count": 2, "user": "acct:b@example.com"}, + {"count": 1, "user": "acct:a@example.com"}, + ], + ], + [1, [{"count": 2, "user": "acct:b@example.com"}]], + ), + ) + def test_it_returns_annotation_counts_by_user( + self, Annotation, search, limit, expected ): - bucket_limit = 2 - - Annotation(userid="acct:pa@example.com") - for _ in range(3): - Annotation(userid="acct:pb@example.com") + Annotation(userid="acct:a@example.com") for _ in range(2): - Annotation(userid="acct:pc@example.com") + Annotation(userid="acct:b@example.com") - search.append_aggregation(query.UsersAggregation(limit=bucket_limit)) + search.append_aggregation(query.UsersAggregation(limit=limit)) result = search.run(webob.multidict.MultiDict({})) - users_results = result.aggregations["users"] - count_pb = next(r for r in users_results if r["user"] == "acct:pb@example.com")[ - "count" - ] - count_pc = next(r for r in users_results if r["user"] == "acct:pc@example.com")[ - "count" - ] - - assert len(users_results) == bucket_limit - assert count_pb == 3 - assert count_pc == 2 + assert result.aggregations["users"] == expected @pytest.fixture diff --git a/tests/h/search/util_test.py b/tests/unit/h/search/util_test.py similarity index 92% rename from tests/h/search/util_test.py rename to tests/unit/h/search/util_test.py index 4baadbeb1bf..db6ca366287 100644 --- a/tests/h/search/util_test.py +++ b/tests/unit/h/search/util_test.py @@ -2,6 +2,11 @@ from h.search import util +pytestmark = [ + pytest.mark.xdist_group("elasticsearch"), + pytest.mark.usefixtures("init_elasticsearch"), +] + @pytest.mark.parametrize( "wildcard_uri,expected", diff --git a/tests/h/security/__init__.py b/tests/unit/h/security/__init__.py similarity index 100% rename from tests/h/security/__init__.py rename to tests/unit/h/security/__init__.py diff --git a/tests/h/security/encryption_test.py b/tests/unit/h/security/encryption_test.py similarity index 100% rename from tests/h/security/encryption_test.py rename to tests/unit/h/security/encryption_test.py diff --git a/tests/h/security/identity_test.py b/tests/unit/h/security/identity_test.py similarity index 100% rename from tests/h/security/identity_test.py rename to tests/unit/h/security/identity_test.py diff --git a/tests/h/security/permits_test.py b/tests/unit/h/security/permits_test.py similarity index 100% rename from tests/h/security/permits_test.py rename to tests/unit/h/security/permits_test.py diff --git a/tests/h/security/policy/__init__.py b/tests/unit/h/security/policy/__init__.py similarity index 100% rename from tests/h/security/policy/__init__.py rename to tests/unit/h/security/policy/__init__.py diff --git a/tests/h/security/policy/_basic_http_auth_test.py b/tests/unit/h/security/policy/_basic_http_auth_test.py similarity index 95% rename from tests/h/security/policy/_basic_http_auth_test.py rename to tests/unit/h/security/policy/_basic_http_auth_test.py index 9afb473ea56..f21854875e8 100644 --- a/tests/h/security/policy/_basic_http_auth_test.py +++ b/tests/unit/h/security/policy/_basic_http_auth_test.py @@ -101,6 +101,13 @@ def test_identify_returns_None_if_forwarded_user_is_not_found( assert AuthClientPolicy().identity(pyramid_request) is None + def test_identify_returns_None_if_forwarded_user_is_marked_as_deleted( + self, user_service, pyramid_request + ): + user_service.fetch.return_value.deleted = True + + assert AuthClientPolicy().identity(pyramid_request) is None + def test_identify_returns_None_if_forwarded_userid_is_invalid( self, user_service, pyramid_request ): diff --git a/tests/h/security/policy/_cookie_test.py b/tests/unit/h/security/policy/_cookie_test.py similarity index 93% rename from tests/h/security/policy/_cookie_test.py rename to tests/unit/h/security/policy/_cookie_test.py index 9125dba1446..76644066324 100644 --- a/tests/h/security/policy/_cookie_test.py +++ b/tests/unit/h/security/policy/_cookie_test.py @@ -17,6 +17,13 @@ def test_identity(self, pyramid_request, auth_cookie_service): user=auth_cookie_service.verify_cookie.return_value ) + def test_identity_when_user_marked_as_deleted( + self, pyramid_request, auth_cookie_service + ): + auth_cookie_service.verify_cookie.return_value.deleted = True + + assert CookiePolicy().identity(pyramid_request) is None + def test_identity_with_no_cookie(self, pyramid_request, auth_cookie_service): auth_cookie_service.verify_cookie.return_value = None diff --git a/tests/h/security/policy/_identity_base_test.py b/tests/unit/h/security/policy/_identity_base_test.py similarity index 100% rename from tests/h/security/policy/_identity_base_test.py rename to tests/unit/h/security/policy/_identity_base_test.py diff --git a/tests/h/security/policy/_remote_user_test.py b/tests/unit/h/security/policy/_remote_user_test.py similarity index 77% rename from tests/h/security/policy/_remote_user_test.py rename to tests/unit/h/security/policy/_remote_user_test.py index 3bfa1dec68c..5d301323c58 100644 --- a/tests/h/security/policy/_remote_user_test.py +++ b/tests/unit/h/security/policy/_remote_user_test.py @@ -26,3 +26,11 @@ def test_identity_returns_None_for_no_user(self, pyramid_request, user_service): user_service.fetch.return_value = None assert RemoteUserPolicy().identity(pyramid_request) is None + + def test_identity_returns_None_for_user_marked_as_deleted( + self, pyramid_request, user_service + ): + pyramid_request.environ["HTTP_X_FORWARDED_USER"] = sentinel.forwarded_user + user_service.fetch.return_value.deleted = True + + assert RemoteUserPolicy().identity(pyramid_request) is None diff --git a/tests/h/security/policy/bearer_token_test.py b/tests/unit/h/security/policy/bearer_token_test.py similarity index 90% rename from tests/h/security/policy/bearer_token_test.py rename to tests/unit/h/security/policy/bearer_token_test.py index a0364592ab0..40ab759f0db 100644 --- a/tests/h/security/policy/bearer_token_test.py +++ b/tests/unit/h/security/policy/bearer_token_test.py @@ -57,3 +57,10 @@ def test_identity_returns_None_for_invalid_users( user_service.fetch.return_value = None assert BearerTokenPolicy().identity(pyramid_request) is None + + def test_identity_returns_None_for_user_marked_as_deleted( + self, pyramid_request, user_service + ): + user_service.fetch.return_value.deleted = True + + assert BearerTokenPolicy().identity(pyramid_request) is None diff --git a/tests/h/security/policy/combined_test.py b/tests/unit/h/security/policy/combined_test.py similarity index 88% rename from tests/h/security/policy/combined_test.py rename to tests/unit/h/security/policy/combined_test.py index 3e54b0da4c4..10059835f90 100644 --- a/tests/h/security/policy/combined_test.py +++ b/tests/unit/h/security/policy/combined_test.py @@ -93,12 +93,12 @@ def test_calls_are_routed_based_on_api_or_not(self, pyramid_request, path, is_ui policy._ui_policy, ) - called_policy.remember.assert_called_once_with( + called_policy.remember.assert_called_once_with( # pylint:disable=no-member pyramid_request, sentinel.userid, kwarg=True ) - assert result == called_policy.remember.return_value + assert result == called_policy.remember.return_value # pylint:disable=no-member - uncalled_policy.remember.assert_not_called() + uncalled_policy.remember.assert_not_called() # pylint:disable=no-member @pytest.mark.parametrize("bearer_returns", (True, False)) @pytest.mark.parametrize("basic_auth_handles", (True, False)) @@ -119,13 +119,19 @@ def test_api_calls_are_passed_on( ) if basic_auth_handles and not bearer_returns: - policy._http_basic_auth_policy.remember.assert_called_once_with( + policy._http_basic_auth_policy.remember.assert_called_once_with( # pylint:disable=no-member pyramid_request, sentinel.userid, kwarg=True ) - assert result == policy._http_basic_auth_policy.remember.return_value + assert ( + result + == policy._http_basic_auth_policy.remember.return_value # pylint:disable=no-member + ) else: - policy._http_basic_auth_policy.remember.assert_not_called() - assert result == policy._bearer_token_policy.remember.return_value + policy._http_basic_auth_policy.remember.assert_not_called() # pylint:disable=no-member + assert ( + result + == policy._bearer_token_policy.remember.return_value # pylint:disable=no-member + ) @pytest.fixture(autouse=True) def BearerTokenPolicy(self, patch): diff --git a/tests/h/security/predicates_test.py b/tests/unit/h/security/predicates_test.py similarity index 100% rename from tests/h/security/predicates_test.py rename to tests/unit/h/security/predicates_test.py diff --git a/tests/h/security/request_methods_test.py b/tests/unit/h/security/request_methods_test.py similarity index 100% rename from tests/h/security/request_methods_test.py rename to tests/unit/h/security/request_methods_test.py diff --git a/tests/h/sentry_filters_test.py b/tests/unit/h/sentry_filters_test.py similarity index 100% rename from tests/h/sentry_filters_test.py rename to tests/unit/h/sentry_filters_test.py diff --git a/tests/h/services/__init__.py b/tests/unit/h/services/__init__.py similarity index 100% rename from tests/h/services/__init__.py rename to tests/unit/h/services/__init__.py diff --git a/tests/unit/h/services/analytics_test.py b/tests/unit/h/services/analytics_test.py new file mode 100644 index 00000000000..10c1786aca3 --- /dev/null +++ b/tests/unit/h/services/analytics_test.py @@ -0,0 +1,16 @@ +import logging +from unittest import mock + +from h.services.analytics import analytics_service_factory + + +class TestAnalyticsService: + @mock.patch.object(logging, "getLogger") + def test_it_logs_events(self, mock_get_logger): + mock_logger = mock.Mock() + mock_get_logger.return_value = mock_logger + + svc = analytics_service_factory({}, None) + svc.create({"foo": "bar"}) + + mock_logger.info.assert_called_once_with({"foo": "bar"}) diff --git a/tests/unit/h/services/annotation_delete_test.py b/tests/unit/h/services/annotation_delete_test.py new file mode 100644 index 00000000000..7787b9bd807 --- /dev/null +++ b/tests/unit/h/services/annotation_delete_test.py @@ -0,0 +1,108 @@ +from datetime import datetime, timedelta +from unittest import mock + +import pytest + +from h.events import AnnotationEvent +from h.models import Annotation, AnnotationSlim +from h.services.annotation_delete import annotation_delete_service_factory + + +class TestAnnotationDeleteService: + def test_it_marks_the_annotation_as_deleted(self, svc, annotation, queue_service): + ann = annotation() + svc.delete(ann) + queue_service.add_by_id.assert_called_once_with( + name="sync_annotation", + annotation_id=ann.id, + tag="AnnotationDeleteService.delete_annotation", + schedule_in=60, + ) + + assert ann.deleted + + def test_it_updates_the_updated_field(self, svc, annotation, datetime): + ann = annotation() + svc.delete(ann) + + assert ann.updated == datetime.utcnow.return_value + + def test_it_publishes_a_delete_event(self, svc, pyramid_request, annotation): + ann = annotation() + svc.delete(ann) + + expected_event = AnnotationEvent(pyramid_request, ann.id, "delete") + actual_event = pyramid_request.notify_after_commit.call_args[0][0] + assert ( + expected_event.request, + expected_event.annotation_id, + expected_event.action, + ) == (actual_event.request, actual_event.annotation_id, actual_event.action) + + def test_it_deletes_all_annotations(self, svc, annotation): + svc.delete = mock.create_autospec(svc.delete, spec_set=True) + + anns = [annotation(), annotation()] + svc.delete_annotations(anns) + + assert svc.delete.mock_calls == [mock.call(anns[0]), mock.call(anns[1])] + + @pytest.mark.parametrize( + "deleted,mins_ago,purged", + [ + # Deleted more than 10 minutes ago... should be purged. + (True, 30, True), + (True, 3600, True), + # Deleted less than 10 minutes ago... should NOT be purged. + (True, -30, False), # annotation from the future! wooOOOooo! + (True, 0, False), + (True, 1, False), + (True, 9, False), + # Not deleted... should NOT be purged. + (False, -30, False), + (False, 0, False), + (False, 1, False), + (False, 9, False), + (False, 30, False), + (False, 3600, False), + ], + ) + def test_bulk_delete(self, db_session, svc, factories, deleted, mins_ago, purged): + updated = datetime.utcnow() - timedelta(minutes=mins_ago) + annotation = factories.Annotation(deleted=deleted, updated=updated) + annotation_slim = factories.AnnotationSlim( + deleted=deleted, updated=updated, annotation=annotation + ) + db_session.add(annotation) + db_session.add(annotation_slim) + + svc.bulk_delete() + + if purged: + assert not db_session.query(Annotation).count() + assert not db_session.query(AnnotationSlim).count() + else: + assert db_session.query(Annotation).count() == 1 + assert db_session.query(AnnotationSlim).count() == 1 + + @pytest.fixture + def datetime(self, patch): + return patch("h.services.annotation_delete.datetime") + + +@pytest.fixture +def annotation(factories): + return lambda factories=factories: factories.Annotation() + + +# pylint:disable=unused-argument +@pytest.fixture +def svc(db_session, pyramid_request, annotation_write_service, queue_service): + pyramid_request.db = db_session + return annotation_delete_service_factory({}, pyramid_request) + + +@pytest.fixture +def pyramid_request(pyramid_request): + pyramid_request.notify_after_commit = mock.Mock() + return pyramid_request diff --git a/tests/h/services/annotation_json_test.py b/tests/unit/h/services/annotation_json_test.py similarity index 82% rename from tests/h/services/annotation_json_test.py rename to tests/unit/h/services/annotation_json_test.py index bd793b858f7..20095051308 100644 --- a/tests/h/services/annotation_json_test.py +++ b/tests/unit/h/services/annotation_json_test.py @@ -4,8 +4,8 @@ import pytest from h_matchers import Any from pyramid.authorization import Everyone -from sqlalchemy import event +from h.models import Annotation from h.security.permissions import Permission from h.services.annotation_json import AnnotationJSONService, factory from h.traversal import AnnotationContext @@ -174,14 +174,24 @@ def test_present_for_user_hidden_shows_everything_to_moderators( assert result["tags"] def test_present_all_for_user( - self, service, annotation, user, flag_service, user_service + self, + service, + annotation, + user, + annotation_read_service, + flag_service, + user_service, ): - annotation_ids = [annotation.id] + annotation_read_service.get_annotations_by_id.return_value = [annotation] - result = service.present_all_for_user(annotation_ids, user) + result = service.present_all_for_user(sentinel.annotation_ids, user) - flag_service.all_flagged.assert_called_once_with(user, annotation_ids) - flag_service.flag_counts.assert_called_once_with(annotation_ids) + annotation_read_service.get_annotations_by_id.assert_called_once_with( + ids=sentinel.annotation_ids, + eager_load=[Annotation.document, Annotation.moderation, Annotation.group], + ) + flag_service.all_flagged.assert_called_once_with(user, sentinel.annotation_ids) + flag_service.flag_counts.assert_called_once_with(sentinel.annotation_ids) user_service.fetch_all.assert_called_once_with([annotation.userid]) assert result == [ @@ -189,49 +199,12 @@ def test_present_all_for_user( Any.dict.containing({"id": Any(), "hidden": False}) ] - @pytest.mark.parametrize("attribute", ("document", "moderation", "group")) - @pytest.mark.parametrize("with_preload", (True, False)) - def test_present_all_for_userpreloading_is_effective( - self, - service, - annotation, - user, - db_session, - query_counter, - attribute, - with_preload, - ): - # Ensure SQLAlchemy forgets all about our annotation - db_session.flush() - db_session.expire(annotation) - if with_preload: - service.present_all_for_user([annotation.id], user) - - query_counter.reset() - getattr(annotation, attribute) - - # If we preloaded, we shouldn't execute any queries (and vice versa) - assert bool(query_counter.count) != with_preload - - @pytest.fixture - def query_counter(self, db_engine): - class QueryCounter: - count = 0 - - def __call__(self, *args, **kwargs): - self.count += 1 - - def reset(self): - self.count = 0 - - query_counter = QueryCounter() - event.listen(db_engine, "before_cursor_execute", query_counter) - return query_counter - @pytest.fixture - def service(self, db_session, links_service, flag_service, user_service): + def service( + self, annotation_read_service, links_service, flag_service, user_service + ): return AnnotationJSONService( - session=db_session, + annotation_read_service=annotation_read_service, links_service=links_service, flag_service=flag_service, user_service=user_service, @@ -269,26 +242,21 @@ def test_it( self, pyramid_request, AnnotationJSONService, + annotation_read_service, flag_service, links_service, user_service, ): service = factory(sentinel.context, pyramid_request) - assert service == AnnotationJSONService.return_value - AnnotationJSONService.assert_called_once_with( - session=pyramid_request.db, + annotation_read_service=annotation_read_service, links_service=links_service, flag_service=flag_service, user_service=user_service, ) + assert service == AnnotationJSONService.return_value @pytest.fixture def AnnotationJSONService(self, patch): return patch("h.services.annotation_json.AnnotationJSONService") - - @pytest.fixture - def pyramid_request(self, pyramid_request, factories): - pyramid_request.user = factories.User() - return pyramid_request diff --git a/tests/unit/h/services/annotation_metadata_test.py b/tests/unit/h/services/annotation_metadata_test.py new file mode 100644 index 00000000000..16e65af2ea8 --- /dev/null +++ b/tests/unit/h/services/annotation_metadata_test.py @@ -0,0 +1,44 @@ +from unittest.mock import sentinel + +import pytest + +from h.models import AnnotationMetadata +from h.services.annotation_metadata import AnnotationMetadataService, factory + + +class TestAnnotationMetadataService: + def test_it(self, svc, factories, db_session): + metadata = {"some": "data"} + anno = factories.Annotation() + anno_slim = factories.AnnotationSlim(annotation=anno) + db_session.flush() + + svc.set(anno, metadata) + + anno_metadata = ( + db_session.query(AnnotationMetadata) + .filter_by(annotation_id=anno_slim.id) + .one() + ) + assert anno_metadata.data == metadata + + # Second call updates the existing record + metadata = {"new": "data"} + svc.set(anno, metadata) + db_session.refresh(anno_metadata) + assert anno_metadata.data == metadata + + def test_factory(self, AnnotationMetadataService, db_session, pyramid_request): + svc = factory(sentinel.context, pyramid_request) + + AnnotationMetadataService.assert_called_once_with(db=db_session) + assert svc == AnnotationMetadataService.return_value + + @pytest.fixture + def svc(self, db_session, pyramid_request): + pyramid_request.db = db_session + return AnnotationMetadataService(db_session) + + @pytest.fixture + def AnnotationMetadataService(self, patch): + return patch("h.services.annotation_metadata.AnnotationMetadataService") diff --git a/tests/h/services/annotation_moderation_test.py b/tests/unit/h/services/annotation_moderation_test.py similarity index 100% rename from tests/h/services/annotation_moderation_test.py rename to tests/unit/h/services/annotation_moderation_test.py diff --git a/tests/unit/h/services/annotation_read_test.py b/tests/unit/h/services/annotation_read_test.py new file mode 100644 index 00000000000..7eaab7b98fc --- /dev/null +++ b/tests/unit/h/services/annotation_read_test.py @@ -0,0 +1,89 @@ +from unittest.mock import sentinel + +import pytest +import sqlalchemy as sa + +from h.models import Annotation +from h.services.annotation_read import AnnotationReadService, service_factory + + +class TestAnnotationReadService: + def test_get_annotation_by_id(self, svc, annotation): + assert svc.get_annotation_by_id(annotation.id) == annotation + + def test_get_annotation_by_id_with_invalid_uuid(self, svc): + assert not svc.get_annotation_by_id("NOTVALID") + + @pytest.mark.parametrize("reverse", (True, False)) + def test_get_annotations_by_id(self, svc, factories, reverse): + annotations = factories.Annotation.create_batch(3) + if reverse: + annotations = list(reversed(annotations)) + + results = svc.get_annotations_by_id( + [annotation.id for annotation in annotations] + ) + + assert results == annotations + + def test_get_annotations_by_id_with_no_input(self, svc): + assert not svc.get_annotations_by_id(ids=[]) + + @pytest.mark.parametrize("attribute", ("document", "moderation", "group")) + def test_get_annotations_by_id_preloading( + self, svc, factories, db_session, query_counter, attribute + ): + annotation = factories.Annotation() + + # Ensure SQLAlchemy forgets all about our annotation + db_session.flush() + db_session.expire(annotation) + svc.get_annotations_by_id( + [annotation.id], + eager_load=[ + getattr(Annotation, attribute), + # Add another, so we see if we are constructing the list right + Annotation.group, + ], + ) + query_counter.reset() + + getattr(annotation, attribute) + + # If we preloaded, we shouldn't execute any queries + assert not query_counter.count + + @pytest.fixture + def query_counter(self, db_engine): + class QueryCounter: + count = 0 + + def __call__(self, *args, **kwargs): + self.count += 1 + + def reset(self): + self.count = 0 + + query_counter = QueryCounter() + sa.event.listen(db_engine, "before_cursor_execute", query_counter) + return query_counter + + @pytest.fixture + def annotation(self, factories): + return factories.Annotation() + + @pytest.fixture + def svc(self, db_session): + return AnnotationReadService(db_session=db_session) + + +class TestServiceFactory: + def test_it(self, pyramid_request, AnnotationReadService): + svc = service_factory(sentinel.context, pyramid_request) + + AnnotationReadService.assert_called_once_with(db_session=pyramid_request.db) + assert svc == AnnotationReadService.return_value + + @pytest.fixture + def AnnotationReadService(self, patch): + return patch("h.services.annotation_read.AnnotationReadService") diff --git a/tests/h/services/annotation_stats_test.py b/tests/unit/h/services/annotation_stats_test.py similarity index 100% rename from tests/h/services/annotation_stats_test.py rename to tests/unit/h/services/annotation_stats_test.py diff --git a/tests/unit/h/services/annotation_sync_test.py b/tests/unit/h/services/annotation_sync_test.py new file mode 100644 index 00000000000..57ff7f2154f --- /dev/null +++ b/tests/unit/h/services/annotation_sync_test.py @@ -0,0 +1,714 @@ +import datetime +from unittest.mock import create_autospec, sentinel + +import pytest +from h_matchers import Any + +from h.db.types import URLSafeUUID +from h.search.index import BatchIndexer +from h.services.annotation_sync import ( + AnnotationSyncService, + Counter, + DBHelper, + ESHelper, + factory, +) +from h.services.search_index import SearchIndexService + +pytestmark = [ + pytest.mark.xdist_group("elasticsearch"), + pytest.mark.usefixtures("init_elasticsearch"), +] + + +class TestAnnotationSyncService: + def test_it_does_nothing_if_the_queue_is_empty( + self, batch_indexer, svc, queue_service + ): + queue_service.get.return_value = [] + counts = svc.sync(1) + + assert counts == {} + batch_indexer.index.assert_not_called() + + def test_if_the_job_has_force_True_it_indexes_the_annotation_and_deletes_the_job( + self, batch_indexer, factories, svc, queue_service + ): + job = factories.SyncAnnotationJob(force=True) + queue_service.get.return_value = [job] + + counts = svc.sync(1) + + assert counts == { + Counter.Result.SYNCED_FORCED.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TAG_TOTAL.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TOTAL: 1, + Counter.Result.COMPLETED_FORCED.format(tag="test_tag"): 1, + Counter.Result.COMPLETED_TAG_TOTAL.format(tag="test_tag"): 1, + Counter.Result.COMPLETED_TOTAL: 1, + } + queue_service.delete.assert_called_once_with([job]) + batch_indexer.index.assert_called_once_with([url_safe_annotation_id(job)]) + + def test_if_the_annotation_is_marked_as_deleted_in_the_DB_then_it_deletes_it_from_Elastic( + self, factories, svc, queue_service, index + ): + annotation = factories.Annotation() + index(annotation) + job = factories.SyncAnnotationJob(annotation=annotation) + queue_service.get.return_value = [job] + annotation.deleted = True + + counts = svc.sync(1) + + assert counts == { + Counter.Result.SYNCED_DELETED.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TAG_TOTAL.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TOTAL: 1, + } + queue_service.delete.assert_called_once_with([]) + + def test_if_the_annotation_isnt_in_the_DB_then_it_deletes_it_from_Elastic( + self, factories, svc, queue_service, index, db_session + ): + # We have to actually create an annotation and save it to the DB in + # order to get a valid annotation ID. Then we delete the annotation + # from the DB again because we actually don't want the annotation to be + # in the DB in this test. + annotation = factories.Annotation() + index(annotation) + job = factories.SyncAnnotationJob(annotation=annotation) + queue_service.get.return_value = [job] + db_session.delete(annotation) + db_session.commit() + + counts = svc.sync(1) + + assert counts == { + Counter.Result.SYNCED_DELETED.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TAG_TOTAL.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TOTAL: 1, + } + queue_service.delete.assert_called_once_with([]) + + def test_if_the_annotation_is_marked_as_deleted_in_the_DB_and_Elastic_it_deletes_the_job_from_the_queue( + self, factories, svc, queue_service, delete_from_elasticsearch + ): + annotation = factories.Annotation(deleted=True) + annotation.deleted = True + delete_from_elasticsearch(annotation) + job = factories.SyncAnnotationJob(annotation=annotation) + queue_service.get.return_value = [job] + + counts = svc.sync(1) + + assert counts == { + Counter.Result.COMPLETED_DELETED.format(tag="test_tag"): 1, + Counter.Result.COMPLETED_TAG_TOTAL.format(tag="test_tag"): 1, + Counter.Result.COMPLETED_TOTAL: 1, + } + queue_service.delete.assert_called_once_with([job]) + + def test_if_the_annotation_isnt_in_the_DB_or_Elastic_it_deletes_the_job_from_the_queue( + self, db_session, factories, svc, queue_service + ): + # We have to actually create an annotation and save it to the DB in + # order to get a valid annotation ID. Then we delete the annotation + # from the DB again because we actually don't want the annotation to be + # in the DB in this test. + annotation = factories.Annotation() + job = factories.SyncAnnotationJob(annotation=annotation) + queue_service.get.return_value = [job] + db_session.delete(annotation) + db_session.commit() + + counts = svc.sync(1) + + assert counts == { + Counter.Result.COMPLETED_DELETED.format(tag="test_tag"): 1, + Counter.Result.COMPLETED_TAG_TOTAL.format(tag="test_tag"): 1, + Counter.Result.COMPLETED_TOTAL: 1, + } + queue_service.delete.assert_called_once_with([job]) + + def test_if_the_annotation_is_marked_as_deleted_in_the_DB_it_deletes_the_job_from_the_queue( + self, factories, svc, queue_service + ): + annotation = factories.Annotation() + job = factories.SyncAnnotationJob(annotation=annotation) + queue_service.get.return_value = [job] + annotation.deleted = True + + counts = svc.sync(1) + + assert counts == { + Counter.Result.COMPLETED_DELETED.format(tag="test_tag"): 1, + Counter.Result.COMPLETED_TAG_TOTAL.format(tag="test_tag"): 1, + Counter.Result.COMPLETED_TOTAL: 1, + } + queue_service.delete.assert_called_once_with([job]) + + def test_if_the_annotation_is_missing_from_Elastic_it_indexes_it( + self, batch_indexer, factories, svc, queue_service + ): + job = factories.SyncAnnotationJob() + queue_service.get.return_value = [job] + + counts = svc.sync(1) + + assert counts == { + Counter.Result.SYNCED_MISSING.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TAG_TOTAL.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TOTAL: 1, + } + batch_indexer.index.assert_called_once_with([url_safe_annotation_id(job)]) + + def test_if_the_annotation_is_already_in_Elastic_it_removes_the_job_from_the_queue( + self, batch_indexer, factories, index, svc, queue_service + ): + annotation = factories.Annotation() + index(annotation) + job = factories.SyncAnnotationJob(annotation=annotation) + queue_service.get.return_value = [job] + + counts = svc.sync(1) + + assert counts == { + Counter.Result.COMPLETED_UP_TO_DATE.format(tag="test_tag"): 1, + Counter.Result.COMPLETED_TAG_TOTAL.format(tag="test_tag"): 1, + Counter.Result.COMPLETED_TOTAL: 1, + } + queue_service.delete.assert_called_once_with([job]) + batch_indexer.index.assert_not_called() + + def test_if_the_annotation_has_a_different_updated_time_in_Elastic_it_indexes_it( + self, batch_indexer, factories, index, now, svc, queue_service + ): + annotation = factories.Annotation() + index(annotation) + job = factories.SyncAnnotationJob(annotation=annotation) + queue_service.get.return_value = [job] + # Simulate the annotation having been updated in the DB after it was + # indexed. + annotation.updated = now + + counts = svc.sync(1) + + assert counts == { + Counter.Result.SYNCED_DIFFERENT.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TAG_TOTAL.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TOTAL: 1, + } + batch_indexer.index.assert_called_once_with([annotation.id]) + + def test_if_the_annotation_has_a_different_userid_in_Elastic_it_indexes_it( + self, batch_indexer, factories, index, svc, queue_service + ): + annotation = factories.Annotation() + index(annotation) + job = factories.SyncAnnotationJob(annotation=annotation) + queue_service.get.return_value = [job] + # Simulate the user having been renamed in the DB. + annotation.userid = "new_userid" + + counts = svc.sync(1) + + assert counts == { + Counter.Result.SYNCED_DIFFERENT.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TAG_TOTAL.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TOTAL: 1, + } + batch_indexer.index.assert_called_once_with([annotation.id]) + + def test_if_there_are_multiple_jobs_with_the_same_annotation_id( + self, batch_indexer, factories, svc, queue_service + ): + annotation = factories.Annotation() + jobs = factories.SyncAnnotationJob.create_batch(size=2, annotation=annotation) + queue_service.get.return_value = jobs + + counts = svc.sync(len(jobs)) + + assert counts == { + Counter.Result.SYNCED_MISSING.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TAG_TOTAL.format(tag="test_tag"): 1, + Counter.Result.SYNCED_TOTAL: 1, + } + # It only syncs the annotation to Elasticsearch once, even though it + # processed two separate jobs (for the same annotation). + batch_indexer.index.assert_called_once_with([annotation.id]) + + def test_deleting_multiple_jobs_with_the_same_annotation_id( + self, batch_indexer, factories, index, svc, queue_service + ): + annotation = factories.Annotation() + index(annotation) + jobs = factories.SyncAnnotationJob.create_batch(size=2, annotation=annotation) + queue_service.get.return_value = jobs + + counts = svc.sync(len(jobs)) + + assert counts == { + Counter.Result.COMPLETED_UP_TO_DATE.format(tag="test_tag"): 2, + Counter.Result.COMPLETED_TAG_TOTAL.format(tag="test_tag"): 2, + Counter.Result.COMPLETED_TOTAL: 2, + } + queue_service.delete.assert_called_once_with(Any.list.containing(jobs).only()) + batch_indexer.index.assert_not_called() + + def test_metrics(self, factories, index, now, svc, queue_service): + queue_service.get.return_value = [] + + def add_job(indexed=True, updated=False, deleted=False, **kwargs): + annotation = factories.Annotation() + job = factories.SyncAnnotationJob(annotation=annotation, **kwargs) + queue_service.get.return_value.append(job) + + if indexed: + index(annotation) + + if updated: + annotation.updated = now + datetime.timedelta(weeks=1) + + if deleted: + annotation.deleted = True + + add_job() + add_job(indexed=False) + add_job(updated=True) + add_job(deleted=True) + add_job(tag="tag_2", force=True) + + counts = svc.sync(5) + + assert counts == { + "Synced/Total": 4, + "Completed/Total": 2, + "Synced/test_tag/Total": 3, + "Completed/test_tag/Total": 1, + "Synced/test_tag/Deleted_from_db": 1, + "Synced/test_tag/Different_in_Elastic": 1, + "Synced/test_tag/Missing_from_Elastic": 1, + "Synced/tag_2/Forced": 1, + "Synced/tag_2/Total": 1, + "Completed/tag_2/Forced": 1, + "Completed/tag_2/Total": 1, + "Completed/test_tag/Up_to_date_in_Elastic": 1, + } + + @pytest.fixture + def now(self): + """Return the current UTC time.""" + return datetime.datetime.utcnow() + + @pytest.fixture(autouse=True) + def noise_annotations(self, factories, index): + """ + Create some noise annotations in the DB. + + Also add some of the noise annotations to Elasticsearch, some not. + + None of these noise annotations should ever be touched by the sync() + method in these tests. + """ + annotations = factories.Annotation.create_batch(size=2) + index(annotations[0]) + + @pytest.fixture + def batch_indexer(self): + """Return a mock BatchIndexer instance.""" + return create_autospec(BatchIndexer, spec_set=True, instance=True) + + @pytest.fixture + def svc(self, batch_indexer, db_session, es_client, queue_service): + return AnnotationSyncService( + batch_indexer=batch_indexer, + db_helper=DBHelper(db=db_session), + es_helper=ESHelper(es=es_client), + queue_service=queue_service, + ) + + +class TestDBHelper: + def test_get_with_no_jobs(self, db_helper): + assert db_helper.get([]) == {} + + def test_get_when_all_jobs_have_force_True(self, db_helper, db_session, factories): + jobs = factories.SyncAnnotationJob.create_batch(2, force=True) + # Flush the DB to generate job.id values. + db_session.flush() + + assert db_helper.get(jobs) == {} + + def test_get_filters_out_duplicate_annotations( + self, db_helper, db_session, factories + ): + annotation = factories.Annotation() + # Two jobs for the same annotation. + jobs = factories.SyncAnnotationJob.create_batch(2, annotation=annotation) + # Flush the DB to generate job.id values. + db_session.flush() + + result = db_helper.get(jobs) + + assert list(result.keys()) == [annotation.id] + + def test_get(self, db_helper, db_session, factories): + annotations = factories.Annotation.create_batch(2) + jobs = [ + factories.SyncAnnotationJob(annotation=annotation) + for annotation in annotations + ] + # A duplicate job for one of the same annotations. This should be ignored. + jobs.append(factories.SyncAnnotationJob(annotation=annotations[0])) + # A job whose annotation is marked as deleted. This should be ignored. + jobs.append( + factories.SyncAnnotationJob(annotation=factories.Annotation(deleted=True)) + ) + # A job that has force=True. This should be ignored. + jobs.append(factories.SyncAnnotationJob(force=True)) + # An annotation that has no job. This should be ignored. + factories.Annotation() + # Flush the DB to generate job.id values. + db_session.flush() + + result = db_helper.get(jobs) + + assert result == { + annotations[0].id: ( + annotations[0].id, + annotations[0].updated, + annotations[0].userid, + ), + annotations[1].id: ( + annotations[1].id, + annotations[1].updated, + annotations[1].userid, + ), + } + + # TODO: Annotations that don't exist in the DB. + + @pytest.fixture + def db_helper(self, db_session): + return DBHelper(db_session) + + +class TestESHelper: + def test_get_with_no_jobs(self, es_helper): + assert es_helper.get([]) == {} + + def test_get_when_all_jobs_have_force_True(self, db_session, es_helper, factories): + jobs = factories.SyncAnnotationJob.create_batch(2, force=True) + # Flush the DB to generate job.id values. + db_session.flush() + + assert es_helper.get(jobs) == {} + + def test_get_filters_out_duplicate_annotations( + self, db_session, es_helper, factories, index + ): + annotation = factories.Annotation() + index(annotation) + # Two jobs for the same annotation. + jobs = factories.SyncAnnotationJob.create_batch(2, annotation=annotation) + # Flush the DB to generate job.id values. + db_session.flush() + + result = es_helper.get(jobs) + + assert list(result.keys()) == [annotation.id] + + def test_get_doesnt_return_annotations_that_arent_in_the_search_index( + self, db_session, es_helper, factories + ): + jobs = factories.SyncAnnotationJob.create_batch(1) + # Flush the DB to generate job.id values. + db_session.flush() + + assert es_helper.get(jobs) == {} + + def test_get_doesnt_return_annotations_that_have_been_marked_as_deleted_in_the_search_index( + self, db_session, es_helper, factories, delete_from_elasticsearch + ): + annotation = factories.Annotation() + job = factories.SyncAnnotationJob(annotation=annotation) + # Flush the DB to generate job.id values. + db_session.flush() + delete_from_elasticsearch(annotation) + + assert es_helper.get([job]) == {} + + def test_get(self, db_session, es_helper, factories, index): + annotations = factories.Annotation.create_batch(2) + for annotation in annotations: + index(annotation) + jobs = [ + factories.SyncAnnotationJob(annotation=annotation) + for annotation in annotations + ] + # An annotation with no job. This should be ignored. + index(factories.Annotation()) + # Flush the DB to generate job.id values. + db_session.flush() + + result = es_helper.get(jobs) + + assert result == { + annotations[0].id: { + "updated": annotations[0].updated, + "user": annotations[0].userid, + }, + annotations[1].id: { + "updated": annotations[1].updated, + "user": annotations[1].userid, + }, + } + + @pytest.fixture + def es_helper(self, es_client): + return ESHelper(es_client) + + +class TestCounter: + def test_annotation_synced(self, counter, db_session, factories): + foo_jobs = factories.SyncAnnotationJob.create_batch(4, tag="foo") + bar_jobs = factories.SyncAnnotationJob.create_batch(2, tag="bar") + # Flush the DB to generate job.id values. + db_session.flush() + + counter.annotation_synced(counter.Result.SYNCED_MISSING, foo_jobs[0]) + counter.annotation_synced(counter.Result.SYNCED_MISSING, bar_jobs[0]) + counter.annotation_synced(counter.Result.SYNCED_FORCED, foo_jobs[1]) + counter.annotation_synced(counter.Result.SYNCED_DIFFERENT, foo_jobs[2]) + counter.annotation_synced(counter.Result.SYNCED_MISSING, foo_jobs[3]) + counter.annotation_synced(counter.Result.SYNCED_DIFFERENT, bar_jobs[1]) + + assert counter.counts == { + counter.Result.SYNCED_MISSING.format(tag="foo"): 2, + counter.Result.SYNCED_MISSING.format(tag="bar"): 1, + counter.Result.SYNCED_FORCED.format(tag="foo"): 1, + counter.Result.SYNCED_DIFFERENT.format(tag="foo"): 1, + counter.Result.SYNCED_DIFFERENT.format(tag="bar"): 1, + counter.Result.SYNCED_TAG_TOTAL.format(tag="foo"): 4, + counter.Result.SYNCED_TAG_TOTAL.format(tag="bar"): 2, + counter.Result.SYNCED_TOTAL: 6, + } + assert ( + counter.annotation_ids_to_sync + == Any.list.containing( + [url_safe_annotation_id(job) for job in foo_jobs + bar_jobs] + ).only() + ) + + def test_annotation_synced_ignores_duplicates(self, counter, db_session, factories): + # Two jobs for the same annotation. + jobs = factories.SyncAnnotationJob.create_batch( + 2, annotation=factories.Annotation(), tag="foo" + ) + # Flush the DB to generate job.id values. + db_session.flush() + + counter.annotation_synced(counter.Result.SYNCED_MISSING, jobs[0]) + counter.annotation_synced(counter.Result.SYNCED_MISSING, jobs[1]) + + assert counter.counts == { + counter.Result.SYNCED_MISSING.format(tag="foo"): 1, + counter.Result.SYNCED_TAG_TOTAL.format(tag="foo"): 1, + counter.Result.SYNCED_TOTAL: 1, + } + assert counter.annotation_ids_to_sync == [url_safe_annotation_id(jobs[0])] + + def test_annotation_deleted(self, counter, db_session, factories): + jobs = [ + *factories.SyncAnnotationJob.create_batch(2, tag="foo"), + factories.SyncAnnotationJob(tag="bar"), + ] + # Flush the DB to generate job.id values. + db_session.flush() + + counter.annotation_deleted(counter.Result.SYNCED_DELETED, jobs[0]) + counter.annotation_deleted(counter.Result.SYNCED_DELETED, jobs[1]) + counter.annotation_deleted(counter.Result.SYNCED_DELETED, jobs[2]) + + assert counter.counts == { + counter.Result.SYNCED_DELETED.format(tag="foo"): 2, + counter.Result.SYNCED_DELETED.format(tag="bar"): 1, + counter.Result.SYNCED_TAG_TOTAL.format(tag="foo"): 2, + counter.Result.SYNCED_TAG_TOTAL.format(tag="bar"): 1, + counter.Result.SYNCED_TOTAL: 3, + } + assert ( + counter.annotation_ids_to_delete + == Any.list.containing([url_safe_annotation_id(job) for job in jobs]).only() + ) + + def test_job_completed(self, counter, db_session, factories): + foo_jobs = factories.SyncAnnotationJob.create_batch(4, tag="foo") + bar_jobs = factories.SyncAnnotationJob.create_batch(2, tag="bar") + # Flush the DB to generate job.id values. + db_session.flush() + + counter.job_completed(counter.Result.COMPLETED_UP_TO_DATE, foo_jobs[0]) + counter.job_completed(counter.Result.COMPLETED_UP_TO_DATE, bar_jobs[0]) + counter.job_completed(counter.Result.COMPLETED_FORCED, foo_jobs[1]) + counter.job_completed(counter.Result.COMPLETED_DELETED, foo_jobs[2]) + counter.job_completed(counter.Result.COMPLETED_UP_TO_DATE, foo_jobs[3]) + counter.job_completed(counter.Result.COMPLETED_DELETED, bar_jobs[1]) + + assert counter.counts == { + counter.Result.COMPLETED_UP_TO_DATE.format(tag="foo"): 2, + counter.Result.COMPLETED_UP_TO_DATE.format(tag="bar"): 1, + counter.Result.COMPLETED_FORCED.format(tag="foo"): 1, + counter.Result.COMPLETED_DELETED.format(tag="foo"): 1, + counter.Result.COMPLETED_DELETED.format(tag="bar"): 1, + counter.Result.COMPLETED_TAG_TOTAL.format(tag="foo"): 4, + counter.Result.COMPLETED_TAG_TOTAL.format(tag="bar"): 2, + counter.Result.COMPLETED_TOTAL: 6, + } + assert counter.jobs_to_delete == Any.list.containing(foo_jobs + bar_jobs).only() + + def test_job_completed_ignores_duplicates(self, counter, db_session, factories): + # Two jobs for the same annotation. + job = factories.SyncAnnotationJob() + # Flush the DB to generate job.id values. + db_session.flush() + + counter.job_completed(counter.Result.COMPLETED_UP_TO_DATE, job) + counter.job_completed(counter.Result.COMPLETED_UP_TO_DATE, job) + + assert counter.counts == { + counter.Result.COMPLETED_UP_TO_DATE.format(tag=job.tag): 1, + counter.Result.COMPLETED_TAG_TOTAL.format(tag=job.tag): 1, + counter.Result.COMPLETED_TOTAL: 1, + } + assert counter.jobs_to_delete == [job] + + def test_annotation_synced_and_job_completed_together( + self, counter, db_session, factories + ): + jobs = factories.SyncAnnotationJob.create_batch(2, tag="foo") + # Flush the DB to generate job.id values. + db_session.flush() + + counter.annotation_synced(counter.Result.SYNCED_MISSING, jobs[0]) + counter.job_completed(counter.Result.COMPLETED_UP_TO_DATE, jobs[1]) + + assert counter.counts == { + counter.Result.SYNCED_MISSING.format(tag="foo"): 1, + counter.Result.SYNCED_TAG_TOTAL.format(tag="foo"): 1, + counter.Result.SYNCED_TOTAL: 1, + counter.Result.COMPLETED_UP_TO_DATE.format(tag="foo"): 1, + counter.Result.COMPLETED_TAG_TOTAL.format(tag="foo"): 1, + counter.Result.COMPLETED_TOTAL: 1, + } + + @pytest.fixture + def counter(self): + return Counter() + + +class TestFactory: + def test_it( + self, + AnnotationSyncService, + BatchIndexer, + DBHelper, + ESHelper, + db_session, + pyramid_request, + queue_service, + ): + svc = factory(sentinel.context, pyramid_request) + + BatchIndexer.assert_called_once_with( + pyramid_request.db, pyramid_request.es, pyramid_request + ) + DBHelper.assert_called_once_with(db=db_session) + ESHelper.assert_called_once_with(es=pyramid_request.es) + AnnotationSyncService.assert_called_once_with( + batch_indexer=BatchIndexer.return_value, + db_helper=DBHelper.return_value, + es_helper=ESHelper.return_value, + queue_service=queue_service, + ) + assert svc == AnnotationSyncService.return_value + + @pytest.fixture(autouse=True) + def AnnotationSyncService(self, patch): + return patch("h.services.annotation_sync.AnnotationSyncService") + + @pytest.fixture(autouse=True) + def BatchIndexer(self, patch): + return patch("h.services.annotation_sync.BatchIndexer") + + @pytest.fixture(autouse=True) + def DBHelper(self, patch): + return patch("h.services.annotation_sync.DBHelper") + + @pytest.fixture(autouse=True) + def ESHelper(self, patch): + return patch("h.services.annotation_sync.ESHelper") + + @pytest.fixture + def pyramid_request(self, pyramid_request): + pyramid_request.es = sentinel.es + return pyramid_request + + +@pytest.fixture +def search_index_service( + pyramid_request, + es_client, + moderation_service, # pylint:disable=unused-argument + nipsa_service, # pylint:disable=unused-argument +): + # Construct a real (not mock) SearchIndexService so we can call its + # methods to index annotations. + # + # This isn't ideal because it means these AnnotationSyncService + # unit tests are coupled to SearchIndexService and any other services + # or code that SearchIndexService calls. + # + # On the other hand, this avoids these tests having to duplicate + # SearchIndexService's code for indexing annotations and ensures that + # the documents in the search index are the same as they would be in + # production. + # + # (FIXME: The real solution to this issue is to refactor the services + # to be more coherent and avoid this testing dilemma.) + return SearchIndexService( + request=pyramid_request, + es=es_client, + settings={}, + annotation_read_service=sentinel.annotation_read_service, + ) + + +@pytest.fixture +def index(search_index_service, es_client): + """Return a method that indexes an annotation into Elasticsearch.""" + + def index(annotation): + """Index `annotation` into Elasticsearch.""" + search_index_service.add_annotation(annotation) + es_client.conn.indices.refresh(index=es_client.index) + + return index + + +@pytest.fixture +def delete_from_elasticsearch(search_index_service, es_client): + """Return a method that deletes an annotation from Elasticsearch.""" + + def delete_from_elasticsearch(annotation): + """Delete `annotation` from Elasticsearch.""" + search_index_service.delete_annotation_by_id(annotation.id) + es_client.conn.indices.refresh(index=es_client.index) + + return delete_from_elasticsearch + + +def url_safe_annotation_id(job): + """Return the URL-safe version of the given job's annotation ID.""" + return URLSafeUUID.hex_to_url_safe(job.kwargs["annotation_id"]) diff --git a/tests/unit/h/services/annotation_write_test.py b/tests/unit/h/services/annotation_write_test.py new file mode 100644 index 00000000000..f978aadb7a2 --- /dev/null +++ b/tests/unit/h/services/annotation_write_test.py @@ -0,0 +1,339 @@ +from datetime import datetime, timedelta +from unittest.mock import Mock, patch, sentinel + +import pytest +from h_matchers import Any + +from h.models import Annotation, AnnotationModeration, AnnotationSlim, User +from h.schemas import ValidationError +from h.security import Permission +from h.services.annotation_write import AnnotationWriteService, service_factory +from h.traversal.group import GroupContext + + +class TestAnnotationWriteService: + def test_create_annotation( + self, + svc, + create_data, + factories, + update_document_metadata, + queue_service, + annotation_read_service, + _validate_group, + db_session, + ): + root_annotation = factories.Annotation() + annotation_read_service.get_annotation_by_id.return_value = root_annotation + create_data["references"] = [root_annotation.id, factories.Annotation().id] + create_data["groupid"] = "IGNORED" + update_document_metadata.return_value = factories.Document() + + anno = svc.create_annotation(create_data) + + annotation_read_service.get_annotation_by_id.assert_called_once_with( + root_annotation.id + ) + _validate_group.assert_called_once_with(anno) + queue_service.add_by_id.assert_called_once_with( + "sync_annotation", + annotation_id=anno.id, + tag="storage.create_annotation", + schedule_in=60, + ) + + assert anno == Any.instance_of(Annotation).with_attrs( + { + "userid": create_data["userid"], + "groupid": root_annotation.groupid, + "target_uri": create_data["target_uri"], + "references": create_data["references"], + "document": update_document_metadata.return_value, + } + ) + self.assert_annotation_slim(db_session, anno) + + def test_create_annotation_with_metadata( + self, svc, create_data, annotation_metadata_service, factories + ): + group = factories.Group() + create_data["references"] = None + create_data["groupid"] = group.pubid + create_data["metadata"] = sentinel.metadata + + result = svc.create_annotation(create_data) + + annotation_metadata_service.set.assert_called_once_with( + result, sentinel.metadata + ) + + def test_create_annotation_as_root( + self, svc, create_data, factories, annotation_read_service + ): + group = factories.Group() + create_data["references"] = None + create_data["groupid"] = group.pubid + + result = svc.create_annotation(create_data) + + annotation_read_service.get_annotation_by_id.assert_not_called() + assert result.groupid == group.pubid + + def test_create_annotation_with_invalid_parent( + self, svc, create_data, annotation_read_service + ): + create_data["references"] = ["NOPE!"] + annotation_read_service.get_annotation_by_id.return_value = None + + with pytest.raises(ValidationError): + svc.create_annotation(create_data) + + def test_update_annotation( + self, + svc, + db_session, + annotation, + update_document_metadata, + queue_service, + _validate_group, + ): + then = datetime.now() - timedelta(days=1) + annotation.extra = {"key": "value"} + annotation.updated = then + + anno = svc.update_annotation( + annotation, + { + "target_uri": "new_target_uri", + "text": "new_text", + "extra": {"extra_key": "extra_value"}, + "document": { + "document_meta_dicts": {"meta": 1}, + "document_uri_dicts": {"uri": 1}, + }, + }, + update_timestamp=True, + enforce_write_permission=sentinel.enforce_write_permission, + ) + + _validate_group.assert_called_once_with( + annotation, enforce_write_permission=sentinel.enforce_write_permission + ) + update_document_metadata.assert_called_once_with( + db_session, + anno.target_uri, + {"meta": 1}, + {"uri": 1}, + updated=anno.updated, + ) + + queue_service.add_by_id.assert_called_once_with( + "sync_annotation", + annotation_id=annotation.id, + tag="storage.update_annotation", + schedule_in=60, + force=False, + ) + assert anno.document == update_document_metadata.return_value + assert anno.target_uri == "new_target_uri" + assert anno.text == "new_text" + assert anno.updated > then + assert anno.extra == {"key": "value", "extra_key": "extra_value"} + self.assert_annotation_slim(db_session, anno) + + def test_update_annotation_with_non_defaults(self, svc, annotation, queue_service): + then = datetime.now() - timedelta(days=1) + annotation.updated = then + + result = svc.update_annotation( + annotation, {}, update_timestamp=False, reindex_tag="custom_tag" + ) + + queue_service.add_by_id.assert_called_once_with( + "sync_annotation", + annotation_id=Any(), + tag="custom_tag", + schedule_in=Any(), + force=True, + ) + assert result.updated == then + + def test_update_annotation_with_metadata( + self, svc, annotation, annotation_metadata_service + ): + result = svc.update_annotation( + annotation, + {"metadata": sentinel.metadata}, + update_timestamp=False, + reindex_tag="custom_tag", + ) + + annotation_metadata_service.set.assert_called_once_with( + result, sentinel.metadata + ) + + def test__validate_group_with_no_group(self, svc, annotation): + annotation.group = None + + with pytest.raises(ValidationError): + svc._validate_group(annotation) # pylint: disable=protected-access + + def test__validate_group_with_no_permission(self, svc, annotation, has_permission): + has_permission.return_value = False + + with pytest.raises(ValidationError): + svc._validate_group(annotation) # pylint: disable=protected-access + + has_permission.assert_called_once_with( + Permission.Group.WRITE, context=GroupContext(annotation.group) + ) + + def test__validate_group_with_no_permission_and_checking_disabled( + self, svc, annotation, has_permission + ): + has_permission.return_value = False + + # pylint: disable=protected-access + svc._validate_group(annotation, enforce_write_permission=False) + + has_permission.assert_not_called() + + @pytest.mark.parametrize("enforce_scope", (True, False)) + @pytest.mark.parametrize("matching_scope", (True, False)) + @pytest.mark.parametrize("has_scopes", (True, False)) + def test__validate_group_with_url_not_in_scopes( + self, svc, annotation, factories, enforce_scope, matching_scope, has_scopes + ): + annotation.group.enforce_scope = enforce_scope + annotation.target_uri = "http://scope" if matching_scope else "http://MISMATCH" + if has_scopes: + annotation.group.scopes = [factories.GroupScope(scope="http://scope")] + + if enforce_scope and has_scopes and not matching_scope: + with pytest.raises(ValidationError): + svc._validate_group(annotation) # pylint: disable=protected-access + else: + svc._validate_group(annotation) # pylint: disable=protected-access + + def test_hide_hides_the_annotation(self, annotation, svc): + annotation.moderation = None + + svc.hide(annotation) + + assert annotation.is_hidden + + def test_hide_does_not_modify_an_already_hidden_annotation(self, annotation, svc): + moderation = AnnotationModeration() + annotation.moderation = moderation + + svc.hide(annotation) + + assert annotation.is_hidden + # It's the same one not a new one + assert annotation.moderation == moderation + + def test_unhide(self, annotation, svc): + moderation = AnnotationModeration() + annotation.moderation = moderation + + svc.unhide(annotation) + + assert not annotation.is_hidden + + def test_upsert_annotation_slim_with_deleted_group(self, annotation, svc): + annotation.groupid = "deleted group" + + svc.upsert_annotation_slim(annotation) + + def test_upsert_annotation_slim_with_deleted_user(self, annotation, svc): + annotation.userid = "deleted user" + + svc.upsert_annotation_slim(annotation) + + @pytest.fixture + def create_data(self, factories): + user = factories.User() + + return { + "userid": user.userid, + "target_uri": "http://example.com/target", + "document": { + "document_uri_dicts": sentinel.uri_dicts, + "document_meta_dicts": sentinel.document_dicts, + }, + } + + @pytest.fixture + def annotation(self, factories): + user = factories.User() + return factories.Annotation(userid=user.userid) + + @pytest.fixture + def has_permission(self): + return Mock(return_value=True) + + @pytest.fixture + def svc( + self, + db_session, + has_permission, + queue_service, + annotation_read_service, + annotation_metadata_service, + ): + return AnnotationWriteService( + db_session=db_session, + has_permission=has_permission, + queue_service=queue_service, + annotation_read_service=annotation_read_service, + annotation_metadata_service=annotation_metadata_service, + ) + + @pytest.fixture + def _validate_group(self, svc): + with patch.object(svc, "_validate_group") as _validate_group: + yield _validate_group + + @pytest.fixture(autouse=True) + def update_document_metadata(self, patch, factories): + update_document_metadata = patch( + "h.services.annotation_write.update_document_metadata" + ) + update_document_metadata.return_value = factories.Document() + return update_document_metadata + + def assert_annotation_slim(self, db_session, annotation): + slim = db_session.query(AnnotationSlim).filter_by(pubid=annotation.id).one() + + assert ( + slim.user_id + == db_session.query(User).filter_by(userid=annotation.userid).one().id + ) + assert slim.group_id == annotation.group.id + assert slim.document_id == annotation.document_id + assert slim.deleted == annotation.deleted + + +class TestServiceFactory: + def test_it( + self, + pyramid_request, + AnnotationWriteService, + queue_service, + annotation_read_service, + annotation_metadata_service, + ): + svc = service_factory(sentinel.context, pyramid_request) + + AnnotationWriteService.assert_called_once_with( + db_session=pyramid_request.db, + has_permission=pyramid_request.has_permission, + queue_service=queue_service, + annotation_read_service=annotation_read_service, + annotation_metadata_service=annotation_metadata_service, + ) + assert svc == AnnotationWriteService.return_value + + @pytest.fixture + def AnnotationWriteService(self, patch): + return patch("h.services.annotation_write.AnnotationWriteService") diff --git a/tests/h/services/auth_cookie_test.py b/tests/unit/h/services/auth_cookie_test.py similarity index 94% rename from tests/h/services/auth_cookie_test.py rename to tests/unit/h/services/auth_cookie_test.py index 7a344079cc4..d08eb2e57d0 100644 --- a/tests/h/services/auth_cookie_test.py +++ b/tests/unit/h/services/auth_cookie_test.py @@ -138,9 +138,9 @@ class TestFactory: def test_it( self, pyramid_request, SignedCookieProfile, AuthCookieService, user_service ): - pyramid_request.registry.settings[ - "h_auth_cookie_secret" - ] = sentinel.cookie_secret + pyramid_request.registry.settings["h_auth_cookie_secret"] = ( + sentinel.cookie_secret + ) cookie_service = factory(sentinel.context, pyramid_request) @@ -148,7 +148,7 @@ def test_it( secret=pyramid_request.registry.settings["h_auth_cookie_secret"], salt="authsanity", cookie_name="auth", - secure=False, + secure=True, max_age=2592000, httponly=True, ) @@ -167,3 +167,8 @@ def SignedCookieProfile(self, patch): @pytest.fixture def AuthCookieService(self, patch): return patch("h.services.auth_cookie.AuthCookieService") + + @pytest.fixture + def pyramid_request(self, pyramid_request): + pyramid_request.scheme = "https" # Simulate production environment + return pyramid_request diff --git a/tests/h/services/auth_token_test.py b/tests/unit/h/services/auth_token_test.py similarity index 95% rename from tests/h/services/auth_token_test.py rename to tests/unit/h/services/auth_token_test.py index c37023a8f27..212dbff8b4d 100644 --- a/tests/h/services/auth_token_test.py +++ b/tests/unit/h/services/auth_token_test.py @@ -17,7 +17,7 @@ def test_validate_returns_database_token(self, svc, factories): result = svc.validate(token_model.value) assert result.expires == token_model.expires - assert result.userid == token_model.userid + assert result.userid == token_model.user.userid def test_validate_caches_database_token(self, svc, factories, db_session): token_model = factories.DeveloperToken(expires=self.time(1)) @@ -103,9 +103,7 @@ class TestLongLivedToken: ), ) def test_it(self, expires, is_valid, factories): - token = LongLivedToken( - factories.OAuth2Token(userid="acct:foo@example.com", expires=expires) - ) + token = LongLivedToken(factories.OAuth2Token(expires=expires)) assert token.is_valid() == is_valid diff --git a/tests/unit/h/services/bulk_api/_helpers_test.py b/tests/unit/h/services/bulk_api/_helpers_test.py new file mode 100644 index 00000000000..0f359401e72 --- /dev/null +++ b/tests/unit/h/services/bulk_api/_helpers_test.py @@ -0,0 +1,52 @@ +from unittest.mock import sentinel + +import pytest +from _pytest.mark import param +from h_matchers import Any +from sqlalchemy import select + +from h.models import Annotation +from h.services.bulk_api._helpers import date_match +from h.services.bulk_api.exceptions import BadDateFilter + + +class TestDateMatch: + @pytest.mark.parametrize( + "spec,expected", + ( + param({"gt": "2001-01-01"}, ["2"], id="gt"), + param({"gte": "2001-01-01"}, ["1", "2"], id="gte"), + param({"lt": "2001-01-01"}, ["0"], id="lt"), + param({"lte": "2001-01-01"}, ["0", "1"], id="lte"), + param({"eq": "2001-01-01"}, ["1"], id="eq"), + param({"ne": "2001-01-01"}, ["0", "2"], id="ne"), + param({"gt": "2000-01-01", "lt": "2002-01-01"}, ["1"], id="combo"), + ), + ) + def test_it(self, db_session, factories, spec, expected): + factories.Annotation(text="0", created="2000-01-01") + factories.Annotation(text="1", created="2001-01-01") + factories.Annotation(text="2", created="2002-01-01") + + annotations = ( + db_session.execute( + select(Annotation).where(date_match(Annotation.created, spec)) + ) + .scalars() + .all() + ) + + assert [anno.text for anno in annotations] == Any.list.containing( + expected + ).only() + + @pytest.mark.parametrize( + "bad_spec", + ( + param({}, id="empty"), + param({"bad_op": "2002-01-01"}, id="bad_op"), + ), + ) + def test_it_raises_for_bad_spec(self, bad_spec): + with pytest.raises(BadDateFilter): + date_match(sentinel.column, bad_spec) diff --git a/tests/unit/h/services/bulk_api/annotation_test.py b/tests/unit/h/services/bulk_api/annotation_test.py new file mode 100644 index 00000000000..4ac7d5d6a5f --- /dev/null +++ b/tests/unit/h/services/bulk_api/annotation_test.py @@ -0,0 +1,138 @@ +from unittest.mock import sentinel + +import pytest +from h_matchers import Any + +from h.services.bulk_api.annotation import ( + BulkAnnotation, + BulkAnnotationService, + service_factory, +) + + +class TestBulkAnnotationService: + AUTHORITY = "my.authority" + + @pytest.mark.parametrize( + "key,value,visible", + ( + (None, None, True), + ("shared", False, False), + ("deleted", True, False), + ("nipsad", True, False), + ("with_metadata", True, True), + ("with_metadata", False, True), + ("moderated", True, False), + ("created", "2020-01-01", False), + ("created", "2020-01-02", True), + ("created", "2022-01-01", True), + ("created", "2022-01-02", False), + ), + ) + @pytest.mark.parametrize("username", ["USERNAME", "username", "user.name"]) + def test_it_with_single_annotation( + self, svc, factories, key, value, visible, username + ): + values = { + "shared": True, + "deleted": False, + "nipsad": False, + "moderated": False, + "created": "2021-01-01", + "with_metadata": True, + } + if key: + values[key] = value + + viewer = factories.User(authority=self.AUTHORITY) + author = factories.User( + authority=self.AUTHORITY, nipsa=values["nipsad"], username=username + ) + group = factories.Group(members=[author, viewer]) + anno_slim = factories.AnnotationSlim( + user=author, + group=group, + shared=values["shared"], + deleted=values["deleted"], + created=values["created"], + moderated=values["moderated"], + ) + + if values["with_metadata"]: + factories.AnnotationMetadata( + annotation_slim=anno_slim, data={"some": "value"} + ) + + annotations = svc.annotation_search( + authority=self.AUTHORITY, + username="USERNAME", + created={"gt": "2020-01-01", "lte": "2022-01-01"}, + ) + + if visible: + assert annotations == [ + BulkAnnotation( + username=author.username, + authority_provided_id=group.authority_provided_id, + metadata={"some": "value"} if values["with_metadata"] else {}, + ) + ] + else: + assert not annotations + + def test_it_with_more_complex_grouping(self, svc, factories): + viewer, author = factories.User.create_batch(2, authority=self.AUTHORITY) + + annotations = [ + factories.AnnotationSlim( + user=author, + group=factories.Group(members=group_members), + shared=True, + deleted=False, + ) + for group_members in ( + # The first two annotations should match, because they are in + # groups the viewer is in + [author, viewer], + [author, viewer], + # This one is just noise and shouldn't match + [author], + ) + ] + + matched_annos = svc.annotation_search( + authority=self.AUTHORITY, + username=viewer.username, + created={"gt": "2020-01-01", "lte": "2099-01-01"}, + ) + + # Only the first two annotations should match + assert ( + matched_annos + == Any.list.containing( + [ + BulkAnnotation( + username=author.username, + authority_provided_id=annotation.group.authority_provided_id, + metadata={}, + ) + for annotation in annotations[:2] + ] + ).only() + ) + + @pytest.fixture + def svc(self, db_session): + return BulkAnnotationService(db_session) + + +class TestServiceFactory: + def test_it(self, pyramid_request, BulkAnnotationService): + svc = service_factory(sentinel.context, pyramid_request) + + BulkAnnotationService.assert_called_once_with(db_session=pyramid_request.db) + assert svc == BulkAnnotationService.return_value + + @pytest.fixture + def BulkAnnotationService(self, patch): + return patch("h.services.bulk_api.annotation.BulkAnnotationService") diff --git a/tests/unit/h/services/bulk_api/group_test.py b/tests/unit/h/services/bulk_api/group_test.py new file mode 100644 index 00000000000..72db87fd499 --- /dev/null +++ b/tests/unit/h/services/bulk_api/group_test.py @@ -0,0 +1,48 @@ +from datetime import datetime, timedelta +from unittest.mock import sentinel + +import pytest +from h_matchers import Any + +from h.services.bulk_api.group import BulkGroup, BulkGroupService, service_factory + + +class TestBulkGroupService: + def test_it(self, svc, factories): + since = datetime(2023, 1, 1) + group = factories.Group() + group_without_annos = factories.Group() + group_with_annos_in_other_dates = factories.Group() + another_group = factories.Group() + factories.Annotation(group=group, created=since + timedelta(days=1)) + factories.Annotation( + group=group_with_annos_in_other_dates, created=since - timedelta(days=1) + ) + + groups = svc.group_search( + groups=[ + group.authority_provided_id, + group_without_annos.authority_provided_id, + group_with_annos_in_other_dates.authority_provided_id, + another_group.authority_provided_id, + ], + annotations_created={"gt": "2023-01-01", "lte": "2023-12-31"}, + ) + + assert groups == [BulkGroup(authority_provided_id=group.authority_provided_id)] + + @pytest.fixture + def svc(self, db_session): + return BulkGroupService(db_session) + + +class TestServiceFactory: + def test_it(self, pyramid_request, BulkGroupService): + svc = service_factory(sentinel.context, pyramid_request) + + BulkGroupService.assert_called_once_with(db_replica=pyramid_request.db_replica) + assert svc == BulkGroupService.return_value + + @pytest.fixture + def BulkGroupService(self, patch): + return patch("h.services.bulk_api.group.BulkGroupService") diff --git a/tests/unit/h/services/bulk_api/lms_stats_test.py b/tests/unit/h/services/bulk_api/lms_stats_test.py new file mode 100644 index 00000000000..bb131cf1b35 --- /dev/null +++ b/tests/unit/h/services/bulk_api/lms_stats_test.py @@ -0,0 +1,119 @@ +from datetime import datetime, timedelta +from unittest.mock import sentinel + +import pytest +from h_matchers import Any + +from h.services.bulk_api.lms_stats import ( + BulkLMSStatsService, + CountsByAssignment, + CountsByUser, + service_factory, +) + + +class TestBulkLMSStatsService: + def test_get_counts_by_user( + self, svc, group, user, annotation, annotation_reply, reply_user + ): + stats = svc.get_counts_by_user( + groups=[group.authority_provided_id], assignment_id="ASSIGNMENT_ID" + ) + + assert stats == [ + CountsByUser( + userid=user.userid, + display_name=user.display_name, + annotations=1, + replies=0, + last_activity=annotation.created, + ), + CountsByUser( + userid=reply_user.userid, + display_name=reply_user.display_name, + annotations=0, + replies=1, + last_activity=annotation_reply.created, + ), + ] + + @pytest.mark.usefixtures("user", "annotation", "reply_user") + def test_get_counts_by_assignment(self, svc, group, annotation_reply): + stats = svc.get_counts_by_assignment(groups=[group.authority_provided_id]) + + assert stats == [ + CountsByAssignment( + assignment_id="ASSIGNMENT_ID", + annotations=1, + replies=1, + last_activity=annotation_reply.created, + ), + ] + + @pytest.fixture + def group(self, factories): + return factories.Group() + + @pytest.fixture + def user(self, factories): + return factories.User() + + @pytest.fixture + def reply_user(self, factories): + return factories.User() + + @pytest.fixture + def annotation(self, factories, user, group): + anno = factories.Annotation(group=group) + anno_slim = factories.AnnotationSlim( + annotation=anno, + user=user, + deleted=False, + shared=True, + moderated=False, + group=group, + ) + factories.AnnotationMetadata( + annotation_slim=anno_slim, + data={"lms": {"assignment": {"resource_link_id": "ASSIGNMENT_ID"}}}, + ) + + return anno_slim + + @pytest.fixture + def annotation_reply(self, factories, reply_user, group, annotation): + anno_reply = factories.Annotation(group=group, references=[annotation.id]) + anno_slim_reply = factories.AnnotationSlim( + annotation=anno_reply, + user=reply_user, + deleted=False, + shared=True, + moderated=False, + group=group, + ) + factories.AnnotationMetadata( + annotation_slim=anno_slim_reply, + data={"lms": {"assignment": {"resource_link_id": "ASSIGNMENT_ID"}}}, + ) + + return anno_slim_reply + + @pytest.fixture + def svc(self, db_session): + return BulkLMSStatsService(db_session, "example.com") + + +class TestServiceFactory: + @pytest.mark.usefixtures("with_auth_client") + def test_it(self, pyramid_request, BulkLMSStatsService): + svc = service_factory(sentinel.context, pyramid_request) + + BulkLMSStatsService.assert_called_once_with( + db=pyramid_request.db, + authorized_authority=pyramid_request.identity.auth_client.authority, + ) + assert svc == BulkLMSStatsService.return_value + + @pytest.fixture + def BulkLMSStatsService(self, patch): + return patch("h.services.bulk_api.lms_stats.BulkLMSStatsService") diff --git a/tests/h/services/bulk_executor/__init__.py b/tests/unit/h/services/bulk_executor/__init__.py similarity index 100% rename from tests/h/services/bulk_executor/__init__.py rename to tests/unit/h/services/bulk_executor/__init__.py diff --git a/tests/h/services/bulk_executor/_actions_test.py b/tests/unit/h/services/bulk_executor/_actions_test.py similarity index 99% rename from tests/h/services/bulk_executor/_actions_test.py rename to tests/unit/h/services/bulk_executor/_actions_test.py index 0148403a854..86e1547f7a7 100644 --- a/tests/h/services/bulk_executor/_actions_test.py +++ b/tests/unit/h/services/bulk_executor/_actions_test.py @@ -20,7 +20,7 @@ GroupUpsertAction, UserUpsertAction, ) -from tests.h.services.bulk_executor.conftest import ( +from tests.unit.h.services.bulk_executor.conftest import ( AUTHORITY, group_membership_create, group_upsert_command, diff --git a/tests/h/services/bulk_executor/_executor_test.py b/tests/unit/h/services/bulk_executor/_executor_test.py similarity index 98% rename from tests/h/services/bulk_executor/_executor_test.py rename to tests/unit/h/services/bulk_executor/_executor_test.py index a3c1374db28..a065165280f 100644 --- a/tests/h/services/bulk_executor/_executor_test.py +++ b/tests/unit/h/services/bulk_executor/_executor_test.py @@ -5,7 +5,7 @@ from pytest import param from h.services.bulk_executor._executor import BulkExecutor -from tests.h.services.bulk_executor.conftest import ( +from tests.unit.h.services.bulk_executor.conftest import ( AUTHORITY, group_upsert_command, upsert_user_command, diff --git a/tests/h/services/bulk_executor/conftest.py b/tests/unit/h/services/bulk_executor/conftest.py similarity index 99% rename from tests/h/services/bulk_executor/conftest.py rename to tests/unit/h/services/bulk_executor/conftest.py index ddcc2dd0a52..8ac1bd87906 100644 --- a/tests/h/services/bulk_executor/conftest.py +++ b/tests/unit/h/services/bulk_executor/conftest.py @@ -1,4 +1,5 @@ """Re-usable fixtures for the bulk executor tests.""" + import pytest from h_api.bulk_api import CommandBuilder diff --git a/tests/unit/h/services/developer_token_test.py b/tests/unit/h/services/developer_token_test.py new file mode 100644 index 00000000000..cfcf22c2d39 --- /dev/null +++ b/tests/unit/h/services/developer_token_test.py @@ -0,0 +1,90 @@ +import pytest +from h_matchers import Any + +from h import models +from h.services.developer_token import ( + DeveloperTokenService, + developer_token_service_factory, +) + +pytestmark = pytest.mark.usefixtures("user_service") + + +class TestDeveloperTokenService: + def test_fetch_returns_developer_token_for_userid( + self, svc, developer_token, user, user_service + ): + user_service.fetch.return_value = user + + assert svc.fetch(user.userid) == developer_token + user_service.fetch.assert_called_once_with(user.userid) + + def test_fetch_returns_none_for_missing_userid(self, svc): + assert svc.fetch(None) is None + + def test_fetch_returns_none_for_missing_developer_token( + self, svc, user, user_service + ): + user_service.fetch.return_value = user + + assert svc.fetch(user.userid) is None + user_service.fetch.assert_called_once_with(user.userid) + + def test_create_creates_new_developer_token_for_userid( + self, svc, db_session, user, user_service + ): + assert not db_session.query(models.Token).count() + user_service.fetch.return_value = user + + svc.create(user.userid) + + user_service.fetch.assert_called_once_with(user.userid) + assert db_session.query(models.Token).all() == [ + Any.instance_of(models.Token).with_attrs({"user": user}) + ] + + def test_create_returns_new_developer_token_for_userid( + self, svc, user, patch, user_service + ): + user_service.fetch.return_value = user + token_urlsafe = patch("h.services.developer_token.security.token_urlsafe") + token_urlsafe.return_value = "secure-token" + + token = svc.create(user.userid) + + assert token.user == user + assert token.value == "6879-secure-token" + assert token.expires is None + assert token.authclient is None + assert token.refresh_token is None + + def test_regenerate_sets_a_new_token_value(self, svc, developer_token): + old_user = developer_token.user + old_value = developer_token.value + + svc.regenerate(developer_token) + + assert old_user == developer_token.user + assert old_value != developer_token.value + + @pytest.fixture + def svc(self, pyramid_request): + return developer_token_service_factory(None, pyramid_request) + + @pytest.fixture + def developer_token(self, factories, user): + return factories.DeveloperToken(user=user) + + @pytest.fixture + def user(self, factories): + return factories.User() + + +class TestDeveloperTokenServiceFactory: + def test_it_returns_developer_token_service(self, pyramid_request): + svc = developer_token_service_factory(None, pyramid_request) + assert isinstance(svc, DeveloperTokenService) + + def test_it_provides_request_db_as_session(self, pyramid_request): + svc = developer_token_service_factory(None, pyramid_request) + assert svc.session == pyramid_request.db diff --git a/tests/h/services/document_test.py b/tests/unit/h/services/document_test.py similarity index 66% rename from tests/h/services/document_test.py rename to tests/unit/h/services/document_test.py index 42210d63df7..0bf744443c4 100644 --- a/tests/h/services/document_test.py +++ b/tests/unit/h/services/document_test.py @@ -1,7 +1,9 @@ +from unittest.mock import sentinel + import pytest from h_matchers import Any -from h.services.document import DocumentService +from h.services.document import DocumentService, document_service_factory class TestFetchByGroupid: @@ -87,40 +89,46 @@ def test_it_returns_documents_ordered_by_last_activity_desc( annotations[0].document, ] + @pytest.fixture + def target_user(self, factories): + return factories.User() -@pytest.fixture -def target_user(factories): - return factories.User() - - -@pytest.fixture -def other_user(factories): - return factories.User() + @pytest.fixture + def other_user(self, factories): + return factories.User() + @pytest.fixture + def groups(self, factories): + return {"target_group": factories.Group(), "other_group": factories.Group()} -@pytest.fixture -def groups(factories): - return {"target_group": factories.Group(), "other_group": factories.Group()} + @pytest.fixture + def annotations(self, factories, groups): + return [ + factories.Annotation(groupid=groups["target_group"].pubid, shared=True), + factories.Annotation(groupid=groups["target_group"].pubid, shared=True), + factories.Annotation(groupid=groups["target_group"].pubid, shared=True), + ] + @pytest.fixture + def other_annotations(self, factories, groups): + return [ + factories.Annotation(groupid=groups["other_group"].pubid, shared=True), + factories.Annotation(groupid=groups["other_group"].pubid, shared=True), + factories.Annotation(groupid=groups["other_group"].pubid, shared=True), + ] -@pytest.fixture -def annotations(factories, groups): - return [ - factories.Annotation(groupid=groups["target_group"].pubid, shared=True), - factories.Annotation(groupid=groups["target_group"].pubid, shared=True), - factories.Annotation(groupid=groups["target_group"].pubid, shared=True), - ] + @pytest.fixture + def svc(self, db_session): + return DocumentService(session=db_session) -@pytest.fixture -def other_annotations(factories, groups): - return [ - factories.Annotation(groupid=groups["other_group"].pubid, shared=True), - factories.Annotation(groupid=groups["other_group"].pubid, shared=True), - factories.Annotation(groupid=groups["other_group"].pubid, shared=True), - ] +class TestServiceFactory: + def test_it(self, pyramid_request, DocumentService): + svc = document_service_factory(sentinel.context, pyramid_request) + DocumentService.assert_called_once_with(session=pyramid_request.db) + assert svc == DocumentService.return_value -@pytest.fixture -def svc(db_session): - return DocumentService(session=db_session) + @pytest.fixture + def DocumentService(self, patch): + return patch("h.services.document.DocumentService") diff --git a/tests/h/services/exceptions_test.py b/tests/unit/h/services/exceptions_test.py similarity index 100% rename from tests/h/services/exceptions_test.py rename to tests/unit/h/services/exceptions_test.py diff --git a/tests/h/services/feature_test.py b/tests/unit/h/services/feature_test.py similarity index 91% rename from tests/h/services/feature_test.py rename to tests/unit/h/services/feature_test.py index 831aade1e63..3e38798c64a 100644 --- a/tests/h/services/feature_test.py +++ b/tests/unit/h/services/feature_test.py @@ -64,6 +64,15 @@ def test_enabled_true_if_everyone_true(self, db_session): assert svc.enabled("on-for-everyone") is True + def test_enabled_if_first_party(self, db_session, factories): + user = factories.User(authority="foobar.com") + third_party_user = factories.User(authority="othersite.com") + svc = FeatureService(session=db_session, default_authority=user.authority) + + assert svc.enabled("on-for-first-party") is False + assert svc.enabled("on-for-first-party", user) is True + assert svc.enabled("on-for-first-party", third_party_user) is False + def test_enabled_false_when_admins_true_no_user(self, db_session): svc = FeatureService(session=db_session) @@ -132,6 +141,7 @@ def test_all_returns_feature_dictionary(self, db_session): "foo": False, "bar": False, "on-for-everyone": True, + "on-for-first-party": False, "on-for-staff": False, "on-for-admins": False, "on-for-cohort": False, @@ -147,6 +157,7 @@ def test_all_respects_user_param(self, db_session, factories): "foo": False, "bar": False, "on-for-everyone": True, + "on-for-first-party": False, "on-for-staff": True, "on-for-admins": False, "on-for-cohort": False, @@ -159,6 +170,7 @@ def features(self, cohort, factories, patch): factories.Feature(name="foo"), factories.Feature(name="bar"), factories.Feature(name="on-for-everyone", everyone=True), + factories.Feature(name="on-for-first-party", first_party=True), factories.Feature(name="on-for-staff", staff=True), factories.Feature(name="on-for-admins", admins=True), factories.Feature(name="on-for-cohort", cohorts=[cohort]), diff --git a/tests/h/services/flag_test.py b/tests/unit/h/services/flag_test.py similarity index 100% rename from tests/h/services/flag_test.py rename to tests/unit/h/services/flag_test.py diff --git a/tests/h/services/group_create_test.py b/tests/unit/h/services/group_create_test.py similarity index 94% rename from tests/h/services/group_create_test.py rename to tests/unit/h/services/group_create_test.py index 2cc02cdb60b..2f517b1f32d 100644 --- a/tests/h/services/group_create_test.py +++ b/tests/unit/h/services/group_create_test.py @@ -218,17 +218,24 @@ def test_it_does_not_publish_join_event(self, svc, creator, publish, origins): publish.assert_not_called() - def test_it_sets_scopes(self, svc, creator): - origins = ["https://biopub.org", "http://example.com", "https://wikipedia.com"] - + @pytest.mark.parametrize( + "origins", + (["http://example.com", "http://example.org"], [], None), + ) + def test_it_sets_scopes(self, svc, creator, origins): group = svc.create_open_group( name="test_group", userid=creator.userid, scopes=origins ) - assert ( - group.scopes - == Any.list.containing([GroupScopeWithOrigin(h) for h in origins]).only() - ) + if origins: + assert ( + group.scopes + == Any.list.containing( + [GroupScopeWithOrigin(origin) for origin in origins] + ).only() + ) + else: + assert group.scopes == [] def test_it_always_creates_new_scopes(self, factories, svc, creator): # It always creates a new scope, even if a scope with the given origin @@ -365,17 +372,24 @@ def test_it_publishes_join_event(self, svc, creator, publish, origins): publish.assert_called_once_with("group-join", group.pubid, creator.userid) - def test_it_sets_scopes(self, svc, creator): - origins = ["https://biopub.org", "http://example.com", "https://wikipedia.com"] - + @pytest.mark.parametrize( + "origins", + (["http://example.com", "http://example.org"], [], None), + ) + def test_it_sets_scopes(self, svc, creator, origins): group = svc.create_restricted_group( name="test_group", userid=creator.userid, scopes=origins ) - assert ( - group.scopes - == Any.list.containing([GroupScopeWithOrigin(h) for h in origins]).only() - ) + if origins: + assert ( + group.scopes + == Any.list.containing( + [GroupScopeWithOrigin(origin) for origin in origins] + ).only() + ) + else: + assert group.scopes == [] def test_it_with_mismatched_authorities_raises_value_error( self, svc, origins, creator, factories diff --git a/tests/h/services/delete_group_test.py b/tests/unit/h/services/group_delete_test.py similarity index 78% rename from tests/h/services/delete_group_test.py rename to tests/unit/h/services/group_delete_test.py index 4a1142d2588..d1e9d37eb37 100644 --- a/tests/h/services/delete_group_test.py +++ b/tests/unit/h/services/group_delete_test.py @@ -3,15 +3,15 @@ import pytest from h.services.annotation_delete import AnnotationDeleteService -from h.services.delete_group import ( - DeleteGroupService, +from h.services.group_delete import ( DeletePublicGroupError, - delete_group_service_factory, + GroupDeleteService, + service_factory, ) @pytest.mark.usefixtures("annotation_delete_service") -class TestDeleteGroupService: +class TestGroupDeleteService: def test_it_does_not_delete_public_group(self, svc, factories): group = factories.Group() group.pubid = "__world__" @@ -43,17 +43,17 @@ def test_it_deletes_annotations(self, svc, factories, annotation_delete_service) @pytest.mark.usefixtures("annotation_delete_service") -class TestDeleteGroupServiceFactory: - def test_it_returns_delete_group_service_instance(self, pyramid_request): - svc = delete_group_service_factory(None, pyramid_request) +class TestServiceFactory: + def test_it_returns_group_delete_service_instance(self, pyramid_request): + svc = service_factory(None, pyramid_request) - assert isinstance(svc, DeleteGroupService) + assert isinstance(svc, GroupDeleteService) @pytest.fixture def svc(db_session, pyramid_request): pyramid_request.db = db_session - return delete_group_service_factory({}, pyramid_request) + return service_factory({}, pyramid_request) @pytest.fixture diff --git a/tests/h/services/group_links_test.py b/tests/unit/h/services/group_links_test.py similarity index 100% rename from tests/h/services/group_links_test.py rename to tests/unit/h/services/group_links_test.py diff --git a/tests/h/services/group_list_test.py b/tests/unit/h/services/group_list_test.py similarity index 95% rename from tests/h/services/group_list_test.py rename to tests/unit/h/services/group_list_test.py index f4303febf34..5e01201ce09 100644 --- a/tests/h/services/group_list_test.py +++ b/tests/unit/h/services/group_list_test.py @@ -1,4 +1,5 @@ from unittest import mock +from unittest.mock import sentinel import pytest from h_matchers import Any @@ -62,9 +63,12 @@ def test_it_does_not_return_private_groups_if_user_is_not_member( # the creator of the group. That means that this private group is still associated # with this user in some form—but we want to make sure it does not appear # in these results. - private_group = factories.Group( - creator=user, authority=user.authority, members=[] - ) + private_group = factories.Group(creator=user, authority=user.authority) + # Remove `private_group.creator` from `private_group.members`. + # The creator is still attached to `private_group` as `private_group.creator`. + private_group.members = [ + user for user in private_group.members if user is not private_group.creator + ] groups = svc.associated_groups(user) @@ -214,6 +218,11 @@ def test_it_fetches_matching_scopes_from_group_scope_service( group_scope_service.fetch_by_scope.assert_called_once_with(document_uri) + def test_it_returns_empty_list_if_no_document_url(self, svc): + results = svc.scoped_groups(sentinel.authority, document_uri=None) + + assert results == [] + def test_it_returns_empty_list_if_no_matching_scopes( self, svc, default_authority, document_uri, group_scope_service ): @@ -316,11 +325,6 @@ def other_authority_user(factories, other_authority): return factories.User(authority=other_authority) -@pytest.fixture -def origin(): - return "http://foo.com" - - @pytest.fixture def document_uri(): return "http://foo.com/bar/fun.html" diff --git a/tests/h/services/group_members_test.py b/tests/unit/h/services/group_members_test.py similarity index 93% rename from tests/h/services/group_members_test.py rename to tests/unit/h/services/group_members_test.py index 2c05bfc63ee..5bc254fbb50 100644 --- a/tests/h/services/group_members_test.py +++ b/tests/unit/h/services/group_members_test.py @@ -2,9 +2,8 @@ import pytest -from h.models import GroupScope, User +from h.models import User from h.services.group_members import GroupMembersService, group_members_factory -from tests.common.matchers import Matcher class TestMemberJoin: @@ -207,11 +206,6 @@ def fetch(userid): return fetch -@pytest.fixture -def origins(): - return ["http://example.com"] - - @pytest.fixture def publish(): return mock.Mock(spec_set=[]) @@ -225,17 +219,3 @@ def group_members_service(db_session, usr_group_members_service, publish): @pytest.fixture def creator(factories): return factories.User(username="group_creator") - - -class GroupScopeWithOrigin(Matcher): - """Matches any GroupScope with the given origin.""" - - def __init__( - self, origin - ): # pylint:disable=super-init-not-called #:(Overwriting __eq__ instead) - self.origin = origin - - def __eq__(self, group_scope): - if not isinstance(group_scope, GroupScope): - return False - return group_scope.origin == self.origin diff --git a/tests/h/services/group_scope_test.py b/tests/unit/h/services/group_scope_test.py similarity index 100% rename from tests/h/services/group_scope_test.py rename to tests/unit/h/services/group_scope_test.py diff --git a/tests/h/services/group_test.py b/tests/unit/h/services/group_test.py similarity index 80% rename from tests/h/services/group_test.py rename to tests/unit/h/services/group_test.py index f670e346836..b29e5dda4ad 100644 --- a/tests/h/services/group_test.py +++ b/tests/unit/h/services/group_test.py @@ -2,11 +2,11 @@ from unittest import mock import pytest +from h_matchers import Any -from h.models import Group, GroupScope, User +from h.models import Group from h.models.group import ReadableBy from h.services.group import GroupService, groups_factory -from tests.common.matchers import Matcher class TestGroupServiceFetch: @@ -64,7 +64,9 @@ def test_it_filters_by_name(self, svc): filtered_groups = svc.filter_by_name(name="Hello") assert len(filtered_groups.all()) == 1 - assert filtered_groups.all() == [GroupWithName("Hello")] + assert filtered_groups.all() == [ + Any.instance_of(Group).with_attrs({"name": "Hello"}) + ] def test_it_returns_all_groups_if_name_is_None(self, svc, groups): filtered_groups = svc.filter_by_name() @@ -86,8 +88,8 @@ def test_results_sorted_by_created_desc(self, svc): filtered_groups = svc.filter_by_name("Finger") assert filtered_groups.all() == [ - GroupWithName("Fingers"), - GroupWithName("Finger"), + Any.instance_of(Group).with_attrs({"name": "Fingers"}), + Any.instance_of(Group).with_attrs({"name": "Finger"}), ] @pytest.fixture @@ -197,45 +199,5 @@ def test_wraps_user_service_as_user_fetcher(self, pyramid_request, user_service) @pytest.fixture -def usr_svc(db_session): - def fetch(userid): - # One doesn't want to couple to the user fetching service but - # we do want to be able to fetch user models for internal - # module behavior tests - return db_session.query(User).filter_by(userid=userid).one_or_none() - - return fetch - - -@pytest.fixture -def svc(db_session, usr_svc): - return GroupService(db_session, usr_svc) - - -class GroupWithName(Matcher): - """Matches any Group with the given name.""" - - def __init__( - self, name - ): # pylint:disable=super-init-not-called #:Overwriting __eq__ instead - self.name = name - - def __eq__(self, group): - """Return True if group is instance of :class:h.models.Group and has matching name.""" - if not isinstance(group, Group): - return False - return group.name == self.name - - -class GroupScopeWithOrigin(Matcher): - """Matches any GroupScope with the given origin.""" - - def __init__( - self, origin - ): # pylint:disable=super-init-not-called #: Overwriting __eq__ instead - self.origin = origin - - def __eq__(self, group_scope): - if not isinstance(group_scope, GroupScope): - return False - return group_scope.origin == self.origin +def svc(db_session, user_service): + return GroupService(db_session, user_service) diff --git a/tests/h/services/group_update_test.py b/tests/unit/h/services/group_update_test.py similarity index 100% rename from tests/h/services/group_update_test.py rename to tests/unit/h/services/group_update_test.py diff --git a/tests/h/services/job_queue/metrics_test.py b/tests/unit/h/services/job_queue_metrics_test.py similarity index 95% rename from tests/h/services/job_queue/metrics_test.py rename to tests/unit/h/services/job_queue_metrics_test.py index ecb5ab1ad7f..f7b79001255 100644 --- a/tests/h/services/job_queue/metrics_test.py +++ b/tests/unit/h/services/job_queue_metrics_test.py @@ -3,7 +3,7 @@ import pytest -from h.services.job_queue.metrics import JobQueueMetrics, factory +from h.services.job_queue_metrics import JobQueueMetrics, factory class TestJobQueue: diff --git a/tests/unit/h/services/job_queue_test.py b/tests/unit/h/services/job_queue_test.py new file mode 100644 index 00000000000..035ca4b8349 --- /dev/null +++ b/tests/unit/h/services/job_queue_test.py @@ -0,0 +1,211 @@ +import uuid +from datetime import datetime, timedelta +from unittest.mock import patch, sentinel + +import pytest +from freezegun import freeze_time +from h_matchers import Any +from sqlalchemy.sql.expression import BinaryExpression + +from h.db.types import URLSafeUUID +from h.models import Annotation, Job +from h.services.job_queue import JobQueueService, Priority, factory + +ONE_WEEK = timedelta(weeks=1) +ONE_WEEK_IN_SECONDS = int(ONE_WEEK.total_seconds()) + + +class TestQueueService: + def test_get_ignores_jobs_that_are_expired(self, factories, svc): + now = datetime.utcnow() + + factories.SyncAnnotationJob(expires_at=now - timedelta(hours=1)) + + assert not svc.get("sync_annotation", limit=100) + + def test_it_ignores_jobs_that_arent_scheduled_yet(self, factories, svc): + now = datetime.utcnow() + factories.SyncAnnotationJob(scheduled_at=now + timedelta(hours=1)) + + assert not svc.get("sync_annotation", limit=100) + + def test_it_ignores_jobs_beyond_limit(self, factories, svc): + limit = 1 + factories.SyncAnnotationJob.create_batch(size=limit + 1) + + jobs = svc.get("sync_annotation", limit=limit) + + assert len(jobs) == limit + + @freeze_time("2023-01-01") + def test_add_where(self, factories, db_session, svc): + now = datetime.utcnow() + matching = [ + factories.Annotation(shared=True), + factories.Annotation(shared=True), + ] + # Add some noise + factories.Annotation(shared=False) + + svc.add_where( + "sync_annotation", + where=[Annotation.shared.is_(True)], + tag="test_tag", + priority=1234, + schedule_in=ONE_WEEK_IN_SECONDS, + ) + + assert ( + db_session.query(Job).all() + == Any.list.containing( + [ + Any.instance_of(Job).with_attrs( + { + "enqueued_at": Any.instance_of(datetime), + "scheduled_at": now + ONE_WEEK, + "tag": "test_tag", + "priority": 1234, + "kwargs": { + "annotation_id": self.database_id(annotation), + "force": False, + }, + } + ) + for annotation in matching + ] + ).only() + ) + + @pytest.mark.parametrize( + "force,expected_force", + ( + (True, True), + (1, True), + (False, False), + ("", False), + ), + ) + def test_add_where_with_force( + self, db_session, factories, force, expected_force, svc + ): + annotation = factories.Annotation() + + svc.add_where( + "sync_annotation", + [Annotation.id == annotation.id], + "test_tag", + 1, + force=force, + ) + + assert db_session.query(Job).one().kwargs["force"] == expected_force + + def test_add_by_id(self, svc, add_where): + svc.add_by_id( + sentinel.name, + sentinel.annotation_id, + sentinel.tag, + schedule_in=sentinel.schedule_in, + force=sentinel.force, + ) + + add_where.assert_called_once_with( + sentinel.name, + [Any.instance_of(BinaryExpression)], + sentinel.tag, + Priority.SINGLE_ITEM, + sentinel.force, + sentinel.schedule_in, + ) + + where = add_where.call_args[0][1] + assert where[0].compare(Annotation.id == sentinel.annotation_id) + + def test_add_annotations_between_times(self, svc, add_where): + svc.add_between_times( + sentinel.name, + sentinel.start_time, + sentinel.end_time, + sentinel.tag, + force=sentinel.force, + ) + + add_where.assert_called_once_with( + sentinel.name, + [Any.instance_of(BinaryExpression)] * 2, + sentinel.tag, + Priority.BETWEEN_TIMES, + sentinel.force, + ) + + where = add_where.call_args[0][1] + assert where[0].compare(Annotation.updated >= sentinel.start_time) + assert where[1].compare(Annotation.updated <= sentinel.end_time) + + def test_add_users_annotations(self, svc, add_where): + svc.add_by_user( + sentinel.name, + sentinel.userid, + sentinel.tag, + force=sentinel.force, + schedule_in=sentinel.schedule_in, + ) + + add_where.assert_called_once_with( + sentinel.name, + [Any.instance_of(BinaryExpression)], + sentinel.tag, + Priority.SINGLE_USER, + sentinel.force, + sentinel.schedule_in, + ) + + where = add_where.call_args[0][1] + assert where[0].compare(Annotation.userid == sentinel.userid) + + def test_add_group_annotations(self, svc, add_where): + svc.add_by_group( + sentinel.name, + sentinel.groupid, + sentinel.tag, + force=sentinel.force, + schedule_in=sentinel.schedule_in, + ) + + add_where.assert_called_once_with( + sentinel.name, + [Any.instance_of(BinaryExpression)], + sentinel.tag, + Priority.SINGLE_GROUP, + sentinel.force, + sentinel.schedule_in, + ) + + where = add_where.call_args[0][1] + assert where[0].compare(Annotation.groupid == sentinel.groupid) + + def test_delete(self, factories, svc, db_session): + jobs = factories.SyncAnnotationJob.create_batch(size=5) + db_session.flush() + + svc.delete(jobs) + + assert not db_session.query(Job).all() + + def test_factory(self, pyramid_request, db_session): + svc = factory(sentinel.context, pyramid_request) + + assert svc._db == db_session # pylint:disable=protected-access + + def database_id(self, annotation): + """Return `annotation.id` in the internal format used within the database.""" + return str(uuid.UUID(URLSafeUUID.url_safe_to_hex(annotation.id))) + + @pytest.fixture() + def add_where(self, svc): + with patch.object(svc, "add_where") as add_where: + yield add_where + + @pytest.fixture() + def svc(self, db_session): + return JobQueueService(db_session) diff --git a/tests/h/services/links_test.py b/tests/unit/h/services/links_test.py similarity index 100% rename from tests/h/services/links_test.py rename to tests/unit/h/services/links_test.py diff --git a/tests/h/services/list_organizations_test.py b/tests/unit/h/services/list_organizations_test.py similarity index 100% rename from tests/h/services/list_organizations_test.py rename to tests/unit/h/services/list_organizations_test.py diff --git a/tests/h/services/nipsa_test.py b/tests/unit/h/services/nipsa_test.py similarity index 80% rename from tests/h/services/nipsa_test.py rename to tests/unit/h/services/nipsa_test.py index d8c9d99181b..b1c35005da9 100644 --- a/tests/h/services/nipsa_test.py +++ b/tests/unit/h/services/nipsa_test.py @@ -25,12 +25,13 @@ def test_flag_sets_nipsa_true(self, svc, users): assert svc.is_flagged("acct:unflagged_user@example.com") assert users["unflagged_user"].nipsa is True - def test_flag_triggers_reindex_job(self, svc, users, search_index): + def test_flag_triggers_reindex_job(self, svc, users, tasks): svc.flag(users["unflagged_user"]) - search_index.add_users_annotations.assert_called_once_with( + tasks.job_queue.add_annotations_from_user.delay.assert_called_once_with( + "sync_annotation", "acct:unflagged_user@example.com", - "NipsaService.flag", + tag="NipsaService.flag", force=True, schedule_in=30, ) @@ -41,12 +42,13 @@ def test_unflag_sets_nipsa_false(self, svc, users): assert not svc.is_flagged("acct:flagged_user@example.com") assert not users["flagged_user"].nipsa - def test_unflag_triggers_reindex_job(self, svc, users, search_index): + def test_unflag_triggers_reindex_job(self, svc, users, tasks): svc.unflag(users["flagged_user"]) - search_index.add_users_annotations.assert_called_once_with( + tasks.job_queue.add_annotations_from_user.delay.assert_called_once_with( + "sync_annotation", "acct:flagged_user@example.com", - "NipsaService.unflag", + tag="NipsaService.unflag", force=True, schedule_in=30, ) @@ -65,9 +67,9 @@ def test_fetch_all_flagged_userids_caches_lookup(self, svc, users): def test_flag_updates_cache(self, svc, users): svc.fetch_all_flagged_userids() svc.flag(users["unflagged_user"]) - users[ - "unflagged_user" - ].nipsa = False # Make sure result below comes from cache. + users["unflagged_user"].nipsa = ( + False # Make sure result below comes from cache. + ) assert svc.is_flagged(users["unflagged_user"].userid) @@ -86,8 +88,12 @@ def test_clear_resets_cache(self, svc, users): assert not svc.is_flagged("acct:flagged_user@example.com") @pytest.fixture - def svc(self, db_session, search_index): - return NipsaService(db_session, lambda: search_index) + def svc(self, db_session): + return NipsaService(db_session) + + @pytest.fixture(autouse=True) + def tasks(self, patch): + return patch("h.services.nipsa.tasks") @pytest.fixture(autouse=True) def users(self, db_session, factories): @@ -100,9 +106,8 @@ def users(self, db_session, factories): return users -def test_nipsa_factory(pyramid_request, search_index): +def test_nipsa_factory(pyramid_request): svc = nipsa_factory(None, pyramid_request) assert isinstance(svc, NipsaService) assert svc.session == pyramid_request.db - assert svc._get_search_index() == search_index # pylint:disable=protected-access diff --git a/tests/h/services/job_queue/__init__.py b/tests/unit/h/services/oauth/__init__.py similarity index 100% rename from tests/h/services/job_queue/__init__.py rename to tests/unit/h/services/oauth/__init__.py diff --git a/tests/h/services/oauth/_bearer_token_test.py b/tests/unit/h/services/oauth/_bearer_token_test.py similarity index 100% rename from tests/h/services/oauth/_bearer_token_test.py rename to tests/unit/h/services/oauth/_bearer_token_test.py diff --git a/tests/h/services/oauth/_errors_test.py b/tests/unit/h/services/oauth/_errors_test.py similarity index 100% rename from tests/h/services/oauth/_errors_test.py rename to tests/unit/h/services/oauth/_errors_test.py diff --git a/tests/h/services/oauth/_jwt_grant_test.py b/tests/unit/h/services/oauth/_jwt_grant_test.py similarity index 100% rename from tests/h/services/oauth/_jwt_grant_test.py rename to tests/unit/h/services/oauth/_jwt_grant_test.py diff --git a/tests/h/services/oauth/_jwt_grant_token_test.py b/tests/unit/h/services/oauth/_jwt_grant_token_test.py similarity index 100% rename from tests/h/services/oauth/_jwt_grant_token_test.py rename to tests/unit/h/services/oauth/_jwt_grant_token_test.py diff --git a/tests/h/services/oauth/_validator_test.py b/tests/unit/h/services/oauth/_validator_test.py similarity index 97% rename from tests/h/services/oauth/_validator_test.py rename to tests/unit/h/services/oauth/_validator_test.py index 7abcc401e27..842c3c68e7d 100644 --- a/tests/h/services/oauth/_validator_test.py +++ b/tests/unit/h/services/oauth/_validator_test.py @@ -244,8 +244,8 @@ def test_it_deletes_authz_code(self, svc, oauth_request, factories, db_session): ) db_session.flush() - assert db_session.query(models.AuthzCode).get(id_1) is None - assert db_session.query(models.AuthzCode).get(id_2) is not None + assert db_session.get(models.AuthzCode, id_1) is None + assert db_session.get(models.AuthzCode, id_2) is not None def test_it_skips_deleting_when_authz_code_is_missing( self, svc, oauth_request, db_session, factories @@ -257,7 +257,7 @@ def test_it_skips_deleting_when_authz_code_is_missing( ) db_session.flush() - assert db_session.query(models.AuthzCode).get(keep_code.id) is not None + assert db_session.get(models.AuthzCode, keep_code.id) is not None class TestFindToken: @@ -384,7 +384,7 @@ def test_it_saves_token(self, svc, db_session, token_payload, oauth_request): def test_it_sets_userid(self, svc, token_payload, oauth_request): token = svc.save_bearer_token(token_payload, oauth_request) - assert token.userid == oauth_request.user.userid + assert token.user == oauth_request.user def test_it_sets_value(self, svc, token_payload, oauth_request): token = svc.save_bearer_token(token_payload, oauth_request) @@ -638,14 +638,12 @@ def test_returns_True_when_access_token_expired( result = svc.validate_refresh_token(token.refresh_token, client, oauth_request) assert result is True - def test_sets_user_when_token_valid( - self, svc, client, oauth_request, token, user_service - ): - user_service.fetch.return_value = mock.Mock() - + def test_sets_user_when_token_valid(self, svc, client, oauth_request, token): assert oauth_request.user is None + svc.validate_refresh_token(token.refresh_token, client, oauth_request) - assert oauth_request.user == user_service.fetch.return_value + + assert oauth_request.user == token.user @pytest.fixture def token(self, factories, client): @@ -699,8 +697,8 @@ def test_returns_False_for_none_scopes(self, svc): @pytest.fixture -def svc(db_session, user_service): - return OAuthValidator(db_session, user_service) +def svc(db_session): + return OAuthValidator(db_session) @pytest.fixture diff --git a/tests/h/services/oauth/service_test.py b/tests/unit/h/services/oauth/service_test.py similarity index 97% rename from tests/h/services/oauth/service_test.py rename to tests/unit/h/services/oauth/service_test.py index 97c637f3255..260d47eaf4d 100644 --- a/tests/h/services/oauth/service_test.py +++ b/tests/unit/h/services/oauth/service_test.py @@ -114,9 +114,7 @@ def test_it_returns_oauth_provider_service( ): service = factory(None, pyramid_request) - OAuthValidator.assert_called_once_with( - session=pyramid_request.db, user_svc=user_service - ) + OAuthValidator.assert_called_once_with(session=pyramid_request.db) OAuthProviderService.assert_called_once_with( oauth_validator=OAuthValidator.return_value, user_svc=user_service, diff --git a/tests/h/services/organization_test.py b/tests/unit/h/services/organization_test.py similarity index 100% rename from tests/h/services/organization_test.py rename to tests/unit/h/services/organization_test.py diff --git a/tests/h/services/search_index/service_test.py b/tests/unit/h/services/search_index_test.py similarity index 69% rename from tests/h/services/search_index/service_test.py rename to tests/unit/h/services/search_index_test.py index a7a3bb96671..c318d9cc7f2 100644 --- a/tests/h/services/search_index/service_test.py +++ b/tests/unit/h/services/search_index_test.py @@ -1,29 +1,36 @@ -import datetime from unittest.mock import MagicMock, call, create_autospec, patch, sentinel import pytest from h_matchers import Any from h.events import AnnotationEvent -from h.services.search_index._queue import Queue -from h.services.search_index.service import SearchIndexService +from h.services.search_index import SearchIndexService, factory from h.services.settings import SettingsService +pytestmark = [ + pytest.mark.xdist_group("elasticsearch"), + pytest.mark.usefixtures("init_elasticsearch"), +] + class TestAddAnnotationById: - def test_it(self, search_index, root_annotation, storage, add_annotation): - storage.fetch_annotation.return_value = root_annotation + def test_it( + self, search_index, root_annotation, add_annotation, annotation_read_service + ): + annotation_read_service.get_annotation_by_id.return_value = root_annotation search_index.add_annotation_by_id(root_annotation.id) - storage.fetch_annotation.assert_called_once_with( - search_index._db, root_annotation.id # pylint:disable=protected-access + annotation_read_service.get_annotation_by_id.assert_called_once_with( + root_annotation.id ) add_annotation.assert_called_once_with(root_annotation) - def test_it_returns_with_no_annotation(self, search_index, storage, add_annotation): - storage.fetch_annotation.return_value = None + def test_it_returns_with_no_annotation( + self, search_index, annotation_read_service, add_annotation + ): + annotation_read_service.get_annotation_by_id.return_value = None search_index.add_annotation_by_id(sentinel.any_id) @@ -39,18 +46,22 @@ def test_it_does_nothing_if_the_annotation_is_deleted( mock_es_client.conn.index.assert_not_called() def test_it_also_adds_the_thread_root( - self, search_index, reply_annotation, root_annotation, storage, add_annotation + self, + search_index, + reply_annotation, + root_annotation, + annotation_read_service, + add_annotation, ): - storage.fetch_annotation.side_effect = [reply_annotation, root_annotation] + annotation_read_service.get_annotation_by_id.side_effect = ( + reply_annotation, + root_annotation, + ) search_index.add_annotation_by_id(reply_annotation.id) - storage.fetch_annotation.assert_has_calls( - # pylint:disable=protected-access - [ - call(search_index._db, reply_annotation.id), - call(search_index._db, root_annotation.id), - ] + annotation_read_service.get_annotation_by_id.assert_has_calls( + [call(reply_annotation.id), call(root_annotation.id)] ) add_annotation.assert_has_calls([call(reply_annotation), call(root_annotation)]) @@ -134,55 +145,9 @@ def test_it_does_nothing_if_the_annotation_is_deleted( def annotation(self, factories): return factories.Annotation.build() - -class TestAddAnnotationsBetweenTimes: - def test_it(self, indexer, search_index): - start_time = datetime.datetime(2020, 9, 9) - end_time = datetime.datetime(2020, 9, 11) - - search_index.add_annotations_between_times( - start_time, - end_time, - "test_tag", - ) - - indexer.add_annotations_between_times.delay.assert_called_once_with( - start_time, end_time, "test_tag" - ) - - -class TestAddUsersAnnotations: - def test_it(self, indexer, search_index): - search_index.add_users_annotations( - sentinel.userid, - sentinel.tag, - force=sentinel.force, - schedule_in=sentinel.schedule_in, - ) - - indexer.add_users_annotations.delay.assert_called_once_with( - sentinel.userid, - sentinel.tag, - force=sentinel.force, - schedule_in=sentinel.schedule_in, - ) - - -class TestAddGroupAnnotations: - def test_it(self, indexer, search_index): - search_index.add_group_annotations( - sentinel.groupid, - sentinel.tag, - force=sentinel.force, - schedule_in=sentinel.schedule_in, - ) - - indexer.add_group_annotations.delay.assert_called_once_with( - sentinel.groupid, - sentinel.tag, - force=sentinel.force, - schedule_in=sentinel.schedule_in, - ) + @pytest.fixture(autouse=True) + def AnnotationSearchIndexPresenter(self, patch): + return patch("h.services.search_index.AnnotationSearchIndexPresenter") class TestDeleteAnnotationById: @@ -249,7 +214,7 @@ def test_we_fallback_to_async_if_sync_fails( assert result == async_handler.return_value @pytest.fixture(autouse=True) - def handler_for(self, add_annotation_by_id, delete_annotation_by_id, indexer): + def handler_for(self, add_annotation_by_id, delete_annotation_by_id, tasks): handler_map = { True: { "create": add_annotation_by_id, @@ -257,9 +222,9 @@ def handler_for(self, add_annotation_by_id, delete_annotation_by_id, indexer): "delete": delete_annotation_by_id, }, False: { - "create": indexer.add_annotation.delay, - "update": indexer.add_annotation.delay, - "delete": indexer.delete_annotation.delay, + "create": tasks.indexer.add_annotation.delay, + "update": tasks.indexer.add_annotation.delay, + "delete": tasks.indexer.delete_annotation.delay, }, } @@ -285,17 +250,34 @@ def delete_annotation_by_id(self, search_index): yield delete_annotation_by_id -class TestSync: - def test_it(self, search_index, queue): - returned = search_index.sync(10) +class TestFactory: + def test_it( + self, pyramid_request, SearchIndexService, settings, annotation_read_service + ): + result = factory(sentinel.context, pyramid_request) - queue.sync.assert_called_once_with(10) - assert returned == queue.sync.return_value + SearchIndexService.assert_called_once_with( + request=pyramid_request, + es=pyramid_request.es, + settings=settings, + annotation_read_service=annotation_read_service, + ) + assert result == SearchIndexService.return_value + @pytest.fixture + def settings(self, pyramid_config): + settings = sentinel.settings + pyramid_config.register_service(settings, name="settings") + return settings -@pytest.fixture(autouse=True) -def AnnotationSearchIndexPresenter(patch): - return patch("h.services.search_index.service.AnnotationSearchIndexPresenter") + @pytest.fixture + def pyramid_request(self, pyramid_request): + pyramid_request.es = sentinel.es + return pyramid_request + + @pytest.fixture(autouse=True) + def SearchIndexService(self, patch): + return patch("h.services.search_index.SearchIndexService") @pytest.fixture @@ -315,34 +297,28 @@ def settings_service(pyramid_config): @pytest.fixture -def queue(): - return create_autospec(Queue, spec_set=True, instance=True) - - -@pytest.fixture -def search_index(mock_es_client, pyramid_request, settings_service, queue): +def search_index( + mock_es_client, + pyramid_request, + settings_service, + annotation_read_service, +): return SearchIndexService( - session=pyramid_request.db, - es_client=mock_es_client, request=pyramid_request, + es=mock_es_client, settings=settings_service, - queue=queue, + annotation_read_service=annotation_read_service, ) @pytest.fixture(autouse=True) -def indexer(patch): - return patch("h.services.search_index.service.indexer") +def tasks(patch): + return patch("h.services.search_index.tasks") @pytest.fixture(autouse=True) def report_exception(patch): - return patch("h.services.search_index.service.report_exception") - - -@pytest.fixture(autouse=True) -def storage(patch): - return patch("h.services.search_index.service.storage") + return patch("h.services.search_index.report_exception") @pytest.fixture diff --git a/tests/h/services/settings_test.py b/tests/unit/h/services/settings_test.py similarity index 89% rename from tests/h/services/settings_test.py rename to tests/unit/h/services/settings_test.py index d1c2d4bd926..05f3e6a7e33 100644 --- a/tests/h/services/settings_test.py +++ b/tests/unit/h/services/settings_test.py @@ -20,7 +20,7 @@ def test_get_returns_none_when_missing(self, svc): def test_put_creates_new_setting(self, db_session, svc): svc.put("custom-color", "red") - setting = db_session.query(Setting).get("custom-color") + setting = db_session.get(Setting, "custom-color") assert setting.key == "custom-color" assert setting.value == "red" @@ -29,7 +29,7 @@ def test_put_overrides_existing_setting(self, db_session, svc, factories): svc.put(setting.key, "green") - setting = db_session.query(Setting).get(setting.key) + setting = db_session.get(Setting, setting.key) assert setting.value == "green" def test_delete_deletes_existing_setting(self, db_session, svc, factories): @@ -38,7 +38,7 @@ def test_delete_deletes_existing_setting(self, db_session, svc, factories): svc.delete(setting.key) db_session.flush() - assert db_session.query(Setting).get(setting.key) is None + assert db_session.get(Setting, setting.key) is None def test_delete_is_noop_when_setting_missing(self, svc, factories): # create a random setting diff --git a/tests/h/services/subscription_test.py b/tests/unit/h/services/subscription_test.py similarity index 89% rename from tests/h/services/subscription_test.py rename to tests/unit/h/services/subscription_test.py index 6a085f87c85..e94229f3cbf 100644 --- a/tests/h/services/subscription_test.py +++ b/tests/unit/h/services/subscription_test.py @@ -1,4 +1,4 @@ -from unittest.mock import sentinel +from unittest.mock import patch, sentinel import pytest from h_matchers import Any @@ -42,6 +42,16 @@ def test_get_subscription_with_a_missing_subscription(self, svc): } ) + def test_get_all_subscriptions(self, svc): + with patch.object(svc, "get_subscription") as get_subscription: + subscriptions = svc.get_all_subscriptions(sentinel.user_id) + + # Despite the name, there is only one subscription type + get_subscription.assert_called_once_with( + sentinel.user_id, Subscriptions.Type.REPLY + ) + assert subscriptions == [get_subscription.return_value] + def test_get_unsubscribe_token(self, svc, SignedSerializer): result = svc.get_unsubscribe_token( user_id="acct:user@example.com", type_=Subscriptions.Type.REPLY diff --git a/tests/h/services/url_migration_test.py b/tests/unit/h/services/url_migration_test.py similarity index 67% rename from tests/h/services/url_migration_test.py rename to tests/unit/h/services/url_migration_test.py index 5d5e33f33ea..47f33907688 100644 --- a/tests/h/services/url_migration_test.py +++ b/tests/unit/h/services/url_migration_test.py @@ -1,24 +1,24 @@ -from unittest.mock import Mock +from unittest.mock import Mock, sentinel import pytest from h_matchers import Any -from h.services.url_migration import URLMigrationService +from h.services.url_migration import URLMigrationService, service_factory class TestURLMigrationService: def test_move_annotations_does_nothing_if_annotation_was_deleted( - self, update_annotation, svc + self, svc, annotation_write_service ): svc.move_annotations( ["id-that-does-not-exist"], "https://somesite.com", {"url": "https://example.org"}, ) - update_annotation.assert_not_called() + annotation_write_service.update_annotation.assert_not_called() def test_move_annotations_does_nothing_if_url_no_longer_matches( - self, db_session, factories, update_annotation, svc + self, svc, db_session, factories, annotation_write_service ): ann = factories.Annotation(target_uri="https://example.com") db_session.flush() @@ -33,10 +33,10 @@ def test_move_annotations_does_nothing_if_url_no_longer_matches( ) assert ann.target_uri == "https://example.com" - update_annotation.assert_not_called() + annotation_write_service.update_annotation.assert_not_called() def test_move_annotations_updates_urls( - self, db_session, factories, pyramid_request, update_annotation, svc + self, svc, db_session, factories, annotation_write_service ): anns = [ factories.Annotation(target_uri="https://example.com"), @@ -50,18 +50,18 @@ def test_move_annotations_updates_urls( {"url": "https://example.org"}, ) - assert update_annotation.call_count == 2 + assert annotation_write_service.update_annotation.call_count == 2 for ann in anns[0:2]: - update_annotation.assert_any_call( - pyramid_request, - ann.id, - {"target_uri": "https://example.org"}, + annotation_write_service.update_annotation.assert_any_call( + annotation=ann, + data={"target_uri": "https://example.org"}, update_timestamp=False, reindex_tag="URLMigrationService.move_annotations", + enforce_write_permission=False, ) def test_move_annotations_updates_selectors( - self, db_session, factories, pyramid_request, update_annotation, svc + self, svc, db_session, factories, annotation_write_service ): ann = factories.Annotation(target_uri="https://example.com") ann.target_selectors = [ @@ -84,10 +84,9 @@ def test_move_annotations_updates_selectors( }, ) - update_annotation.assert_called_once_with( - pyramid_request, - ann.id, - { + annotation_write_service.update_annotation.assert_called_once_with( + annotation=ann, + data={ "target_uri": "https://example.org", "target_selectors": [ {"type": "TextQuoteSelector", "exact": "foobar"}, @@ -97,16 +96,11 @@ def test_move_annotations_updates_selectors( }, update_timestamp=False, reindex_tag="URLMigrationService.move_annotations", + enforce_write_permission=False, ) def test_move_annotations_updates_documents( - self, - db_session, - factories, - pyramid_request, - update_annotation, - transform_document, - svc, + self, svc, db_session, factories, annotation_write_service, transform_document ): ann = factories.Annotation(target_uri="https://example.com") db_session.flush() @@ -123,25 +117,25 @@ def test_move_annotations_updates_documents( transform_document.assert_called_with( {"title": "The new example.com"}, "https://example.org" ) - update_annotation.assert_called_once_with( - pyramid_request, - ann.id, - { + annotation_write_service.update_annotation.assert_called_once_with( + annotation=ann, + data={ "target_uri": "https://example.org", "document": transform_document.return_value, }, update_timestamp=False, reindex_tag="URLMigrationService.move_annotations", + enforce_write_permission=False, ) def test_move_annotations_by_url_moves_matching_annotations( self, + svc, db_session, factories, pyramid_request, - update_annotation, + annotation_write_service, move_annotations_task, - svc, ): anns = [ factories.Annotation(target_uri="https://example.com"), @@ -157,25 +151,27 @@ def test_move_annotations_by_url_moves_matching_annotations( ) # First annotation should be moved synchronously. - assert update_annotation.call_count == 1 - update_annotation.assert_called_with( - pyramid_request, - Any.of([a.id for a in anns]), - {"target_uri": "https://example.org"}, + annotation_write_service.update_annotation.assert_called_once_with( + annotation=Any(), + data={"target_uri": "https://example.org"}, update_timestamp=False, reindex_tag="URLMigrationService.move_annotations", + enforce_write_permission=False, ) + # The first annotation (the one that was moved synchronously). + first_annotation = annotation_write_service.update_annotation.call_args[1][ + "annotation" + ] + assert first_annotation in anns pyramid_request.tm.commit.assert_called_once() - moved_ann_id = update_annotation.call_args[0][1] + # The remaining annotations that match the given URL should be moved in + # separate tasks. remaining_ann_ids = [ - a.id - for a in anns - if a.target_uri == "https://example.com" and a.id != moved_ann_id + ann.id + for ann in anns + if ann != first_annotation and ann.target_uri == "https://example.com" ] - - # Remaining matching annotations should be moved in separate tasks. - assert move_annotations_task.delay.call_count == 1 move_annotations_task.delay.assert_called_once_with( Any.list.containing(remaining_ann_ids).only(), "https://example.com", @@ -183,7 +179,12 @@ def test_move_annotations_by_url_moves_matching_annotations( ) def test_move_annotations_by_url_handles_no_matches( - self, db_session, factories, update_annotation, move_annotations_task, svc + self, + svc, + db_session, + factories, + annotation_write_service, + move_annotations_task, ): # Make sure there are some non-matching annotations in the DB. factories.Annotation(target_uri="https://foo.com") @@ -196,17 +197,13 @@ def test_move_annotations_by_url_handles_no_matches( {"url": "https://example.org"}, ) - update_annotation.assert_not_called() + annotation_write_service.update_annotation.assert_not_called() move_annotations_task.delay.assert_not_called() @pytest.fixture(autouse=True) def transform_document(self, patch): return patch("h.services.url_migration.transform_document") - @pytest.fixture(autouse=True) - def update_annotation(self, patch): - return patch("h.storage.update_annotation") - @pytest.fixture(autouse=True) def move_annotations_task(self, patch): return patch("h.services.url_migration.move_annotations") @@ -217,5 +214,21 @@ def pyramid_request(self, pyramid_request): return pyramid_request @pytest.fixture - def svc(self, pyramid_request): - return URLMigrationService(pyramid_request) + def svc(self, pyramid_request, annotation_write_service): + return URLMigrationService( + request=pyramid_request, annotation_write_service=annotation_write_service + ) + + +class TestServiceFactory: + def test_it(self, pyramid_request, URLMigrationService, annotation_write_service): + svc = service_factory(sentinel.context, pyramid_request) + + URLMigrationService.assert_called_once_with( + request=pyramid_request, annotation_write_service=annotation_write_service + ) + assert svc == URLMigrationService.return_value + + @pytest.fixture + def URLMigrationService(self, patch): + return patch("h.services.url_migration.URLMigrationService") diff --git a/tests/unit/h/services/user_delete_test.py b/tests/unit/h/services/user_delete_test.py new file mode 100644 index 00000000000..05d31d72125 --- /dev/null +++ b/tests/unit/h/services/user_delete_test.py @@ -0,0 +1,600 @@ +import logging +from datetime import datetime +from unittest.mock import call, sentinel + +import pytest +from h_matchers import Any +from sqlalchemy import Select, func, select + +from h.models import ( + Annotation, + AuthTicket, + FeatureCohortUser, + Flag, + Group, + GroupMembership, + Job, + Token, + User, + UserDeletion, +) +from h.services.user_delete import ( + LimitedWorker, + LimitReached, + UserDeleteService, + UserPurger, + service_factory, +) + + +class TestUserDeleteService: + def test_delete_user(self, db_session, factories, svc): + user, other_user, requested_by = factories.User.create_batch(3) + user_annotations = factories.Annotation.create_batch(2, userid=user.userid) + + svc.delete_user(user, requested_by, "test_tag") + + assert user.deleted is True + assert other_user.deleted is False + assert db_session.scalars(select(Job)).all() == [ + Any.instance_of(Job).with_attrs( + { + "name": "purge_user", + "priority": 0, + "tag": "UserDeleteService.delete_user", + "kwargs": {"userid": user.userid}, + } + ) + ] + assert ( + db_session.scalars(select(UserDeletion)).all() + == Any.list.containing( + [ + Any.instance_of(UserDeletion).with_attrs( + { + "userid": user.userid, + "requested_by": requested_by.userid, + "tag": "test_tag", + "registered_date": user.registered_date, + "num_annotations": len(user_annotations), + } + ) + ] + ).only() + ) + + def test_purge_deleted_users( + self, + db_session, + factories, + queue_service, + svc, + user_service, + LimitedWorker, + limited_worker, + UserPurger, + purger, + caplog, + ): + users = factories.User.create_batch(3) + user_service.fetch.side_effect = users + jobs = [factories.Job(kwargs={"userid": user.userid}) for user in users] + queue_service.get.return_value = jobs + # Make UserPurger raise LimitReached part-way through purging + # the third user, when delete_annotations() is called the third time. + purger.delete_annotations.side_effect = [None, None, LimitReached] + + svc.purge_deleted_users() + + queue_service.get.assert_called_once_with("purge_user", 1000) + LimitedWorker.assert_called_once_with(db_session, 1000) + UserPurger.assert_called_once_with(db_session, queue_service, limited_worker) + assert user_service.fetch.call_args_list == [ + call(user.userid) for user in users + ] + assert caplog.record_tuples == [ + ( + "h.services.user_delete", + logging.INFO, + f"Purging user: {user.userid}", + ) + for user in users + ] + assert purger.delete_authtickets.call_args_list == [ + call(user) for user in users + ] + assert purger.delete_tokens.call_args_list == [call(user) for user in users] + assert purger.delete_flags.call_args_list == [call(user) for user in users] + assert purger.delete_featurecohort_memberships.call_args_list == [ + call(user) for user in users + ] + assert purger.delete_annotations.call_args_list == [ + call(user) for user in users + ] + assert purger.delete_groups.call_args_list == [call(user) for user in users[:2]] + assert purger.delete_group_memberships.call_args_list == [ + call(user) for user in users[:2] + ] + assert purger.delete_group_creators.call_args_list == [ + call(user) for user in users[:2] + ] + assert purger.delete_user.call_args_list == [call(user) for user in users[:2]] + queue_service.delete.assert_called_once_with(jobs[:2]) + + def test_purge_deleted_users_with_no_jobs( + self, svc, queue_service, caplog, LimitedWorker, UserPurger, user_service + ): + queue_service.get.return_value = [] + + svc.purge_deleted_users() + + assert caplog.record_tuples == [] + LimitedWorker.assert_not_called() + UserPurger.assert_not_called() + user_service.fetch.assert_not_called() + queue_service.delete.assert_not_called() + + def test_purge_deleted_users_with_an_invalid_job( + self, svc, queue_service, caplog, factories + ): + invalid_job = factories.Job(kwargs={}) # No Job.kwargs["userid"]. + queue_service.get.return_value = [invalid_job] + + svc.purge_deleted_users() + + assert caplog.record_tuples == [ + ( + "h.services.user_delete", + logging.INFO, + f"Invalid 'JobName.PURGE_USER' job: {invalid_job!r}", + ) + ] + queue_service.delete.assert_called_once_with([invalid_job]) + + def test_purge_deleted_users_when_a_jobs_user_doesnt_exist( + self, svc, queue_service, user_service, caplog, factories + ): + job = factories.Job(kwargs={"userid": "doesnt_exist"}) + queue_service.get.return_value = [job] + user_service.fetch.return_value = None + + svc.purge_deleted_users() + + assert caplog.record_tuples == [ + ( + "h.services.user_delete", + logging.INFO, + "Couldn't fetch user: doesnt_exist", + ) + ] + queue_service.delete.assert_called_once_with([job]) + + @pytest.fixture(autouse=True) + def UserPurger(self, mocker): + return mocker.patch("h.services.user_delete.UserPurger") + + @pytest.fixture + def purger(self, UserPurger): + return UserPurger.return_value + + @pytest.fixture(autouse=True) + def LimitedWorker(self, mocker): + return mocker.patch("h.services.user_delete.LimitedWorker") + + @pytest.fixture + def limited_worker(self, LimitedWorker): + return LimitedWorker.return_value + + +class TestUserPurger: + def test_delete_authtickets(self, worker, purger, factories, user, db_session): + factories.AuthTicket.create_batch(2, user=user) + # An AuthTicket belonging to another user. This shouldn't get deleted. + other_ticket = factories.AuthTicket() + + purger.delete_authtickets(user) + + worker.delete.assert_called_once_with(AuthTicket, Any.instance_of(Select)) + assert db_session.scalars(select(AuthTicket)).all() == [other_ticket] + + def test_delete_tokens(self, worker, purger, factories, user, db_session): + factories.DeveloperToken(user=user) + factories.OAuth2Token(user=user) + # Tokens belonging to other users. These shouldn't get deleted. + other_tokens = [factories.DeveloperToken(), factories.OAuth2Token()] + + purger.delete_tokens(user) + + worker.delete.assert_called_once_with(Token, Any.instance_of(Select)) + assert ( + db_session.scalars(select(Token)).all() + == Any.list.containing(other_tokens).only() + ) + + def test_delete_flags(self, worker, purger, factories, user, db_session): + factories.Flag.create_batch(2, user=user) + # A flag created by another user. This shouldn't get deleted. + other_flag = factories.Flag() + + purger.delete_flags(user) + + worker.delete.assert_called_once_with(Flag, Any.instance_of(Select)) + assert db_session.scalars(select(Flag)).all() == [other_flag] + + def test_delete_featurecohort_memberships( + self, worker, purger, user, factories, db_session + ): + cohorts = factories.FeatureCohort.create_batch(2, members=[user]) + # A FeatureCohortUser belonging to a different user. + # This shouldn't get deleted. + other_user = factories.User() + cohorts[0].members.append(other_user) + + purger.delete_featurecohort_memberships(user) + + worker.delete.assert_called_once_with( + FeatureCohortUser, Any.instance_of(Select) + ) + assert db_session.scalars(select(FeatureCohortUser)).all() == [ + Any.instance_of(FeatureCohortUser).with_attrs( + {"cohort_id": cohorts[0].id, "user_id": other_user.id} + ) + ] + + def test_delete_annotations( + self, caplog, worker, purger, user, factories, queue_service + ): + annotations = factories.Annotation.create_batch(2, userid=user.userid) + annotation_slims = [ + factories.AnnotationSlim(annotation=annotation) + for annotation in annotations + ] + # An annotation belonging to a different user. + # This shouldn't get deleted. + other_users_annotation = factories.Annotation() + + purger.delete_annotations(user) + + worker.update.assert_called_once_with( + Annotation, + Any.instance_of(Select), + {"deleted": True, "updated": Any.instance_of(datetime)}, + ) + for annotation in annotations: + assert annotation.deleted is True + for annotation_slim in annotation_slims: + assert annotation_slim.deleted is True + assert other_users_annotation.deleted is False + assert ( + queue_service.add_by_id.call_args_list + == Any.list.containing( + [ + call( + name="sync_annotation", + annotation_id=annotation.id, + tag="UserDeleteService.delete_annotations", + schedule_in=60, + ) + for annotation in annotations + ] + ).only() + ) + assert ( + caplog.record_tuples + == Any.list.containing( + [ + ( + "h.services.user_delete", + logging.INFO, + "Updated 2 rows from annotation", + ), + ( + "h.services.user_delete", + logging.INFO, + "Updated 2 rows from annotation_slim", + ), + ( + "h.services.user_delete", + logging.INFO, + f"Enqueued jobs to delete {len(annotations)} annotations from Elasticsearch", + ), + ] + ).only() + ) + + def test_delete_groups(self, user, db_session, worker, factories, purger): + factories.Group(creator=user) + + purger.delete_groups(user) + + worker.delete.assert_called_once_with(Group, Any.instance_of(Select)) + assert ( + db_session.scalars(select(Group).where(Group.creator == user)).all() == [] + ) + + def test_delete_groups_still_deletes_groups_if_they_have_deleted_annotations( + self, user, db_session, factories, purger + ): + group = factories.Group(creator=user) + # An annotation in the group, but the annotation has already been + # marked as deleted (meaning it'll soon be purged from the DB) so this + # shouldn't prevent the group from being deleted. + factories.Annotation(group=group, deleted=True) + + purger.delete_groups(user) + + assert ( + db_session.scalars(select(Group).where(Group.creator == user)).all() == [] + ) + + def test_delete_groups_doesnt_delete_groups_created_by_other_users( + self, user, db_session, factories, purger + ): + group = factories.Group() + + purger.delete_groups(user) + + assert group in db_session.scalars(select(Group)).all() + + def test_delete_groups_doesnt_delete_groups_with_annotations( + self, user, db_session, factories, purger + ): + group = factories.Group(creator=user) + # The group contains an annotation by another user. + # This should prevent the group from being deleted. + factories.Annotation(group=group) + + purger.delete_groups(user) + + assert group in db_session.scalars(select(Group)).all() + + def test_delete_group_memberships( + self, user, factories, purger, worker, db_session + ): + other_user = factories.User() + groups = [ + # A group that `user` created. + factories.Group(creator=user, members=[other_user]), + # A group that `user` is a member of but didn't create. + factories.Group(members=[user, other_user]), + # A group that `user` is neither a creator or member of. + factories.Group(members=[other_user]), + ] + + purger.delete_group_memberships(user) + + worker.delete.assert_called_once_with(GroupMembership, Any.instance_of(Select)) + # It deletes the given user's group memberships. + assert ( + db_session.scalars( + select(GroupMembership).where(GroupMembership.user_id == user.id) + ).all() + == [] + ) + # It doesn't delete group memberships of other users. + assert ( + db_session.scalars( + select(GroupMembership).where(GroupMembership.user_id == other_user.id) + ).all() + == Any.list.containing( + [ + Any.instance_of(GroupMembership).with_attrs( + {"group_id": group.id, "user_id": other_user.id} + ) + for group in groups + ] + ).only() + ) + + def test_delete_group_creators(self, user, factories, purger, worker): + groups = factories.Group.create_batch(2, creator=user) + other_group = factories.Group() + + purger.delete_group_creators(user) + + worker.update.assert_called_once_with( + Group, Any.instance_of(Select), {"creator_id": None} + ) + for group in groups: + assert group.creator_id is None + assert other_group.creator_id + + def test_delete_group_creators_doesnt_delete_other_group_creators( + self, user, factories, purger + ): + other_group_creator = factories.User() + group = factories.Group(creator=other_group_creator) + + purger.delete_group_creators(user) + + assert group.creator_id == other_group_creator.id + + def test_delete_user(self, db_session, purger, factories, user): + other_user = factories.User() + + purger.delete_user(user) + + assert db_session.scalars(select(User)).all() == [other_user] + + @pytest.mark.parametrize( + "method", + [ + "delete_authtickets", + "delete_tokens", + "delete_flags", + "delete_featurecohort_memberships", + "delete_annotations", + "delete_groups", + "delete_group_memberships", + "delete_group_creators", + "delete_user", + ], + ) + def test_it_when_limit_exceeded( + self, db_session, queue_service, mocker, factories, method + ): + worker = mocker.create_autospec(LimitedWorker, spec_set=True, instance=True) + worker.delete.side_effect = LimitReached + worker.update.side_effect = LimitReached + purger = UserPurger(db_session, queue_service, worker) + + with pytest.raises(LimitReached): + getattr(purger, method)(factories.User()) + + @pytest.fixture + def worker(self, db_session, mocker): + worker = LimitedWorker(db_session, limit=1000) + mocker.spy(worker, "delete") + mocker.spy(worker, "update") + return worker + + @pytest.fixture + def purger(self, db_session, queue_service, worker): + return UserPurger(db_session, queue_service, worker) + + @pytest.fixture + def user(self, factories, db_session): + user = factories.User() + # Flush the DB to generate user.id. + db_session.flush() + return user + + +class TestLimitedWorker: + def test_update_when_limit_exceeded(self, db_session, factories): + annotation = factories.Annotation() + original_text = annotation.text + worker = LimitedWorker(db_session, limit=0) + + with pytest.raises(LimitReached): + worker.update(Annotation, select(Annotation.id), {"text": "UPDATED"}) + + # pylint:disable=use-implicit-booleaness-not-comparison-to-zero + assert worker.limit == 0 + assert annotation.text == original_text + + def test_update_with_limit_remaining(self, caplog, db_session, factories): + annotations = factories.Annotation.create_batch(2) + original_limit = len(annotations) + 1 + worker = LimitedWorker(db_session, original_limit) + + updated_annotation_ids = worker.update( + Annotation, select(Annotation.id), {"text": "UPDATED"} + ) + + assert sorted(updated_annotation_ids) == sorted( + [annotation.id for annotation in annotations] + ) + assert worker.limit == original_limit - len(updated_annotation_ids) + for annotation in annotations: + assert annotation.text == "UPDATED" + assert caplog.record_tuples == [ + ("h.services.user_delete", logging.INFO, "Updated 2 rows from annotation") + ] + + def test_update_when_limit_reached(self, caplog, db_session, factories): + annotations = factories.Annotation.create_batch(2) + original_limit = len(annotations) - 1 + worker = LimitedWorker(db_session, original_limit) + + updated_annotation_ids = worker.update( + Annotation, select(Annotation.id), {"text": "UPDATED"} + ) + + assert len(updated_annotation_ids) == original_limit + assert len(set(updated_annotation_ids)) == len(updated_annotation_ids) + for updated_annotation_id in updated_annotation_ids: + assert updated_annotation_id in [ + annotation.id for annotation in annotations + ] + # pylint:disable=use-implicit-booleaness-not-comparison-to-zero + assert worker.limit == 0 + for annotation in annotations: + if annotation.id in updated_annotation_ids: + assert annotation.text == "UPDATED" + else: + assert annotation.text != "UPDATED" + assert caplog.record_tuples == [ + ("h.services.user_delete", logging.INFO, "Updated 1 rows from annotation") + ] + + def test_delete_when_limit_exceeded(self, db_session, factories): + annotation = factories.Annotation() + worker = LimitedWorker(db_session, limit=0) + + with pytest.raises(LimitReached): + worker.delete(Annotation, select(Annotation.id)) + + # pylint:disable=use-implicit-booleaness-not-comparison-to-zero + assert worker.limit == 0 + assert db_session.scalars(select(Annotation)).all() == [annotation] + + def test_delete_with_limit_remaining(self, caplog, db_session, factories): + annotations = factories.Annotation.create_batch(2) + original_limit = len(annotations) + 1 + worker = LimitedWorker(db_session, original_limit) + + deleted_annotation_ids = worker.delete(Annotation, select(Annotation.id)) + + assert sorted(deleted_annotation_ids) == sorted( + [annotation.id for annotation in annotations] + ) + assert worker.limit == original_limit - len(deleted_annotation_ids) + assert db_session.scalars(select(Annotation)).all() == [] + assert caplog.record_tuples == [ + ("h.services.user_delete", logging.INFO, "Deleted 2 rows from annotation") + ] + + def test_delete_when_limit_reached(self, caplog, db_session, factories): + annotations = factories.Annotation.create_batch(2) + original_limit = len(annotations) - 1 + worker = LimitedWorker(db_session, original_limit) + + deleted_annotation_ids = worker.delete(Annotation, select(Annotation.id)) + + assert len(deleted_annotation_ids) == original_limit + assert len(set(deleted_annotation_ids)) == len(deleted_annotation_ids) + for deleted_annotation_id in deleted_annotation_ids: + assert deleted_annotation_id in [ + annotation.id for annotation in annotations + ] + # pylint:disable=use-implicit-booleaness-not-comparison-to-zero + assert worker.limit == 0 + assert ( + db_session.scalar(select(func.count(Annotation.id))) + == len(annotations) - original_limit + ) + assert caplog.record_tuples == [ + ("h.services.user_delete", logging.INFO, "Deleted 1 rows from annotation") + ] + + +class TestServiceFactory: + def test_it(self, pyramid_request, UserDeleteService, queue_service, user_service): + svc = service_factory(sentinel.context, pyramid_request) + + UserDeleteService.assert_called_once_with( + pyramid_request.db, + job_queue=queue_service, + user_svc=user_service, + ) + assert svc == UserDeleteService.return_value + + @pytest.fixture(autouse=True) + def UserDeleteService(self, patch): + return patch("h.services.user_delete.UserDeleteService") + + +@pytest.fixture +def svc(db_session, queue_service, user_service): + return UserDeleteService( + db_session, + job_queue=queue_service, + user_svc=user_service, + ) + + +@pytest.fixture +def caplog(caplog): + caplog.set_level(logging.INFO) + return caplog diff --git a/tests/h/services/user_password_test.py b/tests/unit/h/services/user_password_test.py similarity index 87% rename from tests/h/services/user_password_test.py rename to tests/unit/h/services/user_password_test.py index c9ddcb2e97f..605fa3ca78d 100644 --- a/tests/h/services/user_password_test.py +++ b/tests/unit/h/services/user_password_test.py @@ -1,8 +1,10 @@ +from unittest.mock import sentinel + import pytest from passlib.context import CryptContext from h.security import password_context -from h.services.user_password import UserPasswordService +from h.services.user_password import UserPasswordService, user_password_service_factory class TestUserPasswordService: @@ -104,3 +106,15 @@ def svc(self, hasher): @pytest.fixture def user(self, factories): return factories.User.build() + + +class TestServiceFactory: + def test_it(self, UserPasswordService): + svc = user_password_service_factory(sentinel.context, sentinel.request) + + UserPasswordService.assert_called_once_with() + assert svc == UserPasswordService.return_value + + @pytest.fixture + def UserPasswordService(self, patch): + return patch("h.services.user_password.UserPasswordService") diff --git a/tests/h/services/rename_user_test.py b/tests/unit/h/services/user_rename_test.py similarity index 75% rename from tests/h/services/rename_user_test.py rename to tests/unit/h/services/user_rename_test.py index 726eb7ce5cc..d5a14d8c3af 100644 --- a/tests/h/services/rename_user_test.py +++ b/tests/unit/h/services/user_rename_test.py @@ -1,12 +1,13 @@ from unittest import mock +from unittest.mock import sentinel import pytest from h import models -from h.services.rename_user import RenameUserService, UserRenameError +from h.services.user_rename import UserRenameError, UserRenameService, service_factory -class TestRenameUserService: +class TestUserRenameService: def test_check_returns_true_when_new_username_does_not_exist(self, service, user): assert service.check(user, "panda") is True @@ -51,7 +52,7 @@ def test_rename_checks_first(self, service, check, user): def test_rename_changes_the_username(self, service, user, db_session): service.rename(user, "panda") - assert db_session.query(models.User).get(user.id).username == "panda" + assert db_session.get(models.User, user.id).username == "panda" def test_rename_deletes_auth_tickets(self, service, user, db_session, factories): ids = [factories.AuthTicket(user=user).id for _ in range(3)] @@ -65,8 +66,8 @@ def test_rename_deletes_auth_tickets(self, service, user, db_session, factories) ) assert not count - def test_rename_updates_tokens(self, service, user, db_session): - token = models.Token(userid=user.userid, value="foo") + def test_rename_updates_tokens(self, service, user, db_session, factories): + token = factories.DeveloperToken(user=user) db_session.add(token) service.rename(user, "panda") @@ -74,7 +75,7 @@ def test_rename_updates_tokens(self, service, user, db_session): updated_token = ( db_session.query(models.Token).filter(models.Token.id == token.id).one() ) - assert updated_token.userid == user.userid + assert updated_token.user == user @pytest.mark.usefixtures("annotations") def test_rename_changes_the_users_annotations_userid( @@ -85,24 +86,25 @@ def test_rename_changes_the_users_annotations_userid( userids = [ann.userid for ann in db_session.query(models.Annotation)] assert {user.userid} == set(userids) - def test_rename_reindexes_the_users_annotations(self, service, user, search_index): + def test_rename_reindexes_the_users_annotations(self, service, user, tasks): original_userid = user.userid service.rename(user, "panda") - search_index.add_users_annotations.assert_called_once_with( + tasks.job_queue.add_annotations_from_user.delay.assert_called_once_with( + "sync_annotation", original_userid, tag="RenameUserService.rename", schedule_in=30, ) @pytest.fixture - def service(self, pyramid_request, search_index): - return RenameUserService(session=pyramid_request.db, search_index=search_index) + def service(self, pyramid_request): + return UserRenameService(session=pyramid_request.db) @pytest.fixture def check(self, patch): - return patch("h.services.rename_user.RenameUserService.check") + return patch("h.services.user_rename.UserRenameService.check") @pytest.fixture def user(self, factories, db_session): @@ -119,3 +121,19 @@ def annotations(self, user, factories, db_session): db_session.flush() return anns + + @pytest.fixture(autouse=True) + def tasks(self, patch): + return patch("h.services.user_rename.tasks") + + +class TestServiceFactory: + def test_it(self, pyramid_request, UserRenameService): + svc = service_factory(sentinel.context, pyramid_request) + + UserRenameService.assert_called_once_with(session=pyramid_request.db) + assert svc == UserRenameService.return_value + + @pytest.fixture + def UserRenameService(self, patch): + return patch("h.services.user_rename.UserRenameService") diff --git a/tests/h/services/user_signup_test.py b/tests/unit/h/services/user_signup_test.py similarity index 100% rename from tests/h/services/user_signup_test.py rename to tests/unit/h/services/user_signup_test.py diff --git a/tests/h/services/user_test.py b/tests/unit/h/services/user_test.py similarity index 95% rename from tests/h/services/user_test.py rename to tests/unit/h/services/user_test.py index f7fee96a3b9..78fdfa72d9e 100644 --- a/tests/h/services/user_test.py +++ b/tests/unit/h/services/user_test.py @@ -77,6 +77,16 @@ def test_fetch_for_login_by_email_not_activated(self, svc): with pytest.raises(UserNotActivated): svc.fetch_for_login("mirthe@deboer.com") + def test_fetch_for_login_by_username_deleted(self, svc, factories): + user = factories.User(deleted=True) + + assert svc.fetch_for_login(user.username) is None + + def test_fetch_for_login_by_email_deleted(self, svc, factories): + user = factories.User(deleted=True) + + assert svc.fetch_for_login(user.email) is None + def test_update_preferences_tutorial_enable(self, svc, factories): user = factories.User.build(sidebar_tutorial_dismissed=True) diff --git a/tests/h/services/user_unique_test.py b/tests/unit/h/services/user_unique_test.py similarity index 100% rename from tests/h/services/user_unique_test.py rename to tests/unit/h/services/user_unique_test.py diff --git a/tests/h/services/user_update_test.py b/tests/unit/h/services/user_update_test.py similarity index 100% rename from tests/h/services/user_update_test.py rename to tests/unit/h/services/user_update_test.py diff --git a/tests/h/session_test.py b/tests/unit/h/session_test.py similarity index 100% rename from tests/h/session_test.py rename to tests/unit/h/session_test.py diff --git a/tests/h/settings_test.py b/tests/unit/h/settings_test.py similarity index 94% rename from tests/h/settings_test.py rename to tests/unit/h/settings_test.py index c18c013c4da..a04574dad57 100644 --- a/tests/h/settings_test.py +++ b/tests/unit/h/settings_test.py @@ -2,14 +2,7 @@ import pytest -from h.settings import SettingError, SettingsManager, database_url - - -def test_database_url(): - url = "postgres://postgres:1234/database" - expected = "postgresql+psycopg2://postgres:1234/database" - - assert database_url(url) == expected +from h.settings import SettingError, SettingsManager class TestSettingsManager: diff --git a/tests/unit/h/storage_test.py b/tests/unit/h/storage_test.py new file mode 100644 index 00000000000..d6ae25b417d --- /dev/null +++ b/tests/unit/h/storage_test.py @@ -0,0 +1,77 @@ +import pytest + +from h import storage +from h.models.document import Document, DocumentURI + + +@pytest.mark.usefixtures("search_index") +class TestExpandURI: + @pytest.mark.parametrize( + "normalized,expected_uris", + ( + (False, ["http://example.com/"]), + (True, ["httpx://example.com"]), + ), + ) + def test_expand_uri_no_document(self, db_session, normalized, expected_uris): + uris = storage.expand_uri( + db_session, "http://example.com/", normalized=normalized + ) + + assert uris == expected_uris + + @pytest.mark.parametrize( + "normalized,expected_uris", + ( + (False, ["http://example.com/"]), + (True, ["httpx://example.com"]), + ), + ) + def test_expand_uri_document_doesnt_expand_canonical_uris( + self, db_session, normalized, expected_uris + ): + document = Document( + document_uris=[ + DocumentURI( + uri="http://example.com/", + type="rel-canonical", + claimant="http://example.com", + ), + DocumentURI( + uri="http://noise.example.com/", claimant="http://example.com" + ), + ] + ) + db_session.add(document) + db_session.flush() + + uris = storage.expand_uri( + db_session, "http://example.com/", normalized=normalized + ) + + assert uris == expected_uris + + @pytest.mark.parametrize( + "normalized,expected_uris", + ( + (False, ["http://example.com/", "http://alt.example.com/"]), + (True, ["httpx://example.com", "httpx://alt.example.com"]), + ), + ) + def test_expand_uri_document_uris(self, db_session, normalized, expected_uris): + document = Document( + document_uris=[ + DocumentURI(uri="http://example.com/", claimant="http://example.com"), + DocumentURI( + uri="http://alt.example.com/", claimant="http://example.com" + ), + ] + ) + db_session.add(document) + db_session.flush() + + uris = storage.expand_uri( + db_session, "http://alt.example.com/", normalized=normalized + ) + + assert uris == expected_uris diff --git a/tests/h/services/oauth/__init__.py b/tests/unit/h/streamer/__init__.py similarity index 100% rename from tests/h/services/oauth/__init__.py rename to tests/unit/h/streamer/__init__.py diff --git a/tests/h/streamer/app_test.py b/tests/unit/h/streamer/app_test.py similarity index 100% rename from tests/h/streamer/app_test.py rename to tests/unit/h/streamer/app_test.py diff --git a/tests/h/streamer/conftest.py b/tests/unit/h/streamer/conftest.py similarity index 100% rename from tests/h/streamer/conftest.py rename to tests/unit/h/streamer/conftest.py diff --git a/tests/h/streamer/db_test.py b/tests/unit/h/streamer/db_test.py similarity index 76% rename from tests/h/streamer/db_test.py rename to tests/unit/h/streamer/db_test.py index 80f092caf20..4d7160cad36 100644 --- a/tests/h/streamer/db_test.py +++ b/tests/unit/h/streamer/db_test.py @@ -9,10 +9,10 @@ class TestMakeSession: def test_it(self, db): - session = get_session(sentinel.settings) + session = get_session({"sqlalchemy.url": sentinel.sqlalchemy_url}) - db.make_engine.assert_called_once_with(sentinel.settings) - db.Session.assert_called_once_with(bind=db.make_engine.return_value) + db.create_engine.assert_called_once_with(sentinel.sqlalchemy_url) + db.Session.assert_called_once_with(bind=db.create_engine.return_value) assert session == db.Session.return_value @pytest.fixture @@ -21,13 +21,14 @@ def db(self, patch): class TestReadOnlyTransaction: - def test_it_starts_a_read_only_transaction(self, session): + def test_it_starts_a_read_only_transaction(self, session, text): with read_only_transaction(session): ... - assert session.method_calls[0] == mock.call.execute( + text.assert_called_once_with( "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY DEFERRABLE" ) + assert session.method_calls[0] == mock.call.execute(text.return_value) def test_it_calls_closes_correctly(self, session): with read_only_transaction(session): @@ -57,3 +58,7 @@ def _assert_rollback_and_close(self, session): @pytest.fixture def session(self): return mock.Mock(spec_set=["close", "commit", "execute", "rollback"]) + + @pytest.fixture + def text(self, patch): + return patch("h.streamer.db.text") diff --git a/tests/h/streamer/filter_test.py b/tests/unit/h/streamer/filter_test.py similarity index 99% rename from tests/h/streamer/filter_test.py rename to tests/unit/h/streamer/filter_test.py index 7692291d21e..a701834d004 100644 --- a/tests/h/streamer/filter_test.py +++ b/tests/unit/h/streamer/filter_test.py @@ -9,7 +9,7 @@ class FakeSocket: - ... + pass class TestFilterHandler: diff --git a/tests/h/streamer/messages_speed_test.py b/tests/unit/h/streamer/messages_speed_test.py similarity index 96% rename from tests/h/streamer/messages_speed_test.py rename to tests/unit/h/streamer/messages_speed_test.py index f10b25d8c38..a7dc20ec281 100644 --- a/tests/h/streamer/messages_speed_test.py +++ b/tests/unit/h/streamer/messages_speed_test.py @@ -65,7 +65,6 @@ def registry(self): "h.app_url": "http://example.com", "h.authority": "example.com", "secret_key": "notasecret", - "sqlalchemy.url": "postgresql://postgres@localhost/htest", } return create_app(None, **settings).registry @@ -78,7 +77,6 @@ def SocketFilter(self, patch): SocketFilter.matching.side_effect = lambda sockets, annotation: iter(sockets) return SocketFilter - @pytest.mark.usefixtures("registry") @pytest.fixture def socket(self): socket = WebSocket( diff --git a/tests/h/streamer/messages_test.py b/tests/unit/h/streamer/messages_test.py similarity index 85% rename from tests/h/streamer/messages_test.py rename to tests/unit/h/streamer/messages_test.py index d4905dfea56..dd379619537 100644 --- a/tests/h/streamer/messages_test.py +++ b/tests/unit/h/streamer/messages_test.py @@ -38,8 +38,8 @@ def test_it_handles_a_full_queue(self, _handler, work_queue): _handler({"foo": "bar"}) - result = work_queue.get_nowait() - assert result.topic == "queue_is_full" + result = work_queue.get_nowait() # pragma: nocover + assert result.topic == "queue_is_full" # pragma: nocover def test_it_raises_if_the_consumer_exits(self, work_queue): with pytest.raises(RuntimeError): @@ -102,33 +102,43 @@ def websocket(self, patch): return patch("h.streamer.websocket.WebSocket") -@pytest.mark.usefixtures("annotation_json_service", "nipsa_service") +@pytest.mark.usefixtures( + "annotation_json_service", "annotation_read_service", "nipsa_service" +) class TestHandleAnnotationEvent: - def test_it_fetches_the_annotation( - self, fetch_annotation, handle_annotation_event, session, message + def test_it( + self, + handle_annotation_event, + message, + socket, + annotation_read_service, + annotation_json_service, + SocketFilter, ): - handle_annotation_event(message=message, session=session) + handle_annotation_event( + message=message, sockets=[socket], session=sentinel.session + ) + + annotation_read_service.get_annotation_by_id.assert_called_once_with( + message["annotation_id"] + ) + annotation = annotation_read_service.get_annotation_by_id.return_value + + SocketFilter.matching.assert_called_once_with( + [socket], annotation, sentinel.session + ) - fetch_annotation.assert_called_once_with(session, message["annotation_id"]) + annotation_json_service.present.assert_called_once_with(annotation) def test_it_skips_notification_when_fetch_failed( - self, fetch_annotation, handle_annotation_event + self, handle_annotation_event, annotation_read_service ): - fetch_annotation.return_value = None + annotation_read_service.get_annotation_by_id.return_value = None result = handle_annotation_event() assert result is None - def test_it_serializes_the_annotation( - self, handle_annotation_event, fetch_annotation, annotation_json_service - ): - handle_annotation_event() - - annotation_json_service.present.assert_called_once_with( - fetch_annotation.return_value - ) - @pytest.mark.parametrize("action", ["create", "update", "delete"]) def test_notification_format( self, handle_annotation_event, action, message, socket, annotation_json_service @@ -150,20 +160,6 @@ def test_notification_format( } ) - def test_it_filters_the_sockets( - self, - handle_annotation_event, - SocketFilter, - fetch_annotation, - socket, - db_session, - ): - handle_annotation_event(sockets=[socket], session=db_session) - - SocketFilter.matching.assert_called_once_with( - [socket], fetch_annotation.return_value, db_session - ) - def test_no_send_for_sender_socket(self, handle_annotation_event, socket, message): message["src_client_id"] = socket.client_id @@ -187,12 +183,12 @@ def test_nipsaed_content_visibility( user_is_nipsaed, socket, nipsa_service, - fetch_annotation, + annotation_read_service, ): """Should return None if the annotation is from a NIPSA'd user.""" nipsa_service.is_flagged.return_value = True - fetch_annotation.return_value.userid = ( + annotation_read_service.get_annotation_by_id.return_value.userid = ( socket.identity.user.userid if user_is_nipsaed else "other_user" ) handle_annotation_event(sockets=[socket]) @@ -206,14 +202,16 @@ def test_visibility_is_based_on_identity( can_see, AnnotationContext, identity_permits, - fetch_annotation, + annotation_read_service, socket, ): identity_permits.return_value = can_see handle_annotation_event(sockets=[socket]) - AnnotationContext.assert_called_once_with(fetch_annotation.return_value) + AnnotationContext.assert_called_once_with( + annotation_read_service.get_annotation_by_id.return_value + ) identity_permits.assert_called_once_with( socket.identity, AnnotationContext.return_value, @@ -248,11 +246,11 @@ def session(self): return sentinel.db_session @pytest.fixture - def message(self, fetch_annotation): + def message(self, annotation_read_service): return { # This is a bit backward from how things really work, but it # ensures the id we look up gives us an annotation that matches - "annotation_id": fetch_annotation.return_value.id, + "annotation_id": annotation_read_service.return_value.id, "action": "update", "src_client_id": "source_socket", } @@ -261,12 +259,6 @@ def message(self, fetch_annotation): def AnnotationContext(self, patch): return patch("h.streamer.messages.AnnotationContext") - @pytest.fixture(autouse=True) - def fetch_annotation(self, factories, patch): - fetch = patch("h.streamer.messages.storage.fetch_annotation") - fetch.return_value = factories.Annotation() - return fetch - @pytest.fixture(autouse=True) def identity_permits(self, patch): identity_permits = patch("h.streamer.messages.identity_permits") diff --git a/tests/h/streamer/metrics_test.py b/tests/unit/h/streamer/metrics_test.py similarity index 100% rename from tests/h/streamer/metrics_test.py rename to tests/unit/h/streamer/metrics_test.py diff --git a/tests/h/streamer/streamer_test.py b/tests/unit/h/streamer/streamer_test.py similarity index 100% rename from tests/h/streamer/streamer_test.py rename to tests/unit/h/streamer/streamer_test.py diff --git a/tests/h/streamer/tweens_test.py b/tests/unit/h/streamer/tweens_test.py similarity index 100% rename from tests/h/streamer/tweens_test.py rename to tests/unit/h/streamer/tweens_test.py diff --git a/tests/h/streamer/views_test.py b/tests/unit/h/streamer/views_test.py similarity index 66% rename from tests/h/streamer/views_test.py rename to tests/unit/h/streamer/views_test.py index ad1e5030f30..d421a2e3978 100644 --- a/tests/h/streamer/views_test.py +++ b/tests/unit/h/streamer/views_test.py @@ -19,6 +19,15 @@ def test_it_adds_work_queue_to_environ(self, pyramid_request): pyramid_request.environ["h.ws.streamer_work_queue"] == streamer.WORK_QUEUE ) + def test_debug_mode_is_disabled_by_default(self, pyramid_request): + views.websocket_view(pyramid_request) + assert pyramid_request.environ["h.ws.debug"] is False + + def test_enable_debug_mode(self, pyramid_request): + pyramid_request.params["debug"] = "1" + views.websocket_view(pyramid_request) + assert pyramid_request.environ["h.ws.debug"] is True + @pytest.fixture def pyramid_request(self, pyramid_request): pyramid_request.get_response = lambda _: None diff --git a/tests/h/streamer/websocket_test.py b/tests/unit/h/streamer/websocket_test.py similarity index 88% rename from tests/h/streamer/websocket_test.py rename to tests/unit/h/streamer/websocket_test.py index b1d3fd98cdc..be2f70849b6 100644 --- a/tests/h/streamer/websocket_test.py +++ b/tests/unit/h/streamer/websocket_test.py @@ -1,3 +1,4 @@ +import json from collections import namedtuple from unittest import mock @@ -114,10 +115,12 @@ def test_invalid_incoming_message_not_queued(self, client, queue): assert queue.empty() + @pytest.mark.parametrize("debug", (True, False)) def test_invalid_incoming_message_closes_connection( - self, client, fake_socket_close + self, client, fake_socket_close, debug ): """Invalid messages should cause termination of the connection.""" + client.debug = debug message = FakeMessage('{"foo":missingquotes}') client.received_message(message) @@ -145,6 +148,20 @@ def test_socket_send_json_skips_when_terminated( assert not fake_socket_send.called + def test_debug_mode(self, fake_environ, log): + sock = mock.Mock(spec_set=["sendall"]) + fake_environ["h.ws.debug"] = True + client = websocket.WebSocket(sock, environ=fake_environ) + + message = FakeMessage(json.dumps({"type": "whoami", "id": 1})) + log.info.reset_mock() + + client.received_message(message) + client.send_json({"type": "whoyouare", "ok": True, "reply_to": 1}) + client.closed(code=1006, reason="Client went away") + + assert len(log.info.mock_calls) == 3 + @pytest.fixture(autouse=True) def with_no_socket_instances(self): # The instances set is automatically populated when web sockets are @@ -163,6 +180,7 @@ def queue(self): @pytest.fixture def fake_environ(self, queue): return { + "h.ws.debug": False, "h.ws.identity": Identity(), "h.ws.registry": mock.sentinel.registry, "h.ws.streamer_work_queue": queue, @@ -183,33 +201,36 @@ def fake_socket_terminated(self, patch): @pytest.mark.usefixtures("handlers") class TestHandleMessage: - def test_uses_unknown_handler_for_missing_type(self, unknown_handler): + def test_uses_unknown_handler_for_missing_type(self, socket, unknown_handler): """If the type is missing, call the `None` handler.""" - socket = mock.Mock(spec_set=["close"]) message = websocket.Message(socket, payload={"foo": "bar"}) websocket.handle_message(message) unknown_handler.assert_called_once_with(message, session=None) - def test_uses_unknown_handler_for_unknown_type(self, unknown_handler): + def test_uses_unknown_handler_for_unknown_type(self, socket, unknown_handler): """If the type is unknown, call the `None` handler.""" - socket = mock.Mock(spec_set=["close"]) message = websocket.Message(socket, payload={"type": "donkeys", "foo": "bar"}) websocket.handle_message(message) unknown_handler.assert_called_once_with(message, session=None) - def test_uses_appropriate_handler_for_known_type(self, foo_handler): + def test_uses_appropriate_handler_for_known_type(self, socket, foo_handler): """If the type is recognised, call the relevant handler.""" - socket = mock.Mock(spec_set=["close"]) message = websocket.Message(socket, payload={"type": "foo", "foo": "bar"}) websocket.handle_message(message) foo_handler.assert_called_once_with(message, session=None) + def test_debug_mode(self, socket, log): + socket.debug = True + message = websocket.Message(socket, payload={"type": "foo", "foo": "bar"}) + websocket.handle_message(message) + log.info.assert_called_once() + @pytest.fixture def foo_handler(self): return mock.Mock(spec_set=[]) @@ -218,6 +239,10 @@ def foo_handler(self): def unknown_handler(self): return mock.Mock(spec_set=[]) + @pytest.fixture + def socket(self): + return mock.create_autospec(websocket.WebSocket, instance=True, spec_set=True) + @pytest.fixture def handlers(self, request, foo_handler, unknown_handler): patcher = mock.patch.dict( @@ -342,3 +367,8 @@ def test_error(self): websocket.handle_unknown_message(message) mock_reply.assert_called_once_with(Any.dict.containing(["error"]), ok=False) + + +@pytest.fixture +def log(patch): + return patch("h.streamer.websocket.log") diff --git a/tests/h/subscribers_test.py b/tests/unit/h/subscribers_test.py similarity index 93% rename from tests/h/subscribers_test.py rename to tests/unit/h/subscribers_test.py index c86c3ae9934..6675fcb7da4 100644 --- a/tests/h/subscribers_test.py +++ b/tests/unit/h/subscribers_test.py @@ -22,11 +22,11 @@ def test_adds_feature_flag_client(self, event, pyramid_request): assert event["feature"] == pyramid_request.feature def test_adds_analytics_tracking_id(self, event, pyramid_request): - pyramid_request.registry.settings["ga_tracking_id"] = "abcd1234" + pyramid_request.registry.settings["gtm_container_id"] = "abcd1234" subscribers.add_renderer_globals(event) - assert event["ga_tracking_id"] == "abcd1234" + assert event["gtm_container_id"] == "abcd1234" def test_adds_frontend_settings(self, event): subscribers.add_renderer_globals(event) @@ -99,12 +99,13 @@ def event(self, pyramid_request): return event +@pytest.mark.usefixtures("annotation_read_service") class TestSendReplyNotifications: def test_it_sends_emails( self, event, pyramid_request, - storage, + annotation_read_service, reply, emails, mailer, @@ -113,10 +114,10 @@ def test_it_sends_emails( # This is a pure plumbing test, checking everything is connected to # everything else as we expect - storage.fetch_annotation.assert_called_once_with( - pyramid_request.db, event.annotation_id + annotation_read_service.get_annotation_by_id.assert_called_once_with( + event.annotation_id ) - annotation = storage.fetch_annotation.return_value + annotation = annotation_read_service.get_annotation_by_id.return_value reply.get_notification.assert_called_once_with( pyramid_request, annotation, event.action ) @@ -170,11 +171,6 @@ def transaction_manager(self, pyramid_request): return pyramid_request.tm -@pytest.fixture(autouse=True) -def storage(patch): - return patch("h.subscribers.storage") - - @pytest.fixture(autouse=True) def reply(patch): return patch("h.subscribers.reply") diff --git a/tests/h/services/search_index/__init__.py b/tests/unit/h/tasks/__init__.py similarity index 100% rename from tests/h/services/search_index/__init__.py rename to tests/unit/h/tasks/__init__.py diff --git a/tests/unit/h/tasks/annotations_test.py b/tests/unit/h/tasks/annotations_test.py new file mode 100644 index 00000000000..415399b44b1 --- /dev/null +++ b/tests/unit/h/tasks/annotations_test.py @@ -0,0 +1,56 @@ +import pytest + +from h.tasks.annotations import sync_annotation_slim + + +class TestSyncAnnotationSlim: + AUTHORITY_1 = "AUTHORITY_1" + AUTHORITY_2 = "AUTHORITY_2" + + USERNAME_1 = "USERNAME_1" + USERNAME_2 = "USERNAME_2" + + def test_it(self, factories, annotation_write_service, queue_service): + annotation = factories.Annotation() + # Some deleted annotations that should not be processed + factories.Annotation.create_batch(10, deleted=True) + job = factories.SyncAnnotationJob(annotation=annotation, name="annotation_slim") + + queue_service.get.return_value = [job] + + sync_annotation_slim(1) + + queue_service.get.assert_called_once_with(name="annotation_slim", limit=1) + annotation_write_service.upsert_annotation_slim.assert_called_once_with( + annotation + ) + queue_service.delete.assert_called_once_with([job]) + + def test_job_for_missing_annotation( + self, factories, annotation_write_service, queue_service, db_session + ): + annotation = factories.Annotation() + job = factories.SyncAnnotationJob(annotation=annotation, name="annotation_slim") + db_session.delete(annotation) + db_session.commit() + + queue_service.get.return_value = [job] + + sync_annotation_slim(1) + + queue_service.get.assert_called_once_with(name="annotation_slim", limit=1) + annotation_write_service.upsert_annotation_slim.assert_not_called() + queue_service.delete.assert_called_once_with([job]) + + def test_it_with_no_pending_jobs(self, queue_service, annotation_write_service): + queue_service.get.return_value = [] + + sync_annotation_slim(1) + + annotation_write_service.upsert_annotation_slim.assert_not_called() + + @pytest.fixture(autouse=True) + def celery(self, patch, pyramid_request): + cel = patch("h.tasks.annotations.celery", autospec=False) + cel.request = pyramid_request + return cel diff --git a/tests/h/tasks/cleanup_test.py b/tests/unit/h/tasks/cleanup_test.py similarity index 78% rename from tests/h/tasks/cleanup_test.py rename to tests/unit/h/tasks/cleanup_test.py index 9152c83932a..1b4f3c5d821 100644 --- a/tests/h/tasks/cleanup_test.py +++ b/tests/unit/h/tasks/cleanup_test.py @@ -2,49 +2,39 @@ import pytest -from h.models import Annotation, AuthTicket, AuthzCode, Token +from h.models import AuthTicket, AuthzCode, Token from h.tasks.cleanup import ( purge_deleted_annotations, + purge_deleted_users, purge_expired_auth_tickets, purge_expired_authz_codes, purge_expired_tokens, purge_removed_features, + report_num_deleted_annotations, ) @pytest.mark.usefixtures("celery") class TestPurgeDeletedAnnotations: - @pytest.mark.parametrize( - "deleted,mins_ago,purged", - [ - # Deleted more than 10 minutes ago... should be purged. - (True, 30, True), - (True, 3600, True), - # Deleted less than 10 minutes ago... should NOT be purged. - (True, -30, False), # annotation from the future! wooOOOooo! - (True, 0, False), - (True, 1, False), - (True, 9, False), - # Not deleted... should NOT be purged. - (False, -30, False), - (False, 0, False), - (False, 1, False), - (False, 9, False), - (False, 30, False), - (False, 3600, False), - ], - ) - def test_purge(self, db_session, factories, deleted, mins_ago, purged): - updated = datetime.utcnow() - timedelta(minutes=mins_ago) - annotation = factories.Annotation(deleted=deleted, updated=updated) - db_session.add(annotation) - + def test_purge(self, annotation_delete_service): purge_deleted_annotations() - if purged: - assert not db_session.query(Annotation).count() - else: - assert db_session.query(Annotation).count() == 1 + annotation_delete_service.bulk_delete.assert_called_once() + + +@pytest.mark.usefixtures("celery") +class TestReportNumDeletedAnnotations: + def test_report_num_deleted_annotations(self, factories, newrelic): + # Annotations marked as deleted, these should be counted. + factories.Annotation.create_batch(2, deleted=True) + # An annotation not marked as deleted, this should not be counted. + factories.Annotation.create() + + report_num_deleted_annotations() + + newrelic.agent.record_custom_metric.assert_called_once_with( + "Custom/Annotations/MarkedAsDeleted", 2 + ) @pytest.mark.usefixtures("celery") @@ -154,8 +144,21 @@ def test_calls_remove_old_flags(self, db_session, patch): Feature.remove_old_flags.assert_called_once_with(db_session) +@pytest.mark.usefixtures("celery") +class TestPurgeDeletedUsers: + def test_it(self, user_delete_service): + purge_deleted_users() + + user_delete_service.purge_deleted_users.assert_called_once_with() + + @pytest.fixture -def celery(patch, db_session): +def celery(patch, pyramid_request): cel = patch("h.tasks.cleanup.celery", autospec=False) - cel.request.db = db_session + cel.request = pyramid_request return cel + + +@pytest.fixture(autouse=True) +def newrelic(mocker): + return mocker.patch("h.tasks.cleanup.newrelic") diff --git a/tests/h/tasks/indexer_test.py b/tests/unit/h/tasks/indexer_test.py similarity index 54% rename from tests/h/tasks/indexer_test.py rename to tests/unit/h/tasks/indexer_test.py index 181441e3917..2be3e122c8b 100644 --- a/tests/h/tasks/indexer_test.py +++ b/tests/unit/h/tasks/indexer_test.py @@ -4,7 +4,7 @@ import pytest -from h.services.job_queue.metrics import JobQueueMetrics +from h.services.job_queue_metrics import JobQueueMetrics from h.tasks import indexer pytestmark = pytest.mark.usefixtures("search_index") @@ -28,57 +28,12 @@ def test_delete_annotation(self, search_index): ) -class TestAddAnnotationsBetweenTimes: - def test_it(self, search_index): - indexer.add_annotations_between_times( - sentinel.start_time, sentinel.end_time, sentinel.tag - ) - - search_index._queue.add_between_times.assert_called_once_with( # pylint:disable=protected-access - sentinel.start_time, sentinel.end_time, sentinel.tag - ) - - -class TestAddUsersAnnotations: - def test_it(self, search_index): - indexer.add_users_annotations( - sentinel.userid, - sentinel.tag, - force=sentinel.force, - schedule_in=sentinel.schedule_in, - ) - - search_index._queue.add_by_user.assert_called_once_with( # pylint:disable=protected-access - sentinel.userid, - sentinel.tag, - force=sentinel.force, - schedule_in=sentinel.schedule_in, - ) - - -class TestAddGroupAnnotations: - def test_it(self, search_index): - indexer.add_group_annotations( - sentinel.groupid, - sentinel.tag, - force=sentinel.force, - schedule_in=sentinel.schedule_in, - ) - - search_index._queue.add_by_group.assert_called_once_with( # pylint:disable=protected-access - sentinel.groupid, - sentinel.tag, - force=sentinel.force, - schedule_in=sentinel.schedule_in, - ) - - class TestSyncAnnotations: - def test_it(self, newrelic, log, search_index): + def test_it(self, newrelic, log, annotation_sync_service): indexer.sync_annotations("test_queue") - search_index.sync.assert_called_once_with("test_queue") - log.info.assert_called_once_with(search_index.sync.return_value) + annotation_sync_service.sync.assert_called_once_with("test_queue") + log.info.assert_called_once_with(annotation_sync_service.sync.return_value) newrelic.agent.record_custom_metrics.assert_called_once_with( [ ("Custom/SyncAnnotations/Queue/foo", 2), @@ -91,9 +46,9 @@ def log(self, patch): return patch("h.tasks.indexer.log") @pytest.fixture - def search_index(self, search_index): - search_index.sync.return_value = Counter({"foo": 2, "bar": 3}) - return search_index + def annotation_sync_service(self, annotation_sync_service): + annotation_sync_service.sync.return_value = Counter({"foo": 2, "bar": 3}) + return annotation_sync_service class TestReportJobQueueMetrics: diff --git a/tests/unit/h/tasks/job_queue_test.py b/tests/unit/h/tasks/job_queue_test.py new file mode 100644 index 00000000000..b3227102ac9 --- /dev/null +++ b/tests/unit/h/tasks/job_queue_test.py @@ -0,0 +1,68 @@ +from unittest import mock +from unittest.mock import sentinel + +import pytest + +from h.tasks import job_queue + + +class TestAddAnnotationsBetweenTimes: + def test_it(self, queue_service): + job_queue.add_annotations_between_times( + sentinel.name, sentinel.start_time, sentinel.end_time, sentinel.tag + ) + + queue_service.add_between_times.assert_called_once_with( + sentinel.name, sentinel.start_time, sentinel.end_time, sentinel.tag + ) + + +class TestAddAnnotationsFromUser: + def test_it(self, queue_service): + job_queue.add_annotations_from_user( + sentinel.name, + sentinel.userid, + sentinel.tag, + force=sentinel.force, + schedule_in=sentinel.schedule_in, + ) + + queue_service.add_by_user.assert_called_once_with( + sentinel.name, + sentinel.userid, + sentinel.tag, + force=sentinel.force, + schedule_in=sentinel.schedule_in, + ) + + +class TestAddAnnotationsFromGroup: + def test_it(self, queue_service): + job_queue.add_annotations_from_group( + sentinel.name, + sentinel.groupid, + sentinel.tag, + force=sentinel.force, + schedule_in=sentinel.schedule_in, + ) + + queue_service.add_by_group.assert_called_once_with( + sentinel.name, + sentinel.groupid, + sentinel.tag, + force=sentinel.force, + schedule_in=sentinel.schedule_in, + ) + + +@pytest.fixture(autouse=True) +def celery(patch, pyramid_request): + cel = patch("h.tasks.job_queue.celery") + cel.request = pyramid_request + return cel + + +@pytest.fixture +def pyramid_request(pyramid_request): + pyramid_request.es = mock.Mock() + return pyramid_request diff --git a/tests/h/tasks/mailer_test.py b/tests/unit/h/tasks/mailer_test.py similarity index 100% rename from tests/h/tasks/mailer_test.py rename to tests/unit/h/tasks/mailer_test.py diff --git a/tests/unit/h/tasks/url_migration_test.py b/tests/unit/h/tasks/url_migration_test.py new file mode 100644 index 00000000000..a56fe009e35 --- /dev/null +++ b/tests/unit/h/tasks/url_migration_test.py @@ -0,0 +1,29 @@ +from unittest.mock import sentinel + +import pytest + +from h.tasks.url_migration import move_annotations, move_annotations_by_url + + +class TestURLMigrationTasks: + def test_move_annotations_by_url(self, url_migration_service): + move_annotations_by_url(sentinel.old_url, sentinel.new_url_info) + + url_migration_service.move_annotations_by_url.assert_called_once_with( + sentinel.old_url, sentinel.new_url_info + ) + + def test_move_annotations(self, url_migration_service): + move_annotations( + sentinel.annotation_ids, sentinel.current_uri_normalized, sentinel.url_info + ) + + url_migration_service.move_annotations.assert_called_once_with( + sentinel.annotation_ids, sentinel.current_uri_normalized, sentinel.url_info + ) + + @pytest.fixture(autouse=True) + def celery(self, patch, pyramid_request): + celery = patch("h.tasks.url_migration.celery") + celery.request = pyramid_request + return celery diff --git a/tests/h/streamer/__init__.py b/tests/unit/h/traversal/__init__.py similarity index 100% rename from tests/h/streamer/__init__.py rename to tests/unit/h/traversal/__init__.py diff --git a/tests/h/traversal/annotation_test.py b/tests/unit/h/traversal/annotation_test.py similarity index 67% rename from tests/h/traversal/annotation_test.py rename to tests/unit/h/traversal/annotation_test.py index 0253d76441f..6f82b73ade6 100644 --- a/tests/h/traversal/annotation_test.py +++ b/tests/unit/h/traversal/annotation_test.py @@ -5,22 +5,25 @@ from h.traversal import AnnotationContext, AnnotationRoot +@pytest.mark.usefixtures("annotation_read_service") class TestAnnotationRoot: def test_getting_by_subscript_returns_AnnotationContext( - self, root, pyramid_request, AnnotationContext, storage + self, root, AnnotationContext, annotation_read_service ): context = root[sentinel.annotation_id] - storage.fetch_annotation.assert_called_once_with( - pyramid_request.db, sentinel.annotation_id + annotation_read_service.get_annotation_by_id.assert_called_once_with( + sentinel.annotation_id + ) + AnnotationContext.assert_called_once_with( + annotation_read_service.get_annotation_by_id.return_value ) - AnnotationContext.assert_called_once_with(storage.fetch_annotation.return_value) assert context == AnnotationContext.return_value def test_getting_by_subscript_raises_KeyError_if_annotation_missing( - self, root, storage + self, root, annotation_read_service ): - storage.fetch_annotation.return_value = None + annotation_read_service.get_annotation_by_id.return_value = None with pytest.raises(KeyError): assert root[sentinel.annotation_id] @@ -29,10 +32,6 @@ def test_getting_by_subscript_raises_KeyError_if_annotation_missing( def root(self, pyramid_request): return AnnotationRoot(pyramid_request) - @pytest.fixture - def storage(self, patch): - return patch("h.traversal.annotation.storage") - @pytest.fixture def AnnotationContext(self, patch): return patch("h.traversal.annotation.AnnotationContext") diff --git a/tests/h/traversal/group_test.py b/tests/unit/h/traversal/group_test.py similarity index 100% rename from tests/h/traversal/group_test.py rename to tests/unit/h/traversal/group_test.py diff --git a/tests/h/traversal/organization_test.py b/tests/unit/h/traversal/organization_test.py similarity index 100% rename from tests/h/traversal/organization_test.py rename to tests/unit/h/traversal/organization_test.py diff --git a/tests/h/traversal/user_test.py b/tests/unit/h/traversal/user_test.py similarity index 100% rename from tests/h/traversal/user_test.py rename to tests/unit/h/traversal/user_test.py diff --git a/tests/h/tweens_test.py b/tests/unit/h/tweens_test.py similarity index 94% rename from tests/h/tweens_test.py rename to tests/unit/h/tweens_test.py index 0ac7134719b..996bc78bf53 100644 --- a/tests/h/tweens_test.py +++ b/tests/unit/h/tweens_test.py @@ -46,7 +46,10 @@ def test_it_redirects_for_redirected_routes(self, pyramid_request): pyramid_request.path = "/foo" tween = tweens.redirect_tween_factory( - lambda req: req.response, pyramid_request.registry, redirects + # pragma: nocover + lambda req: req.response, + pyramid_request.registry, + redirects, ) response = tween(pyramid_request) @@ -58,7 +61,9 @@ def test_it_redirects_for_redirected_routes(self, pyramid_request): class TestSecurityHeaderTween: def test_it_adds_security_headers_to_the_response(self, pyramid_request): tween = tweens.security_header_tween_factory( - lambda req: req.response, pyramid_request.registry + # pragma: nocover + lambda req: req.response, + pyramid_request.registry, ) response = tween(pyramid_request) diff --git a/tests/h/tasks/__init__.py b/tests/unit/h/util/__init__.py similarity index 100% rename from tests/h/tasks/__init__.py rename to tests/unit/h/util/__init__.py diff --git a/tests/h/util/datetime_test.py b/tests/unit/h/util/datetime_test.py similarity index 100% rename from tests/h/util/datetime_test.py rename to tests/unit/h/util/datetime_test.py diff --git a/tests/h/util/db_test.py b/tests/unit/h/util/db_test.py similarity index 90% rename from tests/h/util/db_test.py rename to tests/unit/h/util/db_test.py index b1101d0ddd4..fcea1ff2ac0 100644 --- a/tests/h/util/db_test.py +++ b/tests/unit/h/util/db_test.py @@ -2,6 +2,7 @@ from unittest import mock import pytest +from sqlalchemy.orm import SessionTransaction from h.util.db import lru_cache_in_transaction, on_transaction_end @@ -47,7 +48,7 @@ def random_float(*args, **kwargs): # pylint:disable=unused-argument assert random_float("c", with_keywords=True) == c type(mock_transaction).parent = mock.PropertyMock( - return_value=mock.Mock(spec=db_session.transaction) + return_value=mock.Mock(spec=SessionTransaction) ) db_session.dispatch.after_transaction_end(db_session, mock_transaction) @@ -75,12 +76,12 @@ def test_skips_wrapped_function_when_nested_transaction( ): spy = mock.Mock() type(mock_transaction).parent = mock.PropertyMock( - return_value=mock.Mock(spec=db_session.transaction) + return_value=mock.Mock(spec=SessionTransaction) ) @on_transaction_end(db_session) def transaction_ended(): - spy() + spy() # pragma: nocover db_session.dispatch.after_transaction_end(db_session, mock_transaction) @@ -88,7 +89,7 @@ def transaction_ended(): @pytest.fixture -def mock_transaction(db_session): - transaction = mock.Mock(spec=db_session.transaction) +def mock_transaction(): + transaction = mock.Mock(spec=SessionTransaction) type(transaction).parent = mock.PropertyMock(return_value=None) return transaction diff --git a/tests/h/util/document_claims_test.py b/tests/unit/h/util/document_claims_test.py similarity index 100% rename from tests/h/util/document_claims_test.py rename to tests/unit/h/util/document_claims_test.py diff --git a/tests/h/util/group_scope_test.py b/tests/unit/h/util/group_scope_test.py similarity index 100% rename from tests/h/util/group_scope_test.py rename to tests/unit/h/util/group_scope_test.py diff --git a/tests/h/util/group_test.py b/tests/unit/h/util/group_test.py similarity index 100% rename from tests/h/util/group_test.py rename to tests/unit/h/util/group_test.py diff --git a/tests/h/util/markdown_render_test.py b/tests/unit/h/util/markdown_render_test.py similarity index 99% rename from tests/h/util/markdown_render_test.py rename to tests/unit/h/util/markdown_render_test.py index b50c6613bda..23ffcc66e2c 100644 --- a/tests/h/util/markdown_render_test.py +++ b/tests/unit/h/util/markdown_render_test.py @@ -69,6 +69,7 @@ def test_it_allows_markdown_html(self, text): '

', ), ("", "

"), + (None, None), ], ) def test_it_escapes_evil_html(self, text, expected): diff --git a/tests/h/util/metrics_test.py b/tests/unit/h/util/metrics_test.py similarity index 100% rename from tests/h/util/metrics_test.py rename to tests/unit/h/util/metrics_test.py diff --git a/tests/h/util/redirects_test.py b/tests/unit/h/util/redirects_test.py similarity index 100% rename from tests/h/util/redirects_test.py rename to tests/unit/h/util/redirects_test.py diff --git a/tests/h/util/test_logging_filters.py b/tests/unit/h/util/test_logging_filters.py similarity index 100% rename from tests/h/util/test_logging_filters.py rename to tests/unit/h/util/test_logging_filters.py diff --git a/tests/h/util/uri_test.py b/tests/unit/h/util/uri_test.py similarity index 100% rename from tests/h/util/uri_test.py rename to tests/unit/h/util/uri_test.py diff --git a/tests/h/util/user_test.py b/tests/unit/h/util/user_test.py similarity index 100% rename from tests/h/util/user_test.py rename to tests/unit/h/util/user_test.py diff --git a/tests/h/util/view_test.py b/tests/unit/h/util/view_test.py similarity index 73% rename from tests/h/util/view_test.py rename to tests/unit/h/util/view_test.py index 088c4256e18..1532ef21cd3 100644 --- a/tests/h/util/view_test.py +++ b/tests/unit/h/util/view_test.py @@ -5,27 +5,12 @@ from h.util.view import handle_exception, json_view -@pytest.mark.usefixtures("sys_exc_info") class TestHandleException: def test_sets_response_status_500(self, pyramid_request): handle_exception(pyramid_request, Mock()) assert pyramid_request.response.status_int == 500 - @pytest.fixture - def pyramid_request(self, pyramid_request): - return pyramid_request - - @pytest.fixture - def latest_exception(self): - return Exception("Last exception raised in thread") - - @pytest.fixture - def sys_exc_info(self, patch, latest_exception): - sys_exc_info = patch("h.util.view._exc_info") - sys_exc_info.return_value = (type(latest_exception), latest_exception, None) - return sys_exc_info - @pytest.mark.usefixtures("view_config") class TestJsonView: diff --git a/tests/h/viewderivers_test.py b/tests/unit/h/viewderivers_test.py similarity index 92% rename from tests/h/viewderivers_test.py rename to tests/unit/h/viewderivers_test.py index 34ec8da0017..a55c4deaddd 100644 --- a/tests/h/viewderivers_test.py +++ b/tests/unit/h/viewderivers_test.py @@ -82,11 +82,8 @@ def _impl(view, **kwargs): pyramid_config.add_view(view, route_name="testview", **kwargs) introspector = pyramid_config.registry.introspector - for view_ in introspector.get_category("views"): - if view_["introspectable"]["route_name"] == "testview": - return view_["introspectable"]["derived_callable"] - - return None + view_ = introspector.get_category("views")[0] + return view_["introspectable"]["derived_callable"] return _impl diff --git a/tests/h/viewpredicates_test.py b/tests/unit/h/viewpredicates_test.py similarity index 100% rename from tests/h/viewpredicates_test.py rename to tests/unit/h/viewpredicates_test.py diff --git a/tests/h/traversal/__init__.py b/tests/unit/h/views/__init__.py similarity index 100% rename from tests/h/traversal/__init__.py rename to tests/unit/h/views/__init__.py diff --git a/tests/h/views/account_signup_test.py b/tests/unit/h/views/account_signup_test.py similarity index 100% rename from tests/h/views/account_signup_test.py rename to tests/unit/h/views/account_signup_test.py diff --git a/tests/h/views/accounts_test.py b/tests/unit/h/views/accounts_test.py similarity index 94% rename from tests/h/views/accounts_test.py rename to tests/unit/h/views/accounts_test.py index 165dcafdad1..d7d5971631b 100644 --- a/tests/h/views/accounts_test.py +++ b/tests/unit/h/views/accounts_test.py @@ -6,7 +6,6 @@ from pyramid import httpexceptions from h.models import Subscriptions -from h.services.developer_token import developer_token_service_factory from h.services.user_password import UserPasswordService from h.views import accounts as views @@ -22,7 +21,7 @@ def render(self): class FakeSerializer: - ... + pass @pytest.mark.usefixtures("routes") @@ -805,66 +804,76 @@ def test_post_sets_user_properties(self, form_validating_to, pyramid_request): assert user.location == "Paris" -@pytest.mark.usefixtures("authenticated_userid", "token_service") +@pytest.mark.usefixtures("authenticated_userid", "developer_token_service") class TestDeveloperController: - def test_get_fetches_token(self, controller, token_service, authenticated_userid): + def test_get_fetches_token( + self, controller, developer_token_service, authenticated_userid + ): controller.get() - token_service.fetch.assert_called_once_with(authenticated_userid) + developer_token_service.fetch.assert_called_once_with(authenticated_userid) - def test_get_returns_token_for_authenticated_user(self, controller, token_service): - assert controller.get() == {"token": token_service.fetch.return_value.value} + def test_get_returns_token_for_authenticated_user( + self, controller, developer_token_service + ): + assert controller.get() == { + "token": developer_token_service.fetch.return_value.value + } def test_get_returns_empty_context_for_missing_token( - self, controller, token_service + self, controller, developer_token_service ): - token_service.fetch.return_value = None + developer_token_service.fetch.return_value = None assert controller.get() == {} - def test_post_fetches_token(self, controller, token_service, authenticated_userid): + def test_post_fetches_token( + self, controller, developer_token_service, authenticated_userid + ): controller.post() - token_service.fetch.assert_called_once_with(authenticated_userid) + developer_token_service.fetch.assert_called_once_with(authenticated_userid) - def test_post_regenerates_token_when_found(self, controller, token_service): + def test_post_regenerates_token_when_found( + self, controller, developer_token_service + ): controller.post() - token_service.regenerate.assert_called_once_with( - token_service.fetch.return_value + developer_token_service.regenerate.assert_called_once_with( + developer_token_service.fetch.return_value ) - def test_post_returns_regenerated_token_when_found(self, controller, token_service): + def test_post_returns_regenerated_token_when_found( + self, controller, developer_token_service + ): result = controller.post() - assert result == {"token": token_service.regenerate.return_value.value} + assert result == { + "token": developer_token_service.regenerate.return_value.value + } def test_post_creates_new_token_when_not_found( - self, controller, token_service, authenticated_userid + self, controller, developer_token_service, authenticated_userid ): - token_service.fetch.return_value = None + developer_token_service.fetch.return_value = None controller.post() - token_service.create.assert_called_once_with(authenticated_userid) + developer_token_service.create.assert_called_once_with(authenticated_userid) - def test_post_returns_new_token_when_not_found(self, controller, token_service): - token_service.fetch.return_value = None + def test_post_returns_new_token_when_not_found( + self, controller, developer_token_service + ): + developer_token_service.fetch.return_value = None result = controller.post() - assert result == {"token": token_service.create.return_value.value} + assert result == {"token": developer_token_service.create.return_value.value} @pytest.fixture def controller(self, pyramid_request): return views.DeveloperController(pyramid_request) - @pytest.fixture - def token_service(self, pyramid_config, pyramid_request): - svc = mock.Mock(spec=developer_token_service_factory(None, pyramid_request)) - pyramid_config.register_service(svc, name="developer_token") - return svc - @pytest.fixture def authenticated_userid(self, pyramid_config): userid = "acct:jane@example.com" diff --git a/tests/h/views/activity_test.py b/tests/unit/h/views/activity_test.py similarity index 99% rename from tests/h/views/activity_test.py rename to tests/unit/h/views/activity_test.py index 33caaae07c9..759875b0bd8 100644 --- a/tests/h/views/activity_test.py +++ b/tests/unit/h/views/activity_test.py @@ -1208,8 +1208,7 @@ def group(factories): @pytest.fixture def no_creator_group(factories): - group = factories.Group() - group.creator = None + group = factories.Group(creator=None) group.members.extend([factories.User(), factories.User()]) return group @@ -1236,8 +1235,7 @@ def restricted_group(factories): @pytest.fixture def no_creator_open_group(factories): - open_group = factories.OpenGroup() - open_group.creator = None + open_group = factories.OpenGroup(creator=None) return open_group diff --git a/tests/h/util/__init__.py b/tests/unit/h/views/admin/__init__.py similarity index 100% rename from tests/h/util/__init__.py rename to tests/unit/h/views/admin/__init__.py diff --git a/tests/h/views/admin/admins_test.py b/tests/unit/h/views/admin/admins_test.py similarity index 100% rename from tests/h/views/admin/admins_test.py rename to tests/unit/h/views/admin/admins_test.py diff --git a/tests/h/views/admin/badge_test.py b/tests/unit/h/views/admin/badge_test.py similarity index 100% rename from tests/h/views/admin/badge_test.py rename to tests/unit/h/views/admin/badge_test.py diff --git a/tests/h/views/admin/documents_test.py b/tests/unit/h/views/admin/documents_test.py similarity index 82% rename from tests/h/views/admin/documents_test.py rename to tests/unit/h/views/admin/documents_test.py index 2a1f14ba07a..ac85ef73a87 100644 --- a/tests/h/views/admin/documents_test.py +++ b/tests/unit/h/views/admin/documents_test.py @@ -8,12 +8,14 @@ class TestDocumentsAdminViews: + def test_get(self, views): + assert not views.get() + def test_update_annotation_urls_schedules_update( - self, pyramid_request, move_annotations_by_url, flash + self, views, pyramid_request, move_annotations_by_url, flash ): mappings = {"https://example.com": {"url": "https://example.org"}} pyramid_request.POST["url_mappings"] = json.dumps(mappings) - views = DocumentsAdminViews(pyramid_request) views.update_annotation_urls() @@ -22,10 +24,9 @@ def test_update_annotation_urls_schedules_update( flash.assert_called_once_with("URL migration started for 1 URL(s)", "success") def test_it_errors_if_json_does_not_parse( - self, pyramid_request, move_annotations_by_url, flash + self, views, pyramid_request, move_annotations_by_url, flash ): pyramid_request.POST["url_mappings"] = "not-json" - views = DocumentsAdminViews(pyramid_request) views.update_annotation_urls() @@ -36,10 +37,9 @@ def test_it_errors_if_json_does_not_parse( move_annotations_by_url.chunks.assert_not_called() def test_it_errors_if_validation_fails( - self, pyramid_request, move_annotations_by_url, flash + self, views, pyramid_request, move_annotations_by_url, flash ): pyramid_request.POST["url_mappings"] = json.dumps({"not-a-url": "foo"}) - views = DocumentsAdminViews(pyramid_request) views.update_annotation_urls() @@ -53,6 +53,10 @@ def test_it_errors_if_validation_fails( def move_annotations_by_url(self, patch): return patch("h.views.admin.documents.move_annotations_by_url") + @pytest.fixture + def views(self, pyramid_request): + return DocumentsAdminViews(pyramid_request) + @pytest.fixture def flash(self, pyramid_request): flash = create_autospec(pyramid_request.session.flash) diff --git a/tests/h/views/admin/features_test.py b/tests/unit/h/views/admin/features_test.py similarity index 95% rename from tests/h/views/admin/features_test.py rename to tests/unit/h/views/admin/features_test.py index 2a9db977ca5..80fe02bf0d4 100644 --- a/tests/h/views/admin/features_test.py +++ b/tests/unit/h/views/admin/features_test.py @@ -45,13 +45,22 @@ def test_features_save_sets_attributes_when_checkboxes_on(Feature, pyramid_reque Feature.all.return_value = [feature_foo, feature_bar] pyramid_request.POST = { "foo[everyone]": "on", + "foo[first_party]": "on", "foo[staff]": "on", "bar[admins]": "on", } features_save(pyramid_request) - assert feature_foo.everyone is feature_foo.staff is feature_bar.admins is True + expected_true = { + (feature_foo, "everyone"), + (feature_foo, "first_party"), + (feature_foo, "staff"), + (feature_bar, "admins"), + } + for feature in [feature_foo, feature_bar]: + for group in ["everyone", "first_party", "staff", "admins"]: + assert getattr(feature, group) is ((feature, group) in expected_true) @features_save_fixtures diff --git a/tests/h/views/admin/groups_test.py b/tests/unit/h/views/admin/groups_test.py similarity index 99% rename from tests/h/views/admin/groups_test.py rename to tests/unit/h/views/admin/groups_test.py index 7a860868d36..d90c3930850 100644 --- a/tests/h/views/admin/groups_test.py +++ b/tests/unit/h/views/admin/groups_test.py @@ -359,12 +359,12 @@ def call_on_success( # pylint:disable=unused-argument group, [fetched_user.userid, fetched_user.userid] ) - def test_delete_deletes_group(self, group, delete_group_service, pyramid_request): + def test_delete_deletes_group(self, group, group_delete_service, pyramid_request): view = GroupEditViews(GroupContext(group), pyramid_request) view.delete() - delete_group_service.delete.assert_called_once_with(group) + group_delete_service.delete.assert_called_once_with(group) def _expected_form(self, group): return { diff --git a/tests/h/views/admin/index_test.py b/tests/unit/h/views/admin/index_test.py similarity index 100% rename from tests/h/views/admin/index_test.py rename to tests/unit/h/views/admin/index_test.py diff --git a/tests/h/views/admin/mailer_test.py b/tests/unit/h/views/admin/mailer_test.py similarity index 100% rename from tests/h/views/admin/mailer_test.py rename to tests/unit/h/views/admin/mailer_test.py diff --git a/tests/h/views/admin/nipsa_test.py b/tests/unit/h/views/admin/nipsa_test.py similarity index 100% rename from tests/h/views/admin/nipsa_test.py rename to tests/unit/h/views/admin/nipsa_test.py diff --git a/tests/h/views/admin/oauthclients_test.py b/tests/unit/h/views/admin/oauthclients_test.py similarity index 100% rename from tests/h/views/admin/oauthclients_test.py rename to tests/unit/h/views/admin/oauthclients_test.py diff --git a/tests/h/views/admin/organizations_test.py b/tests/unit/h/views/admin/organizations_test.py similarity index 100% rename from tests/h/views/admin/organizations_test.py rename to tests/unit/h/views/admin/organizations_test.py diff --git a/tests/h/views/admin/search_test.py b/tests/unit/h/views/admin/search_test.py similarity index 65% rename from tests/h/views/admin/search_test.py rename to tests/unit/h/views/admin/search_test.py index 24469680aeb..08f6ab9be44 100644 --- a/tests/h/views/admin/search_test.py +++ b/tests/unit/h/views/admin/search_test.py @@ -6,25 +6,25 @@ from h.services.group import GroupService from h.views.admin.search import NotFoundError, SearchAdminViews -pytestmark = pytest.mark.usefixtures("search_index") - class TestSearchAdminViews: def test_get(self, views): assert views.get() == {} - def test_reindex_date(self, views, search_index, pyramid_request): + def test_reindex_date(self, views, tasks, pyramid_request): pyramid_request.params = { "start": "2020-09-09", "end": "2020-09-11", + "name": "sync_annotation", } views.reindex_date() - search_index.add_annotations_between_times.assert_called_once_with( + tasks.job_queue.add_annotations_between_times.delay.assert_called_once_with( + "sync_annotation", datetime.datetime(year=2020, month=9, day=9), datetime.datetime(year=2020, month=9, day=11), - "reindex_date", + tag="reindex_date", ) assert pyramid_request.session.peek_flash("success") == [ "Began reindexing from 2020-09-09 00:00:00 to 2020-09-11 00:00:00" @@ -32,17 +32,23 @@ def test_reindex_date(self, views, search_index, pyramid_request): @pytest.mark.parametrize("force", [True, False]) def test_reindex_user_reindexes_annotations( - self, views, pyramid_request, search_index, factories, force + self, views, pyramid_request, tasks, factories, force ): user = factories.User(username="johnsmith") - pyramid_request.params = {"username": "johnsmith"} + pyramid_request.params = { + "username": "johnsmith", + "name": "sync_annotation", + } if force: pyramid_request.params["reindex_user_force"] = "on" views.reindex_user() - search_index.add_users_annotations.assert_called_once_with( - user.userid, "reindex_user", force=force + tasks.job_queue.add_annotations_from_user.delay.assert_called_once_with( + "sync_annotation", + user.userid, + tag="reindex_user", + force=force, ) assert pyramid_request.session.peek_flash("success") == [ @@ -50,17 +56,17 @@ def test_reindex_user_reindexes_annotations( ] def test_reindex_user_errors_if_user_not_found(self, views, pyramid_request): - pyramid_request.params = {"username": "johnsmith"} + pyramid_request.params = {"username": "johnsmith", "name": "sync_annotation"} with pytest.raises(NotFoundError, match="User johnsmith not found"): views.reindex_user() @pytest.mark.parametrize("force", [True, False]) def test_reindex_group_reindexes_annotations( - self, views, pyramid_request, search_index, factories, group_service, force + self, views, pyramid_request, tasks, factories, group_service, force ): group = factories.Group(pubid="abc123") - pyramid_request.params = {"groupid": "abc123"} + pyramid_request.params = {"groupid": "abc123", "name": "sync_annotation"} if force: pyramid_request.params["reindex_group_force"] = "on" group_service.fetch_by_pubid.return_value = group @@ -68,8 +74,11 @@ def test_reindex_group_reindexes_annotations( views.reindex_group() group_service.fetch_by_pubid.assert_called_with(group.pubid) - search_index.add_group_annotations.assert_called_once_with( - group.pubid, "reindex_group", force=force + tasks.job_queue.add_annotations_from_group.delay.assert_called_once_with( + "sync_annotation", + group.pubid, + tag="reindex_group", + force=force, ) assert pyramid_request.session.peek_flash("success") == [ @@ -79,16 +88,20 @@ def test_reindex_group_reindexes_annotations( def test_reindex_group_errors_if_group_not_found( self, views, pyramid_request, group_service ): - pyramid_request.params = {"groupid": "def456"} + pyramid_request.params = {"groupid": "def456", "name": "sync_annotation"} group_service.fetch_by_pubid.return_value = None with pytest.raises(NotFoundError, match="Group def456 not found"): views.reindex_group() @pytest.fixture - def views(self, pyramid_request): + def views(self, pyramid_request, queue_service): # pylint:disable=unused-argument return SearchAdminViews(pyramid_request) + @pytest.fixture(autouse=True) + def tasks(self, patch): + return patch("h.views.admin.search.tasks") + @pytest.fixture(autouse=True) def routes(self, pyramid_config): pyramid_config.add_route("admin.search", "/admin/search") diff --git a/tests/h/views/admin/staff_test.py b/tests/unit/h/views/admin/staff_test.py similarity index 100% rename from tests/h/views/admin/staff_test.py rename to tests/unit/h/views/admin/staff_test.py diff --git a/tests/h/views/admin/users_test.py b/tests/unit/h/views/admin/users_test.py similarity index 74% rename from tests/h/views/admin/users_test.py rename to tests/unit/h/views/admin/users_test.py index a1f03eeb340..586064ed185 100644 --- a/tests/h/views/admin/users_test.py +++ b/tests/unit/h/views/admin/users_test.py @@ -6,10 +6,11 @@ from h.models import Annotation from h.services.annotation_stats import AnnotationStatsService -from h.services.delete_user import DeleteUserService +from h.services.user_delete import UserDeleteService from h.views.admin.users import ( UserNotFoundError, format_date, + user_not_found, users_activate, users_delete, users_index, @@ -76,23 +77,28 @@ def test_users_index_strips_spaces(models, pyramid_request): @users_index_fixtures -def test_users_index_queries_annotation_count_by_userid( - models, factories, pyramid_request, annotation_stats_service -): - user = factories.User.build(username="bob") - models.User.get_by_username.return_value = user - annotation_stats_service.total_user_annotation_count.return_value = 8 +def test_users_index_no_user_found(models, pyramid_request): + pyramid_request.params = {"username": "bob", "authority": "foo.org"} + models.User.get_by_username.return_value = None + models.User.get_by_email.return_value = None - pyramid_request.params = {"username": "bob", "authority": user.authority} result = users_index(pyramid_request) - assert result["user_meta"]["annotations_count"] == 8 + + assert result == { + "default_authority": "example.com", + "username": "bob", + "authority": "foo.org", + "user": None, + "user_meta": {}, + "format_date": format_date, + } @users_index_fixtures -def test_users_index_no_user_found(models, pyramid_request): +def test_users_index_user_marked_as_deleted(models, pyramid_request, factories): pyramid_request.params = {"username": "bob", "authority": "foo.org"} - models.User.get_by_username.return_value = None - models.User.get_by_email.return_value = None + user = factories.User.build(username="bob", authority="foo.org", deleted=True) + models.User.get_by_username.return_value = user result = users_index(pyramid_request) @@ -107,10 +113,13 @@ def test_users_index_no_user_found(models, pyramid_request): @users_index_fixtures -def test_users_index_user_found(models, pyramid_request, factories): +def test_users_index_user_found( + models, pyramid_request, factories, annotation_stats_service +): pyramid_request.params = {"username": "bob", "authority": "foo.org"} user = factories.User.build(username="bob", authority="foo.org") models.User.get_by_username.return_value = user + annotation_stats_service.total_user_annotation_count.return_value = 8 result = users_index(pyramid_request) @@ -119,7 +128,7 @@ def test_users_index_user_found(models, pyramid_request, factories): "username": "bob", "authority": "foo.org", "user": user, - "user_meta": {"annotations_count": 0}, + "user_meta": {"annotations_count": 8}, "format_date": format_date, } @@ -128,71 +137,29 @@ def test_users_index_user_found(models, pyramid_request, factories): @users_activate_fixtures -def test_users_activate_gets_user(user_service, pyramid_request): +def test_users_activate(user_service, pyramid_request, notify, ActivationEvent): pyramid_request.params = {"userid": "acct:bob@example.org"} - users_activate(pyramid_request) + result = users_activate(pyramid_request) user_service.fetch.assert_called_once_with("acct:bob@example.org") - - -@users_activate_fixtures -def test_users_activate_user_not_found_error(user_service, pyramid_request): - pyramid_request.params = {"userid": "acct:bob@foo.org"} - user_service.fetch.return_value = None - - with pytest.raises(UserNotFoundError): - users_activate(pyramid_request) - - -@users_activate_fixtures -def test_users_activate_activates_user(user_service, pyramid_request): - pyramid_request.params = {"userid": "acct:bob@example.org"} - - users_activate(pyramid_request) - user_service.fetch.return_value.activate.assert_called_once_with() - - -@users_activate_fixtures -def test_users_activate_flashes_success(pyramid_request): - pyramid_request.params = {"userid": "acct:bob@example.com"} - - users_activate(pyramid_request) - success_flash = pyramid_request.session.peek_flash("success") - - assert success_flash - - -@users_activate_fixtures -def test_users_activate_inits_ActivationEvent( - ActivationEvent, user_service, pyramid_request -): - pyramid_request.params = {"userid": "acct:bob@example.com"} - - users_activate(pyramid_request) + assert pyramid_request.session.peek_flash("success") ActivationEvent.assert_called_once_with( pyramid_request, user_service.fetch.return_value ) - - -@users_activate_fixtures -def test_users_activate_calls_notify(ActivationEvent, notify, pyramid_request): - pyramid_request.params = {"userid": "acct:bob@example.com"} - - users_activate(pyramid_request) - notify.assert_called_with(ActivationEvent.return_value) + assert isinstance(result, httpexceptions.HTTPFound) @users_activate_fixtures -def test_users_activate_redirects(pyramid_request): - pyramid_request.params = {"userid": "acct:bob@example.com"} - - result = users_activate(pyramid_request) +def test_users_activate_user_not_found_error(user_service, pyramid_request): + pyramid_request.params = {"userid": "acct:bob@foo.org"} + user_service.fetch.return_value = None - assert isinstance(result, httpexceptions.HTTPFound) + with pytest.raises(UserNotFoundError): + users_activate(pyramid_request) def test_users_delete_user_not_found_error(user_service, pyramid_request): @@ -204,7 +171,14 @@ def test_users_delete_user_not_found_error(user_service, pyramid_request): users_delete(pyramid_request) -def test_users_delete_deletes_user(user_service, delete_user_service, pyramid_request): +def test_user_not_found_view(pyramid_request): + result = user_not_found(UserNotFoundError("error"), pyramid_request) + + assert pyramid_request.session.peek_flash("error") + assert isinstance(result, httpexceptions.HTTPFound) + + +def test_users_delete_deletes_user(user_service, user_delete_service, pyramid_request): pyramid_request.params = {"userid": "acct:bob@example.com"} user = mock.MagicMock() @@ -212,7 +186,11 @@ def test_users_delete_deletes_user(user_service, delete_user_service, pyramid_re users_delete(pyramid_request) - delete_user_service.delete.assert_called_once_with(user) + user_delete_service.delete_user.assert_called_once_with( + user, + requested_by=pyramid_request.user, + tag=pyramid_request.matched_route.name, + ) @pytest.fixture(autouse=True) @@ -242,8 +220,8 @@ def annotation_stats_service(pyramid_config, pyramid_request): @pytest.fixture -def delete_user_service(pyramid_config, pyramid_request): - service = mock.create_autospec(DeleteUserService, instance=True, spec_set=True) +def user_delete_service(pyramid_config, pyramid_request): + service = mock.create_autospec(UserDeleteService, instance=True, spec_set=True) service.return_value.request = pyramid_request - pyramid_config.register_service(service, name="delete_user") + pyramid_config.register_service(service, name="user_delete") return service diff --git a/tests/h/views/__init__.py b/tests/unit/h/views/api/__init__.py similarity index 100% rename from tests/h/views/__init__.py rename to tests/unit/h/views/api/__init__.py diff --git a/tests/unit/h/views/api/analytics_test.py b/tests/unit/h/views/api/analytics_test.py new file mode 100644 index 00000000000..6ad0f981faa --- /dev/null +++ b/tests/unit/h/views/api/analytics_test.py @@ -0,0 +1,23 @@ +import pytest + +from h.schemas import ValidationError +from h.views.api.analytics import create_event + + +@pytest.mark.usefixtures("analytics_service") +class TestCreateEvent: + def test_analytics_service_is_invoked(self, pyramid_request, analytics_service): + pyramid_request.json_body = {"event": "client.realtime.apply_updates"} + res = create_event(pyramid_request) + + assert analytics_service.create.called + assert res.status_code == 204 + + def test_error_if_invalid_event_payload_is_provided( + self, pyramid_request, analytics_service + ): + pyramid_request.json_body = {} + with pytest.raises(ValidationError): + create_event(pyramid_request) + + assert not analytics_service.create.called diff --git a/tests/h/views/api/annotations_test.py b/tests/unit/h/views/api/annotations_test.py similarity index 62% rename from tests/h/views/api/annotations_test.py rename to tests/unit/h/views/api/annotations_test.py index 4a7e50ab9de..55cdf51f415 100644 --- a/tests/h/views/api/annotations_test.py +++ b/tests/unit/h/views/api/annotations_test.py @@ -3,11 +3,10 @@ import pytest from webob.multidict import MultiDict, NestedMultiDict -from h.schemas import ValidationError from h.search.core import SearchResult -from h.services.annotation_delete import AnnotationDeleteService from h.traversal import AnnotationContext from h.views.api import annotations as views +from h.views.api.exceptions import PayloadError @pytest.mark.usefixtures("annotation_json_service", "search_lib") @@ -85,71 +84,44 @@ def search_run(self, search_lib): return search_lib.Search.return_value.run -@pytest.mark.usefixtures( - "AnnotationEvent", - "create_schema", - "links_service", - "annotation_json_service", - "storage", -) class TestCreate: - def test_it(self, pyramid_request, create_schema, storage, annotation_json_service): + def test_it( + self, + pyramid_request, + CreateAnnotationSchema, + annotation_write_service, + annotation_json_service, + AnnotationEvent, + ): result = views.create(pyramid_request) - create_schema.assert_called_once_with(pyramid_request) - create_schema.return_value.validate.assert_called_once_with( - pyramid_request.json_body + # Check we validate + CreateAnnotationSchema.assert_called_once_with(pyramid_request) + schema = CreateAnnotationSchema.return_value + schema.validate.assert_called_once_with(pyramid_request.json_body) + # Check we create + annotation_write_service.create_annotation.assert_called_once_with( + data=schema.validate.return_value ) - storage.create_annotation.assert_called_once_with( - pyramid_request, create_schema.return_value.validate.return_value - ) - - annotation_json_service.present_for_user.assert_called_once_with( - annotation=storage.create_annotation.return_value, user=pyramid_request.user - ) - - assert result == annotation_json_service.present_for_user.return_value - - def test_it_publishes_annotation_event( - self, AnnotationEvent, pyramid_request, storage - ): - views.create(pyramid_request) - - annotation = storage.create_annotation.return_value + annotation = annotation_write_service.create_annotation.return_value + # Check the event is raised AnnotationEvent.assert_called_once_with( pyramid_request, annotation.id, "create" ) pyramid_request.notify_after_commit.assert_called_once_with( AnnotationEvent.return_value ) + # Check we present + annotation_json_service.present_for_user.assert_called_once_with( + annotation=annotation, user=pyramid_request.user + ) + assert result == annotation_json_service.present_for_user.return_value - def test_it_raises_if_json_parsing_fails(self, pyramid_request): - """It raises PayloadError if parsing of the request body fails.""" - # Make accessing the request.json_body property raise ValueError. - type(pyramid_request).json_body = {} - with mock.patch.object( - type(pyramid_request), "json_body", new_callable=mock.PropertyMock - ) as json_body: - json_body.side_effect = ValueError() - with pytest.raises(views.PayloadError): - views.create(pyramid_request) - - def test_it_raises_if_validate_raises(self, pyramid_request, create_schema): - create_schema.return_value.validate.side_effect = ValidationError("asplode") - - with pytest.raises(ValidationError) as exc: - views.create(pyramid_request) - - assert str(exc.value) == "asplode" - - def test_it_raises_if_create_annotation_raises(self, pyramid_request, storage): - storage.create_annotation.side_effect = ValidationError("asplode") - - with pytest.raises(ValidationError) as exc: + @pytest.mark.usefixtures("with_invalid_json_body") + def test_it_raises_for_invalid_json(self, pyramid_request): + with pytest.raises(PayloadError): views.create(pyramid_request) - assert str(exc.value) == "asplode" - @pytest.fixture def pyramid_request(self, pyramid_request): pyramid_request.json_body = {} @@ -157,7 +129,7 @@ def pyramid_request(self, pyramid_request): return pyramid_request @pytest.fixture - def create_schema(self, patch): + def CreateAnnotationSchema(self, patch): return patch("h.views.api.annotations.CreateAnnotationSchema") @@ -214,84 +186,52 @@ def AnnotationJSONLDPresenter(self, patch): return patch("h.views.api.annotations.AnnotationJSONLDPresenter") -@pytest.mark.usefixtures( - "AnnotationEvent", - "links_service", - "annotation_json_service", - "update_schema", - "storage", -) class TestUpdate: def test_it( self, annotation_context, pyramid_request, - update_schema, - storage, + UpdateAnnotationSchema, + annotation_write_service, annotation_json_service, + AnnotationEvent, ): returned = views.update(annotation_context, pyramid_request) - update_schema.assert_called_once_with( + # Check it validates the annotation + UpdateAnnotationSchema.assert_called_once_with( pyramid_request, annotation_context.annotation.target_uri, annotation_context.annotation.groupid, ) - update_schema.return_value.validate.assert_called_once_with( - pyramid_request.json_body - ) - - storage.update_annotation.assert_called_once_with( - pyramid_request, - annotation_context.annotation.id, - update_schema.return_value.validate.return_value, + schema = UpdateAnnotationSchema.return_value + # Check it updates the annotation + schema.validate.assert_called_once_with(pyramid_request.json_body) + annotation_write_service.update_annotation.assert_called_once_with( + annotation_context.annotation, + schema.validate.return_value, ) - - annotation_json_service.present_for_user.assert_called_once_with( - annotation=storage.update_annotation.return_value, user=pyramid_request.user - ) - - assert returned == annotation_json_service.present_for_user.return_value - - def test_it_publishes_annotation_event( - self, annotation_context, AnnotationEvent, storage, pyramid_request - ): - views.update(annotation_context, pyramid_request) - + # Check it publishes event AnnotationEvent.assert_called_once_with( - pyramid_request, storage.update_annotation.return_value.id, "update" + pyramid_request, + annotation_write_service.update_annotation.return_value.id, + "update", ) pyramid_request.notify_after_commit.assert_called_once_with( AnnotationEvent.return_value ) + # Check it presents the annotation + annotation_json_service.present_for_user.assert_called_once_with( + annotation=annotation_write_service.update_annotation.return_value, + user=pyramid_request.user, + ) + assert returned == annotation_json_service.present_for_user.return_value - def test_it_raises_if_storage_raises( - self, annotation_context, pyramid_request, storage - ): - storage.update_annotation.side_effect = ValidationError("asplode") - - with pytest.raises(ValidationError): - views.update(annotation_context, pyramid_request) - - def test_it_raises_if_validate_raises( - self, annotation_context, pyramid_request, update_schema - ): - update_schema.return_value.validate.side_effect = ValidationError("asplode") - - with pytest.raises(ValidationError): + @pytest.mark.usefixtures("with_invalid_json_body") + def test_it_raises_for_invalid_json(self, pyramid_request, annotation_context): + with pytest.raises(PayloadError): views.update(annotation_context, pyramid_request) - def test_it_raises_if_json_parsing_fails(self, annotation_context, pyramid_request): - """It raises PayloadError if parsing of the request body fails.""" - # Make accessing the request.json_body property raise ValueError. - type(pyramid_request).json_body = {} - with mock.patch.object( - type(pyramid_request), "json_body", new_callable=mock.PropertyMock - ) as json_body: - json_body.side_effect = ValueError() - with pytest.raises(views.PayloadError): - views.update(annotation_context, pyramid_request) - @pytest.fixture def pyramid_request(self, pyramid_request): pyramid_request.json_body = {} @@ -299,7 +239,7 @@ def pyramid_request(self, pyramid_request): return pyramid_request @pytest.fixture - def update_schema(self, patch): + def UpdateAnnotationSchema(self, patch): return patch("h.views.api.annotations.UpdateAnnotationSchema") @@ -340,20 +280,10 @@ def annotation(factories): @pytest.fixture -def pyramid_request(pyramid_request): - pyramid_request.notify_after_commit = mock.Mock(spec_set=[]) - return pyramid_request - - -@pytest.fixture -def storage(patch): - return patch("h.views.api.annotations.storage") - - -@pytest.fixture -def annotation_delete_service(pyramid_config): - service = mock.create_autospec( - AnnotationDeleteService, spec_set=True, instance=True - ) - pyramid_config.register_service(service, name="annotation_delete") - return service +def with_invalid_json_body(pyramid_request): + type(pyramid_request).json_body = None + with mock.patch.object( + type(pyramid_request), "json_body", new_callable=mock.PropertyMock + ) as json_body: + json_body.side_effect = ValueError() + yield json_body diff --git a/tests/h/views/api/auth_test.py b/tests/unit/h/views/api/auth_test.py similarity index 98% rename from tests/h/views/api/auth_test.py rename to tests/unit/h/views/api/auth_test.py index 8ff1ecc4ded..d18af57e1e1 100644 --- a/tests/h/views/api/auth_test.py +++ b/tests/unit/h/views/api/auth_test.py @@ -254,13 +254,7 @@ def pyramid_request(self, pyramid_request): def authenticated_user(self, factories, pyramid_config, user_service): user = factories.User.build() pyramid_config.testing_securitypolicy(user.userid) - - def fake_fetch(userid): - if userid == user.userid: - return user - return None - - user_service.fetch.side_effect = fake_fetch + user_service.fetch.return_value = user return user @@ -392,7 +386,7 @@ def test_it(self, pyramid_request, auth_token_service, oauth_token): "expired": oauth_token.expired, "expires_at": "2001-11-30T17:45:50.000000+00:00", "issued_at": "2000-10-16T15:51:59.000000+00:00", - "userid": oauth_token.userid, + "userid": oauth_token.user.userid, } def test_it_without_auth_client(self, pyramid_request, oauth_token): diff --git a/tests/h/views/admin/__init__.py b/tests/unit/h/views/api/bulk/__init__.py similarity index 100% rename from tests/h/views/admin/__init__.py rename to tests/unit/h/views/api/bulk/__init__.py diff --git a/tests/h/views/api/bulk/_ndjson_test.py b/tests/unit/h/views/api/bulk/_ndjson_test.py similarity index 88% rename from tests/h/views/api/bulk/_ndjson_test.py rename to tests/unit/h/views/api/bulk/_ndjson_test.py index 3fd940e98a8..d820515c58c 100644 --- a/tests/h/views/api/bulk/_ndjson_test.py +++ b/tests/unit/h/views/api/bulk/_ndjson_test.py @@ -31,10 +31,11 @@ def test_it_returns_204_if_no_content_is_to_be_returned(self): assert result.status == "204 No Content" def test_it_captures_initial_errors(self): - def failing_method(): - raise ValueError("Oh no!") + def failing_method(fail=True): + if fail: + raise ValueError("Oh no!") - yield 1 # pylint: disable=unreachable + yield 1 # pragma: nocover with pytest.raises(ValueError): get_ndjson_response(failing_method()) diff --git a/tests/h/views/api/bulk/action_test.py b/tests/unit/h/views/api/bulk/action_test.py similarity index 100% rename from tests/h/views/api/bulk/action_test.py rename to tests/unit/h/views/api/bulk/action_test.py diff --git a/tests/h/views/api/bulk/annotation_test.py b/tests/unit/h/views/api/bulk/annotation_test.py similarity index 70% rename from tests/h/views/api/bulk/annotation_test.py rename to tests/unit/h/views/api/bulk/annotation_test.py index f098f3d371d..3b2ab6e112a 100644 --- a/tests/h/views/api/bulk/annotation_test.py +++ b/tests/unit/h/views/api/bulk/annotation_test.py @@ -1,10 +1,9 @@ -from unittest.mock import sentinel - import pytest from h_matchers import Any from h.schemas import ValidationError -from h.services.bulk_annotation import BadDateFilter, BadFieldSpec, service_factory +from h.services.bulk_api.annotation import BulkAnnotation +from h.services.bulk_api.exceptions import BadDateFilter from h.views.api.bulk.annotation import BulkAnnotationSchema, bulk_annotation @@ -32,21 +31,28 @@ def test_it( get_ndjson_response, ): bulk_annotation_service.annotation_search.return_value = [ - [f"USERNAME_{i}", f"AUTHORITY_PROVIDED_ID_{i}"] for i in range(3) + BulkAnnotation( + username=f"USERNAME_{i}", + authority_provided_id=f"AUTHORITY_PROVIDED_ID_{i}", + metadata={"key": i}, + ) + for i in range(3) ] response = bulk_annotation(pyramid_request) bulk_annotation_service.annotation_search.assert_called_once_with( authority=pyramid_request.identity.auth_client.authority, - fields=valid_request["fields"], - **valid_request["filter"], + username=valid_request["filter"]["username"], + limit=valid_request["filter"]["limit"], + created=valid_request["filter"]["created"], ) return_data = [ { "author": {"username": f"USERNAME_{i}"}, "group": {"authority_provided_id": f"AUTHORITY_PROVIDED_ID_{i}"}, + "metadata": {"key": i}, } for i in range(3) ] @@ -63,11 +69,10 @@ def test_it_raises_with_invalid_request(self, pyramid_request): bulk_annotation(pyramid_request) @pytest.mark.usefixtures("valid_request") - @pytest.mark.parametrize("exception", (BadDateFilter, BadFieldSpec)) def test_it_raises_with_errors_from_the_bulk_service( - self, pyramid_request, bulk_annotation_service, exception + self, pyramid_request, bulk_annotation_service ): - bulk_annotation_service.annotation_search.side_effect = exception + bulk_annotation_service.annotation_search.side_effect = BadDateFilter with pytest.raises(ValidationError): bulk_annotation(pyramid_request) @@ -77,13 +82,12 @@ def valid_request(self, pyramid_request): pyramid_request.json = { "filter": { "limit": 2000, - "audience": {"username": ["3a022b6c146dfd9df4ea8662178eac"]}, - "updated": { + "username": "3a022b6c146dfd9df4ea8662178eac", + "created": { "gt": "2018-11-13T20:20:39+00:00", "lte": "2018-11-13T20:20:39+00:00", }, }, - "fields": ["author.username", "group.authority_provided_id"], } return pyramid_request.json @@ -91,15 +95,3 @@ def valid_request(self, pyramid_request): @pytest.fixture(autouse=True) def get_ndjson_response(self, patch): return patch("h.views.api.bulk.annotation.get_ndjson_response") - - -class TestServiceFactory: - def test_it(self, pyramid_request, BulkAnnotationService): - svc = service_factory(sentinel.context, pyramid_request) - - BulkAnnotationService.assert_called_once_with(db_session=pyramid_request.db) - assert svc == BulkAnnotationService.return_value - - @pytest.fixture - def BulkAnnotationService(self, patch): - return patch("h.services.bulk_annotation.BulkAnnotationService") diff --git a/tests/h/views/api/bulk/conftest.py b/tests/unit/h/views/api/bulk/conftest.py similarity index 100% rename from tests/h/views/api/bulk/conftest.py rename to tests/unit/h/views/api/bulk/conftest.py diff --git a/tests/unit/h/views/api/bulk/group_test.py b/tests/unit/h/views/api/bulk/group_test.py new file mode 100644 index 00000000000..8ca81b50d08 --- /dev/null +++ b/tests/unit/h/views/api/bulk/group_test.py @@ -0,0 +1,87 @@ +import pytest +from h_matchers import Any + +from h.schemas import ValidationError +from h.services.bulk_api.exceptions import BadDateFilter +from h.services.bulk_api.group import BulkGroup +from h.views.api.bulk.group import BulkGroupSchema, bulk_group + + +class TestBulkGroupSchema: + def test_it_is_a_valid_schema(self, schema): + # Extremely basic self checking that this is a valid JSON schema + assert not schema.validator.check_schema(schema.schema) + + def test_examples_are_valid(self, schema): + for example in schema.schema["examples"]: + schema.validate(example) + + @pytest.fixture + def schema(self): + return BulkGroupSchema() + + +@pytest.mark.usefixtures("bulk_group_service", "with_auth_client") +class TestBulkGroup: + def test_it( + self, + pyramid_request, + valid_request, + bulk_group_service, + get_ndjson_response, + ): + bulk_group_service.group_search.return_value = [ + BulkGroup( + authority_provided_id=f"AUTHORITY_PROVIDED_ID_{i}", + ) + for i in range(3) + ] + + response = bulk_group(pyramid_request) + + bulk_group_service.group_search.assert_called_once_with( + groups=valid_request["filter"]["groups"], + annotations_created=valid_request["filter"]["annotations_created"], + ) + + return_data = [ + {"authority_provided_id": f"AUTHORITY_PROVIDED_ID_{i}"} for i in range(3) + ] + get_ndjson_response.assert_called_once_with( + Any.iterable.containing(return_data).only() + ) + + assert response == get_ndjson_response.return_value + + def test_it_raises_with_invalid_request(self, pyramid_request): + pyramid_request.json = {"nope": True} + + with pytest.raises(ValidationError): + bulk_group(pyramid_request) + + @pytest.mark.usefixtures("valid_request") + def test_it_raises_with_errors_from_the_bulk_service( + self, pyramid_request, bulk_group_service + ): + bulk_group_service.group_search.side_effect = BadDateFilter + + with pytest.raises(ValidationError): + bulk_group(pyramid_request) + + @pytest.fixture + def valid_request(self, pyramid_request): + pyramid_request.json = { + "filter": { + "groups": ["3a022b6c146dfd9df4ea8662178eac"], + "annotations_created": { + "gt": "2018-11-13T20:20:39+00:00", + "lte": "2018-11-13T20:20:39+00:00", + }, + }, + } + + return pyramid_request.json + + @pytest.fixture(autouse=True) + def get_ndjson_response(self, patch): + return patch("h.views.api.bulk.group.get_ndjson_response") diff --git a/tests/unit/h/views/api/bulk/stats_test.py b/tests/unit/h/views/api/bulk/stats_test.py new file mode 100644 index 00000000000..75f259e18ef --- /dev/null +++ b/tests/unit/h/views/api/bulk/stats_test.py @@ -0,0 +1,103 @@ +from datetime import datetime + +import pytest + +from h.services.bulk_api.lms_stats import CountsByAssignment, CountsByUser +from h.views.api.bulk.stats import ( + AssignmentStatsSchema, + get_counts_by_assignment, + get_counts_by_user, +) + + +class TestSchema: + def test_it_is_a_valid_schema(self, schema): + # Extremely basic self checking that this is a valid JSON schema + assert not schema.validator.check_schema(schema.schema) + + @pytest.fixture + def schema(self): + return AssignmentStatsSchema() + + +@pytest.mark.usefixtures("bulk_stats_service", "with_auth_client") +class TestBulkGroup: + def test_assignment(self, pyramid_request, assignment_request, bulk_stats_service): + bulk_stats_service.get_counts_by_user.return_value = [ + CountsByUser( + display_name=f"display_name{i}", + userid=i, + annotations=i, + replies=i, + last_activity=datetime.now(), + ) + for i in range(3) + ] + + response = get_counts_by_user(pyramid_request) + + bulk_stats_service.get_counts_by_user.assert_called_once_with( + groups=assignment_request["filter"]["groups"], + assignment_id=assignment_request["filter"]["assignment_id"], + ) + return_data = [ + { + "display_name": row.display_name, + "userid": row.userid, + "annotations": row.annotations, + "replies": row.replies, + "last_activity": row.last_activity.isoformat(), + } + for row in bulk_stats_service.get_counts_by_user.return_value + ] + assert response.json == return_data + assert response.status_code == 200 + assert response.content_type == "application/x-ndjson" + + def test_course(self, pyramid_request, course_request, bulk_stats_service): + bulk_stats_service.get_counts_by_assignment.return_value = [ + CountsByAssignment( + assignment_id=f"assignmnt_id_{i}", + annotations=i, + replies=i, + last_activity=datetime.now(), + ) + for i in range(3) + ] + + response = get_counts_by_assignment(pyramid_request) + + bulk_stats_service.get_counts_by_assignment.assert_called_once_with( + groups=course_request["filter"]["groups"] + ) + return_data = [ + { + "assignment_id": row.assignment_id, + "annotations": row.annotations, + "replies": row.replies, + "last_activity": row.last_activity.isoformat(), + } + for row in bulk_stats_service.get_counts_by_assignment.return_value + ] + assert response.json == return_data + assert response.status_code == 200 + assert response.content_type == "application/x-ndjson" + + @pytest.fixture + def assignment_request(self, pyramid_request): + pyramid_request.json = { + "filter": { + "groups": ["3a022b6c146dfd9df4ea8662178eac"], + "assignment_id": "ASSIGNMENT_ID", + }, + } + + return pyramid_request.json + + @pytest.fixture + def course_request(self, pyramid_request): + pyramid_request.json = { + "filter": {"groups": ["3a022b6c146dfd9df4ea8662178eac"]}, + } + + return pyramid_request.json diff --git a/tests/h/views/api/config_test.py b/tests/unit/h/views/api/config_test.py similarity index 100% rename from tests/h/views/api/config_test.py rename to tests/unit/h/views/api/config_test.py diff --git a/tests/h/views/api/__init__.py b/tests/unit/h/views/api/decorators/__init__.py similarity index 100% rename from tests/h/views/api/__init__.py rename to tests/unit/h/views/api/decorators/__init__.py diff --git a/tests/h/views/api/decorators/client_errors_test.py b/tests/unit/h/views/api/decorators/client_errors_test.py similarity index 100% rename from tests/h/views/api/decorators/client_errors_test.py rename to tests/unit/h/views/api/decorators/client_errors_test.py diff --git a/tests/h/views/api/decorators/response_test.py b/tests/unit/h/views/api/decorators/response_test.py similarity index 100% rename from tests/h/views/api/decorators/response_test.py rename to tests/unit/h/views/api/decorators/response_test.py diff --git a/tests/h/views/api/errors_test.py b/tests/unit/h/views/api/errors_test.py similarity index 100% rename from tests/h/views/api/errors_test.py rename to tests/unit/h/views/api/errors_test.py diff --git a/tests/h/views/api/exceptions_test.py b/tests/unit/h/views/api/exceptions_test.py similarity index 100% rename from tests/h/views/api/exceptions_test.py rename to tests/unit/h/views/api/exceptions_test.py diff --git a/tests/h/views/api/flags_test.py b/tests/unit/h/views/api/flags_test.py similarity index 100% rename from tests/h/views/api/flags_test.py rename to tests/unit/h/views/api/flags_test.py diff --git a/tests/h/views/api/groups_test.py b/tests/unit/h/views/api/groups_test.py similarity index 100% rename from tests/h/views/api/groups_test.py rename to tests/unit/h/views/api/groups_test.py diff --git a/tests/h/views/api/bulk/__init__.py b/tests/unit/h/views/api/helpers/__init__.py similarity index 100% rename from tests/h/views/api/bulk/__init__.py rename to tests/unit/h/views/api/helpers/__init__.py diff --git a/tests/h/views/api/helpers/angular_test.py b/tests/unit/h/views/api/helpers/angular_test.py similarity index 100% rename from tests/h/views/api/helpers/angular_test.py rename to tests/unit/h/views/api/helpers/angular_test.py diff --git a/tests/h/views/api/helpers/cors_test.py b/tests/unit/h/views/api/helpers/cors_test.py similarity index 100% rename from tests/h/views/api/helpers/cors_test.py rename to tests/unit/h/views/api/helpers/cors_test.py diff --git a/tests/h/views/api/helpers/links_test.py b/tests/unit/h/views/api/helpers/links_test.py similarity index 100% rename from tests/h/views/api/helpers/links_test.py rename to tests/unit/h/views/api/helpers/links_test.py diff --git a/tests/h/views/api/helpers/media_types_test.py b/tests/unit/h/views/api/helpers/media_types_test.py similarity index 100% rename from tests/h/views/api/helpers/media_types_test.py rename to tests/unit/h/views/api/helpers/media_types_test.py diff --git a/tests/h/views/api/index_test.py b/tests/unit/h/views/api/index_test.py similarity index 100% rename from tests/h/views/api/index_test.py rename to tests/unit/h/views/api/index_test.py diff --git a/tests/h/views/api/links_test.py b/tests/unit/h/views/api/links_test.py similarity index 100% rename from tests/h/views/api/links_test.py rename to tests/unit/h/views/api/links_test.py diff --git a/tests/unit/h/views/api/moderation_test.py b/tests/unit/h/views/api/moderation_test.py new file mode 100644 index 00000000000..8e3e0a0b482 --- /dev/null +++ b/tests/unit/h/views/api/moderation_test.py @@ -0,0 +1,76 @@ +from unittest import mock + +import pytest +from pyramid.httpexceptions import HTTPNoContent + +from h.traversal import AnnotationContext +from h.views.api import moderation as views + + +class TestCreate: + def test_it( + self, + pyramid_request, + annotation_context, + annotation_write_service, + events, + annotation, + ): + response = views.create(annotation_context, pyramid_request) + + annotation_write_service.hide.assert_called_once_with( + annotation_context.annotation + ) + events.AnnotationEvent.assert_called_once_with( + pyramid_request, annotation.id, "update" + ) + + pyramid_request.notify_after_commit.assert_called_once_with( + events.AnnotationEvent.return_value + ) + assert isinstance(response, HTTPNoContent) + + +class TestDelete: + def test_it( + self, + pyramid_request, + annotation_context, + annotation_write_service, + events, + annotation, + ): + response = views.delete(annotation_context, pyramid_request) + + annotation_write_service.unhide.assert_called_once_with( + annotation_context.annotation + ) + events.AnnotationEvent.assert_called_once_with( + pyramid_request, annotation.id, "update" + ) + + pyramid_request.notify_after_commit.assert_called_once_with( + events.AnnotationEvent.return_value + ) + assert isinstance(response, HTTPNoContent) + + +@pytest.fixture +def annotation(factories): + return factories.Annotation() + + +@pytest.fixture +def annotation_context(annotation): + return AnnotationContext(annotation) + + +@pytest.fixture +def events(patch): + return patch("h.views.api.moderation.events") + + +@pytest.fixture +def pyramid_request(pyramid_request): + pyramid_request.notify_after_commit = mock.Mock() + return pyramid_request diff --git a/tests/h/views/api/profile_test.py b/tests/unit/h/views/api/profile_test.py similarity index 100% rename from tests/h/views/api/profile_test.py rename to tests/unit/h/views/api/profile_test.py diff --git a/tests/h/views/api/users_test.py b/tests/unit/h/views/api/users_test.py similarity index 92% rename from tests/h/views/api/users_test.py rename to tests/unit/h/views/api/users_test.py index 57643990572..b5ad86ec37a 100644 --- a/tests/h/views/api/users_test.py +++ b/tests/unit/h/views/api/users_test.py @@ -3,9 +3,7 @@ import pytest from pyramid.httpexceptions import HTTPConflict -from h.models.auth_client import GrantType from h.schemas import ValidationError -from h.security import Identity from h.services.user_unique import DuplicateUserError from h.traversal import UserContext from h.views.api.exceptions import PayloadError @@ -20,7 +18,9 @@ def test_it(self, pyramid_request, context, TrustedUserJSONPresenter): assert result == TrustedUserJSONPresenter.return_value.asdict.return_value -@pytest.mark.usefixtures("user_signup_service", "user_unique_service") +@pytest.mark.usefixtures( + "user_signup_service", "user_unique_service", "with_auth_client" +) class TestCreate: def test_it( self, @@ -155,23 +155,11 @@ def UpdateUserAPISchema(self, patch): return patch("h.views.api.users.UpdateUserAPISchema") -@pytest.fixture -def auth_client(factories): - return factories.ConfidentialAuthClient(grant_type=GrantType.client_credentials) - - @pytest.fixture def context(factories, auth_client): return UserContext(user=factories.User(authority=auth_client.authority)) -@pytest.fixture(autouse=True) -def with_auth_client(auth_client, pyramid_config): - pyramid_config.testing_securitypolicy( - identity=Identity.from_models(auth_client=auth_client) - ) - - @pytest.fixture(autouse=True) def TrustedUserJSONPresenter(patch): return patch("h.views.api.users.TrustedUserJSONPresenter") diff --git a/tests/h/views/badge_test.py b/tests/unit/h/views/badge_test.py similarity index 100% rename from tests/h/views/badge_test.py rename to tests/unit/h/views/badge_test.py diff --git a/tests/h/views/client_test.py b/tests/unit/h/views/client_test.py similarity index 100% rename from tests/h/views/client_test.py rename to tests/unit/h/views/client_test.py diff --git a/tests/h/views/errors_test.py b/tests/unit/h/views/errors_test.py similarity index 100% rename from tests/h/views/errors_test.py rename to tests/unit/h/views/errors_test.py diff --git a/tests/unit/h/views/feeds_test.py b/tests/unit/h/views/feeds_test.py new file mode 100644 index 00000000000..3c491427e39 --- /dev/null +++ b/tests/unit/h/views/feeds_test.py @@ -0,0 +1,66 @@ +from unittest.mock import sentinel + +import pytest + +from h.views.feeds import stream_atom, stream_rss + + +class TestStreamAtom: + def test_it(self, render_atom, pyramid_request, annotation_read_service): + result = stream_atom(pyramid_request) + + render_atom.assert_called_once_with( + request=pyramid_request, + annotations=annotation_read_service.get_annotations_by_id.return_value, + atom_url="http://example.com/stream_atom", + html_url="http://example.com/stream", + title=sentinel.feed_title, + subtitle=sentinel.feed_subtitle, + ) + + assert result == render_atom.return_value + + @pytest.fixture + def render_atom(self, patch): + return patch("h.views.feeds.render_atom") + + +class TestStreamRSS: + def test_it(self, render_rss, pyramid_request, annotation_read_service): + result = stream_rss(pyramid_request) + + render_rss.assert_called_once_with( + request=pyramid_request, + annotations=annotation_read_service.get_annotations_by_id.return_value, + rss_url="http://example.com/stream_rss", + html_url="http://example.com/stream", + title=sentinel.feed_title, + description=sentinel.feed_description, + ) + + assert result == render_rss.return_value + + @pytest.fixture + def render_rss(self, patch): + return patch("h.views.feeds.render_rss") + + +@pytest.fixture +def pyramid_settings(pyramid_settings): + pyramid_settings["h.feed.title"] = sentinel.feed_title + pyramid_settings["h.feed.subtitle"] = sentinel.feed_subtitle + pyramid_settings["h.feed.description"] = sentinel.feed_description + + return pyramid_settings + + +@pytest.fixture(autouse=True) +def Search(patch): + return patch("h.views.feeds.Search") + + +@pytest.fixture(autouse=True) +def routes(pyramid_config): + pyramid_config.add_route("stream_atom", "/stream_atom") + pyramid_config.add_route("stream_rss", "/stream_rss") + pyramid_config.add_route("stream", "/stream") diff --git a/tests/h/views/groups_test.py b/tests/unit/h/views/groups_test.py similarity index 100% rename from tests/h/views/groups_test.py rename to tests/unit/h/views/groups_test.py diff --git a/tests/h/views/help_test.py b/tests/unit/h/views/help_test.py similarity index 100% rename from tests/h/views/help_test.py rename to tests/unit/h/views/help_test.py diff --git a/tests/h/views/home_test.py b/tests/unit/h/views/home_test.py similarity index 90% rename from tests/h/views/home_test.py rename to tests/unit/h/views/home_test.py index 336a54cec61..7670919ded8 100644 --- a/tests/h/views/home_test.py +++ b/tests/unit/h/views/home_test.py @@ -23,9 +23,9 @@ def test_redirects_to_search_if_no_user(self, pyramid_request): assert exc.value.location == "http://example.com/s" def test_respects_setting(self, pyramid_request): - pyramid_request.registry.settings[ - "h.homepage_redirect_url" - ] = "https://web.hypothes.is" + pyramid_request.registry.settings["h.homepage_redirect_url"] = ( + "https://web.hypothes.is" + ) pyramid_request.user = None with pytest.raises(HTTPFound) as exc: diff --git a/tests/h/views/main_test.py b/tests/unit/h/views/main_test.py similarity index 100% rename from tests/h/views/main_test.py rename to tests/unit/h/views/main_test.py diff --git a/tests/h/views/notification_test.py b/tests/unit/h/views/notification_test.py similarity index 100% rename from tests/h/views/notification_test.py rename to tests/unit/h/views/notification_test.py diff --git a/tests/h/views/organizations_test.py b/tests/unit/h/views/organizations_test.py similarity index 100% rename from tests/h/views/organizations_test.py rename to tests/unit/h/views/organizations_test.py diff --git a/tests/unit/h/views/status_test.py b/tests/unit/h/views/status_test.py new file mode 100644 index 00000000000..220950c763c --- /dev/null +++ b/tests/unit/h/views/status_test.py @@ -0,0 +1,55 @@ +from unittest import mock + +import pytest +from pyramid.httpexceptions import HTTPInternalServerError + +from h.views.status import status + + +@pytest.mark.usefixtures("db") +class TestStatus: + def test_it_returns_okay_on_success(self, pyramid_request, capture_message): + result = status(pyramid_request) + assert result + capture_message.assert_not_called() + + def test_it_fails_when_database_unreachable(self, pyramid_request, db): + db.execute.side_effect = Exception("explode!") + + with pytest.raises(HTTPInternalServerError) as exc: + status(pyramid_request) + + assert "Database connection failed" in str(exc.value) + + def test_it_sends_test_messages_to_sentry(self, pyramid_request, capture_message): + pyramid_request.params["sentry"] = "" + + status(pyramid_request) + + capture_message.assert_called_once_with("Test message from h's status view") + + def test_it_access_the_replica(self, pyramid_request, db_replica): + pyramid_request.params["replica"] = "" + db_replica.execute.side_effect = Exception("explode!") + + with pytest.raises(HTTPInternalServerError) as exc: + status(pyramid_request) + + assert "Replica database connection failed" in str(exc.value) + + @pytest.fixture + def db(self, pyramid_request): + db = mock.Mock() + pyramid_request.db = db + return db + + @pytest.fixture + def db_replica(self, pyramid_request): + db = mock.Mock() + pyramid_request.db_replica = db + return db + + +@pytest.fixture(autouse=True) +def capture_message(patch): + return patch("h.views.status.capture_message") diff --git a/tox.ini b/tox.ini index b2e3c637343..a0eaa502bcc 100644 --- a/tox.ini +++ b/tox.ini @@ -33,76 +33,107 @@ filterwarnings = # See https://docs.python.org/3/library/warnings.html and # https://docs.pytest.org/en/latest/warnings.html ignore:^Use of \.\. or absolute path in a resource path is not allowed and will raise exceptions in a future release\.$:DeprecationWarning:pkg_resources + ignore:^Use of \.\. or absolute path in a resource path is not allowed and will raise exceptions in a future release\.$:DeprecationWarning:pyramid ignore:^the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses$:DeprecationWarning:newrelic.api.import_hook ignore:^The behavior of AcceptLanguageValidHeader\.__iter__ is currently maintained for backward compatibility, but will change in the future.$:DeprecationWarning:webob.acceptparse # pkg_resources is calling its own deprecated function? Anyway I don't think the problem is with us. ignore:^Deprecated call to .pkg_resources\.declare_namespace\('.*'\).\.:DeprecationWarning:pkg_resources + # pkg_resources used in some of our dependencies + ignore:^pkg_resources is deprecated as an API$:DeprecationWarning:pkg_resources + ignore:^pkg_resources is deprecated as an API:DeprecationWarning:pyramid + ignore:^pkg_resources is deprecated as an API:DeprecationWarning:chameleon + ignore:^pkg_resources is deprecated as an API:DeprecationWarning:deform + # Usage of deprecated method of urllib3 within the elasticsearch library + ignore:^HTTPResponse.getheaders\(\) is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.$:DeprecationWarning:elasticsearch + + # Ignore a warning triggered by pytest-cov that's out of our control. + # See https://github.com/pytest-dev/pytest-xdist/issues/840. + ignore:^The --rsyncdir command line argument and rsyncdirs config variable are deprecated\.:DeprecationWarning + + # https://github.com/webpy/webpy/issues/732 + ignore:^'cgi' is deprecated and slated for removal in Python 3.13:DeprecationWarning:webob + + # https://foss.heptapod.net/python-libs/passlib/-/issues/148 + ignore:^'crypt' is deprecated and slated for removal in Python 3.13:DeprecationWarning:passlib [testenv] skip_install = true sitepackages = {env:SITE_PACKAGES:false} passenv = HOME - dev: AUTHORITY dev: BOUNCER_URL dev: CLIENT_OAUTH_ID dev: CLIENT_RPC_ALLOWED_ORIGINS dev: CLIENT_URL - dev: GOOGLE_ANALYTICS_TRACKING_ID + dev: GOOGLE_TAG_MANAGER_CONTAINER_ID dev: H_GUNICORN_CERTFILE dev: H_GUNICORN_KEYFILE dev: SENTRY_DSN dev: SENTRY_DSN_CLIENT dev: SENTRY_DSN_FRONTEND dev: SENTRY_ENVIRONMENT + dev: TOSDR_URL dev: USE_HTTPS dev: NEW_RELIC_LICENSE_KEY dev: NEW_RELIC_APP_NAME dev: NODE_ENV dev: PROXY_AUTH - {tests,functests}: TEST_DATABASE_URL + {tests,functests}: DATABASE_URL {tests,functests}: ELASTICSEARCH_URL {tests,functests}: PYTEST_ADDOPTS functests: BROKER_URL setenv = PYTHONUNBUFFERED = 1 REPORT_FDW_USERS=lms-fdw report-fdw + dev: AUTHORITY = {env:AUTHORITY:localhost} + {tests,functests}: AUTHORITY = {env:AUTHORITY:example.com} + dev: DEV = {env:DEV:true} + dev: HTTP_HOST = {env:HTTP_HOST:localhost:5000} dev: PYTHONPATH = . dev: APP_URL = {env:APP_URL:http://localhost:5000} + dev: ASSET_PATH = {env:ASSET_PATH:/assets} dev: WEBSOCKET_URL = {env:WEBSOCKET_URL:ws://localhost:5001/ws} dev: ENABLE_WEB = {env:ENABLE_WEB:true} dev: ENABLE_WEBSOCKET = {env:ENABLE_WEBSOCKET:true} dev: ENABLE_WORKER = {env:ENABLE_WORKER:true} + dev: ALEMBIC_CONFIG = {env:ALEMBIC_CONFIG:conf/alembic.ini} + dev: JWE_SECRET_LMS = {env:JWE_SECRET_LMS:SUPER_SECRET} + dev: WEB_CONCURRENCY = {env:WEB_CONCURRENCY:2} + tests: COVERAGE_FILE = {env:COVERAGE_FILE:.coverage.{envname}} + dev: DATABASE_URL = {env:DATABASE_URL:postgresql://postgres@localhost/postgres} + dev: REPLICA_DATABASE_URL = {env:DATABASE_URL:postgresql://postgres@localhost/postgres} + tests: DATABASE_URL = {env:DATABASE_URL:postgresql://postgres@localhost/h_tests} + functests: DATABASE_URL = {env:DATABASE_URL:postgresql://postgres@localhost/h_functests} OBJC_DISABLE_INITIALIZE_FORK_SAFETY = YES SQLALCHEMY_SILENCE_UBER_WARNING=1 deps = -r requirements/{env:TOX_ENV_NAME}.txt whitelist_externals = - {dev,tests,functests,dockercompose}: sh + {dev,tests,functests}: sh depends = {coverage,functests}: tests commands = pip-sync-faster requirements/{env:TOX_ENV_NAME}.txt --pip-args '--disable-pip-version-check' - dev: sh bin/hypothesis --dev init dev: {posargs:supervisord -c conf/supervisord-dev.conf} lint: pylint {posargs:h} bin - lint: pylint --rcfile=tests/.pylintrc tests bin + lint: pylint --rcfile=tests/pyproject.toml tests bin lint: pydocstyle h tests bin lint: pycodestyle h tests bin format: black h tests bin format: isort --quiet --atomic h tests bin checkformatting: black --check h tests bin checkformatting: isort --quiet --check-only h tests bin - {tests,functests}: sh bin/create-testdb - tests: coverage run -m pytest {posargs:tests/h/} - functests: pytest {posargs:tests/functional/} + tests: sh bin/create-testdb h_tests + functests: sh bin/create-testdb h_functests + {tests,functests}: python3 -m h.scripts.init_db --delete --create + tests: python -m pytest --cov --cov-report= --cov-fail-under=0 --numprocesses logical --dist loadgroup {posargs:tests/unit/} + functests: python -m pytest {posargs:tests/functional/} docs: sphinx-autobuild -qT --open-browser -b dirhtml -d {envdir}/doctrees docs {envdir}/html checkdocs: sphinx-build -qTWn -b dirhtml -d {envdir}/doctrees docs {envdir}/html - coverage: -coverage combine + coverage: coverage combine coverage: coverage report - dockercompose: docker-compose {posargs} [testenv:dev] # By default when you Ctrl-c the `make dev` command tox is too aggressive about diff --git a/yarn.lock b/yarn.lock index f6ccbee3e02..d88d65a4fa6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,6202 +1,9465 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" - integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== - dependencies: - "@jridgewell/gen-mapping" "^0.1.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== - dependencies: - "@babel/highlight" "^7.18.6" - -"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.1", "@babel/compat-data@^7.20.5": - version "7.20.14" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.14.tgz#4106fc8b755f3e3ee0a0a7c27dde5de1d2b2baf8" - integrity sha512-0YpKHD6ImkWMEINCyDAD0HLLUH/lPCefG8ld9it8DJB2wnApraKuhgYTvTY1z7UFIfBTGy5LwncZ+5HWWGbhFw== - -"@babel/core@^7.0.0", "@babel/core@^7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.0.tgz#1341aefdcc14ccc7553fcc688dd8986a2daffc13" - integrity sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.21.0" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-module-transforms" "^7.21.0" - "@babel/helpers" "^7.21.0" - "@babel/parser" "^7.21.0" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.21.0" - "@babel/types" "^7.21.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.2" - semver "^6.3.0" - -"@babel/generator@^7.21.0", "@babel/generator@^7.21.1": - version "7.21.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd" - integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA== - dependencies: - "@babel/types" "^7.21.0" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/helper-annotate-as-pure@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" - integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.6.tgz#f14d640ed1ee9246fb33b8255f08353acfe70e6a" - integrity sha512-KT10c1oWEpmrIRYnthbzHgoOf6B+Xd6a5yhdbNtdhtG7aO1or5HViuf1TQR36xY/QprXA5nvxO6nAjhJ4y38jw== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.18.6" - "@babel/types" "^7.18.6" - -"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0", "@babel/helper-compilation-targets@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz#a6cd33e93629f5eb473b021aac05df62c4cd09bb" - integrity sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ== - 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" - -"@babel/helper-create-class-features-plugin@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.6.tgz#6f15f8459f3b523b39e00a99982e2c040871ed72" - integrity sha512-YfDzdnoxHGV8CzqHGyCbFvXg5QESPFkXlHtvdCkesLjjVMT2Adxe4FGUR5ChIb3DxSaXO12iIOCWoXdsUVwnqw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.6" - "@babel/helper-function-name" "^7.18.6" - "@babel/helper-member-expression-to-functions" "^7.18.6" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-replace-supers" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - -"@babel/helper-create-regexp-features-plugin@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz#3e35f4e04acbbf25f1b3534a657610a000543d3c" - integrity sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - regexpu-core "^5.1.0" - -"@babel/helper-create-regexp-features-plugin@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" - integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - regexpu-core "^5.1.0" - -"@babel/helper-define-polyfill-provider@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" - integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== - 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" - -"@babel/helper-environment-visitor@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz#b7eee2b5b9d70602e59d1a6cad7dd24de7ca6cd7" - integrity sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q== - -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== - -"@babel/helper-explode-assignable-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" - integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-function-name@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz#8334fecb0afba66e6d87a7e8c6bb7fed79926b83" - integrity sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw== - dependencies: - "@babel/template" "^7.18.6" - "@babel/types" "^7.18.6" - -"@babel/helper-function-name@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz#940e6084a55dee867d33b4e487da2676365e86b0" - integrity sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A== - dependencies: - "@babel/template" "^7.18.6" - "@babel/types" "^7.18.9" - -"@babel/helper-function-name@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" - integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== - dependencies: - "@babel/template" "^7.18.10" - "@babel/types" "^7.19.0" - -"@babel/helper-function-name@^7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4" - integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg== - dependencies: - "@babel/template" "^7.20.7" - "@babel/types" "^7.21.0" - -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-member-expression-to-functions@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.6.tgz#44802d7d602c285e1692db0bad9396d007be2afc" - integrity sha512-CeHxqwwipekotzPDUuJOfIMtcIHBuc7WAzLmTYWctVigqS5RktNMQ5bEwQSuGewzYnCtTWa3BARXeiLxDTv+Ng== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-member-expression-to-functions@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.20.7.tgz#a6f26e919582275a93c3aa6594756d71b0bb7f05" - integrity sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw== - dependencies: - "@babel/types" "^7.20.7" - -"@babel/helper-module-imports@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.0": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz#160caafa4978ac8c00ac66636cb0fa37b024e2d2" - integrity sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ== - 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.21.2" - "@babel/types" "^7.21.2" - -"@babel/helper-optimise-call-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" - integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" - integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== - -"@babel/helper-remap-async-to-generator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.6.tgz#fa1f81acd19daee9d73de297c0308783cd3cfc23" - integrity sha512-z5wbmV55TveUPZlCLZvxWHtrjuJd+8inFhk7DG0WW87/oJuGDcjDiu7HIvGcpf5464L6xKCg3vNkmlVVz9hwyQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.6" - "@babel/helper-wrap-function" "^7.18.6" - "@babel/types" "^7.18.6" - -"@babel/helper-remap-async-to-generator@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" - integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== - 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" - -"@babel/helper-replace-supers@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.18.6.tgz#efedf51cfccea7b7b8c0f00002ab317e7abfe420" - integrity sha512-fTf7zoXnUGl9gF25fXCWE26t7Tvtyn6H4hkLSYhATwJvw2uYxd3aoXplMSe0g9XbwK7bmxNes7+FGO0rB/xC0g== - dependencies: - "@babel/helper-environment-visitor" "^7.18.6" - "@babel/helper-member-expression-to-functions" "^7.18.6" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/traverse" "^7.18.6" - "@babel/types" "^7.18.6" - -"@babel/helper-replace-supers@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz#243ecd2724d2071532b2c8ad2f0f9f083bcae331" - integrity sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A== - 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" - -"@babel/helper-simple-access@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" - integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== - dependencies: - "@babel/types" "^7.20.2" - -"@babel/helper-skip-transparent-expression-wrappers@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz#778d87b3a758d90b471e7b9918f34a9a02eb5818" - integrity sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw== - dependencies: - "@babel/types" "^7.18.9" - -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-string-parser@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" - integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== - -"@babel/helper-validator-identifier@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" - integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== - -"@babel/helper-validator-identifier@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== - -"@babel/helper-validator-option@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" - integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== - -"@babel/helper-wrap-function@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.18.6.tgz#ec44ea4ad9d8988b90c3e465ba2382f4de81a073" - integrity sha512-I5/LZfozwMNbwr/b1vhhuYD+J/mU+gfGAj5td7l5Rv9WYmH6i3Om69WGKNmlIpsVW/mF6O5bvTKbvDQZVgjqOw== - dependencies: - "@babel/helper-function-name" "^7.18.6" - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.6" - "@babel/types" "^7.18.6" - -"@babel/helper-wrap-function@^7.18.9": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.18.10.tgz#a7fcd3ab9b1be4c9b52cf7d7fdc1e88c2ce93396" - integrity sha512-95NLBP59VWdfK2lyLKe6eTMq9xg+yWKzxzxbJ1wcYNi1Auz200+83fMDADjRxBvc2QQor5zja2yTQzXGhk2GtQ== - dependencies: - "@babel/helper-function-name" "^7.18.9" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.18.10" - "@babel/types" "^7.18.10" - -"@babel/helpers@^7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.21.0.tgz#9dd184fb5599862037917cdc9eecb84577dc4e7e" - integrity sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA== - dependencies: - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.21.0" - "@babel/types" "^7.21.0" - -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.20.7", "@babel/parser@^7.21.0", "@babel/parser@^7.21.2": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3" - integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ== - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": - version "7.18.6" - 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.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" - integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50" - integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" - "@babel/plugin-proposal-optional-chaining" "^7.18.9" - -"@babel/plugin-proposal-async-generator-functions@^7.20.1": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz#bfb7276d2d573cb67ba379984a2334e262ba5326" - integrity sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA== - 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" - -"@babel/plugin-proposal-class-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" - integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-proposal-class-static-block@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" - integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - -"@babel/plugin-proposal-dynamic-import@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" - integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - -"@babel/plugin-proposal-export-namespace-from@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" - integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-proposal-json-strings@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" - integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-json-strings" "^7.8.3" - -"@babel/plugin-proposal-logical-assignment-operators@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23" - integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" - integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - -"@babel/plugin-proposal-numeric-separator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" - integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-object-rest-spread@^7.20.2": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" - integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== - 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" - -"@babel/plugin-proposal-optional-catch-binding@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" - integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-proposal-optional-chaining@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993" - integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-proposal-private-methods@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" - integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-proposal-private-property-in-object@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503" - integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - -"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" - integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@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-class-properties@^7.12.13": - 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-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-import-assertions@^7.20.0": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz#bb50e0d4bea0957235390641209394e87bdb9cc4" - integrity sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ== - dependencies: - "@babel/helper-plugin-utils" "^7.19.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-logical-assignment-operators@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.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-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.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.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.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-transform-arrow-functions@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" - integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-async-to-generator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" - integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== - dependencies: - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-remap-async-to-generator" "^7.18.6" - -"@babel/plugin-transform-block-scoped-functions@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" - integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-block-scoping@^7.20.2": - version "7.20.14" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.14.tgz#2f5025f01713ba739daf737997308e0d29d1dd75" - integrity sha512-sMPepQtsOs5fM1bwNvuJJHvaCfOEQfmc01FGw0ELlTpTJj5Ql/zuNRRldYhAPys4ghXdBIQJbRVYi44/7QflQQ== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - -"@babel/plugin-transform-classes@^7.20.2": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.7.tgz#f438216f094f6bb31dc266ebfab8ff05aecad073" - integrity sha512-LWYbsiXTPKl+oBlXUGlwNlJZetXD5Am+CyBdqhPsDVjM9Jc8jwBJFrKhHf900Kfk2eZG1y9MAG3UNajol7A4VQ== - 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" - -"@babel/plugin-transform-computed-properties@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" - integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - -"@babel/plugin-transform-destructuring@^7.20.2": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz#8bda578f71620c7de7c93af590154ba331415454" - integrity sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - -"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" - integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-duplicate-keys@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" - integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - -"@babel/plugin-transform-exponentiation-operator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" - integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-for-of@^7.18.8": - version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" - integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-function-name@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" - integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== - dependencies: - "@babel/helper-compilation-targets" "^7.18.9" - "@babel/helper-function-name" "^7.18.9" - "@babel/helper-plugin-utils" "^7.18.9" - -"@babel/plugin-transform-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" - integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - -"@babel/plugin-transform-member-expression-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" - integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-modules-amd@^7.19.6": - version "7.20.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz#3daccca8e4cc309f03c3a0c4b41dc4b26f55214a" - integrity sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g== - dependencies: - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helper-plugin-utils" "^7.20.2" - -"@babel/plugin-transform-modules-commonjs@^7.19.6": - version "7.20.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.20.11.tgz#8cb23010869bf7669fd4b3098598b6b2be6dc607" - integrity sha512-S8e1f7WQ7cimJQ51JkAaDrEtohVEitXjgCGAS2N8S31Y42E+kWwfSz83LYz57QdBm7q9diARVqanIaH2oVgQnw== - dependencies: - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-simple-access" "^7.20.2" - -"@babel/plugin-transform-modules-systemjs@^7.19.6": - version "7.20.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz#467ec6bba6b6a50634eea61c9c232654d8a4696e" - integrity sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw== - 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" - -"@babel/plugin-transform-modules-umd@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" - integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== - dependencies: - "@babel/helper-module-transforms" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888" - integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.19.0" - "@babel/helper-plugin-utils" "^7.19.0" - -"@babel/plugin-transform-new-target@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" - integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-object-super@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" - integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-replace-supers" "^7.18.6" - -"@babel/plugin-transform-parameters@^7.20.1", "@babel/plugin-transform-parameters@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz#0ee349e9d1bc96e78e3b37a7af423a4078a7083f" - integrity sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - -"@babel/plugin-transform-property-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" - integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-regenerator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73" - integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - regenerator-transform "^0.15.0" - -"@babel/plugin-transform-reserved-words@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" - integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-shorthand-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" - integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-spread@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" - integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== - dependencies: - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" - -"@babel/plugin-transform-sticky-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" - integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-template-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" - integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - -"@babel/plugin-transform-typeof-symbol@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" - integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - -"@babel/plugin-transform-unicode-escapes@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" - integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - -"@babel/plugin-transform-unicode-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" - integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/preset-env@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.20.2.tgz#9b1642aa47bb9f43a86f9630011780dab7f86506" - integrity sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg== - 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" - -"@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/runtime@^7.0.0", "@babel/runtime@^7.8.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" - integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.18.10", "@babel/template@^7.18.6", "@babel/template@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" - integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - -"@babel/traverse@^7.18.10", "@babel/traverse@^7.18.6", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.2.tgz#ac7e1f27658750892e815e60ae90f382a46d8e75" - integrity sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.21.1" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.21.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.21.2" - "@babel/types" "^7.21.2" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.4.4": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.2.tgz#92246f6e00f91755893c2876ad653db70c8310d1" - integrity sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw== - dependencies: - "@babel/helper-string-parser" "^7.19.4" - "@babel/helper-validator-identifier" "^7.19.1" - to-fast-properties "^2.0.0" - -"@colors/colors@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" - integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== - -"@eslint/eslintrc@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.0.tgz#943309d8697c52fc82c076e90c1c74fbbe69dbff" - integrity sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.4.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" - -"@eslint/js@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.35.0.tgz#b7569632b0b788a0ca0e438235154e45d42813a7" - integrity sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw== - -"@humanwhocodes/config-array@^0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" - integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== - dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@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== - -"@hypothesis/frontend-build@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@hypothesis/frontend-build/-/frontend-build-1.2.0.tgz#2938212d0ac655484692e9fbcac26f301d8b3638" - integrity sha512-iPNS6bkXVujNEKUUSaFLgoQU38qfH5zA3ox9gUP2rVTWuU8Tt2VsZDp+MiPcqFSqV3WVkBWM/aydoCKUgetA7A== - dependencies: - commander "^8.2.0" - fancy-log "^1.3.3" - glob "^7.2.0" - -"@jridgewell/gen-mapping@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" - integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/source-map@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" - integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/trace-mapping@^0.3.17": - version "0.3.17" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" - integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== - dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" - -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.14" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" - integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@rollup/plugin-babel@^6.0.3": - version "6.0.3" - resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-6.0.3.tgz#07ccde15de278c581673034ad6accdb4a153dfeb" - integrity sha512-fKImZKppa1A/gX73eg4JGo+8kQr/q1HBQaCGKECZ0v4YBBv3lFqi14+7xyApECzvkLTHCifx+7ntcrvtBIRcpg== - dependencies: - "@babel/helper-module-imports" "^7.18.6" - "@rollup/pluginutils" "^5.0.1" - -"@rollup/plugin-commonjs@^24.0.1": - version "24.0.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-24.0.1.tgz#d54ba26a3e3c495dc332bd27a81f7e9e2df46f90" - integrity sha512-15LsiWRZk4eOGqvrJyu3z3DaBu5BhXIMeWnijSRvd8irrrg9SHpQ1pH+BUK4H6Z9wL9yOxZJMTLU+Au86XHxow== - dependencies: - "@rollup/pluginutils" "^5.0.1" - commondir "^1.0.1" - estree-walker "^2.0.2" - glob "^8.0.3" - is-reference "1.2.1" - magic-string "^0.27.0" - -"@rollup/plugin-node-resolve@^15.0.1": - version "15.0.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.0.1.tgz#72be449b8e06f6367168d5b3cd5e2802e0248971" - integrity sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg== - dependencies: - "@rollup/pluginutils" "^5.0.1" - "@types/resolve" "1.20.2" - deepmerge "^4.2.2" - is-builtin-module "^3.2.0" - is-module "^1.0.0" - resolve "^1.22.1" - -"@rollup/pluginutils@^5.0.1": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.2.tgz#012b8f53c71e4f6f9cb317e311df1404f56e7a33" - integrity sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA== - dependencies: - "@types/estree" "^1.0.0" - estree-walker "^2.0.2" - picomatch "^2.3.1" - -"@sinonjs/commons@^1.7.0": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" - integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/commons@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-2.0.0.tgz#fd4ca5b063554307e8327b4564bd56d3b73924a3" - integrity sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz#d10549ed1f423d80639c528b6c7f5a1017747d0c" - integrity sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw== - dependencies: - "@sinonjs/commons" "^2.0.0" - -"@sinonjs/fake-timers@^7.0.4": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz#2524eae70c4910edccf99b2f4e6efc5894aff7b5" - integrity sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg== - dependencies: - "@sinonjs/commons" "^1.7.0" - -"@sinonjs/samsam@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-7.0.1.tgz#5b5fa31c554636f78308439d220986b9523fc51f" - integrity sha512-zsAk2Jkiq89mhZovB2LLOdTCxJF4hqqTToGP0ASWlhp4I1hqOjcfmZGafXntCN7MDC6yySH0mFHrYtHceOeLmw== - dependencies: - "@sinonjs/commons" "^2.0.0" - lodash.get "^4.4.2" - type-detect "^4.0.8" - -"@sinonjs/text-encoding@^0.7.1": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" - integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== - -"@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== - -"@types/component-emitter@^1.2.10": - version "1.2.11" - resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506" - integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ== - -"@types/cookie@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" - integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== - -"@types/cors@^2.8.12": - version "2.8.12" - resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" - integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== - -"@types/estree@*": - version "0.0.50" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" - integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== - -"@types/estree@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" - integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== - -"@types/node@*", "@types/node@>=10.0.0": - version "18.11.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.9.tgz#02d013de7058cea16d36168ef2fc653464cfbad4" - integrity sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg== - -"@types/resolve@1.20.2": - version "1.20.2" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" - integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== - -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: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.5.0: - version "8.7.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" - integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== - -acorn@^8.8.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" - integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== - -ajv@^6.10.0, ajv@^6.12.4: - 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" - -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-colors@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" - integrity sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA== - dependencies: - ansi-wrap "^0.1.0" - -ansi-gray@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" - integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= - dependencies: - ansi-wrap "0.1.0" - -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-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, 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-wrap@0.1.0, ansi-wrap@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -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" - -append-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" - integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE= - dependencies: - buffer-equal "^1.0.0" - -archy@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" - integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= - -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== - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-filter@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/arr-filter/-/arr-filter-1.1.2.tgz#43fdddd091e8ef11aa4c45d9cdc18e2dff1711ee" - integrity sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4= - dependencies: - make-iterator "^1.0.0" - -arr-flatten@^1.0.1, arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-map@^2.0.0, arr-map@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/arr-map/-/arr-map-2.0.2.tgz#3a77345ffc1cf35e2a91825601f9e58f2e24cac4" - integrity sha1-Onc0X/wc814qkYJWAfnljy4kysQ= - dependencies: - make-iterator "^1.0.0" - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-each@^1.0.0, array-each@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" - integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8= - -array-includes@^3.1.3, array-includes@^3.1.6: - version "3.1.6" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" - integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== - 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" - -array-initial@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795" - integrity sha1-L6dLJnOTccOUe9enrcc74zSz15U= - dependencies: - array-slice "^1.0.0" - is-number "^4.0.0" - -array-last@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/array-last/-/array-last-1.3.0.tgz#7aa77073fec565ddab2493f5f88185f404a9d336" - integrity sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg== - dependencies: - is-number "^4.0.0" - -array-slice@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4" - integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w== - -array-sort@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-1.0.0.tgz#e4c05356453f56f53512a7d1d6123f2c54c0a88a" - integrity sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg== - dependencies: - default-compare "^1.0.0" - get-value "^2.0.6" - kind-of "^5.0.2" - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - -array.prototype.flatmap@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" - integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - es-shim-unscopables "^1.0.0" - -array.prototype.tosorted@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz#ccf44738aa2b5ac56578ffda97c03fd3e23dd532" - integrity sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ== - 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" - -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -async-done@^1.2.0, async-done@^1.2.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.3.2.tgz#5e15aa729962a4b07414f528a88cdf18e0b290a2" - integrity sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.2" - process-nextick-args "^2.0.0" - stream-exhaust "^1.0.1" - -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -async-settle@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b" - integrity sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs= - dependencies: - async-done "^1.2.2" - -atob@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -autoprefixer@^10.4.13: - version "10.4.13" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8" - integrity sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg== - 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" - -babel-plugin-mockable-imports@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/babel-plugin-mockable-imports/-/babel-plugin-mockable-imports-2.0.1.tgz#4f51c80cfb43f4900dcfab70f8f3ed6caaaf7c8a" - integrity sha512-/6rA20YQAwjRFtcAJ+677pON1NL1oynH0+jm1MRWHKVOq55nTUP7TX7k6UlrJFYBl0pdKakOC3TFLXXHvF/GfA== - -babel-plugin-polyfill-corejs2@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" - integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== - dependencies: - "@babel/compat-data" "^7.17.7" - "@babel/helper-define-polyfill-provider" "^0.3.3" - semver "^6.1.1" - -babel-plugin-polyfill-corejs3@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" - integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" - core-js-compat "^3.25.1" - -babel-plugin-polyfill-regenerator@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" - integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" - -bach@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880" - integrity sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA= - dependencies: - arr-filter "^1.1.1" - arr-flatten "^1.0.1" - arr-map "^2.0.0" - array-each "^1.0.0" - array-initial "^1.0.0" - array-last "^1.1.1" - async-done "^1.2.2" - async-settle "^1.0.0" - now-and-later "^2.0.0" - -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== - -base64id@2.0.0, base64id@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" - integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - -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" - -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= - -bootstrap@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.6.2.tgz#8e0cd61611728a5bf65a3a2b8d6ff6c77d5d7479" - integrity sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ== - -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@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -braces@^3.0.2, 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" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -browserslist@^4.21.3, browserslist@^4.21.4: - version "4.21.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" - integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== - dependencies: - caniuse-lite "^1.0.30001400" - electron-to-chromium "^1.4.251" - node-releases "^2.0.6" - update-browserslist-db "^1.0.9" - -buffer-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" - integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -builtin-modules@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" - integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== - -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== - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -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== - -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= - -camelcase@^6.0.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" - integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== - -caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426: - version "1.0.30001429" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001429.tgz#70cdae959096756a85713b36dd9cb82e62325639" - integrity sha512-511ThLu1hF+5RRRt0zYCf2U2yRr9GPF6m5y90SBCWsvSoYoW7yAGlv/elyPaNfvGCkp6kj/KFZWU0BMA69Prsg== - -chai@^4.3.7: - version "4.3.7" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" - integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^4.1.2" - get-func-name "^2.0.0" - loupe "^2.3.1" - pathval "^1.1.1" - type-detect "^4.0.5" - -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0, chalk@^4.1.0: - 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" - -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= - -chokidar@3.5.3, "chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.1: - 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" - -chokidar@^2.0.0: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - -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-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= - -clone@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= - -cloneable-readable@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.3.tgz#120a00cb053bfb63a222e709f9683ea2e11d8cec" - integrity sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ== - dependencies: - inherits "^2.0.1" - process-nextick-args "^2.0.0" - readable-stream "^2.3.5" - -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= - -collection-map@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-map/-/collection-map-1.0.0.tgz#aea0f06f8d26c780c2b75494385544b2255af18c" - integrity sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw= - dependencies: - arr-map "^2.0.2" - for-own "^1.0.0" - make-iterator "^1.0.0" - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0: - version "1.9.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: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-support@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - -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@^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.2.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -component-emitter@^1.2.1, component-emitter@~1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -concat-stream@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -connect@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" - integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== - dependencies: - debug "2.6.9" - finalhandler "1.1.2" - parseurl "~1.3.3" - utils-merge "1.0.1" - -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== - -convert-source-map@^1.5.0, convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" - -cookie@~0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -copy-props@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.5.tgz#03cf9ae328d4ebb36f8f1d804448a6af9ee3f2d2" - integrity sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw== - dependencies: - each-props "^1.3.2" - is-plain-object "^5.0.0" - -core-js-compat@^3.25.1: - version "3.25.4" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.25.4.tgz#730a255d4a47a937513abf1672bf278dc24dcebf" - integrity sha512-gCEcIEEqCR6230WroNunK/653CWKhqyCKJ9b+uESqOt/WFJA8B4lTnnQFdpYY5vmBcwJAA90Bo5vXs+CVsf6iA== - dependencies: - browserslist "^4.21.4" - -core-js@^3.0.0: - version "3.19.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.19.0.tgz#9e40098a9bc326c7e81b486abbd5e12b9d275176" - integrity sha512-L1TpFRWXZ76vH1yLM+z6KssLZrP8Z6GxxW4auoCj+XiViOzNPJCAuTIkn03BGdFe6Z5clX5t64wRIRypsZQrUg== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cors@~2.8.5: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - -cross-spawn@^7.0.2: - 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" - -css-select@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.1.3.tgz#a70440f70317f2669118ad74ff105e65849c7067" - integrity sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA== - dependencies: - boolbase "^1.0.0" - css-what "^5.0.0" - domhandler "^4.2.0" - domutils "^2.6.0" - nth-check "^2.0.0" - -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-what@^5.0.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== - -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" - -custom-event@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" - integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU= - -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - -date-format@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.3.tgz#f63de5dc08dc02efd8ef32bf2a6918e486f35873" - integrity sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ== - -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: - 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.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@~4.3.1, debug@~4.3.2: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -decamelize@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decamelize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" - integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== - -decode-uri-component@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" - integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== - -deep-eql@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.2.tgz#270ceb902f87724077e6f6449aed81463f42fc1c" - integrity sha512-gT18+YW4CcW/DBNTwAmqTtkJh7f9qqScu2qFVlx7kCoeY9tlBu9cUcr7+I+Z/noG8INehS3xQgLpTtd/QUTn4w== - dependencies: - type-detect "^4.0.0" - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -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-compare@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" - integrity sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ== - dependencies: - kind-of "^5.0.2" - -default-resolution@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684" - integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ= - -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" - -define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -detect-file@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" - integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= - -di@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" - integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw= - -diff@5.0.0, diff@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== - -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-serialize@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" - integrity sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs= - dependencies: - custom-event "~1.0.0" - ent "~2.2.0" - extend "^3.0.0" - void-elements "^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" - -domelementtype@^2.0.1, domelementtype@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== - -domhandler@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.2.tgz#e825d721d19a86b8c201a35264e226c678ee755f" - integrity sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w== - dependencies: - domelementtype "^2.2.0" - -domutils@^2.6.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" - -duplexify@^3.6.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -duplexify@^4.1.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0" - integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw== - dependencies: - end-of-stream "^1.4.1" - inherits "^2.0.3" - readable-stream "^3.1.1" - stream-shift "^1.0.0" - -each-props@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.2.tgz#ea45a414d16dd5cfa419b1a81720d5ca06892333" - integrity sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA== - dependencies: - is-plain-object "^2.0.1" - object.defaults "^1.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= - -electron-to-chromium@^1.4.251: - version "1.4.270" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.270.tgz#2c6ea409b45cdb5c3e0cb2c08cf6c0ba7e0f2c26" - integrity sha512-KNhIzgLiJmDDC444dj9vEOpZEgsV96ult9Iff98Vanumn+ShJHd5se8aX6KeVxdc0YQeqdrezBZv89rleDbvSg== - -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== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: - 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" - -engine.io-parser@~5.0.3: - version "5.0.4" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.4.tgz#0b13f704fa9271b3ec4f33112410d8f3f41d0fc0" - integrity sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg== - -engine.io@~6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.2.1.tgz#e3f7826ebc4140db9bbaa9021ad6b1efb175878f" - integrity sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA== - dependencies: - "@types/cookie" "^0.4.1" - "@types/cors" "^2.8.12" - "@types/node" ">=10.0.0" - accepts "~1.3.4" - base64id "2.0.0" - cookie "~0.4.1" - cors "~2.8.5" - debug "~4.3.1" - engine.io-parser "~5.0.3" - ws "~8.2.3" - -ent@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" - integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= - -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== - -error-ex@^1.2.0: - 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" - -es-abstract@^1.19.0: - 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.19.5: - version "1.20.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" - integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-symbols "^1.0.3" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-weakref "^1.0.2" - object-inspect "^1.12.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - regexp.prototype.flags "^1.4.3" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" - unbox-primitive "^1.0.2" - -es-abstract@^1.20.4: - version "1.20.4" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.4.tgz#1d103f9f8d78d4cf0713edcd6d0ed1a46eed5861" - integrity sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA== - dependencies: - call-bind "^1.0.2" - 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" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-symbols "^1.0.3" - internal-slot "^1.0.3" - 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-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.5" - string.prototype.trimstart "^1.0.5" - unbox-primitive "^1.0.2" - -es-shim-unscopables@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" - integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== - dependencies: - has "^1.0.3" - -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" - -es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50: - version "0.10.53" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" - integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.3" - next-tick "~1.0.0" - -es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-symbol@^3.1.1, es6-symbol@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== - dependencies: - d "^1.0.1" - ext "^1.1.2" - -es6-weak-map@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" - integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== - dependencies: - d "1" - es5-ext "^0.10.46" - es6-iterator "^2.0.3" - es6-symbol "^3.1.1" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-html@^1.0.3, 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@4.0.0, 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== - -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= - -eslint-config-hypothesis@2.6: - version "2.6.0" - resolved "https://registry.yarnpkg.com/eslint-config-hypothesis/-/eslint-config-hypothesis-2.6.0.tgz#627a3f0478c6d732ea776d813be6a70ac2f2d9dd" - integrity sha512-CMQSym4Oz2RVKwAAD+cftYPoSRzj3CUBfkytf0UG41wBsKh7eHGCAer8AcibYP8G2JelKoB6K6CzOYviCiBi/A== - -eslint-plugin-mocha@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-10.1.0.tgz#69325414f875be87fb2cb00b2ef33168d4eb7c8d" - integrity sha512-xLqqWUF17llsogVOC+8C6/jvQ+4IoOREbN7ZCHuOHuD6cT5cDD4h7f2LgsZuzMAiwswWE21tO7ExaknHVDrSkw== - dependencies: - eslint-utils "^3.0.0" - rambda "^7.1.0" - -eslint-plugin-react-hooks@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" - integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== - -eslint-plugin-react@^7.32.2: - version "7.32.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz#e71f21c7c265ebce01bcbc9d0955170c55571f10" - integrity sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg== - 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" - -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@^2.0.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.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@^8.35.0: - version "8.35.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.35.0.tgz#fffad7c7e326bae606f0e8f436a6158566d42323" - integrity sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw== - dependencies: - "@eslint/eslintrc" "^2.0.0" - "@eslint/js" "8.35.0" - "@humanwhocodes/config-array" "^0.11.8" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - 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.4.0" - 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" - grapheme-splitter "^1.0.4" - ignore "^5.2.0" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-sdsl "^4.1.4" - 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.1" - regexpp "^3.2.0" - strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" - text-table "^0.2.0" - -espree@^9.4.0: - version "9.4.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.0.tgz#cd4bc3d6e9336c433265fc0aa016fc1aaf182f8a" - integrity sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw== - dependencies: - acorn "^8.8.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.3.0" - -esquery@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.2.tgz#c6d3fee05dd665808e2ad870631f221f5617b1d1" - integrity sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng== - 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@^5.1.0, estraverse@^5.2.0, 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@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== - -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== - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -expand-tilde@^2.0.0, expand-tilde@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= - dependencies: - homedir-polyfill "^1.0.1" - -ext@^1.1.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" - integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== - dependencies: - type "^2.5.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extend@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -fancy-log@^1.3.2, fancy-log@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" - integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - parse-node-version "^1.0.0" - time-stamp "^1.0.0" - -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-json-stable-stringify@^2.0.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@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz#e6a754cc8f15e58987aa9cbd27af66fd6f4e5af9" - integrity sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk= - -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= - -fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== - dependencies: - reusify "^1.0.4" - -fetch-mock@^9.11.0: - version "9.11.0" - resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-9.11.0.tgz#371c6fb7d45584d2ae4a18ee6824e7ad4b637a3f" - integrity sha512-PG1XUv+x7iag5p/iNHD4/jdpxL9FtVSqRMUQhPab4hVDt80T1MH5ehzVrL2IdXO9Q2iBggArFvPqjUbHFuI58Q== - dependencies: - "@babel/core" "^7.0.0" - "@babel/runtime" "^7.0.0" - core-js "^3.0.0" - debug "^4.1.1" - glob-to-regexp "^0.4.0" - is-subset "^0.1.1" - lodash.isequal "^4.5.0" - path-to-regexp "^2.2.1" - querystring "^0.2.0" - whatwg-url "^6.5.0" - -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-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - 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-up@5.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" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -findup-sync@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" - integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= - dependencies: - detect-file "^1.0.0" - is-glob "^3.1.0" - micromatch "^3.0.4" - resolve-dir "^1.0.1" - -findup-sync@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" - integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== - dependencies: - detect-file "^1.0.0" - is-glob "^4.0.0" - micromatch "^3.0.4" - resolve-dir "^1.0.1" - -fined@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fined/-/fined-1.2.0.tgz#d00beccf1aa2b475d16d423b0238b713a2c4a37b" - integrity sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng== - dependencies: - expand-tilde "^2.0.2" - is-plain-object "^2.0.3" - object.defaults "^1.1.0" - object.pick "^1.2.0" - parse-filepath "^1.0.1" - -flagged-respawn@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41" - integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q== - -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" - -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - -flatted@^3.1.0, flatted@^3.2.4: - version "3.2.4" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" - integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== - -flush-write-stream@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" - integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== - dependencies: - inherits "^2.0.3" - readable-stream "^2.3.6" - -follow-redirects@^1.0.0: - 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== - -for-in@^1.0.1, for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -for-own@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" - integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= - dependencies: - for-in "^1.0.1" - -fork-stream@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/fork-stream/-/fork-stream-0.0.4.tgz#db849fce77f6708a5f8f386ae533a0907b54ae70" - integrity sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA= - -fraction.js@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" - integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -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-mkdirp-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" - integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes= - dependencies: - graceful-fs "^4.1.11" - through2 "^2.0.3" - -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@^1.2.7: - version "1.2.13" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" - integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" - -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.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - -functions-have-names@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -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@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - -get-caller-file@^2.0.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-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= - -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-intrinsic@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" - integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -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" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-parent@^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-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-stream@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" - integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ= - dependencies: - extend "^3.0.0" - glob "^7.1.1" - glob-parent "^3.1.0" - is-negated-glob "^1.0.0" - ordered-read-streams "^1.0.0" - pumpify "^1.3.5" - readable-stream "^2.1.5" - remove-trailing-separator "^1.0.1" - to-absolute-glob "^2.0.0" - unique-stream "^2.0.2" - -glob-to-regexp@^0.4.0: - 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-watcher@^5.0.3: - version "5.0.5" - resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.5.tgz#aa6bce648332924d9a8489be41e3e5c52d4186dc" - integrity sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw== - dependencies: - anymatch "^2.0.0" - async-done "^1.2.0" - chokidar "^2.0.0" - is-negated-glob "^1.0.0" - just-debounce "^1.0.0" - normalize-path "^3.0.0" - object.defaults "^1.1.0" - -glob@7.2.0, glob@^7.1.1, glob@^7.1.3, glob@^7.1.7, glob@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e" - integrity sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^5.0.1" - once "^1.3.0" - -global-modules@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" - integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== - dependencies: - global-prefix "^1.0.1" - is-windows "^1.0.1" - resolve-dir "^1.0.0" - -global-prefix@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" - integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= - dependencies: - expand-tilde "^2.0.2" - homedir-polyfill "^1.0.1" - ini "^1.3.4" - is-windows "^1.0.1" - which "^1.2.14" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.19.0: - version "13.19.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.19.0.tgz#7a42de8e6ad4f7242fbcca27ea5b23aca367b5c8" - integrity sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ== - dependencies: - type-fest "^0.20.2" - -glogg@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" - integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA== - dependencies: - sparkles "^1.0.0" - -graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.6: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== - -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== - -gulp-changed@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/gulp-changed/-/gulp-changed-4.0.3.tgz#f9f57944b2cbb72b3cdbb93f51fb5cbd1adda898" - integrity sha512-oIymgTNmmIvdqRRpdtohmELix81q+CA/D9DgVCvaM4Ulai0xgalf+XS6A95JwskbxRGQKtzzhMmdWZEuikX67w== - dependencies: - make-dir "^3.0.0" - plugin-error "^1.0.1" - replace-ext "^1.0.0" - through2 "^3.0.1" - touch "^3.1.0" - -gulp-cli@^2.2.0, gulp-cli@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.3.0.tgz#ec0d380e29e52aa45e47977f0d32e18fd161122f" - integrity sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A== - dependencies: - ansi-colors "^1.0.1" - archy "^1.0.0" - array-sort "^1.0.0" - color-support "^1.1.3" - concat-stream "^1.6.0" - copy-props "^2.0.1" - fancy-log "^1.3.2" - gulplog "^1.0.0" - interpret "^1.4.0" - isobject "^3.0.1" - liftoff "^3.1.0" - matchdep "^2.0.0" - mute-stdout "^1.0.0" - pretty-hrtime "^1.0.0" - replace-homedir "^1.0.0" - semver-greatest-satisfied-range "^1.1.0" - v8flags "^3.2.0" - yargs "^7.1.0" - -gulp-if@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/gulp-if/-/gulp-if-3.0.0.tgz#6c3e7edc8bafadc34f2ebecb314bf43324ba1e40" - integrity sha512-fCUEngzNiEZEK2YuPm+sdMpO6ukb8+/qzbGfJBXyNOXz85bCG7yBI+pPSl+N90d7gnLvMsarthsAImx0qy7BAw== - dependencies: - gulp-match "^1.1.0" - ternary-stream "^3.0.0" - through2 "^3.0.1" - -gulp-match@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/gulp-match/-/gulp-match-1.1.0.tgz#552b7080fc006ee752c90563f9fec9d61aafdf4f" - integrity sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ== - dependencies: - minimatch "^3.0.3" - -gulp-svgmin@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/gulp-svgmin/-/gulp-svgmin-4.1.0.tgz#38c7928663b036a676c56e78cc62fd3f906a0133" - integrity sha512-WKpif+yu3+oIlp1e11CQi5F64YddP699l2mFmxpz8swv8/P8dhxVcMKdCPFWouArlVyn7Ma1eWCJHw5gx4NMtw== - dependencies: - lodash.clonedeep "^4.5.0" - plugin-error "^1.0.1" - svgo "^2.7.0" - -gulp@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/gulp/-/gulp-4.0.2.tgz#543651070fd0f6ab0a0650c6a3e6ff5a7cb09caa" - integrity sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA== - dependencies: - glob-watcher "^5.0.3" - gulp-cli "^2.2.0" - undertaker "^1.2.1" - vinyl-fs "^3.0.0" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= - dependencies: - glogg "^1.0.0" - -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-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -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-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== - dependencies: - get-intrinsic "^1.1.1" - -has-symbols@^1.0.1, 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-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -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-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has@^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== - -homedir-polyfill@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" - integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== - dependencies: - parse-passwd "^1.0.0" - -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== - -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-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" - -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" - -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== - -immutable@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" - integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== - -import-fresh@^3.0.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" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -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.1, inherits@^2.0.3, inherits@^2.0.4, 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@^1.3.4: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -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" - -interpret@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= - -is-absolute@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" - integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== - dependencies: - is-relative "^1.0.0" - is-windows "^1.0.1" - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - -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.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-builtin-module@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.0.tgz#bb0310dfe881f144ca83f30100ceb10cf58835e0" - integrity sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw== - dependencies: - builtin-modules "^3.3.0" - -is-callable@^1.1.4, 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-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-core-module@^2.9.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" - integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== - dependencies: - has "^1.0.3" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - 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@^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-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.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-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-negated-glob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" - integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= - -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-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" - integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - -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-path-inside@^3.0.3: - 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@^2.1.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-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-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-reference@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" - integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== - dependencies: - "@types/estree" "*" - -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-relative@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" - integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== - dependencies: - is-unc-path "^1.0.0" - -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-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" - -is-string@^1.0.5, 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, 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-unc-path@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" - integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== - dependencies: - unc-path-regex "^0.1.2" - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -is-utf8@^0.2.0, is-utf8@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-valid-glob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" - integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= - -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-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -is-windows@^1.0.1, is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -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, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isbinaryfile@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.8.tgz#5d34b94865bd4946633ecc78a026fc76c5b11fcf" - integrity sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w== - -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@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -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" - -jquery@^3.6.3: - version "3.6.3" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.3.tgz#23ed2ffed8a19e048814f13391a19afcdba160e6" - integrity sha512-bZ5Sy3YzKo9Fyc8wH2iIQK4JImJ6R0GWI9kL1/k7Z91ZBNgkRXE6U0JfHIizZbort8ZunhSI3jw9I6253ahKfg== - -js-sdsl@^4.1.4: - version "4.1.5" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.1.5.tgz#1ff1645e6b4d1b028cd3f862db88c9d887f26e2a" - integrity sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q== - -"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@4.1.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" - -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-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-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= - -json5@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -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" - -"jsx-ast-utils@^2.4.1 || ^3.0.0": - 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" - -just-debounce@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.1.0.tgz#2f81a3ad4121a76bc7cb45dbf704c0d76a8e5ddf" - integrity sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ== - -just-extend@^4.0.2: - version "4.2.1" - resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.2.1.tgz#ef5e589afb61e5d66b24eca749409a8939a8c744" - integrity sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg== - -karma-chai@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/karma-chai/-/karma-chai-0.1.0.tgz#bee5ad40400517811ae34bb945f762909108b79a" - integrity sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o= - -karma-chrome-launcher@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz#baca9cc071b1562a1db241827257bfe5cab597ea" - integrity sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ== - dependencies: - which "^1.2.1" - -karma-mocha-reporter@^2.2.5: - version "2.2.5" - resolved "https://registry.yarnpkg.com/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz#15120095e8ed819186e47a0b012f3cd741895560" - integrity sha1-FRIAlejtgZGG5HoLAS8810GJVWA= - dependencies: - chalk "^2.1.0" - log-symbols "^2.1.0" - strip-ansi "^4.0.0" - -karma-mocha@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-2.0.1.tgz#4b0254a18dfee71bdbe6188d9a6861bf86b0cd7d" - integrity sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ== - dependencies: - minimist "^1.2.3" - -karma-sinon@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/karma-sinon/-/karma-sinon-1.0.5.tgz#4e3443f2830fdecff624d3747163f1217daa2a9a" - integrity sha1-TjRD8oMP3s/2JNN0cWPxIX2qKpo= - -karma-source-map-support@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz#58526ceccf7e8730e56effd97a4de8d712ac0d6b" - integrity sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A== - dependencies: - source-map-support "^0.5.5" - -karma@^6.4.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/karma/-/karma-6.4.1.tgz#f2253716dd3a41aaa813fa9f54b6ee047e1127d9" - integrity sha512-Cj57NKOskK7wtFWSlMvZf459iX+kpYIPXmkNUzP2WAFcA7nhr/ALn5R7sw3w+1udFDcpMx/tuB8d5amgm3ijaA== - dependencies: - "@colors/colors" "1.5.0" - body-parser "^1.19.0" - braces "^3.0.2" - chokidar "^3.5.1" - connect "^3.7.0" - di "^0.0.1" - dom-serialize "^2.2.1" - glob "^7.1.7" - graceful-fs "^4.2.6" - http-proxy "^1.18.1" - isbinaryfile "^4.0.8" - lodash "^4.17.21" - log4js "^6.4.1" - mime "^2.5.2" - minimatch "^3.0.4" - mkdirp "^0.5.5" - qjobs "^1.2.0" - range-parser "^1.2.1" - rimraf "^3.0.2" - socket.io "^4.4.1" - source-map "^0.6.1" - tmp "^0.2.1" - ua-parser-js "^0.7.30" - yargs "^16.1.1" - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0, kind-of@^5.0.2: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -last-run@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b" - integrity sha1-RblpQsF7HHnHchmCWbqUO+v4yls= - dependencies: - default-resolution "^2.0.0" - es6-weak-map "^2.0.1" - -lazystream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" - integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw== - dependencies: - readable-stream "^2.0.5" - -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= - dependencies: - invert-kv "^1.0.0" - -lead@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" - integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI= - dependencies: - flush-write-stream "^1.0.2" - -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" - -liftoff@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3" - integrity sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog== - dependencies: - extend "^3.0.0" - findup-sync "^3.0.0" - fined "^1.0.1" - flagged-respawn "^1.0.0" - is-plain-object "^2.0.4" - object.map "^1.0.0" - rechoir "^0.6.2" - resolve "^1.1.7" - -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -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.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= - -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.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - -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.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.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@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -log-symbols@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -log-symbols@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - -log4js@^6.4.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.4.1.tgz#9d3a8bf2c31c1e213fe3fc398a6053f7a2bc53e8" - integrity sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg== - dependencies: - date-format "^4.0.3" - debug "^4.3.3" - flatted "^3.2.4" - rfdc "^1.3.0" - streamroller "^3.0.2" - -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" - -loupe@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.2.tgz#799a566ba5aa8d11b93ddccc92c569bbae7e9490" - integrity sha512-QgVamnvj0jX1LMPlCAq0MK6hATORFtGqHoUKXTkwNe13BqlN6aePQCKnnTcFvdDYEEITcJ+gBl4mTW7YJtJbyQ== - dependencies: - get-func-name "^2.0.0" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -magic-string@^0.27.0: - version "0.27.0" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" - integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.4.13" - -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -make-iterator@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" - integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw== - dependencies: - kind-of "^6.0.2" - -map-cache@^0.2.0, map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -matchdep@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e" - integrity sha1-xvNINKDY28OzfCfui7yyfHd1WC4= - dependencies: - findup-sync "^2.0.0" - micromatch "^3.0.4" - resolve "^1.4.0" - stack-trace "0.0.10" - -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== - -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= - -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== - -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -mime-db@1.50.0: - version "1.50.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" - integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A== - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@~2.1.24: - version "2.1.33" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb" - integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g== - dependencies: - mime-db "1.50.0" - -mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@^2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" - integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== - -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" - -minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2: - 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.1.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7" - integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg== - dependencies: - brace-expansion "^2.0.1" - -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== - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -mocha@^10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" - integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== - dependencies: - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.5.3" - debug "4.3.4" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "7.2.0" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "5.0.1" - ms "2.1.3" - nanoid "3.3.3" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - workerpool "6.2.1" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" - -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.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -mute-stdout@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331" - integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg== - -nan@^2.12.1: - version "2.15.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== - -nanocolors@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.1.12.tgz#8577482c58cbd7b5bb1681db4cf48f11a87fd5f6" - integrity sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ== - -nanoid@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" - integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== - -nanoid@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" - integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -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= - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -next-tick@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - -nise@^5.1.2: - version "5.1.3" - resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.3.tgz#f46197e5f60ae9a96401b602bd9d8239b1ee8656" - integrity sha512-U597iWTTBBYIV72986jyU382/MMZ70ApWcRmkoF1AZ75bpqOtI3Gugv/6+0jLgoDOabmcSwYBkSSAWIp1eA5cg== - dependencies: - "@sinonjs/commons" "^2.0.0" - "@sinonjs/fake-timers" "^7.0.4" - "@sinonjs/text-encoding" "^0.7.1" - just-extend "^4.0.2" - path-to-regexp "^1.7.0" - -node-releases@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" - integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== - -nopt@~1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= - dependencies: - abbrev "1" - -normalize-package-data@^2.3.2: - 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-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.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.css@^8.0.0: - version "8.0.1" - resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3" - integrity sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg== - -now-and-later@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.1.tgz#8e579c8685764a7cc02cb680380e94f43ccb1f7c" - integrity sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ== - dependencies: - once "^1.3.2" - -nth-check@^2.0.0: - 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= - -object-assign@^4, 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-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-inspect@^1.11.0, object-inspect@^1.9.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.12.0, object-inspect@^1.12.2: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - -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-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.assign@^4.0.4, object.assign@^4.1.0, 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.assign@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" - integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -object.defaults@^1.0.0, object.defaults@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" - integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8= - dependencies: - array-each "^1.0.1" - array-slice "^1.0.0" - for-own "^1.0.0" - isobject "^3.0.0" - -object.entries@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.6.tgz#9737d0e5b8291edd340a3e3264bb8a3b00d5fa23" - integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -object.fromentries@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.6.tgz#cdb04da08c539cffa912dcd368b886e0904bfa73" - integrity sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -object.hasown@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92" - integrity sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw== - dependencies: - define-properties "^1.1.4" - es-abstract "^1.20.4" - -object.map@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" - integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc= - dependencies: - for-own "^1.0.0" - make-iterator "^1.0.0" - -object.pick@^1.2.0, object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - -object.reduce@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object.reduce/-/object.reduce-1.0.1.tgz#6fe348f2ac7fa0f95ca621226599096825bb03ad" - integrity sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60= - dependencies: - for-own "^1.0.0" - make-iterator "^1.0.0" - -object.values@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" - integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -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" - -once@^1.3.0, once@^1.3.1, once@^1.3.2, 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" - -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" - -ordered-read-streams@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" - integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4= - dependencies: - readable-stream "^2.0.1" - -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= - dependencies: - lcid "^1.0.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-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" - -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-filepath@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" - integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE= - dependencies: - is-absolute "^1.0.0" - map-cache "^0.2.0" - path-root "^0.1.1" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - -parse-node-version@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" - integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== - -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= - -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== - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" - -path-exists@^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-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -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-root-regex@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" - integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0= - -path-root@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" - integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc= - dependencies: - path-root-regex "^0.1.0" - -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-to-regexp@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.4.0.tgz#35ce7f333d5616f1c1e1bfe266c3aba2e5b2e704" - integrity sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w== - -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -pathval@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" - integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== - -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: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== - -picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -plugin-error@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c" - integrity sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA== - dependencies: - ansi-colors "^1.0.1" - arr-diff "^4.0.0" - arr-union "^3.1.0" - extend-shallow "^3.0.2" - -popper.js@^1.16.1: - version "1.16.1" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" - integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -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@^8.4.21: - version "8.4.21" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" - integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg== - dependencies: - nanoid "^3.3.4" - 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== - -prettier@^2.8.4: - version "2.8.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.4.tgz#34dd2595629bfbb79d344ac4a91ff948694463c3" - integrity sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw== - -pretty-hrtime@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" - integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= - -process-nextick-args@^2.0.0, 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== - -prop-types@^15.8.1: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -pump@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pumpify@^1.3.5: - version "1.5.1" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" - integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== - dependencies: - duplexify "^3.6.0" - inherits "^2.0.3" - pump "^2.0.0" - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qjobs@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" - integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== - -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== - -querystring@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd" - integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -rambda@^7.1.0: - version "7.1.4" - resolved "https://registry.yarnpkg.com/rambda/-/rambda-7.1.4.tgz#7faa9665a54c5d81773975532a942b3113bb4a56" - integrity sha512-bPK8sSiVHIC7CqdWga8R+hRi5hfc4hK6S01lZW4KrLwSNryQoKaCOJA9GNiF20J7Nbe1vejRfR37/ASQXFL5EA== - -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.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== - -raven-js@^3.7.0: - version "3.27.2" - resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.27.2.tgz#6c33df952026cd73820aa999122b7b7737a66775" - integrity sha512-mFWQcXnhRFEQe5HeFroPaEghlnqy7F5E2J3Fsab189ondqUzcjwSVi7el7F36cr6PvQYXoZ1P2F5CSF2/azeMQ== - -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" - -react-is@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -"readable-stream@2 || 3", readable-stream@^3.1.1: - 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.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -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" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= - dependencies: - resolve "^1.1.6" - -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@^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: - 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.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537" - integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg== - dependencies: - "@babel/runtime" "^7.8.4" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - -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@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.1.0.tgz#2f8504c3fd0ebe11215783a41541e21c79942c6d" - integrity sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA== - 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" - -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.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" - -remove-bom-buffer@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" - integrity sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ== - dependencies: - is-buffer "^1.1.5" - is-utf8 "^0.2.1" - -remove-bom-stream@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" - integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM= - dependencies: - remove-bom-buffer "^3.0.0" - safe-buffer "^5.1.0" - through2 "^2.0.3" - -remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -replace-ext@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.1.tgz#2d6d996d04a15855d967443631dd5f77825b016a" - integrity sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw== - -replace-homedir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-homedir/-/replace-homedir-1.0.0.tgz#e87f6d513b928dde808260c12be7fec6ff6e798c" - integrity sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw= - dependencies: - homedir-polyfill "^1.0.1" - is-absolute "^1.0.0" - remove-trailing-separator "^1.1.0" - -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-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= - -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= - -resolve-dir@^1.0.0, resolve-dir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" - integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= - dependencies: - expand-tilde "^2.0.0" - global-modules "^1.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-options@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" - integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE= - dependencies: - value-or-function "^3.0.0" - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.22.1, resolve@^1.4.0: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== - dependencies: - is-core-module "^2.9.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@^2.0.0-next.4: - version "2.0.0-next.4" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" - integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ== - dependencies: - is-core-module "^2.9.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -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== - -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.2: - 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.79.1: - version "2.79.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" - integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== - optionalDependencies: - fsevents "~2.3.2" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-buffer@^5.1.0, 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== - -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-regex-test@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" - integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" - is-regex "^1.1.4" - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sass@^1.58.3: - version "1.58.3" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.58.3.tgz#2348cc052061ba4f00243a208b09c40e031f270d" - integrity sha512-Q7RaEtYf6BflYrQ+buPudKR26/lH+10EmO9bBqbmPh/KeLqv8bjpTNqxe71ocONqXq+jYiCbpPUmQMS+JJPk4A== - dependencies: - chokidar ">=3.0.0 <4.0.0" - immutable "^4.0.0" - source-map-js ">=0.6.2 <2.0.0" - -scroll-into-view@^1.16.2: - version "1.16.2" - resolved "https://registry.yarnpkg.com/scroll-into-view/-/scroll-into-view-1.16.2.tgz#ea3e810dacc861fb9c115eac7bf603e564f0104a" - integrity sha512-vyTE0i27o6eldt9xinjHec41Dw05y+faoI+s2zNKJAVOdbA5M2XZrYq/obJ8E+QDQulJ2gDjgui9w9m9RZSRng== - -semver-greatest-satisfied-range@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz#13e8c2658ab9691cb0cd71093240280d36f77a5b" - integrity sha1-E+jCZYq5aRywzXEJMkAoDTb3els= - dependencies: - sver-compat "^1.5.0" - -"semver@2 || 3 || 4 || 5": - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -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== - -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" - -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" - -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= - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - -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@^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== - -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" - -sinon@^15.0.1: - version "15.0.1" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-15.0.1.tgz#ce062611a0b131892e2c18f03055b8eb6e8dc234" - integrity sha512-PZXKc08f/wcA/BMRGBze2Wmw50CWPiAH3E21EOi4B49vJ616vW4DQh4fQrqsYox2aNR/N3kCqLuB0PwwOucQrg== - dependencies: - "@sinonjs/commons" "^2.0.0" - "@sinonjs/fake-timers" "10.0.2" - "@sinonjs/samsam" "^7.0.1" - diff "^5.0.0" - nise "^5.1.2" - supports-color "^7.2.0" - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -socket.io-adapter@~2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz#b50a4a9ecdd00c34d4c8c808224daa1a786152a6" - integrity sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg== - -socket.io-parser@~4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.5.tgz#cb404382c32324cc962f27f3a44058cf6e0552df" - integrity sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig== - dependencies: - "@types/component-emitter" "^1.2.10" - component-emitter "~1.3.0" - debug "~4.3.1" - -socket.io@^4.4.1: - version "4.5.0" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.0.tgz#78ae2e84784c29267086a416620c18ef95b37186" - integrity sha512-slTYqU2jCgMjXwresG8grhUi/cC6GjzmcfqArzaH3BN/9I/42eZk9yamNvZJdBfTubkjEdKAKs12NEztId+bUA== - dependencies: - accepts "~1.3.4" - base64id "~2.0.0" - debug "~4.3.2" - engine.io "~6.2.0" - socket.io-adapter "~2.4.0" - socket.io-parser "~4.0.4" - -"source-map-js@>=0.6.2 <2.0.0", 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-resolve@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@^0.5.5, 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.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - -source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, 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== - -sparkles@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" - integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== - -spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.10" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz#0d9becccde7003d6c658d487dd48a32f0bf3014b" - integrity sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA== - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -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-trace@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -stream-exhaust@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d" - integrity sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw== - -stream-shift@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" - integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== - -streamroller@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.0.2.tgz#30418d0eee3d6c93ec897f892ed098e3a81e68b7" - integrity sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA== - dependencies: - date-format "^4.0.3" - debug "^4.1.1" - fs-extra "^10.0.0" - -string-width@^1.0.1, string-width@^1.0.2: - 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@^4.1.0, string-width@^4.2.0: - 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.prototype.matchall@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3" - integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg== - 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" - -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.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -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.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -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" - -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-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - -strip-json-comments@3.1.1, 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== - -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-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, supports-color@^7.2.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-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== - -sver-compat@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8" - integrity sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg= - dependencies: - es6-iterator "^2.0.1" - es6-symbol "^3.1.1" - -svgo@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.7.0.tgz#e164cded22f4408fe4978f082be80159caea1e2d" - integrity sha512-aDLsGkre4fTDCWvolyW+fs8ZJFABpzLXbtdK1y71CKnHzAnpDxKXPj2mNKj+pyOXUCzFHzuxRJ94XOFygOWV3w== - dependencies: - "@trysound/sax" "0.2.0" - commander "^7.2.0" - css-select "^4.1.3" - css-tree "^1.1.3" - csso "^4.2.0" - nanocolors "^0.1.12" - stable "^0.1.8" - -syn@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/syn/-/syn-0.2.2.tgz#0c02b7901b782b6f58982fac4243c7719eade5eb" - integrity sha1-DAK3kBt4K29YmC+sQkPHcZ6t5es= - -ternary-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ternary-stream/-/ternary-stream-3.0.0.tgz#7951930ea9e823924d956f03d516151a2d516253" - integrity sha512-oIzdi+UL/JdktkT+7KU5tSIQjj8pbShj3OASuvDEhm0NT5lppsm7aXWAmAq4/QMaBIyfuEcNLbAQA+HpaISobQ== - dependencies: - duplexify "^4.1.1" - fork-stream "^0.0.4" - merge-stream "^2.0.0" - through2 "^3.0.1" - -terser@^5.0.0: - version "5.14.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10" - integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA== - dependencies: - "@jridgewell/source-map" "^0.3.2" - acorn "^8.5.0" - commander "^2.20.0" - source-map-support "~0.5.20" - -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= - -through2-filter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" - integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@^2.0.0, through2@^2.0.3, 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@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" - integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ== - dependencies: - inherits "^2.0.4" - readable-stream "2 || 3" - -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= - -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" - -to-absolute-glob@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" - integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs= - dependencies: - is-absolute "^1.0.0" - is-negated-glob "^1.0.0" - -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-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -to-through@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" - integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY= - dependencies: - through2 "^2.0.3" - -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== - -touch@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" - integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== - dependencies: - nopt "~1.0.10" - -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" - -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-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5, 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.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-is@~1.6.17: - 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" - -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -type@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d" - integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -ua-parser-js@^0.7.30: - version "0.7.33" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532" - integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw== - -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" - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -unc-path-regex@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" - integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= - -undertaker-registry@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/undertaker-registry/-/undertaker-registry-1.0.1.tgz#5e4bda308e4a8a2ae584f9b9a4359a499825cc50" - integrity sha1-XkvaMI5KiirlhPm5pDWaSZglzFA= - -undertaker@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.3.0.tgz#363a6e541f27954d5791d6fa3c1d321666f86d18" - integrity sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg== - dependencies: - arr-flatten "^1.0.1" - arr-map "^2.0.0" - bach "^1.0.0" - collection-map "^1.0.0" - es6-weak-map "^2.0.1" - fast-levenshtein "^1.0.0" - last-run "^1.1.0" - object.defaults "^1.0.0" - object.reduce "^1.0.0" - undertaker-registry "^1.0.0" - -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@^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@^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@^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== - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -unique-stream@^2.0.2: - version "2.3.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" - integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A== - dependencies: - json-stable-stringify-without-jsonify "^1.0.1" - through2-filter "^3.0.0" - -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -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= - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - -update-browserslist-db@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz#2924d3927367a38d5c555413a7ce138fc95fcb18" - integrity sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -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= - -v8flags@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.2.0.tgz#b243e3b4dfd731fa774e7492128109a0fe66d656" - integrity sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg== - dependencies: - homedir-polyfill "^1.0.1" - -validate-npm-package-license@^3.0.1: - 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" - -value-or-function@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" - integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= - -vary@^1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== - -vinyl-fs@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7" - integrity sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng== - dependencies: - fs-mkdirp-stream "^1.0.0" - glob-stream "^6.1.0" - graceful-fs "^4.0.0" - is-valid-glob "^1.0.0" - lazystream "^1.0.0" - lead "^1.0.0" - object.assign "^4.0.4" - pumpify "^1.3.5" - readable-stream "^2.3.3" - remove-bom-buffer "^3.0.0" - remove-bom-stream "^1.2.0" - resolve-options "^1.1.0" - through2 "^2.0.0" - to-through "^2.0.0" - value-or-function "^3.0.0" - vinyl "^2.0.0" - vinyl-sourcemap "^1.1.0" - -vinyl-sourcemap@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" - integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY= - dependencies: - append-buffer "^1.0.2" - convert-source-map "^1.5.0" - graceful-fs "^4.1.6" - normalize-path "^2.1.1" - now-and-later "^2.0.0" - remove-bom-buffer "^3.0.0" - vinyl "^2.0.0" - -vinyl@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.1.tgz#23cfb8bbab5ece3803aa2c0a1eb28af7cbba1974" - integrity sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw== - dependencies: - clone "^2.1.1" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - -void-elements@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" - integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= - -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== - -whatwg-url@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8" - integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ== - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - -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-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= - -which@^1.2.1, which@^1.2.14: - 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: - 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" - -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== - -workerpool@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" - integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -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= - -ws@~8.2.3: - version "8.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" - integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== - -xtend@~4.0.0, 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@^3.2.1: - version "3.2.2" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" - integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== - -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.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -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: - 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-parser@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.1.tgz#7ede329c1d8cdbbe209bd25cdb990e9b1ebbb394" - integrity sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA== - dependencies: - camelcase "^3.0.0" - object.assign "^4.1.0" - -yargs-unparser@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@16.2.0, yargs@^16.1.1: - 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" - -yargs@^7.1.0: - version "7.1.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.2.tgz#63a0a5d42143879fdbb30370741374e0641d55db" - integrity sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA== - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^5.0.1" - -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 + +"@ampproject/remapping@npm:^2.2.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 + +"@babel/code-frame@npm:^7.22.13": + 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/code-frame@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/code-frame@npm:7.22.5" + dependencies: + "@babel/highlight": ^7.22.5 + checksum: cfe804f518f53faaf9a1d3e0f9f74127ab9a004912c3a16fda07fb6a633393ecb9918a053cb71804204c1b7ec3d49e1699604715e2cfb0c9f7bc4933d324ebb6 + languageName: node + linkType: hard + +"@babel/code-frame@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/code-frame@npm:7.23.5" + dependencies: + "@babel/highlight": ^7.23.4 + chalk: ^2.4.2 + checksum: d90981fdf56a2824a9b14d19a4c0e8db93633fd488c772624b4e83e0ceac6039a27cd298a247c3214faa952bf803ba23696172ae7e7235f3b97f43ba278c569a + languageName: node + linkType: hard + +"@babel/code-frame@npm:^7.24.2": + version: 7.24.2 + resolution: "@babel/code-frame@npm:7.24.2" + dependencies: + "@babel/highlight": ^7.24.2 + picocolors: ^1.0.0 + checksum: 70e867340cfe09ca5488b2f36372c45cabf43c79a5b6426e6df5ef0611ff5dfa75a57dda841895693de6008f32c21a7c97027a8c7bcabd63a7d17416cbead6f8 + languageName: node + linkType: hard + +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9": + version: 7.22.9 + resolution: "@babel/compat-data@npm:7.22.9" + checksum: bed77d9044ce948b4327b30dd0de0779fa9f3a7ed1f2d31638714ed00229fa71fc4d1617ae0eb1fad419338d3658d0e9a5a083297451e09e73e078d0347ff808 + languageName: node + linkType: hard + +"@babel/compat-data@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/compat-data@npm:7.23.5" + checksum: 06ce244cda5763295a0ea924728c09bae57d35713b675175227278896946f922a63edf803c322f855a3878323d48d0255a2a3023409d2a123483c8a69ebb4744 + languageName: node + linkType: hard + +"@babel/compat-data@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/compat-data@npm:7.24.4" + checksum: 52ce371658dc7796c9447c9cb3b9c0659370d141b76997f21c5e0028cca4d026ca546b84bc8d157ce7ca30bd353d89f9238504eb8b7aefa9b1f178b4c100c2d4 + languageName: node + linkType: hard + +"@babel/core@npm:^7.0.0": + version: 7.22.9 + resolution: "@babel/core@npm:7.22.9" + dependencies: + "@ampproject/remapping": ^2.2.0 + "@babel/code-frame": ^7.22.5 + "@babel/generator": ^7.22.9 + "@babel/helper-compilation-targets": ^7.22.9 + "@babel/helper-module-transforms": ^7.22.9 + "@babel/helpers": ^7.22.6 + "@babel/parser": ^7.22.7 + "@babel/template": ^7.22.5 + "@babel/traverse": ^7.22.8 + "@babel/types": ^7.22.5 + convert-source-map: ^1.7.0 + debug: ^4.1.0 + gensync: ^1.0.0-beta.2 + json5: ^2.2.2 + semver: ^6.3.1 + checksum: 7bf069aeceb417902c4efdaefab1f7b94adb7dea694a9aed1bda2edf4135348a080820529b1a300c6f8605740a00ca00c19b2d5e74b5dd489d99d8c11d5e56d1 + languageName: node + linkType: hard + +"@babel/core@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/core@npm:7.24.5" + dependencies: + "@ampproject/remapping": ^2.2.0 + "@babel/code-frame": ^7.24.2 + "@babel/generator": ^7.24.5 + "@babel/helper-compilation-targets": ^7.23.6 + "@babel/helper-module-transforms": ^7.24.5 + "@babel/helpers": ^7.24.5 + "@babel/parser": ^7.24.5 + "@babel/template": ^7.24.0 + "@babel/traverse": ^7.24.5 + "@babel/types": ^7.24.5 + convert-source-map: ^2.0.0 + debug: ^4.1.0 + gensync: ^1.0.0-beta.2 + json5: ^2.2.3 + semver: ^6.3.1 + checksum: f4f0eafde12b145f2cb9cc893085e5f1436e1ef265bb3b7d8aa6282515c9b4e740bbd5e2cbc32114adb9afed2dd62c2336758b9fabb7e46e8ba542f76d4f3f80 + languageName: node + linkType: hard + +"@babel/generator@npm:^7.22.9": + version: 7.22.9 + resolution: "@babel/generator@npm:7.22.9" + dependencies: + "@babel/types": ^7.22.5 + "@jridgewell/gen-mapping": ^0.3.2 + "@jridgewell/trace-mapping": ^0.3.17 + jsesc: ^2.5.1 + checksum: 7c9d2c58b8d5ac5e047421a6ab03ec2ff5d9a5ff2c2212130a0055e063ac349e0b19d435537d6886c999771aef394832e4f54cd9fc810100a7f23d982f6af06b + languageName: node + linkType: hard + +"@babel/generator@npm:^7.23.0": + 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/generator@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/generator@npm:7.24.5" + dependencies: + "@babel/types": ^7.24.5 + "@jridgewell/gen-mapping": ^0.3.5 + "@jridgewell/trace-mapping": ^0.3.25 + jsesc: ^2.5.1 + checksum: a08c0ab900b36e1a17863e18e3216153322ea993246fd7a358ba38a31cfb15bab2af1dc178b2adafe4cb8a9f3ab0e0ceafd3fe6e8ca870dffb435b53b2b2a803 + 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-annotate-as-pure@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-annotate-as-pure@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: 53da330f1835c46f26b7bf4da31f7a496dee9fd8696cca12366b94ba19d97421ce519a74a837f687749318f94d1a37f8d1abcbf35e8ed22c32d16373b2f6198d + languageName: node + linkType: hard + +"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.22.15" + dependencies: + "@babel/types": ^7.22.15 + checksum: 639c697a1c729f9fafa2dd4c9af2e18568190299b5907bd4c2d0bc818fcbd1e83ffeecc2af24327a7faa7ac4c34edd9d7940510a5e66296c19bad17001cf5c7a + languageName: node + linkType: hard + +"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.22.9": + version: 7.22.9 + resolution: "@babel/helper-compilation-targets@npm:7.22.9" + dependencies: + "@babel/compat-data": ^7.22.9 + "@babel/helper-validator-option": ^7.22.5 + browserslist: ^4.21.9 + lru-cache: ^5.1.1 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: ea0006c6a93759025f4a35a25228ae260538c9f15023e8aac2a6d45ca68aef4cf86cfc429b19af9a402cbdd54d5de74ad3fbcf6baa7e48184dc079f1a791e178 + languageName: node + linkType: hard + +"@babel/helper-compilation-targets@npm:^7.23.6": + version: 7.23.6 + resolution: "@babel/helper-compilation-targets@npm:7.23.6" + dependencies: + "@babel/compat-data": ^7.23.5 + "@babel/helper-validator-option": ^7.23.5 + browserslist: ^4.22.2 + lru-cache: ^5.1.1 + semver: ^6.3.1 + checksum: c630b98d4527ac8fe2c58d9a06e785dfb2b73ec71b7c4f2ddf90f814b5f75b547f3c015f110a010fd31f76e3864daaf09f3adcd2f6acdbfb18a8de3a48717590 + languageName: node + linkType: hard + +"@babel/helper-create-class-features-plugin@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/helper-create-class-features-plugin@npm:7.24.1" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-member-expression-to-functions": ^7.23.0 + "@babel/helper-optimise-call-expression": ^7.22.5 + "@babel/helper-replace-supers": ^7.24.1 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 310d063eafbd2a777609770c1aa7b24e43f375122fd84031c45edc512686000197da1cf450b48eca266489131bc06dbaa35db2afed8b7213c9bcfa8c89b82c4d + languageName: node + linkType: hard + +"@babel/helper-create-class-features-plugin@npm:^7.24.4, @babel/helper-create-class-features-plugin@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helper-create-class-features-plugin@npm:7.24.5" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-member-expression-to-functions": ^7.24.5 + "@babel/helper-optimise-call-expression": ^7.22.5 + "@babel/helper-replace-supers": ^7.24.1 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.24.5 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: ea761c1155442620ee02920ec7c3190f869ff4d4fcab48a021a11fd8a46c046ed1facb070e5c76539c2b7efc2c8338f50f08a5e49d0ebf12e48743570e92247b + languageName: node + linkType: hard + +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.18.6" + dependencies: + "@babel/helper-annotate-as-pure": ^7.18.6 + regexpu-core: ^5.1.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 2d76e660cbfd0bfcb01ca9f177f0e9091c871a6b99f68ece6bcf4ab4a9df073485bdc2d87ecdfbde44b7f3723b26d13085d0f92082adb3ae80d31b246099f10a + languageName: node + linkType: hard + +"@babel/helper-create-regexp-features-plugin@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.15" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + regexpu-core: ^5.3.1 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 0243b8d4854f1dc8861b1029a46d3f6393ad72f366a5a08e36a4648aa682044f06da4c6e87a456260e1e1b33c999f898ba591a0760842c1387bcc93fbf2151a6 + languageName: node + linkType: hard + +"@babel/helper-create-regexp-features-plugin@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.5" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + regexpu-core: ^5.3.1 + semver: ^6.3.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 94932145beeb1f91856be25fea8de30b4b81b63fbc7c5a207ed97a5ddc34cd1e9b04041ed28bd24ec09cdcfbb62e8d66f820e4fe864672afe0aa2f357c784e11 + languageName: node + linkType: hard + +"@babel/helper-define-polyfill-provider@npm:^0.6.1": + version: 0.6.1 + resolution: "@babel/helper-define-polyfill-provider@npm:0.6.1" + dependencies: + "@babel/helper-compilation-targets": ^7.22.6 + "@babel/helper-plugin-utils": ^7.22.5 + debug: ^4.1.1 + lodash.debounce: ^4.0.8 + resolve: ^1.14.2 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: b45deb37ce1342d862422e81a3d25ff55f9c7ca52fe303405641e2add8db754091aaaa2119047a0f0b85072221fbddaa92adf53104274661d2795783b56bea2c + languageName: node + linkType: hard + +"@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-environment-visitor@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-environment-visitor@npm:7.22.5" + checksum: 248532077d732a34cd0844eb7b078ff917c3a8ec81a7f133593f71a860a582f05b60f818dc5049c2212e5baa12289c27889a4b81d56ef409b4863db49646c4b1 + languageName: node + linkType: hard + +"@babel/helper-function-name@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-function-name@npm:7.22.5" + dependencies: + "@babel/template": ^7.22.5 + "@babel/types": ^7.22.5 + checksum: 6b1f6ce1b1f4e513bf2c8385a557ea0dd7fa37971b9002ad19268ca4384bbe90c09681fe4c076013f33deabc63a53b341ed91e792de741b4b35e01c00238177a + languageName: node + linkType: hard + +"@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.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.23.0": + version: 7.23.0 + resolution: "@babel/helper-member-expression-to-functions@npm:7.23.0" + dependencies: + "@babel/types": ^7.23.0 + checksum: 494659361370c979ada711ca685e2efe9460683c36db1b283b446122596602c901e291e09f2f980ecedfe6e0f2bd5386cb59768285446530df10c14df1024e75 + languageName: node + linkType: hard + +"@babel/helper-member-expression-to-functions@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helper-member-expression-to-functions@npm:7.24.5" + dependencies: + "@babel/types": ^7.24.5 + checksum: d3ad681655128463aa5c2a239345687345f044542563506ee53c9636d147e97f93a470be320950a8ba5f497ade6b27a8136a3a681794867ff94b90060a6e427c + languageName: node + linkType: hard + +"@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-imports@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-module-imports@npm:7.22.15" + dependencies: + "@babel/types": ^7.22.15 + checksum: ecd7e457df0a46f889228f943ef9b4a47d485d82e030676767e6a2fdcbdaa63594d8124d4b55fd160b41c201025aec01fc27580352b1c87a37c9c6f33d116702 + languageName: node + linkType: hard + +"@babel/helper-module-imports@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-module-imports@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: 9ac2b0404fa38b80bdf2653fbeaf8e8a43ccb41bd505f9741d820ed95d3c4e037c62a1bcdcb6c9527d7798d2e595924c4d025daed73283badc180ada2c9c49ad + languageName: node + linkType: hard + +"@babel/helper-module-imports@npm:^7.24.1, @babel/helper-module-imports@npm:^7.24.3": + version: 7.24.3 + resolution: "@babel/helper-module-imports@npm:7.24.3" + dependencies: + "@babel/types": ^7.24.0 + checksum: c23492189ba97a1ec7d37012336a5661174e8b88194836b6bbf90d13c3b72c1db4626263c654454986f924c6da8be7ba7f9447876d709cd00bd6ffde6ec00796 + languageName: node + linkType: hard + +"@babel/helper-module-transforms@npm:^7.22.9": + version: 7.22.9 + resolution: "@babel/helper-module-transforms@npm:7.22.9" + dependencies: + "@babel/helper-environment-visitor": ^7.22.5 + "@babel/helper-module-imports": ^7.22.5 + "@babel/helper-simple-access": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + "@babel/helper-validator-identifier": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 2751f77660518cf4ff027514d6f4794f04598c6393be7b04b8e46c6e21606e11c19f3f57ab6129a9c21bacdf8b3ffe3af87bb401d972f34af2d0ffde02ac3001 + languageName: node + linkType: hard + +"@babel/helper-module-transforms@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/helper-module-transforms@npm:7.23.3" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-module-imports": ^7.22.15 + "@babel/helper-simple-access": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + "@babel/helper-validator-identifier": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 5d0895cfba0e16ae16f3aa92fee108517023ad89a855289c4eb1d46f7aef4519adf8e6f971e1d55ac20c5461610e17213f1144097a8f932e768a9132e2278d71 + languageName: node + linkType: hard + +"@babel/helper-module-transforms@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helper-module-transforms@npm:7.24.5" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-module-imports": ^7.24.3 + "@babel/helper-simple-access": ^7.24.5 + "@babel/helper-split-export-declaration": ^7.24.5 + "@babel/helper-validator-identifier": ^7.24.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 208c2e3877536c367ae3f39345bb5c5954ad481fdb2204d4d1906063e53ae564e5b7b846951b1aa96ee716ec24ec3b6db01b41d128884c27315b415f62db9fd2 + languageName: node + linkType: hard + +"@babel/helper-optimise-call-expression@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-optimise-call-expression@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: c70ef6cc6b6ed32eeeec4482127e8be5451d0e5282d5495d5d569d39eb04d7f1d66ec99b327f45d1d5842a9ad8c22d48567e93fc502003a47de78d122e355f7c + 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.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": + version: 7.22.5 + resolution: "@babel/helper-plugin-utils@npm:7.22.5" + checksum: c0fc7227076b6041acd2f0e818145d2e8c41968cc52fb5ca70eed48e21b8fe6dd88a0a91cbddf4951e33647336eb5ae184747ca706817ca3bef5e9e905151ff5 + languageName: node + linkType: hard + +"@babel/helper-plugin-utils@npm:^7.24.0": + version: 7.24.0 + resolution: "@babel/helper-plugin-utils@npm:7.24.0" + checksum: e2baa0eede34d2fa2265947042aa84d444aa48dc51e9feedea55b67fc1bc3ab051387e18b33ca7748285a6061390831ab82f8a2c767d08470b93500ec727e9b9 + languageName: node + linkType: hard + +"@babel/helper-plugin-utils@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helper-plugin-utils@npm:7.24.5" + checksum: fa1450c92541b32fe18a6ae85e5c989296a284838fa0a282a2138732cae6f173f36d39dc724890c1740ae72d6d6fbca0b009916b168d4bc874bacc7e5c2fdce0 + languageName: node + linkType: hard + +"@babel/helper-remap-async-to-generator@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-remap-async-to-generator@npm:7.22.20" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-wrap-function": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 2fe6300a6f1b58211dffa0aed1b45d4958506d096543663dba83bd9251fe8d670fa909143a65b45e72acb49e7e20fbdb73eae315d9ddaced467948c3329986e7 + languageName: node + linkType: hard + +"@babel/helper-replace-supers@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/helper-replace-supers@npm:7.24.1" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-member-expression-to-functions": ^7.23.0 + "@babel/helper-optimise-call-expression": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: c04182c34a3195c6396de2f2945f86cb60daa94ca7392db09bd8b0d4e7a15b02fbe1947c70f6062c87eadaea6d7135207129efa35cf458ea0987bab8c0f02d5a + languageName: node + linkType: hard + +"@babel/helper-simple-access@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-simple-access@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: fe9686714caf7d70aedb46c3cce090f8b915b206e09225f1e4dbc416786c2fdbbee40b38b23c268b7ccef749dd2db35f255338fb4f2444429874d900dede5ad2 + languageName: node + linkType: hard + +"@babel/helper-simple-access@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helper-simple-access@npm:7.24.5" + dependencies: + "@babel/types": ^7.24.5 + checksum: 5616044603c98434342f09b056c869394acdeba7cd9ec29e6a9abb0dae1922f779d364aaba74dc2ae4facf85945c6156295adbe0511a8aaecaa8a1559d14757a + languageName: node + linkType: hard + +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: 1012ef2295eb12dc073f2b9edf3425661e9b8432a3387e62a8bc27c42963f1f216ab3124228015c748770b2257b4f1fda882ca8fa34c0bf485e929ae5bc45244 + languageName: node + linkType: hard + +"@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-split-export-declaration@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helper-split-export-declaration@npm:7.24.5" + dependencies: + "@babel/types": ^7.24.5 + checksum: f23ab6942568084a57789462ce55dc9631aef1d2142ffa2ee28fc411ab55ed3ca65adf109e48655aa349bf8df7ca6dd81fd91c8c229fee1dc77e283189dc83c2 + 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-string-parser@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/helper-string-parser@npm:7.23.4" + checksum: c0641144cf1a7e7dc93f3d5f16d5327465b6cf5d036b48be61ecba41e1eece161b48f46b7f960951b67f8c3533ce506b16dece576baef4d8b3b49f8c65410f90 + languageName: node + linkType: hard + +"@babel/helper-string-parser@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/helper-string-parser@npm:7.24.1" + checksum: 8404e865b06013979a12406aab4c0e8d2e377199deec09dfe9f57b833b0c9ce7b6e8c1c553f2da8d0bcd240c5005bd7a269f4fef0d628aeb7d5fe035c436fb67 + languageName: node + linkType: hard + +"@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-identifier@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-validator-identifier@npm:7.22.5" + checksum: 7f0f30113474a28298c12161763b49de5018732290ca4de13cdaefd4fd0d635a6fe3f6686c37a02905fb1e64f21a5ee2b55140cf7b070e729f1bd66866506aea + languageName: node + linkType: hard + +"@babel/helper-validator-identifier@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helper-validator-identifier@npm:7.24.5" + checksum: 75d6f9f475c08f3be87bae4953e9b8d8c72983e16ed2860870b328d048cb20dccb4fcbf85eacbdd817ea1efbb38552a6db9046e2e37bfe13bdec44ac8939024c + languageName: node + linkType: hard + +"@babel/helper-validator-option@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-validator-option@npm:7.22.5" + checksum: bbeca8a85ee86990215c0424997438b388b8d642d69b9f86c375a174d3cdeb270efafd1ff128bc7a1d370923d13b6e45829ba8581c027620e83e3a80c5c414b3 + languageName: node + linkType: hard + +"@babel/helper-validator-option@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helper-validator-option@npm:7.23.5" + checksum: 537cde2330a8aede223552510e8a13e9c1c8798afee3757995a7d4acae564124fe2bf7e7c3d90d62d3657434a74340a274b3b3b1c6f17e9a2be1f48af29cb09e + languageName: node + linkType: hard + +"@babel/helper-wrap-function@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-wrap-function@npm:7.22.20" + dependencies: + "@babel/helper-function-name": ^7.22.5 + "@babel/template": ^7.22.15 + "@babel/types": ^7.22.19 + checksum: 221ed9b5572612aeb571e4ce6a256f2dee85b3c9536f1dd5e611b0255e5f59a3d0ec392d8d46d4152149156a8109f92f20379b1d6d36abb613176e0e33f05fca + languageName: node + linkType: hard + +"@babel/helpers@npm:^7.22.6": + version: 7.22.6 + resolution: "@babel/helpers@npm:7.22.6" + dependencies: + "@babel/template": ^7.22.5 + "@babel/traverse": ^7.22.6 + "@babel/types": ^7.22.5 + checksum: 5c1f33241fe7bf7709868c2105134a0a86dca26a0fbd508af10a89312b1f77ca38ebae43e50be3b208613c5eacca1559618af4ca236f0abc55d294800faeff30 + languageName: node + linkType: hard + +"@babel/helpers@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/helpers@npm:7.24.5" + dependencies: + "@babel/template": ^7.24.0 + "@babel/traverse": ^7.24.5 + "@babel/types": ^7.24.5 + checksum: 941937456ca50ef44dbc5cdcb9a74c6ce18ce38971663acd80b622e7ecf1cc4fa034597de3ccccc37939d324139f159709f493fd8e7c385adbc162cb0888cfee + 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/highlight@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/highlight@npm:7.22.5" + dependencies: + "@babel/helper-validator-identifier": ^7.22.5 + chalk: ^2.0.0 + js-tokens: ^4.0.0 + checksum: f61ae6de6ee0ea8d9b5bcf2a532faec5ab0a1dc0f7c640e5047fc61630a0edb88b18d8c92eb06566d30da7a27db841aca11820ecd3ebe9ce514c9350fbed39c4 + languageName: node + linkType: hard + +"@babel/highlight@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/highlight@npm:7.23.4" + dependencies: + "@babel/helper-validator-identifier": ^7.22.20 + chalk: ^2.4.2 + js-tokens: ^4.0.0 + checksum: 643acecdc235f87d925979a979b539a5d7d1f31ae7db8d89047269082694122d11aa85351304c9c978ceeb6d250591ccadb06c366f358ccee08bb9c122476b89 + languageName: node + linkType: hard + +"@babel/highlight@npm:^7.24.2": + version: 7.24.2 + resolution: "@babel/highlight@npm:7.24.2" + dependencies: + "@babel/helper-validator-identifier": ^7.22.20 + chalk: ^2.4.2 + js-tokens: ^4.0.0 + picocolors: ^1.0.0 + checksum: 5f17b131cc3ebf3ab285a62cf98a404aef1bd71a6be045e748f8d5bf66d6a6e1aefd62f5972c84369472e8d9f22a614c58a89cd331eb60b7ba965b31b1bbeaf5 + languageName: node + linkType: hard + +"@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/parser@npm:^7.22.5, @babel/parser@npm:^7.22.7": + version: 7.22.7 + resolution: "@babel/parser@npm:7.22.7" + bin: + parser: ./bin/babel-parser.js + checksum: 02209ddbd445831ee8bf966fdf7c29d189ed4b14343a68eb2479d940e7e3846340d7cc6bd654a5f3d87d19dc84f49f50a58cf9363bee249dc5409ff3ba3dab54 + languageName: node + linkType: hard + +"@babel/parser@npm:^7.24.0": + version: 7.24.1 + resolution: "@babel/parser@npm:7.24.1" + bin: + parser: ./bin/babel-parser.js + checksum: a1068941dddf82ffdf572565b8b7b2cddb963ff9ddf97e6e28f50e843d820b4285e6def8f59170104a94e2a91ae2e3b326489886d77a57ea29d468f6a5e79bf9 + languageName: node + linkType: hard + +"@babel/parser@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/parser@npm:7.24.5" + bin: + parser: ./bin/babel-parser.js + checksum: a251ea41bf8b5f61048beb320d43017aff68af5a3506bd2ef392180f5fa32c1061513171d582bb3d46ea48e3659dece8b3ba52511a2566066e58abee300ce2a0 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.24.5" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-plugin-utils": ^7.24.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: d9921b3561762b8c7227cfbf1591436d2a12b99472993a7ce382123e88d98cb359952fbc64d66b1a492187d283d02f51e707f524b708c91b9ab82fb2659eae13 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: ec5fddc8db6de0e0082a883f21141d6f4f9f9f0bc190d662a732b5e9a506aae5d7d2337049a1bf055d7cb7add6f128036db6d4f47de5e9ac1be29e043c8b7ca8 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/plugin-transform-optional-chaining": ^7.24.1 + peerDependencies: + "@babel/core": ^7.13.0 + checksum: e18235463e716ac2443938aaec3c18b40c417a1746fba0fa4c26cf4d71326b76ef26c002081ab1b445abfae98e063d561519aa55672dddc1ef80b3940211ffbb + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.24.1" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: b5e5889ce5ef51e813e3063cd548f55eb3c88e925c3c08913f334e15d62496861e538ae52a3974e0c56a3044ed8fd5033faea67a64814324af56edc9865b7359 + languageName: node + linkType: hard + +"@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2": + version: 7.21.0-placeholder-for-preset-env.2 + resolution: "@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d97745d098b835d55033ff3a7fb2b895b9c5295b08a5759e4f20df325aa385a3e0bc9bd5ad8f2ec554a44d4e6525acfc257b8c5848a1345cb40f26a30e277e91 + 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-class-properties@npm:^7.12.13": + 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-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-import-assertions@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2a463928a63b62052e9fb8f8b0018aa11a926e94f32c168260ae012afe864875c6176c6eb361e13f300542c31316dad791b08a5b8ed92436a3095c7a0e4fce65 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-attributes@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 87c8aa4a5ef931313f956871b27f2c051556f627b97ed21e9a5890ca4906b222d89062a956cde459816f5e0dec185ff128d7243d3fdc389504522acb88f0464e + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-meta@npm:^7.10.4": + 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-logical-assignment-operators@npm:^7.10.4": + 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": + 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": + 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-unicode-sets-regex@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-syntax-unicode-sets-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 + checksum: a651d700fe63ff0ddfd7186f4ebc24447ca734f114433139e3c027bc94a900d013cf1ef2e2db8430425ba542e39ae160c3b05f06b59fd4656273a3df97679e9c + languageName: node + linkType: hard + +"@babel/plugin-transform-arrow-functions@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 58f9aa9b0de8382f8cfa3f1f1d40b69d98cd2f52340e2391733d0af745fdddda650ba392e509bc056157c880a2f52834a38ab2c5aa5569af8c61bb6ecbf45f34 + languageName: node + linkType: hard + +"@babel/plugin-transform-async-generator-functions@npm:^7.24.3": + version: 7.24.3 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.24.3" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/helper-remap-async-to-generator": ^7.22.20 + "@babel/plugin-syntax-async-generators": ^7.8.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 309af02610be65d937664435adb432a32d9b6eb42bb3d3232c377d27fbc57014774d931665a5bfdaff3d1841b72659e0ad7adcef84b709f251cb0b8444f19214 + languageName: node + linkType: hard + +"@babel/plugin-transform-async-to-generator@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.24.1" + dependencies: + "@babel/helper-module-imports": ^7.24.1 + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/helper-remap-async-to-generator": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 429004a6596aa5c9e707b604156f49a146f8d029e31a3152b1649c0b56425264fda5fd38e5db1ddaeb33c3fe45c97dc8078d7abfafe3542a979b49f229801135 + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoped-functions@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d8e18bd57b156da1cd4d3c1780ab9ea03afed56c6824ca8e6e74f67959d7989a0e953ec370fe9b417759314f2eef30c8c437395ce63ada2e26c2f469e4704f82 + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoping@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/plugin-transform-block-scoping@npm:7.24.5" + dependencies: + "@babel/helper-plugin-utils": ^7.24.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 898c91efc0f8ac8e2a8d3ece36edf0001963bcf5bbeefe9bf798ac36318a33f366e88a24a90bf7c39a7aeb1593846b720ed9a9ba56709d27279f7ba61c5e43c4 + languageName: node + linkType: hard + +"@babel/plugin-transform-class-properties@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-class-properties@npm:7.24.1" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.24.1 + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 95779e9eef0c0638b9631c297d48aee53ffdbb2b1b5221bf40d7eccd566a8e34f859ff3571f8f20b9159b67f1bff7d7dc81da191c15d69fbae5a645197eae7e0 + languageName: node + linkType: hard + +"@babel/plugin-transform-class-static-block@npm:^7.24.4": + version: 7.24.4 + resolution: "@babel/plugin-transform-class-static-block@npm:7.24.4" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.24.4 + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + peerDependencies: + "@babel/core": ^7.12.0 + checksum: 3b1db3308b57ba21d47772a9f183804234c23fd64c9ca40915d2d65c5dc7a48b49a6de16b8b90b7a354eacbb51232a862f0fca3dbd23e27d34641f511decddab + languageName: node + linkType: hard + +"@babel/plugin-transform-classes@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/plugin-transform-classes@npm:7.24.5" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-compilation-targets": ^7.23.6 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-plugin-utils": ^7.24.5 + "@babel/helper-replace-supers": ^7.24.1 + "@babel/helper-split-export-declaration": ^7.24.5 + globals: ^11.1.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 797bf2bda770148d3ee43e305e1aea26fa16ca78eb81eaaeb95b441428f52e0d12dd98e93f00bda3b65bbfde3001006995725ce911587efdef0465c41bd0a3f3 + languageName: node + linkType: hard + +"@babel/plugin-transform-computed-properties@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-computed-properties@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/template": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f2832bcf100a70f348facbb395873318ef5b9ee4b0fb4104a420d9daaeb6003cc2ecc12fd8083dd2e4a7c2da873272ad73ff94de4497125a0cf473294ef9664e + languageName: node + linkType: hard + +"@babel/plugin-transform-destructuring@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/plugin-transform-destructuring@npm:7.24.5" + dependencies: + "@babel/helper-plugin-utils": ^7.24.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c5def67de09315cd38895c021ee7d02fd53fed596924512c33196ceed143b88f1ea76e4ac777a55bbb9db49be8b63aafb22b12e7d5c7f3051f14caa07e8d4023 + languageName: node + linkType: hard + +"@babel/plugin-transform-dotall-regex@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.24.1" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7f623d25b6f213b94ebc1754e9e31c1077c8e288626d8b7bfa76a97b067ce80ddcd0ede402a546706c65002c0ccf45cd5ec621511c2668eed31ebcabe8391d35 + languageName: node + linkType: hard + +"@babel/plugin-transform-duplicate-keys@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a3b07c07cee441e185858a9bb9739bb72643173c18bf5f9f949dd2d4784ca124e56b01d0a270790fb1ff0cf75d436075db0a2b643fb4285ff9a21df9e8dc6284 + languageName: node + linkType: hard + +"@babel/plugin-transform-dynamic-import@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 59fc561ee40b1a69f969c12c6c5fac206226d6642213985a569dd0f99f8e41c0f4eaedebd36936c255444a8335079842274c42a975a433beadb436d4c5abb79b + languageName: node + linkType: hard + +"@babel/plugin-transform-exponentiation-operator@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.24.1" + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor": ^7.22.15 + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f90841fe1a1e9f680b4209121d3e2992f923e85efcd322b26e5901c180ef44ff727fb89790803a23fac49af34c1ce2e480018027c22b4573b615512ac5b6fc50 + languageName: node + linkType: hard + +"@babel/plugin-transform-export-namespace-from@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/plugin-syntax-export-namespace-from": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: bc710ac231919df9555331885748385c11c5e695d7271824fe56fba51dd637d48d3e5cd52e1c69f2b1a384fbbb41552572bc1ca3a2285ee29571f002e9bb2421 + languageName: node + linkType: hard + +"@babel/plugin-transform-for-of@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-for-of@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 990adde96ea1766ed6008c006c7040127bef59066533bb2977b246ea4a596fe450a528d1881a0db5f894deaf1b81654dfb494b19ad405b369be942738aa9c364 + languageName: node + linkType: hard + +"@babel/plugin-transform-function-name@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-function-name@npm:7.24.1" + dependencies: + "@babel/helper-compilation-targets": ^7.23.6 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 31eb3c75297dda7265f78eba627c446f2324e30ec0124a645ccc3e9f341254aaa40d6787bd62b2280d77c0a5c9fbfce1da2c200ef7c7f8e0a1b16a8eb3644c6f + languageName: node + linkType: hard + +"@babel/plugin-transform-json-strings@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-json-strings@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/plugin-syntax-json-strings": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f42302d42fc81ac00d14e9e5d80405eb80477d7f9039d7208e712d6bcd486a4e3b32fdfa07b5f027d6c773723d8168193ee880f93b0e430c828e45f104fb82a4 + languageName: node + linkType: hard + +"@babel/plugin-transform-literals@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-literals@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2df94e9478571852483aca7588419e574d76bde97583e78551c286f498e01321e7dbb1d0ef67bee16e8f950688f79688809cfde370c5c4b84c14d841a3ef217a + languageName: node + linkType: hard + +"@babel/plugin-transform-logical-assignment-operators@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 895f2290adf457cbf327428bdb4fb90882a38a22f729bcf0629e8ad66b9b616d2721fbef488ac00411b647489d1dda1d20171bb3772d0796bb7ef5ecf057808a + languageName: node + linkType: hard + +"@babel/plugin-transform-member-expression-literals@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4ea641cc14a615f9084e45ad2319f95e2fee01c77ec9789685e7e11a6c286238a426a98f9c1ed91568a047d8ac834393e06e8c82d1ff01764b7aa61bee8e9023 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-amd@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-modules-amd@npm:7.24.1" + dependencies: + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3d777c262f257e93f0405b13e178f9c4a0f31855b409f0191a76bb562a28c541326a027bfe6467fcb74752f3488c0333b5ff2de64feec1b3c4c6ace1747afa03 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-commonjs@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.1" + dependencies: + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/helper-simple-access": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 11402b34c49f76aa921b43c2d76f3f129a32544a1dc4f0d1e48b310f9036ab75269a6d8684ed0198b7a0b07bd7898b12f0cacceb26fbb167999fd2a819aa0802 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-systemjs@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.24.1" + dependencies: + "@babel/helper-hoist-variables": ^7.22.5 + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/helper-validator-identifier": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 903766f6808f04278e887e4adec9b1efa741726279652dad255eaad0f5701df8f8ff0af25eb8541a00eb3c9eae2dccf337b085cfa011426ca33ed1f95d70bf75 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-umd@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-modules-umd@npm:7.24.1" + dependencies: + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4922f5056d34de6fd59a1ab1c85bc3472afa706c776aceeb886289c9ac9117e6eb8e22d06c537eb5bc0ede6c30f6bd85210bdcc150dc0ae2d2373f8252df9364 + languageName: node + linkType: hard + +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.22.5" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 3ee564ddee620c035b928fdc942c5d17e9c4b98329b76f9cefac65c111135d925eb94ed324064cd7556d4f5123beec79abea1d4b97d1c8a2a5c748887a2eb623 + languageName: node + linkType: hard + +"@babel/plugin-transform-new-target@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-new-target@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f56159ba56e8824840b8073f65073434e4bc4ef20e366bc03aa6cae9a4389365574fa72390e48aed76049edbc6eba1181eb810e58fae22c25946c62f9da13db4 + languageName: node + linkType: hard + +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 74025e191ceb7cefc619c15d33753aab81300a03d81b96ae249d9b599bc65878f962d608f452462d3aad5d6e334b7ab2b09a6bdcfe8d101fe77ac7aacca4261e + languageName: node + linkType: hard + +"@babel/plugin-transform-numeric-separator@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3247bd7d409574fc06c59e0eb573ae7470d6d61ecf780df40b550102bb4406747d8f39dcbec57eb59406df6c565a86edd3b429e396ad02e4ce201ad92050832e + languageName: node + linkType: hard + +"@babel/plugin-transform-object-rest-spread@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.24.5" + dependencies: + "@babel/helper-compilation-targets": ^7.23.6 + "@babel/helper-plugin-utils": ^7.24.5 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-transform-parameters": ^7.24.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 427705fe1358ca4862e6cfbfc174dc0fbfdd640b786cfe759dd4881cfb2fd51723e8432ecd89f07a60444e555a9c19e0e7bf4c657b91844994b39a53a602eb16 + languageName: node + linkType: hard + +"@babel/plugin-transform-object-super@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-object-super@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/helper-replace-supers": ^7.24.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d34d437456a54e2a5dcb26e9cf09ed4c55528f2a327c5edca92c93e9483c37176e228d00d6e0cf767f3d6fdbef45ae3a5d034a7c59337a009e20ae541c8220fa + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-catch-binding@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ff7c02449d32a6de41e003abb38537b4a1ad90b1eaa4c0b578cb1b55548201a677588a8c47f3e161c72738400ae811a6673ea7b8a734344755016ca0ac445dac + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-chaining@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0eb5f4abdeb1a101c0f67ef25eba4cce0978a74d8722f6222cdb179a28e60d21ab545eda231855f50169cd63d604ec8268cff44ae9370fd3a499a507c56c2bbd + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-chaining@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.24.5" + dependencies: + "@babel/helper-plugin-utils": ^7.24.5 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 233934463ef1f9a02a9fda96c722e9c162477fd94816a58413f0d4165cc536c7af0482b46fe066e754748a20bbabec255b4bbde194a7fd20b32280e526e1bfec + languageName: node + linkType: hard + +"@babel/plugin-transform-parameters@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/plugin-transform-parameters@npm:7.24.5" + dependencies: + "@babel/helper-plugin-utils": ^7.24.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b052e1cf43b1ea571fc0867baa01041ce32f46576b711c6331f03263ae479a582f81a6039287535cd90ee46d2977e2f3c66f5bdbf454a9f8cdc7c5c6c67b50be + languageName: node + linkType: hard + +"@babel/plugin-transform-private-methods@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-private-methods@npm:7.24.1" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.24.1 + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7208c30bb3f3fbc73fb3a88bdcb78cd5cddaf6d523eb9d67c0c04e78f6fc6319ece89f4a5abc41777ceab16df55b3a13a4120e0efc9275ca6d2d89beaba80aa0 + languageName: node + linkType: hard + +"@babel/plugin-transform-private-property-in-object@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.24.5" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-create-class-features-plugin": ^7.24.5 + "@babel/helper-plugin-utils": ^7.24.5 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 59f9007671f50ef8f9eff33bb2dc3de22a2849612d4b64fc9e4ba502466ddbaf3f94774011695dde5128c4ca2009e241babe928ac63f71a29f27c1cc7ce01e5f + languageName: node + linkType: hard + +"@babel/plugin-transform-property-literals@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-property-literals@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a73646d7ecd95b3931a3ead82c7d5efeb46e68ba362de63eb437d33531f294ec18bd31b6d24238cd3b6a3b919a6310c4a0ba4a2629927721d4d10b0518eb7715 + languageName: node + linkType: hard + +"@babel/plugin-transform-regenerator@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-regenerator@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + regenerator-transform: ^0.15.2 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a04319388a0a7931c3f8e15715d01444c32519692178b70deccc86d53304e74c0f589a4268f6c68578d86f75e934dd1fe6e6ed9071f54ee8379f356f88ef6e42 + languageName: node + linkType: hard + +"@babel/plugin-transform-reserved-words@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-reserved-words@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 132c6040c65aabae2d98a39289efb5c51a8632546dc50d2ad032c8660aec307fbed74ef499856ea4f881fc8505905f49b48e0270585da2ea3d50b75e962afd89 + languageName: node + linkType: hard + +"@babel/plugin-transform-shorthand-properties@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 006a2032d1c57dca76579ce6598c679c2f20525afef0a36e9d42affe3c8cf33c1427581ad696b519cc75dfee46c5e8ecdf0c6a29ffb14250caa3e16dd68cb424 + languageName: node + linkType: hard + +"@babel/plugin-transform-spread@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-spread@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 622ef507e2b5120a9010b25d3df5186c06102ecad8751724a38ec924df8d3527688198fa490c47064eabba14ef2f961b3069855bd22a8c0a1e51a23eed348d02 + languageName: node + linkType: hard + +"@babel/plugin-transform-sticky-regex@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: e326e96a9eeb6bb01dbc4d3362f989411490671b97f62edf378b8fb102c463a018b777f28da65344d41b22aa6efcdfa01ed43d2b11fdcf202046d3174be137c5 + languageName: node + linkType: hard + +"@babel/plugin-transform-template-literals@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-template-literals@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4c9009c72321caf20e3b6328bbe9d7057006c5ae57b794cf247a37ca34d87dfec5e27284169a16df5a6235a083bf0f3ab9e1bfcb005d1c8b75b04aed75652621 + languageName: node + linkType: hard + +"@babel/plugin-transform-typeof-symbol@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.24.5" + dependencies: + "@babel/helper-plugin-utils": ^7.24.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 35504219e4e8b361dbd285400c846f154754e591e931cd30dbe1426a619e41ed0c410b26dd173824ed3a2ff0371d64213ae2304b6f169b32e78b004114f5acd5 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-escapes@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.24.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d4d7cfea91af7be2768fb6bed902e00d6e3190bda738b5149c3a788d570e6cf48b974ec9548442850308ecd8fc9a67681f4ea8403129e7867bcb85adaf6ec238 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-property-regex@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.24.1" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 276099b4483e707f80b054e2d29bc519158bfe52461ef5ff76f70727d592df17e30b1597ef4d8a0f04d810f6cb5a8dd887bdc1d0540af3744751710ef280090f + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-regex@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.24.1" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 400a0927bdb1425b4c0dc68a61b5b2d7d17c7d9f0e07317a1a6a373c080ef94be1dd65fdc4ac9a78fcdb58f89fd128450c7bc0d5b8ca0ae7eca3fbd98e50acba + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-sets-regex@npm:^7.24.1": + version: 7.24.1 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.24.1" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.24.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 364342fb8e382dfaa23628b88e6484dc1097e53fb7199f4d338f1e2cd71d839bb0a35a9b1380074f6a10adb2e98b79d53ca3ec78c0b8c557ca895ffff42180df + languageName: node + linkType: hard + +"@babel/preset-env@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/preset-env@npm:7.24.5" + dependencies: + "@babel/compat-data": ^7.24.4 + "@babel/helper-compilation-targets": ^7.23.6 + "@babel/helper-plugin-utils": ^7.24.5 + "@babel/helper-validator-option": ^7.23.5 + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ^7.24.5 + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.24.1 + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.24.1 + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ^7.24.1 + "@babel/plugin-proposal-private-property-in-object": 7.21.0-placeholder-for-preset-env.2 + "@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.24.1 + "@babel/plugin-syntax-import-attributes": ^7.24.1 + "@babel/plugin-syntax-import-meta": ^7.10.4 + "@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-syntax-unicode-sets-regex": ^7.18.6 + "@babel/plugin-transform-arrow-functions": ^7.24.1 + "@babel/plugin-transform-async-generator-functions": ^7.24.3 + "@babel/plugin-transform-async-to-generator": ^7.24.1 + "@babel/plugin-transform-block-scoped-functions": ^7.24.1 + "@babel/plugin-transform-block-scoping": ^7.24.5 + "@babel/plugin-transform-class-properties": ^7.24.1 + "@babel/plugin-transform-class-static-block": ^7.24.4 + "@babel/plugin-transform-classes": ^7.24.5 + "@babel/plugin-transform-computed-properties": ^7.24.1 + "@babel/plugin-transform-destructuring": ^7.24.5 + "@babel/plugin-transform-dotall-regex": ^7.24.1 + "@babel/plugin-transform-duplicate-keys": ^7.24.1 + "@babel/plugin-transform-dynamic-import": ^7.24.1 + "@babel/plugin-transform-exponentiation-operator": ^7.24.1 + "@babel/plugin-transform-export-namespace-from": ^7.24.1 + "@babel/plugin-transform-for-of": ^7.24.1 + "@babel/plugin-transform-function-name": ^7.24.1 + "@babel/plugin-transform-json-strings": ^7.24.1 + "@babel/plugin-transform-literals": ^7.24.1 + "@babel/plugin-transform-logical-assignment-operators": ^7.24.1 + "@babel/plugin-transform-member-expression-literals": ^7.24.1 + "@babel/plugin-transform-modules-amd": ^7.24.1 + "@babel/plugin-transform-modules-commonjs": ^7.24.1 + "@babel/plugin-transform-modules-systemjs": ^7.24.1 + "@babel/plugin-transform-modules-umd": ^7.24.1 + "@babel/plugin-transform-named-capturing-groups-regex": ^7.22.5 + "@babel/plugin-transform-new-target": ^7.24.1 + "@babel/plugin-transform-nullish-coalescing-operator": ^7.24.1 + "@babel/plugin-transform-numeric-separator": ^7.24.1 + "@babel/plugin-transform-object-rest-spread": ^7.24.5 + "@babel/plugin-transform-object-super": ^7.24.1 + "@babel/plugin-transform-optional-catch-binding": ^7.24.1 + "@babel/plugin-transform-optional-chaining": ^7.24.5 + "@babel/plugin-transform-parameters": ^7.24.5 + "@babel/plugin-transform-private-methods": ^7.24.1 + "@babel/plugin-transform-private-property-in-object": ^7.24.5 + "@babel/plugin-transform-property-literals": ^7.24.1 + "@babel/plugin-transform-regenerator": ^7.24.1 + "@babel/plugin-transform-reserved-words": ^7.24.1 + "@babel/plugin-transform-shorthand-properties": ^7.24.1 + "@babel/plugin-transform-spread": ^7.24.1 + "@babel/plugin-transform-sticky-regex": ^7.24.1 + "@babel/plugin-transform-template-literals": ^7.24.1 + "@babel/plugin-transform-typeof-symbol": ^7.24.5 + "@babel/plugin-transform-unicode-escapes": ^7.24.1 + "@babel/plugin-transform-unicode-property-regex": ^7.24.1 + "@babel/plugin-transform-unicode-regex": ^7.24.1 + "@babel/plugin-transform-unicode-sets-regex": ^7.24.1 + "@babel/preset-modules": 0.1.6-no-external-plugins + babel-plugin-polyfill-corejs2: ^0.4.10 + babel-plugin-polyfill-corejs3: ^0.10.4 + babel-plugin-polyfill-regenerator: ^0.6.1 + core-js-compat: ^3.31.0 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: cced4e5331231158e02ba5903c4de12ef0aa2d2266ebb07fa80a85045b1fe2c63410d7558b702f1916d9d038531f3d79ab31007762188de5f712b16f7a66bb74 + languageName: node + linkType: hard + +"@babel/preset-modules@npm:0.1.6-no-external-plugins": + version: 0.1.6-no-external-plugins + resolution: "@babel/preset-modules@npm:0.1.6-no-external-plugins" + dependencies: + "@babel/helper-plugin-utils": ^7.0.0 + "@babel/types": ^7.4.4 + esutils: ^2.0.2 + peerDependencies: + "@babel/core": ^7.0.0-0 || ^8.0.0-0 <8.0.0 + checksum: 4855e799bc50f2449fb5210f78ea9e8fd46cf4f242243f1e2ed838e2bd702e25e73e822e7f8447722a5f4baa5e67a8f7a0e403f3e7ce04540ff743a9c411c375 + languageName: node + linkType: hard + +"@babel/regjsgen@npm:^0.8.0": + version: 0.8.0 + resolution: "@babel/regjsgen@npm:0.8.0" + checksum: 89c338fee774770e5a487382170711014d49a68eb281e74f2b5eac88f38300a4ad545516a7786a8dd5702e9cf009c94c2f582d200f077ac5decd74c56b973730 + languageName: node + linkType: hard + +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.8.4": + version: 7.15.4 + resolution: "@babel/runtime@npm:7.15.4" + dependencies: + regenerator-runtime: ^0.13.4 + checksum: c40825430400e47c19b97e4142d5315d2910305b9714d44a711472587ee2fd4521fdba5f02ddd9df3902f5e988d9854fa83f4da1e0c091f70f6983fa52480606 + 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/template@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/template@npm:7.22.5" + dependencies: + "@babel/code-frame": ^7.22.5 + "@babel/parser": ^7.22.5 + "@babel/types": ^7.22.5 + checksum: c5746410164039aca61829cdb42e9a55410f43cace6f51ca443313f3d0bdfa9a5a330d0b0df73dc17ef885c72104234ae05efede37c1cc8a72dc9f93425977a3 + languageName: node + linkType: hard + +"@babel/template@npm:^7.24.0": + version: 7.24.0 + resolution: "@babel/template@npm:7.24.0" + dependencies: + "@babel/code-frame": ^7.23.5 + "@babel/parser": ^7.24.0 + "@babel/types": ^7.24.0 + checksum: f257b003c071a0cecdbfceca74185f18fe62c055469ab5c1d481aab12abeebed328e67e0a19fd978a2a8de97b28953fa4bc3da6d038a7345fdf37923b9fcdec8 + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.22.6, @babel/traverse@npm:^7.22.8": + 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/traverse@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/traverse@npm:7.24.5" + dependencies: + "@babel/code-frame": ^7.24.2 + "@babel/generator": ^7.24.5 + "@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.24.5 + "@babel/parser": ^7.24.5 + "@babel/types": ^7.24.5 + debug: ^4.3.1 + globals: ^11.1.0 + checksum: a313fbf4a06946cc4b74b06e9846d7393a9ca1e8b6df6da60c669cff0a9426d6198c21a478041c60807b62b48f980473d4afbd3768764b0d9741ac80f5dfa04f + languageName: node + linkType: hard + +"@babel/types@npm:^7.18.6, @babel/types@npm:^7.22.5, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.22.5 + resolution: "@babel/types@npm:7.22.5" + dependencies: + "@babel/helper-string-parser": ^7.22.5 + "@babel/helper-validator-identifier": ^7.22.5 + to-fast-properties: ^2.0.0 + checksum: c13a9c1dc7d2d1a241a2f8363540cb9af1d66e978e8984b400a20c4f38ba38ca29f06e26a0f2d49a70bad9e57615dac09c35accfddf1bb90d23cd3e0a0bab892 + languageName: node + linkType: hard + +"@babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.23.0": + 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 + +"@babel/types@npm:^7.24.0": + version: 7.24.0 + resolution: "@babel/types@npm:7.24.0" + dependencies: + "@babel/helper-string-parser": ^7.23.4 + "@babel/helper-validator-identifier": ^7.22.20 + to-fast-properties: ^2.0.0 + checksum: 4b574a37d490f621470ff36a5afaac6deca5546edcb9b5e316d39acbb20998e9c2be42f3fc0bf2b55906fc49ff2a5a6a097e8f5a726ee3f708a0b0ca93aed807 + languageName: node + linkType: hard + +"@babel/types@npm:^7.24.5": + version: 7.24.5 + resolution: "@babel/types@npm:7.24.5" + dependencies: + "@babel/helper-string-parser": ^7.24.1 + "@babel/helper-validator-identifier": ^7.24.5 + to-fast-properties: ^2.0.0 + checksum: 8eeeacd996593b176e649ee49d8dc3f26f9bb6aa1e3b592030e61a0e58ea010fb018dccc51e5314c8139409ea6cbab02e29b33e674e1f6962d8e24c52da6375b + 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 + +"@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.6.1": + version: 4.6.2 + resolution: "@eslint-community/regexpp@npm:4.6.2" + checksum: a3c341377b46b54fa228f455771b901d1a2717f95d47dcdf40199df30abc000ba020f747f114f08560d119e979d882a94cf46cfc51744544d54b00319c0f2724 + 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.57.0": + version: 8.57.0 + resolution: "@eslint/js@npm:8.57.0" + checksum: 315dc65b0e9893e2bff139bddace7ea601ad77ed47b4550e73da8c9c2d2766c7a575c3cddf17ef85b8fd6a36ff34f91729d0dcca56e73ca887c10df91a41b0bb + languageName: node + linkType: hard + +"@gulpjs/messages@npm:^1.1.0": + version: 1.1.0 + resolution: "@gulpjs/messages@npm:1.1.0" + checksum: fa23de4f369cee6aec990a3795db0d1b109edca503ccd6c7551986e4936b1f08bdc5b6a2f3022e5828e478b4488ed3ac5677304bc2b691b03c575c9ac4042182 + languageName: node + linkType: hard + +"@gulpjs/to-absolute-glob@npm:^4.0.0": + version: 4.0.0 + resolution: "@gulpjs/to-absolute-glob@npm:4.0.0" + dependencies: + is-negated-glob: ^1.0.0 + checksum: 30ec7825064422b6f02c1975ab6c779ff73409411c37bec2e984262459935afd196c1dbe960075e914967a047743ccf726fce3d3ebb4417ca2e3c34538fbceb8 + languageName: node + linkType: hard + +"@humanwhocodes/config-array@npm:^0.11.14": + 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 + +"@hypothesis/frontend-build@npm:^3.0.0": + version: 3.0.0 + resolution: "@hypothesis/frontend-build@npm:3.0.0" + dependencies: + commander: ^11.0.0 + fancy-log: ^2.0.0 + glob: ^10.0.0 + peerDependencies: + autoprefixer: ^10.3.7 + karma: ^6.3.4 + postcss: ^8.3.9 + rollup: ^4.0.2 + sass: ^1.43.2 + tailwindcss: ^3.0.11 + peerDependenciesMeta: + tailwindcss: + optional: true + checksum: ea05f3c00bc9054cd37aaabb5bc391e39cf7c8abecfc002950a22a6fe61d13a28b89194d2bbba6619d234d37a1c8ca5874a191ad8e50485ed66e77805b8fe385 + languageName: node + linkType: hard + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: ^5.1.2 + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: ^7.0.1 + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: ^8.1.0 + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 4a473b9b32a7d4d3cfb7a614226e555091ff0c5a29a1734c28c72a182c2f6699b26fc6b5c2131dfd841e86b185aea714c72201d7c98c2fba5f17709333a67aeb + 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": + version: 0.3.3 + resolution: "@jridgewell/gen-mapping@npm:0.3.3" + dependencies: + "@jridgewell/set-array": ^1.0.1 + "@jridgewell/sourcemap-codec": ^1.4.10 + "@jridgewell/trace-mapping": ^0.3.9 + checksum: 4a74944bd31f22354fc01c3da32e83c19e519e3bbadafa114f6da4522ea77dd0c2842607e923a591d60a76699d819a2fbb6f3552e277efdb9b58b081390b60ab + languageName: node + linkType: hard + +"@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/gen-mapping@npm:^0.3.5": + version: 0.3.5 + resolution: "@jridgewell/gen-mapping@npm:0.3.5" + dependencies: + "@jridgewell/set-array": ^1.2.1 + "@jridgewell/sourcemap-codec": ^1.4.10 + "@jridgewell/trace-mapping": ^0.3.24 + checksum: ff7a1764ebd76a5e129c8890aa3e2f46045109dabde62b0b6c6a250152227647178ff2069ea234753a690d8f3c4ac8b5e7b267bbee272bffb7f3b0a370ab6e52 + languageName: node + linkType: hard + +"@jridgewell/resolve-uri@npm:3.1.0, @jridgewell/resolve-uri@npm:^3.0.3": + version: 3.1.0 + resolution: "@jridgewell/resolve-uri@npm:3.1.0" + checksum: b5ceaaf9a110fcb2780d1d8f8d4a0bfd216702f31c988d8042e5f8fbe353c55d9b0f55a1733afdc64806f8e79c485d2464680ac48a0d9fcadb9548ee6b81d267 + languageName: node + linkType: hard + +"@jridgewell/resolve-uri@npm:^3.1.0": + version: 3.1.2 + resolution: "@jridgewell/resolve-uri@npm:3.1.2" + checksum: 83b85f72c59d1c080b4cbec0fef84528963a1b5db34e4370fa4bd1e3ff64a0d80e0cee7369d11d73c704e0286fb2865b530acac7a871088fbe92b5edf1000870 + 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/set-array@npm:^1.2.1": + version: 1.2.1 + resolution: "@jridgewell/set-array@npm:1.2.1" + checksum: 832e513a85a588f8ed4f27d1279420d8547743cc37fcad5a5a76fc74bb895b013dfe614d0eed9cb860048e6546b798f8f2652020b4b2ba0561b05caa8c654b10 + languageName: node + linkType: hard + +"@jridgewell/source-map@npm:^0.3.3": + version: 0.3.5 + resolution: "@jridgewell/source-map@npm:0.3.5" + dependencies: + "@jridgewell/gen-mapping": ^0.3.0 + "@jridgewell/trace-mapping": ^0.3.9 + checksum: 1ad4dec0bdafbade57920a50acec6634f88a0eb735851e0dda906fa9894e7f0549c492678aad1a10f8e144bfe87f238307bf2a914a1bc85b7781d345417e9f6f + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.10": + version: 1.4.14 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" + checksum: 61100637b6d173d3ba786a5dff019e1a74b1f394f323c1fee337ff390239f053b87266c7a948777f4b1ee68c01a8ad0ab61e5ff4abb5a012a0b091bec391ab97 + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15": + version: 1.4.15 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" + checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.17": + version: 0.3.17 + resolution: "@jridgewell/trace-mapping@npm:0.3.17" + dependencies: + "@jridgewell/resolve-uri": 3.1.0 + "@jridgewell/sourcemap-codec": 1.4.14 + checksum: 9d703b859cff5cd83b7308fd457a431387db5db96bd781a63bf48e183418dd9d3d44e76b9e4ae13237f6abeeb25d739ec9215c1d5bfdd08f66f750a50074a339 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": + version: 0.3.25 + resolution: "@jridgewell/trace-mapping@npm:0.3.25" + dependencies: + "@jridgewell/resolve-uri": ^3.1.0 + "@jridgewell/sourcemap-codec": ^1.4.14 + checksum: 9d3c40d225e139987b50c48988f8717a54a8c994d8a948ee42e1412e08988761d0754d7d10b803061cc3aebf35f92a5dbbab493bd0e1a9ef9e89a2130e83ba34 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.9": + version: 0.3.14 + resolution: "@jridgewell/trace-mapping@npm:0.3.14" + dependencies: + "@jridgewell/resolve-uri": ^3.0.3 + "@jridgewell/sourcemap-codec": ^1.4.10 + checksum: b9537b9630ffb631aef9651a085fe361881cde1772cd482c257fe3c78c8fd5388d681f504a9c9fe1081b1c05e8f75edf55ee10fdb58d92bbaa8dbf6a7bd6b18c + 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": + version: 2.0.5 + resolution: "@nodelib/fs.stat@npm:2.0.5" + checksum: 012480b5ca9d97bff9261571dbbec7bbc6033f69cc92908bc1ecfad0792361a5a1994bc48674b9ef76419d056a03efadfce5a6cf6dbc0a36559571a7a483f6f0 + languageName: node + linkType: hard + +"@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:^3.1.0": + version: 3.1.0 + resolution: "@npmcli/fs@npm:3.1.0" + dependencies: + semver: ^7.3.5 + checksum: a50a6818de5fc557d0b0e6f50ec780a7a02ab8ad07e5ac8b16bf519e0ad60a144ac64f97d05c443c3367235d337182e1d012bbac0eb8dbae8dc7b40b193efd0e + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 6ad6a00fc4f2f2cfc6bff76fb1d88b8ee20bc0601e18ebb01b6d4be583733a860239a521a7fbca73b612e66705078809483549d2b18f370eb346c5155c8e4a0f + languageName: node + linkType: hard + +"@rollup/plugin-babel@npm:^6.0.4": + version: 6.0.4 + resolution: "@rollup/plugin-babel@npm:6.0.4" + dependencies: + "@babel/helper-module-imports": ^7.18.6 + "@rollup/pluginutils": ^5.0.1 + peerDependencies: + "@babel/core": ^7.0.0 + "@types/babel__core": ^7.1.9 + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + "@types/babel__core": + optional: true + rollup: + optional: true + checksum: c035fd7814ad75b9b584727fe31c86611697be88abd2a4ac836c17fa42a241de46f698c225d9c4e65336374fb19e48a1e9a22cc374a0cc0b867c3970eb62b2f2 + languageName: node + linkType: hard + +"@rollup/plugin-commonjs@npm:^25.0.7": + version: 25.0.7 + resolution: "@rollup/plugin-commonjs@npm:25.0.7" + dependencies: + "@rollup/pluginutils": ^5.0.1 + commondir: ^1.0.1 + estree-walker: ^2.0.2 + glob: ^8.0.3 + is-reference: 1.2.1 + magic-string: ^0.30.3 + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 052e11839a9edc556eda5dcc759ab816dcc57e9f0f905a1e6e14fff954eaa6b1e2d0d544f5bd18d863993c5eba43d8ac9c19d9bb53b1c3b1213f32cfc9d50b2e + languageName: node + linkType: hard + +"@rollup/plugin-node-resolve@npm:^15.2.3": + version: 15.2.3 + resolution: "@rollup/plugin-node-resolve@npm:15.2.3" + dependencies: + "@rollup/pluginutils": ^5.0.1 + "@types/resolve": 1.20.2 + deepmerge: ^4.2.2 + is-builtin-module: ^3.2.1 + is-module: ^1.0.0 + resolve: ^1.22.1 + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 730f32c2f8fdddff07cf0fca86a5dac7c475605fb96930197a868c066e62eb6388c557545e4f7d99b7a283411754c9fbf98944ab086b6074e04fc1292e234aa8 + languageName: node + linkType: hard + +"@rollup/plugin-terser@npm:^0.4.4": + version: 0.4.4 + resolution: "@rollup/plugin-terser@npm:0.4.4" + dependencies: + serialize-javascript: ^6.0.1 + smob: ^1.0.0 + terser: ^5.17.4 + peerDependencies: + rollup: ^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 5472f659fbb7034488df91eb01ecd2ddf6d2cf203d049aa486139225ad5566254c6ec24aad1f5d1167e35f480212ede5160df9cc80e149a28874f78ed6a7fd9a + languageName: node + linkType: hard + +"@rollup/pluginutils@npm:^5.0.1": + version: 5.0.2 + resolution: "@rollup/pluginutils@npm:5.0.2" + dependencies: + "@types/estree": ^1.0.0 + estree-walker: ^2.0.2 + picomatch: ^2.3.1 + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: edea15e543bebc7dcac3b0ac8bc7b8e8e6dbd46e2864dbe5dd28072de1fbd5b0e10d545a610c0edaa178e8a7ac432e2a2a52e547ece1308471412caba47db8ce + languageName: node + linkType: hard + +"@rollup/rollup-android-arm-eabi@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.17.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-android-arm64@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-android-arm64@npm:4.17.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-arm64@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-darwin-arm64@npm:4.17.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-x64@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-darwin-x64@npm:4.17.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-gnueabihf@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.17.2" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-musleabihf@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.17.2" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-gnu@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.17.2" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-musl@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.17.2" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.17.2" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.17.2" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-s390x-gnu@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.17.2" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-gnu@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.17.2" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-musl@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.17.2" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-win32-arm64-msvc@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.17.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-ia32-msvc@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.17.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-msvc@npm:4.17.2": + version: 4.17.2 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.17.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@sinonjs/commons@npm:^2.0.0": + version: 2.0.0 + resolution: "@sinonjs/commons@npm:2.0.0" + dependencies: + type-detect: 4.0.8 + checksum: 5023ba17edf2b85ed58262313b8e9b59e23c6860681a9af0200f239fe939e2b79736d04a260e8270ddd57196851dde3ba754d7230be5c5234e777ae2ca8af137 + languageName: node + linkType: hard + +"@sinonjs/commons@npm:^3.0.0": + version: 3.0.0 + resolution: "@sinonjs/commons@npm:3.0.0" + dependencies: + type-detect: 4.0.8 + checksum: b4b5b73d4df4560fb8c0c7b38c7ad4aeabedd362f3373859d804c988c725889cde33550e4bcc7cd316a30f5152a2d1d43db71b6d0c38f5feef71fd8d016763f8 + languageName: node + linkType: hard + +"@sinonjs/fake-timers@npm:^10.0.2": + version: 10.3.0 + resolution: "@sinonjs/fake-timers@npm:10.3.0" + dependencies: + "@sinonjs/commons": ^3.0.0 + checksum: 614d30cb4d5201550c940945d44c9e0b6d64a888ff2cd5b357f95ad6721070d6b8839cd10e15b76bf5e14af0bcc1d8f9ec00d49a46318f1f669a4bec1d7f3148 + languageName: node + linkType: hard + +"@sinonjs/fake-timers@npm:^11.2.2": + version: 11.2.2 + resolution: "@sinonjs/fake-timers@npm:11.2.2" + dependencies: + "@sinonjs/commons": ^3.0.0 + checksum: 68c29b0e1856fdc280df03ddbf57c726420b78e9f943a241b471edc018fb14ff36fdc1daafd6026cba08c3c7f50c976fb7ae11b88ff44cd7f609692ca7d25158 + languageName: node + linkType: hard + +"@sinonjs/samsam@npm:^8.0.0": + version: 8.0.0 + resolution: "@sinonjs/samsam@npm:8.0.0" + dependencies: + "@sinonjs/commons": ^2.0.0 + lodash.get: ^4.4.2 + type-detect: ^4.0.8 + checksum: 95e40d0bb9f7288e27c379bee1b03c3dc51e7e78b9d5ea6aef66a690da7e81efc4715145b561b449cefc5361a171791e3ce30fb1a46ab247d4c0766024c60a60 + languageName: node + linkType: hard + +"@sinonjs/text-encoding@npm:^0.7.1": + version: 0.7.1 + resolution: "@sinonjs/text-encoding@npm:0.7.1" + checksum: 130de0bb568c5f8a611ec21d1a4e3f80ab0c5ec333010f49cfc1adc5cba6d8808699c8a587a46b0f0b016a1f4c1389bc96141e773e8460fcbb441875b2e91ba7 + languageName: node + linkType: hard + +"@socket.io/component-emitter@npm:~3.1.0": + version: 3.1.0 + resolution: "@socket.io/component-emitter@npm:3.1.0" + checksum: db069d95425b419de1514dffe945cc439795f6a8ef5b9465715acf5b8b50798e2c91b8719cbf5434b3fe7de179d6cdcd503c277b7871cb3dd03febb69bdd50fa + 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 + +"@types/cookie@npm:^0.4.1": + version: 0.4.1 + resolution: "@types/cookie@npm:0.4.1" + checksum: 3275534ed69a76c68eb1a77d547d75f99fedc80befb75a3d1d03662fb08d697e6f8b1274e12af1a74c6896071b11510631ba891f64d30c78528d0ec45a9c1a18 + languageName: node + linkType: hard + +"@types/cors@npm:^2.8.12": + version: 2.8.12 + resolution: "@types/cors@npm:2.8.12" + checksum: 8c45f112c7d1d2d831b4b266f2e6ed33a1887a35dcbfe2a18b28370751fababb7cd045e745ef84a523c33a25932678097bf79afaa367c6cb3fa0daa7a6438257 + languageName: node + linkType: hard + +"@types/estree@npm:*": + version: 0.0.50 + resolution: "@types/estree@npm:0.0.50" + checksum: 9a2b6a4a8c117f34d08fbda5e8f69b1dfb109f7d149b60b00fd7a9fb6ac545c078bc590aa4ec2f0a256d680cf72c88b3b28b60c326ee38a7bc8ee1ee95624922 + languageName: node + linkType: hard + +"@types/estree@npm:1.0.5": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: dd8b5bed28e6213b7acd0fb665a84e693554d850b0df423ac8076cc3ad5823a6bc26b0251d080bdc545af83179ede51dd3f6fa78cad2c46ed1f29624ddf3e41a + languageName: node + linkType: hard + +"@types/estree@npm:^1.0.0": + version: 1.0.0 + resolution: "@types/estree@npm:1.0.0" + checksum: 910d97fb7092c6738d30a7430ae4786a38542023c6302b95d46f49420b797f21619cdde11fa92b338366268795884111c2eb10356e4bd2c8ad5b92941e9e6443 + languageName: node + linkType: hard + +"@types/expect@npm:^1.20.4": + version: 1.20.4 + resolution: "@types/expect@npm:1.20.4" + checksum: c09a9abec2c1776dd8948920dc3bad87b1206c843509d3d3002040983b1769b2e3914202a6c20b72e5c3fb5738a1ab87cb7be9d3fe9efabf2a324173b222a224 + languageName: node + linkType: hard + +"@types/node@npm:*": + version: 20.10.1 + resolution: "@types/node@npm:20.10.1" + dependencies: + undici-types: ~5.26.4 + checksum: 9dfdcd2496ce535dba0ae496985d6e991a8a5d70a180db3a94c947a2123d99318a95dce4aa2a192f7e57c3afa3fdb44d6fd63e18efd49568950d6c239dadcc39 + languageName: node + linkType: hard + +"@types/node@npm:>=10.0.0": + version: 18.11.9 + resolution: "@types/node@npm:18.11.9" + checksum: cc0aae109e9b7adefc32eecb838d6fad931663bb06484b5e9cbbbf74865c721b03d16fd8d74ad90e31dbe093d956a7c2c306ba5429ba0c00f3f7505103d7a496 + languageName: node + linkType: hard + +"@types/resolve@npm:1.20.2": + version: 1.20.2 + resolution: "@types/resolve@npm:1.20.2" + checksum: 61c2cad2499ffc8eab36e3b773945d337d848d3ac6b7b0a87c805ba814bc838ef2f262fc0f109bfd8d2e0898ff8bd80ad1025f9ff64f1f71d3d4294c9f14e5f6 + languageName: node + linkType: hard + +"@types/vinyl@npm:^2.0.9": + version: 2.0.11 + resolution: "@types/vinyl@npm:2.0.11" + dependencies: + "@types/expect": ^1.20.4 + "@types/node": "*" + checksum: e921718775992ada7712a26da9635fb970bcdbcf4c4cc832344092d68710ffaf7dd3cce42b0050b2741b2cf75a30f3e1b87e1032ae26552db1faac17094d2b50 + 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 + +"abbrev@npm:1, 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": + 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-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@npm:^8.8.2": + version: 8.10.0 + resolution: "acorn@npm:8.10.0" + bin: + acorn: bin/acorn + checksum: 538ba38af0cc9e5ef983aee196c4b8b4d87c0c94532334fa7e065b2c8a1f85863467bb774231aae91613fcda5e68740c15d97b1967ae3394d20faddddd8af61d + languageName: node + linkType: hard + +"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 + +"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.3.0 + resolution: "agentkeepalive@npm:4.3.0" + dependencies: + debug: ^4.1.0 + depd: ^2.0.0 + humanize-ms: ^1.2.1 + checksum: 982453aa44c11a06826c836025e5162c846e1200adb56f2d075400da7d32d87021b3b0a58768d949d824811f5654223d5a8a3dad120921a2439625eb847c6260 + 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@npm:^6.12.4": + 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 + +"ansi-colors@npm:4.1.1": + version: 4.1.1 + resolution: "ansi-colors@npm:4.1.1" + checksum: 138d04a51076cb085da0a7e2d000c5c0bb09f6e772ed5c65c53cb118d37f6c5f1637506d7155fb5f330f0abcf6f12fa2e489ac3f8cdab9da393bf1bb4f9a32b0 + languageName: node + linkType: hard + +"ansi-colors@npm:^1.0.1": + version: 1.1.0 + resolution: "ansi-colors@npm:1.1.0" + dependencies: + ansi-wrap: ^0.1.0 + checksum: 0092e5c10f2c396f436457dae2ab9e53af1df077f324a900a1451a1cfa99cd41dd6e0c87b9a3f3a6023a36c49584b243a06334e68ff5e1d8d8bd4cea84f442f1 + languageName: node + linkType: hard + +"ansi-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "ansi-regex@npm:3.0.0" + checksum: 2ad11c416f81c39f5c65eafc88cf1d71aa91d76a2f766e75e457c2a3c43e8a003aadbf2966b61c497aa6a6940a36412486c975b3270cdfc3f413b69826189ec3 + 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:^6.1.0": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 + languageName: node + linkType: hard + +"ansi-wrap@npm:^0.1.0": + version: 0.1.0 + resolution: "ansi-wrap@npm:0.1.0" + checksum: f24f652a5e450c0561cbc7d298ffa62dcd33c72f9da34fd3c24538dbf82de8fc21b7f924dc30cd9d01360bd2893d1954f0a60eee0550ca629bb148dcbeef5c5b + languageName: node + linkType: hard + +"anymatch@npm:^3.1.3": + 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 + +"anymatch@npm:~3.1.2": + version: 3.1.2 + resolution: "anymatch@npm:3.1.2" + dependencies: + normalize-path: ^3.0.0 + picomatch: ^2.0.4 + checksum: 985163db2292fac9e5a1e072bf99f1b5baccf196e4de25a0b0b81865ebddeb3b3eb4480734ef0a2ac8c002845396b91aa89121f5b84f93981a4658164a9ec6e9 + 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 + +"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 + +"argparse@npm:^2.0.1": + version: 2.0.1 + resolution: "argparse@npm:2.0.1" + checksum: 83644b56493e89a254bae05702abf3a1101b4fa4d0ca31df1c9985275a5a5bd47b3c27b7fa0b71098d41114d8ca000e6ed90cad764b306f8a503665e4d517ced + languageName: node + linkType: hard + +"arr-diff@npm:^4.0.0": + version: 4.0.0 + resolution: "arr-diff@npm:4.0.0" + checksum: ea7c8834842ad3869297f7915689bef3494fd5b102ac678c13ffccab672d3d1f35802b79e90c4cfec2f424af3392e44112d1ccf65da34562ed75e049597276a0 + languageName: node + linkType: hard + +"arr-union@npm:^3.1.0": + version: 3.1.0 + resolution: "arr-union@npm:3.1.0" + checksum: b5b0408c6eb7591143c394f3be082fee690ddd21f0fdde0a0a01106799e847f67fcae1b7e56b0a0c173290e29c6aca9562e82b300708a268bc8f88f3d6613cb9 + languageName: node + linkType: hard + +"array-buffer-byte-length@npm:^1.0.0": + version: 1.0.0 + resolution: "array-buffer-byte-length@npm:1.0.0" + dependencies: + call-bind: ^1.0.2 + is-array-buffer: ^3.0.1 + checksum: 044e101ce150f4804ad19c51d6c4d4cfa505c5b2577bd179256e4aa3f3f6a0a5e9874c78cd428ee566ac574c8a04d7ce21af9fe52e844abfdccb82b33035a7c3 + languageName: node + linkType: hard + +"array-buffer-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "array-buffer-byte-length@npm:1.0.1" + dependencies: + call-bind: ^1.0.5 + is-array-buffer: ^3.0.4 + checksum: 53524e08f40867f6a9f35318fafe467c32e45e9c682ba67b11943e167344d2febc0f6977a17e699b05699e805c3e8f073d876f8bbf1b559ed494ad2cd0fae09e + languageName: node + linkType: hard + +"array-each@npm:^1.0.1": + version: 1.0.1 + resolution: "array-each@npm:1.0.1" + checksum: eb2393c1200003993d97dab2b280aa01e6ca339b383198e5d250cc8cd31f8012a0c22b66f275401a80e89e21bfab420e0f4c77c295637dea525fe0e152ba2300 + languageName: node + linkType: hard + +"array-includes@npm:^3.1.3": + 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-includes@npm:^3.1.7": + version: 3.1.8 + resolution: "array-includes@npm:3.1.8" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + get-intrinsic: ^1.2.4 + is-string: ^1.0.7 + checksum: eb39ba5530f64e4d8acab39297c11c1c5be2a4ea188ab2b34aba5fb7224d918f77717a9d57a3e2900caaa8440e59431bdaf5c974d5212ef65d97f132e38e2d91 + languageName: node + linkType: hard + +"array-slice@npm:^1.0.0": + version: 1.1.0 + resolution: "array-slice@npm:1.1.0" + checksum: 3c8ecc7eefe104c97e2207e1d5644be160924c89e08b1807f3cad77f4a8fb10150fc275ebfab90dc02064d178b010cad31b69c9386769d172da270be5e233c51 + languageName: node + linkType: hard + +"array.prototype.findlast@npm:^1.2.4": + version: 1.2.5 + resolution: "array.prototype.findlast@npm:1.2.5" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + es-shim-unscopables: ^1.0.2 + checksum: 83ce4ad95bae07f136d316f5a7c3a5b911ac3296c3476abe60225bc4a17938bf37541972fcc37dd5adbc99cbb9c928c70bbbfc1c1ce549d41a415144030bb446 + languageName: node + linkType: hard + +"array.prototype.flatmap@npm:^1.3.2": + version: 1.3.2 + resolution: "array.prototype.flatmap@npm:1.3.2" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + es-shim-unscopables: ^1.0.0 + checksum: ce09fe21dc0bcd4f30271f8144083aa8c13d4639074d6c8dc82054b847c7fc9a0c97f857491f4da19d4003e507172a78f4bcd12903098adac8b9cd374f734be3 + languageName: node + linkType: hard + +"array.prototype.toreversed@npm:^1.1.2": + version: 1.1.2 + resolution: "array.prototype.toreversed@npm:1.1.2" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + es-shim-unscopables: ^1.0.0 + checksum: 58598193426282155297bedf950dc8d464624a0d81659822fb73124286688644cb7e0e4927a07f3ab2daaeb6617b647736cc3a5e6ca7ade5bb8e573b284e6240 + languageName: node + linkType: hard + +"array.prototype.tosorted@npm:^1.1.3": + version: 1.1.3 + resolution: "array.prototype.tosorted@npm:1.1.3" + dependencies: + call-bind: ^1.0.5 + define-properties: ^1.2.1 + es-abstract: ^1.22.3 + es-errors: ^1.1.0 + es-shim-unscopables: ^1.0.2 + checksum: 555e8808086bbde9e634c5dc5a8c0a2f1773075447b43b2fa76ab4f94f4e90f416d2a4f881024e1ce1a2931614caf76cd6b408af901c9d7cd13061d0d268f5af + languageName: node + linkType: hard + +"arraybuffer.prototype.slice@npm:^1.0.2": + version: 1.0.2 + resolution: "arraybuffer.prototype.slice@npm:1.0.2" + dependencies: + array-buffer-byte-length: ^1.0.0 + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + get-intrinsic: ^1.2.1 + is-array-buffer: ^3.0.2 + is-shared-array-buffer: ^1.0.2 + checksum: c200faf437786f5b2c80d4564ff5481c886a16dee642ef02abdc7306c7edd523d1f01d1dd12b769c7eb42ac9bc53874510db19a92a2c035c0f6696172aafa5d3 + languageName: node + linkType: hard + +"arraybuffer.prototype.slice@npm:^1.0.3": + version: 1.0.3 + resolution: "arraybuffer.prototype.slice@npm:1.0.3" + dependencies: + array-buffer-byte-length: ^1.0.1 + call-bind: ^1.0.5 + define-properties: ^1.2.1 + es-abstract: ^1.22.3 + es-errors: ^1.2.1 + get-intrinsic: ^1.2.3 + is-array-buffer: ^3.0.4 + is-shared-array-buffer: ^1.0.2 + checksum: 352259cba534dcdd969c92ab002efd2ba5025b2e3b9bead3973150edbdf0696c629d7f4b3f061c5931511e8207bdc2306da614703c820b45dabce39e3daf7e3e + languageName: node + linkType: hard + +"assertion-error@npm:^2.0.1": + version: 2.0.1 + resolution: "assertion-error@npm:2.0.1" + checksum: a0789dd882211b87116e81e2648ccb7f60340b34f19877dd020b39ebb4714e475eb943e14ba3e22201c221ef6645b7bfe10297e76b6ac95b48a9898c1211ce66 + languageName: node + linkType: hard + +"assign-symbols@npm:^1.0.0": + version: 1.0.0 + resolution: "assign-symbols@npm:1.0.0" + checksum: c0eb895911d05b6b2d245154f70461c5e42c107457972e5ebba38d48967870dee53bcdf6c7047990586daa80fab8dab3cc6300800fbd47b454247fdedd859a2c + languageName: node + linkType: hard + +"async-done@npm:^2.0.0": + version: 2.0.0 + resolution: "async-done@npm:2.0.0" + dependencies: + end-of-stream: ^1.4.4 + once: ^1.4.0 + stream-exhaust: ^1.0.2 + checksum: 88e31815a760885723d88379b593eec44c5fceb37149dd295ba52eaca809c93696e94e9ea691210d3f1108e262bc9fa00ef4ffd76e78ded6b5bca03bff223fb0 + languageName: node + linkType: hard + +"async-settle@npm:^2.0.0": + version: 2.0.0 + resolution: "async-settle@npm:2.0.0" + dependencies: + async-done: ^2.0.0 + checksum: 69398507b20e7d7628ee6756ca1547c80744eb5b33cc9b1a22e0a8a38a6b864be96b93e0940de45113afa33cb34d89151ee9c85dbffcd51e741c8146cf695d15 + languageName: node + linkType: hard + +"autoprefixer@npm:^10.4.19": + version: 10.4.19 + resolution: "autoprefixer@npm:10.4.19" + dependencies: + browserslist: ^4.23.0 + caniuse-lite: ^1.0.30001599 + fraction.js: ^4.3.7 + 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: 3a4bc5bace05e057396dca2b306503efc175e90e8f2abf5472d3130b72da1d54d97c0ee05df21bf04fe66a7df93fd8c8ec0f1aca72a165f4701a02531abcbf11 + 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 + +"available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: ^1.0.0 + checksum: 1aa3ffbfe6578276996de660848b6e95669d9a95ad149e3dd0c0cda77db6ee1dbd9d1dd723b65b6d277b882dd0c4b91a654ae9d3cf9e1254b7e93e4908d78fd3 + languageName: node + linkType: hard + +"babel-plugin-mockable-imports@npm:^2.0.1": + version: 2.0.1 + resolution: "babel-plugin-mockable-imports@npm:2.0.1" + checksum: 57bf99088d9096bb35f53b6b2e6d091fb1cfcea51000cfe70c2655250ae443b4595982527cfd2550499fc02b23a3fb2e7de8ff055c76f6c77ea509f02dfc47e2 + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs2@npm:^0.4.10": + version: 0.4.10 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.10" + dependencies: + "@babel/compat-data": ^7.22.6 + "@babel/helper-define-polyfill-provider": ^0.6.1 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 2c0e4868789152f50db306f4957fa7934876cefb51d5d86436595f0b091539e45ce0e9c0125b5db2d71f913b29cd48ae76b8e942ba28fcf2273e084f54664a1c + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs3@npm:^0.10.4": + version: 0.10.4 + resolution: "babel-plugin-polyfill-corejs3@npm:0.10.4" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.6.1 + core-js-compat: ^3.36.1 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: b96a54495f7cc8b3797251c8c15f5ed015edddc3110fc122f6b32c94bec33af1e8bc56fa99091808f500bde0cccaaa266889cdc5935d9e6e9cf09898214f02dd + languageName: node + linkType: hard + +"babel-plugin-polyfill-regenerator@npm:^0.6.1": + version: 0.6.1 + resolution: "babel-plugin-polyfill-regenerator@npm:0.6.1" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.6.1 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 9df4a8e9939dd419fed3d9ea26594b4479f2968f37c225e1b2aa463001d7721f5537740e6622909d2a570b61cec23256924a1701404fc9d6fd4474d3e845cedb + languageName: node + linkType: hard + +"bach@npm:^2.0.1": + version: 2.0.1 + resolution: "bach@npm:2.0.1" + dependencies: + async-done: ^2.0.0 + async-settle: ^2.0.0 + now-and-later: ^3.0.0 + checksum: 785d8f27043f247a5eb250d83eb1d7617fe2729903a691c40098affb93bdcfb34dfe3444b3190fa1895153fb412e19b69add0f6c2f92d7c00af2a9672992afd3 + 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 + +"bare-events@npm:^2.2.0": + version: 2.2.2 + resolution: "bare-events@npm:2.2.2" + checksum: 154d3fc044cc171d3b85a89b768e626417b60c050123ac2ac10fc002152b4bdeb359ed1453ad54c0f1d05a7786f780d3b976af68e55c09fe4579d8466d3ff256 + 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 + +"base64id@npm:2.0.0, base64id@npm:~2.0.0": + version: 2.0.0 + resolution: "base64id@npm:2.0.0" + checksum: 581b1d37e6cf3738b7ccdd4d14fe2bfc5c238e696e2720ee6c44c183b838655842e22034e53ffd783f872a539915c51b0d4728a49c7cc678ac5a758e00d62168 + 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 + +"bl@npm:^5.0.0": + version: 5.1.0 + resolution: "bl@npm:5.1.0" + dependencies: + buffer: ^6.0.3 + inherits: ^2.0.4 + readable-stream: ^3.4.0 + checksum: a7a438ee0bc540e80b8eb68cc1ad759a9c87df06874a99411d701d01cc0b36f30cd20050512ac3e77090138890960e07bfee724f3ee6619bb39a569f5cc3b1bc + languageName: node + linkType: hard + +"body-parser@npm:^1.19.0": + version: 1.19.0 + resolution: "body-parser@npm:1.19.0" + 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 + checksum: 490231b4c89bbd43112762f7ba8e5342c174a6c9f64284a3b0fcabf63277e332f8316765596f1e5b15e4f3a6cf0422e005f4bb3149ed3a224bb025b7a36b9ac1 + languageName: node + linkType: hard + +"boolbase@npm:^1.0.0": + version: 1.0.0 + resolution: "boolbase@npm:1.0.0" + checksum: 3e25c80ef626c3a3487c73dbfc70ac322ec830666c9ad915d11b701142fab25ec1e63eff2c450c74347acfd2de854ccde865cd79ef4db1683f7c7b046ea43bb0 + languageName: node + linkType: hard + +"bootstrap@npm:^4.6.2": + version: 4.6.2 + resolution: "bootstrap@npm:4.6.2" + peerDependencies: + jquery: 1.9.1 - 3 + popper.js: ^1.16.1 + checksum: 3f4e7768ff7d618c49d4bf4f02aa54a9bfb679d4eecb0f3854fa4af1a17b9114b147009c435946432cdd1572efffc71d88ec385c55943a12fa66253cde0876b0 + 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.2 + resolution: "braces@npm:3.0.2" + dependencies: + fill-range: ^7.0.1 + checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 + languageName: node + linkType: hard + +"browser-stdout@npm:1.3.1": + version: 1.3.1 + resolution: "browser-stdout@npm:1.3.1" + checksum: b717b19b25952dd6af483e368f9bcd6b14b87740c3d226c2977a65e84666ffd67000bddea7d911f111a9b6ddc822b234de42d52ab6507bce4119a4cc003ef7b3 + languageName: node + linkType: hard + +"browserslist@npm:^4.21.9": + version: 4.21.10 + resolution: "browserslist@npm:4.21.10" + dependencies: + caniuse-lite: ^1.0.30001517 + electron-to-chromium: ^1.4.477 + node-releases: ^2.0.13 + update-browserslist-db: ^1.0.11 + bin: + browserslist: cli.js + checksum: 1e27c0f111a35d1dd0e8fc2c61781b0daefabc2c9471b0b10537ce54843014bceb2a1ce4571af1a82b2bf1e6e6e05d38865916689a158f03bc2c7a4ec2577db8 + languageName: node + linkType: hard + +"browserslist@npm:^4.22.2": + version: 4.22.2 + resolution: "browserslist@npm:4.22.2" + dependencies: + caniuse-lite: ^1.0.30001565 + electron-to-chromium: ^1.4.601 + node-releases: ^2.0.14 + update-browserslist-db: ^1.0.13 + bin: + browserslist: cli.js + checksum: 33ddfcd9145220099a7a1ac533cecfe5b7548ffeb29b313e1b57be6459000a1f8fa67e781cf4abee97268ac594d44134fcc4a6b2b4750ceddc9796e3a22076d9 + languageName: node + linkType: hard + +"browserslist@npm:^4.23.0": + version: 4.23.0 + resolution: "browserslist@npm:4.23.0" + dependencies: + caniuse-lite: ^1.0.30001587 + electron-to-chromium: ^1.4.668 + node-releases: ^2.0.14 + update-browserslist-db: ^1.0.13 + bin: + browserslist: cli.js + checksum: 436f49e796782ca751ebab7edc010cfc9c29f68536f387666cd70ea22f7105563f04dd62c6ff89cb24cc3254d17cba385f979eeeb3484d43e012412ff7e75def + 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:^6.0.3": + version: 6.0.3 + resolution: "buffer@npm:6.0.3" + dependencies: + base64-js: ^1.3.1 + ieee754: ^1.2.1 + checksum: 5ad23293d9a731e4318e420025800b42bf0d264004c0286c8cc010af7a270c7a0f6522e84f54b9ad65cbd6db20b8badbfd8d2ebf4f80fa03dab093b89e68c3f9 + languageName: node + linkType: hard + +"builtin-modules@npm:^3.3.0": + version: 3.3.0 + resolution: "builtin-modules@npm:3.3.0" + checksum: db021755d7ed8be048f25668fe2117620861ef6703ea2c65ed2779c9e3636d5c3b82325bd912244293959ff3ae303afa3471f6a15bf5060c103e4cc3a839749d + languageName: node + linkType: hard + +"bytes@npm:3.1.0": + version: 3.1.0 + resolution: "bytes@npm:3.1.0" + checksum: 7c3b21c5d9d44ed455460d5d36a31abc6fa2ce3807964ba60a4b03fd44454c8cf07bb0585af83bfde1c5cc2ea4bbe5897bc3d18cd15e0acf25a3615a35aba2df + languageName: node + linkType: hard + +"cacache@npm:^17.0.0": + version: 17.1.3 + resolution: "cacache@npm:17.1.3" + dependencies: + "@npmcli/fs": ^3.1.0 + fs-minipass: ^3.0.0 + glob: ^10.2.2 + lru-cache: ^7.7.1 + minipass: ^5.0.0 + minipass-collect: ^1.0.2 + minipass-flush: ^1.0.5 + minipass-pipeline: ^1.2.4 + p-map: ^4.0.0 + ssri: ^10.0.0 + tar: ^6.1.11 + unique-filename: ^3.0.0 + checksum: 385756781e1e21af089160d89d7462b7ed9883c978e848c7075b90b73cb823680e66092d61513050164588387d2ca87dd6d910e28d64bc13a9ac82cd8580c796 + 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 + +"call-bind@npm:^1.0.4, call-bind@npm:^1.0.5": + version: 1.0.5 + resolution: "call-bind@npm:1.0.5" + dependencies: + function-bind: ^1.1.2 + get-intrinsic: ^1.2.1 + set-function-length: ^1.1.1 + checksum: 449e83ecbd4ba48e7eaac5af26fea3b50f8f6072202c2dd7c5a6e7a6308f2421abe5e13a3bbd55221087f76320c5e09f25a8fdad1bab2b77c68ae74d92234ea5 + languageName: node + linkType: hard + +"call-bind@npm:^1.0.6, call-bind@npm:^1.0.7": + version: 1.0.7 + resolution: "call-bind@npm:1.0.7" + dependencies: + es-define-property: ^1.0.0 + es-errors: ^1.3.0 + function-bind: ^1.1.2 + get-intrinsic: ^1.2.4 + set-function-length: ^1.2.1 + checksum: 295c0c62b90dd6522e6db3b0ab1ce26bdf9e7404215bda13cfee25b626b5ff1a7761324d58d38b1ef1607fc65aca2d06e44d2e18d0dfc6c14b465b00d8660029 + 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 + +"camelcase@npm:^6.0.0": + version: 6.2.0 + resolution: "camelcase@npm:6.2.0" + checksum: 8335cfd0ecc472eae685896a42afd8c9dacd193a91f569120b931c87deb053a1ba82102031b9b48a4dbc1d18066caeacf2e4ace8c3c7f0d02936d348dc0b5a87 + languageName: node + linkType: hard + +"caniuse-lite@npm:^1.0.30001517": + version: 1.0.30001518 + resolution: "caniuse-lite@npm:1.0.30001518" + checksum: 1b63272f6e3d628ac52e2547e0b75fc477004d4b19b63e34b2c045de7f2e48909f9ea513978fc5a46c4ab5ac6c9daf9cc5e6a78466e90684fb824c3f2105e8f5 + languageName: node + linkType: hard + +"caniuse-lite@npm:^1.0.30001565": + version: 1.0.30001572 + resolution: "caniuse-lite@npm:1.0.30001572" + checksum: 7d017a99a38e29ccee4ed3fc0ef1eb90cf082fcd3a7909c5c536c4ba1d55c5b26ecc1e4ad82c1caa6bfadce526764b354608710c9b61a75bdc7ce8ca15c5fcf2 + languageName: node + linkType: hard + +"caniuse-lite@npm:^1.0.30001587, caniuse-lite@npm:^1.0.30001599": + version: 1.0.30001599 + resolution: "caniuse-lite@npm:1.0.30001599" + checksum: d7e619e2e723547b7311ba0ca5134d9cd55df548e93dbedcf8a6e4ec74c7db91969c4272fb1ab2fd94cddeac6a8176ebf05853eb06689d5e76bb97d979a214b0 + languageName: node + linkType: hard + +"chai@npm:^5.1.0": + version: 5.1.0 + resolution: "chai@npm:5.1.0" + dependencies: + assertion-error: ^2.0.1 + check-error: ^2.0.0 + deep-eql: ^5.0.1 + loupe: ^3.1.0 + pathval: ^2.0.0 + checksum: f45c8c6ca8b35933efa533eba26a3ecf78378c86acf1d5d0ca82ae0be94a8d25f574f098e3f7e0294a3774e43931eb2e299c991516f22ac24c9042dce8a23ce0 + languageName: node + linkType: hard + +"chalk@npm:^2.0.0, chalk@npm:^2.0.1, chalk@npm:^2.1.0, 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:^4.0.0, 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 + +"chalk@npm:^5.3.0": + version: 5.3.0 + resolution: "chalk@npm:5.3.0" + checksum: 623922e077b7d1e9dedaea6f8b9e9352921f8ae3afe739132e0e00c275971bdd331268183b2628cf4ab1727c45ea1f28d7e24ac23ce1db1eb653c414ca8a5a80 + languageName: node + linkType: hard + +"change-file-extension@npm:^0.1.0": + version: 0.1.0 + resolution: "change-file-extension@npm:0.1.0" + checksum: 9a2321a9a8ca7e2c274983ccf842511c6763b67bfcc8be5cab9ff81307b4f8afe5350dc04dec846d89bf4018e338032888d71925a788f2dabcf290e74bd68858 + languageName: node + linkType: hard + +"check-error@npm:^2.0.0": + version: 2.0.0 + resolution: "check-error@npm:2.0.0" + checksum: 120f252c2e1ad82ef82a616662805345c6c361347bfd6203f8a28c53a158811dd0ea21278f29c8136cc9df12fc7f077d1a07124569d98fb396b3072d08f2f092 + languageName: node + linkType: hard + +"chokidar@npm:3.5.3, chokidar@npm:>=3.0.0 <4.0.0, chokidar@npm:^3.5.1": + 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 + +"chokidar@npm:^3.5.3": + version: 3.6.0 + resolution: "chokidar@npm:3.6.0" + 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: d2f29f499705dcd4f6f3bbed79a9ce2388cf530460122eed3b9c48efeab7a4e28739c6551fd15bec9245c6b9eeca7a32baa64694d64d9b6faeb74ddb8c4a413d + 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 + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 + 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-stats@npm:^1.0.0": + version: 1.0.0 + resolution: "clone-stats@npm:1.0.0" + checksum: 654c0425afc5c5c55a4d95b2e0c6eccdd55b5247e7a1e7cca9000b13688b96b0a157950c72c5307f9fd61f17333ad796d3cd654778f2d605438012391cc4ada5 + languageName: node + linkType: hard + +"clone@npm:^2.1.2": + version: 2.1.2 + resolution: "clone@npm:2.1.2" + checksum: aaf106e9bc025b21333e2f4c12da539b568db4925c0501a1bf4070836c9e848c892fa22c35548ce0d1132b08bbbfa17a00144fe58fccdab6fa900fec4250f67d + 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": + 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 + +"commander@npm:^11.0.0": + version: 11.1.0 + resolution: "commander@npm:11.1.0" + checksum: fd1a8557c6b5b622c89ecdfde703242ab7db3b628ea5d1755784c79b8e7cb0d74d65b4a262289b533359cd58e1bfc0bf50245dfbcd2954682a6f367c828b79ef + 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:^7.2.0": + version: 7.2.0 + resolution: "commander@npm:7.2.0" + checksum: 53501cbeee61d5157546c0bef0fedb6cdfc763a882136284bed9a07225f09a14b82d2a84e7637edfd1a679fb35ed9502fd58ef1d091e6287f60d790147f68ddc + 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 + +"concat-map@npm:0.0.1": + version: 0.0.1 + resolution: "concat-map@npm:0.0.1" + checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af + languageName: node + linkType: hard + +"connect@npm:^3.7.0": + version: 3.7.0 + resolution: "connect@npm:3.7.0" + dependencies: + debug: 2.6.9 + finalhandler: 1.1.2 + parseurl: ~1.3.3 + utils-merge: 1.0.1 + checksum: 96e1c4effcf219b065c7823e57351c94366d2e2a6952fa95e8212bffb35c86f1d5a3f9f6c5796d4cd3a5fdda628368b1c3cc44bf19c66cfd68fe9f9cab9177e2 + 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-type@npm:~1.0.4": + version: 1.0.4 + resolution: "content-type@npm:1.0.4" + checksum: 3d93585fda985d1554eca5ebd251994327608d2e200978fdbfba21c0c679914d5faf266d17027de44b34a72c7b0745b18584ecccaa7e1fdfb6a68ac7114f12e0 + languageName: node + linkType: hard + +"convert-source-map@npm:^1.7.0": + version: 1.8.0 + resolution: "convert-source-map@npm:1.8.0" + dependencies: + safe-buffer: ~5.1.1 + checksum: 985d974a2d33e1a2543ada51c93e1ba2f73eaed608dc39f229afc78f71dcc4c8b7d7c684aa647e3c6a3a204027444d69e53e169ce94e8d1fa8d7dee80c9c8fed + languageName: node + linkType: hard + +"convert-source-map@npm:^2.0.0": + version: 2.0.0 + resolution: "convert-source-map@npm:2.0.0" + checksum: 63ae9933be5a2b8d4509daca5124e20c14d023c820258e484e32dc324d34c2754e71297c94a05784064ad27615037ef677e3f0c00469fb55f409d2bb21261035 + languageName: node + linkType: hard + +"cookie@npm:~0.4.1": + version: 0.4.2 + resolution: "cookie@npm:0.4.2" + checksum: a00833c998bedf8e787b4c342defe5fa419abd96b32f4464f718b91022586b8f1bafbddd499288e75c037642493c83083da426c6a9080d309e3bd90fd11baa9b + languageName: node + linkType: hard + +"copy-props@npm:^4.0.0": + version: 4.0.0 + resolution: "copy-props@npm:4.0.0" + dependencies: + each-props: ^3.0.0 + is-plain-object: ^5.0.0 + checksum: 4e3d4ef8dfcf0751f031cd66fa85848d342bbf736df0b486288cc2930c3dc50ca1c9079d9294f5b41da9be0dc41b29e860e49906b46c07391b03d9b33de9b0df + languageName: node + linkType: hard + +"core-js-compat@npm:^3.31.0": + version: 3.32.0 + resolution: "core-js-compat@npm:3.32.0" + dependencies: + browserslist: ^4.21.9 + checksum: e740b348dfd8dc25ac851ab625a1d5a63c012252bdd6d8ae92d1b2ebf46e6cf57ca6cbec4494cbacdd90d3f8ed822480c8a7106c990dbe9055ebdf5b79fbb92e + languageName: node + linkType: hard + +"core-js-compat@npm:^3.36.1": + version: 3.36.1 + resolution: "core-js-compat@npm:3.36.1" + dependencies: + browserslist: ^4.23.0 + checksum: c9109bd599a97b5d20f25fc8b8339b8c7f3fca5f9a1bebd397805383ff7699e117786c7ffe0f7a95058a6fa5e0e1435d4c10e5cda6ad86ce1957986bb6580562 + languageName: node + linkType: hard + +"core-js@npm:^3.0.0": + version: 3.19.0 + resolution: "core-js@npm:3.19.0" + checksum: 9f03e72f01d9eeafb2724ee5787ab8d6e7dcf0e3b44c4dec23e6a0cfc9e2e0a76460b77ce7d1d0be09db918618b11595fad6838978ff97f2684270738898c5a2 + languageName: node + linkType: hard + +"cors@npm:~2.8.5": + version: 2.8.5 + resolution: "cors@npm:2.8.5" + dependencies: + object-assign: ^4 + vary: ^1 + checksum: ced838404ccd184f61ab4fdc5847035b681c90db7ac17e428f3d81d69e2989d2b680cc254da0e2554f5ed4f8a341820a1ce3d1c16b499f6e2f47a1b9b07b5006 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2": + 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 + +"css-select@npm:^4.1.3": + version: 4.1.3 + resolution: "css-select@npm:4.1.3" + dependencies: + boolbase: ^1.0.0 + css-what: ^5.0.0 + domhandler: ^4.2.0 + domutils: ^2.6.0 + nth-check: ^2.0.0 + checksum: 40928f1aa6c71faf36430e7f26bcbb8ab51d07b98b754caacb71906400a195df5e6c7020a94f2982f02e52027b9bd57c99419220cf7020968c3415f14e4be5f8 + 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:^5.0.0": + version: 5.1.0 + resolution: "css-what@npm:5.1.0" + checksum: 0b75d1bac95c885c168573c85744a6c6843d8c33345f54f717218b37ea6296b0e99bb12105930ea170fd4a921990392a7c790c16c585c1d8960c49e2b7ec39f7 + languageName: node + linkType: hard + +"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 + +"custom-event@npm:~1.0.0": + version: 1.0.1 + resolution: "custom-event@npm:1.0.1" + checksum: 334f48a6d5fb98df95c5f72cab2729417ffdcc74aebb1d51aa9220391bdee028ec36d9e19976a5a64f536e1e4aceb5bb4f0232d4761acc3e8fd74c54573959bd + languageName: node + linkType: hard + +"data-view-buffer@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-buffer@npm:1.0.1" + dependencies: + call-bind: ^1.0.6 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: ce24348f3c6231223b216da92e7e6a57a12b4af81a23f27eff8feabdf06acfb16c00639c8b705ca4d167f761cfc756e27e5f065d0a1f840c10b907fdaf8b988c + languageName: node + linkType: hard + +"data-view-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-byte-length@npm:1.0.1" + dependencies: + call-bind: ^1.0.7 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: dbb3200edcb7c1ef0d68979834f81d64fd8cab2f7691b3a4c6b97e67f22182f3ec2c8602efd7b76997b55af6ff8bce485829c1feda4fa2165a6b71fb7baa4269 + languageName: node + linkType: hard + +"data-view-byte-offset@npm:^1.0.0": + version: 1.0.0 + resolution: "data-view-byte-offset@npm:1.0.0" + dependencies: + call-bind: ^1.0.6 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: 7f0bf8720b7414ca719eedf1846aeec392f2054d7af707c5dc9a753cc77eb8625f067fa901e0b5127e831f9da9056138d894b9c2be79c27a21f6db5824f009c2 + languageName: node + linkType: hard + +"date-format@npm:^4.0.3": + version: 4.0.3 + resolution: "date-format@npm:4.0.3" + checksum: 8ae4d9de3532010169a89bc7b079342051ba3ec88552636aa677bfb53e8eb15113af8394679aea7d41367dc8bb6e9865da17f21ac2802202180b09d6e3f2339e + languageName: node + linkType: hard + +"debug@npm:2.6.9": + 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.1, debug@npm:~4.3.2, 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 + +"decamelize@npm:^4.0.0": + version: 4.0.0 + resolution: "decamelize@npm:4.0.0" + checksum: b7d09b82652c39eead4d6678bb578e3bebd848add894b76d0f6b395bc45b2d692fb88d977e7cfb93c4ed6c119b05a1347cef261174916c2e75c0a8ca57da1809 + languageName: node + linkType: hard + +"deep-eql@npm:^5.0.1": + version: 5.0.1 + resolution: "deep-eql@npm:5.0.1" + checksum: 8009e8a8bf3e0f591a122e7788e304a2bed1299b7774f039be96f9ef35c00fb254292fb1568952651aea0c1d1eb23d0bca484bbdd2cf4fcee685c6f2c43670f3 + languageName: node + linkType: hard + +"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.2.2 + resolution: "deepmerge@npm:4.2.2" + checksum: a8c43a1ed8d6d1ed2b5bf569fa4c8eb9f0924034baf75d5d406e47e157a451075c4db353efea7b6bcc56ec48116a8ce72fccf867b6e078e7c561904b5897530b + languageName: node + linkType: hard + +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1": + version: 1.1.1 + resolution: "define-data-property@npm:1.1.1" + dependencies: + get-intrinsic: ^1.2.1 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.0 + checksum: a29855ad3f0630ea82e3c5012c812efa6ca3078d5c2aa8df06b5f597c1cde6f7254692df41945851d903e05a1668607b6d34e778f402b9ff9ffb38111f1a3f0d + languageName: node + linkType: hard + +"define-data-property@npm:^1.1.4": + version: 1.1.4 + resolution: "define-data-property@npm:1.1.4" + dependencies: + es-define-property: ^1.0.0 + es-errors: ^1.3.0 + gopd: ^1.0.1 + checksum: 8068ee6cab694d409ac25936eb861eea704b7763f7f342adbdfe337fc27c78d7ae0eff2364b2917b58c508d723c7a074326d068eef2e45c4edcd85cf94d0313b + languageName: node + linkType: hard + +"define-properties@npm:^1.1.3": + version: 1.1.3 + resolution: "define-properties@npm:1.1.3" + dependencies: + object-keys: ^1.0.12 + checksum: da80dba55d0cd76a5a7ab71ef6ea0ebcb7b941f803793e4e0257b384cb772038faa0c31659d244e82c4342edef841c1a1212580006a05a5068ee48223d787317 + languageName: node + linkType: hard + +"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 + +"define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": + version: 1.2.1 + resolution: "define-properties@npm:1.2.1" + dependencies: + define-data-property: ^1.0.1 + has-property-descriptors: ^1.0.0 + object-keys: ^1.1.1 + checksum: b4ccd00597dd46cb2d4a379398f5b19fca84a16f3374e2249201992f36b30f6835949a9429669ee6b41b6e837205a163eadd745e472069e70dfc10f03e5fcc12 + 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": + version: 1.1.2 + resolution: "depd@npm:1.1.2" + checksum: 6b406620d269619852885ce15965272b829df6f409724415e0002c8632ab6a8c0a08ec1f0bd2add05dc7bd7507606f7e2cc034fa24224ab829580040b835ecd9 + languageName: node + linkType: hard + +"detect-file@npm:^1.0.0": + version: 1.0.0 + resolution: "detect-file@npm:1.0.0" + checksum: 1861e4146128622e847abe0e1ed80fef01e78532665858a792267adf89032b7a9c698436137707fcc6f02956c2a6a0052d6a0cef5be3d4b76b1ff0da88e2158a + languageName: node + linkType: hard + +"di@npm:^0.0.1": + version: 0.0.1 + resolution: "di@npm:0.0.1" + checksum: 3f09a99534d33e49264585db7f863ea8bc76c25c4d5a60df387c946018ecf1e1516b2c05a2092e5ca51fcdc08cefe609a6adc5253fa831626cb78cad4746505e + languageName: node + linkType: hard + +"diff@npm:5.0.0": + version: 5.0.0 + resolution: "diff@npm:5.0.0" + checksum: f19fe29284b633afdb2725c2a8bb7d25761ea54d321d8e67987ac851c5294be4afeab532bd84531e02583a3fe7f4014aa314a3eda84f5590e7a9e6b371ef3b46 + languageName: node + linkType: hard + +"diff@npm:^5.1.0": + version: 5.1.0 + resolution: "diff@npm:5.1.0" + checksum: c7bf0df7c9bfbe1cf8a678fd1b2137c4fb11be117a67bc18a0e03ae75105e8533dbfb1cda6b46beb3586ef5aed22143ef9d70713977d5fb1f9114e21455fba90 + languageName: node + linkType: hard + +"diff@npm:^5.2.0": + version: 5.2.0 + resolution: "diff@npm:5.2.0" + checksum: 12b63ca9c36c72bafa3effa77121f0581b4015df18bc16bac1f8e263597735649f1a173c26f7eba17fb4162b073fee61788abe49610e6c70a2641fe1895443fd + 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-serialize@npm:^2.2.1": + version: 2.2.1 + resolution: "dom-serialize@npm:2.2.1" + dependencies: + custom-event: ~1.0.0 + ent: ~2.2.0 + extend: ^3.0.0 + void-elements: ^2.0.0 + checksum: 48262e299a694dbfa32905ecceb29b89f2ce59adfc00cb676284f85ee0c8db0225e07961cbf9b06bf309291deebf52c958f855a5b6709d556000acf46d5a46ef + languageName: node + linkType: hard + +"dom-serializer@npm:^1.0.1": + version: 1.3.2 + resolution: "dom-serializer@npm:1.3.2" + dependencies: + domelementtype: ^2.0.1 + domhandler: ^4.2.0 + entities: ^2.0.0 + checksum: bff48714944d67b160db71ba244fb0f3fe72e77ef2ec8414e2eeb56f2d926e404a13456b8b83a5392e217ba47dec2ec0c368801b31481813e94d185276c3e964 + languageName: node + linkType: hard + +"domelementtype@npm:^2.0.1, domelementtype@npm:^2.2.0": + version: 2.2.0 + resolution: "domelementtype@npm:2.2.0" + checksum: 24cb386198640cd58aa36f8c987f2ea61859929106d06ffcc8f547e70cb2ed82a6dc56dcb8252b21fba1f1ea07df6e4356d60bfe57f77114ca1aed6828362629 + languageName: node + linkType: hard + +"domhandler@npm:^4.2.0": + version: 4.2.2 + resolution: "domhandler@npm:4.2.2" + dependencies: + domelementtype: ^2.2.0 + checksum: ad782fef984eca5a6fdd4ce70b90c38aff335ae4d6a51223ac82bd371b6674614efdcfff2dbb1126a7395634357906781f179e4ec028c7c578bb7f2beef8a4a5 + languageName: node + linkType: hard + +"domutils@npm:^2.6.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 + +"duplexify@npm:^4.1.1": + version: 4.1.2 + resolution: "duplexify@npm:4.1.2" + dependencies: + end-of-stream: ^1.4.1 + inherits: ^2.0.3 + readable-stream: ^3.1.1 + stream-shift: ^1.0.0 + checksum: 964376c61c0e92f6ed0694b3ba97c84f199413dc40ab8dfdaef80b7a7f4982fcabf796214e28ed614a5bc1ec45488a29b81e7d46fa3f5ddf65bcb118c20145ad + languageName: node + linkType: hard + +"each-props@npm:^3.0.0": + version: 3.0.0 + resolution: "each-props@npm:3.0.0" + dependencies: + is-plain-object: ^5.0.0 + object.defaults: ^1.1.0 + checksum: 69d493f84692161898956a1251ceadc52fef35b6c4734af55a2de9d344fbf1b4e5643e160095c4a3a8808d893f5ebc5a2178d51039c8716864c6aa0ddf007029 + 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 + +"easy-transform-stream@npm:^1.0.1": + version: 1.0.1 + resolution: "easy-transform-stream@npm:1.0.1" + checksum: 3d783ad3ffa21690c9e84ee54a9993a882f07e86416f15fe8dfcfb2c93ea28ce79f10775c2e56d846bba6a9e85e64f9f867c085d5906031c06c97c5a5234be46 + 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 + +"electron-to-chromium@npm:^1.4.477": + version: 1.4.479 + resolution: "electron-to-chromium@npm:1.4.479" + checksum: a22b70435e163bf413bfb8f4da015c3f099b64fc1eebb0c39829c5ce66ee13a23a2d42c91a33524eb4d1e86e28cc046be940e4b78d74e43b54d883100711f7cd + languageName: node + linkType: hard + +"electron-to-chromium@npm:^1.4.601": + version: 1.4.616 + resolution: "electron-to-chromium@npm:1.4.616" + checksum: 9fd53bd4e5cded61ee51164a0d23ced1d7677ab176ef8e28eb4a27ceaae1deb3bb0038024db48478507204bfcd48ef66866c078721915a9c7b019697cc5680bf + languageName: node + linkType: hard + +"electron-to-chromium@npm:^1.4.668": + version: 1.4.713 + resolution: "electron-to-chromium@npm:1.4.713" + checksum: cffeff470a73c47763463fdc8f58854544102b572afe417defca6f511fa88dbe7e0b1720f0e64cf0cf92053aa3b086f5de24899a68a12a346f6b9b74ff1c0768 + 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 + +"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.4.1, end-of-stream@npm:^1.4.4": + version: 1.4.4 + resolution: "end-of-stream@npm:1.4.4" + dependencies: + once: ^1.4.0 + checksum: 530a5a5a1e517e962854a31693dbb5c0b2fc40b46dad2a56a2deec656ca040631124f4795823acc68238147805f8b021abbe221f4afed5ef3c8e8efc2024908b + languageName: node + linkType: hard + +"engine.io-parser@npm:~5.2.1": + version: 5.2.2 + resolution: "engine.io-parser@npm:5.2.2" + checksum: 470231215f3136a9259efb1268bc9a71f789af4e8c74da8d3b49ceb149fe3cd5c315bf0cd13d2d8d9c8f0f051c6f93b68e8fa9c89a3b612b9217bf33765c943a + languageName: node + linkType: hard + +"engine.io@npm:~6.5.2": + version: 6.5.4 + resolution: "engine.io@npm:6.5.4" + dependencies: + "@types/cookie": ^0.4.1 + "@types/cors": ^2.8.12 + "@types/node": ">=10.0.0" + accepts: ~1.3.4 + base64id: 2.0.0 + cookie: ~0.4.1 + cors: ~2.8.5 + debug: ~4.3.1 + engine.io-parser: ~5.2.1 + ws: ~8.11.0 + checksum: d5b55cbac718c5b1c10800314379923f8c7ef9e3a8a60c6827ed86303d1154b81d354a89fdecf4cbb773515c82c84a98d3c791ff88279393b53625dd67299d30 + languageName: node + linkType: hard + +"ent@npm:~2.2.0": + version: 2.2.0 + resolution: "ent@npm:2.2.0" + checksum: f588b5707d6fef36011ea10d530645912a69530a1eb0831f8708c498ac028363a7009f45cfadd28ceb4dafd9ac17ec15213f88d09ce239cd033cfe1328dd7d7d + 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 + +"es-abstract@npm:^1.19.0": + version: 1.19.1 + resolution: "es-abstract@npm:1.19.1" + 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 + checksum: b6be8410672c5364db3fb01eb786e30c7b4bb32b4af63d381c08840f4382c4a168e7855cd338bf59d4f1a1a1138f4d748d1fd40ec65aaa071876f9e9fbfed949 + languageName: node + linkType: hard + +"es-abstract@npm:^1.19.5": + version: 1.20.1 + resolution: "es-abstract@npm:1.20.1" + dependencies: + call-bind: ^1.0.2 + es-to-primitive: ^1.2.1 + function-bind: ^1.1.1 + function.prototype.name: ^1.1.5 + get-intrinsic: ^1.1.1 + get-symbol-description: ^1.0.0 + has: ^1.0.3 + has-property-descriptors: ^1.0.0 + has-symbols: ^1.0.3 + internal-slot: ^1.0.3 + is-callable: ^1.2.4 + is-negative-zero: ^2.0.2 + is-regex: ^1.1.4 + is-shared-array-buffer: ^1.0.2 + is-string: ^1.0.7 + is-weakref: ^1.0.2 + object-inspect: ^1.12.0 + object-keys: ^1.1.1 + object.assign: ^4.1.2 + regexp.prototype.flags: ^1.4.3 + string.prototype.trimend: ^1.0.5 + string.prototype.trimstart: ^1.0.5 + unbox-primitive: ^1.0.2 + checksum: 28da27ae0ed9c76df7ee8ef5c278df79dcfdb554415faf7068bb7c58f8ba8e2a16bfb59e586844be6429ab4c302ca7748979d48442224cb1140b051866d74b7f + languageName: node + linkType: hard + +"es-abstract@npm:^1.20.4": + version: 1.20.4 + resolution: "es-abstract@npm:1.20.4" + dependencies: + call-bind: ^1.0.2 + 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 + has: ^1.0.3 + has-property-descriptors: ^1.0.0 + has-symbols: ^1.0.3 + internal-slot: ^1.0.3 + 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-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.5 + string.prototype.trimstart: ^1.0.5 + unbox-primitive: ^1.0.2 + checksum: 89297cc785c31aedf961a603d5a07ed16471e435d3a1b6d070b54f157cf48454b95cda2ac55e4b86ff4fe3276e835fcffd2771578e6fa634337da49b26826141 + languageName: node + linkType: hard + +"es-abstract@npm:^1.22.1": + version: 1.22.3 + resolution: "es-abstract@npm:1.22.3" + dependencies: + array-buffer-byte-length: ^1.0.0 + arraybuffer.prototype.slice: ^1.0.2 + available-typed-arrays: ^1.0.5 + call-bind: ^1.0.5 + es-set-tostringtag: ^2.0.1 + es-to-primitive: ^1.2.1 + function.prototype.name: ^1.1.6 + get-intrinsic: ^1.2.2 + get-symbol-description: ^1.0.0 + globalthis: ^1.0.3 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.0 + has-proto: ^1.0.1 + has-symbols: ^1.0.3 + hasown: ^2.0.0 + internal-slot: ^1.0.5 + is-array-buffer: ^3.0.2 + 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.12 + is-weakref: ^1.0.2 + object-inspect: ^1.13.1 + object-keys: ^1.1.1 + object.assign: ^4.1.4 + regexp.prototype.flags: ^1.5.1 + safe-array-concat: ^1.0.1 + safe-regex-test: ^1.0.0 + string.prototype.trim: ^1.2.8 + string.prototype.trimend: ^1.0.7 + string.prototype.trimstart: ^1.0.7 + typed-array-buffer: ^1.0.0 + typed-array-byte-length: ^1.0.0 + typed-array-byte-offset: ^1.0.0 + typed-array-length: ^1.0.4 + unbox-primitive: ^1.0.2 + which-typed-array: ^1.1.13 + checksum: b1bdc962856836f6e72be10b58dc128282bdf33771c7a38ae90419d920fc3b36cc5d2b70a222ad8016e3fc322c367bf4e9e89fc2bc79b7e933c05b218e83d79a + languageName: node + linkType: hard + +"es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2": + version: 1.23.2 + resolution: "es-abstract@npm:1.23.2" + dependencies: + array-buffer-byte-length: ^1.0.1 + arraybuffer.prototype.slice: ^1.0.3 + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 + data-view-buffer: ^1.0.1 + data-view-byte-length: ^1.0.1 + data-view-byte-offset: ^1.0.0 + es-define-property: ^1.0.0 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + es-set-tostringtag: ^2.0.3 + es-to-primitive: ^1.2.1 + function.prototype.name: ^1.1.6 + get-intrinsic: ^1.2.4 + get-symbol-description: ^1.0.2 + globalthis: ^1.0.3 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.2 + has-proto: ^1.0.3 + has-symbols: ^1.0.3 + hasown: ^2.0.2 + internal-slot: ^1.0.7 + is-array-buffer: ^3.0.4 + is-callable: ^1.2.7 + is-data-view: ^1.0.1 + is-negative-zero: ^2.0.3 + is-regex: ^1.1.4 + is-shared-array-buffer: ^1.0.3 + is-string: ^1.0.7 + is-typed-array: ^1.1.13 + is-weakref: ^1.0.2 + object-inspect: ^1.13.1 + object-keys: ^1.1.1 + object.assign: ^4.1.5 + regexp.prototype.flags: ^1.5.2 + safe-array-concat: ^1.1.2 + safe-regex-test: ^1.0.3 + string.prototype.trim: ^1.2.9 + string.prototype.trimend: ^1.0.8 + string.prototype.trimstart: ^1.0.7 + typed-array-buffer: ^1.0.2 + typed-array-byte-length: ^1.0.1 + typed-array-byte-offset: ^1.0.2 + typed-array-length: ^1.0.5 + unbox-primitive: ^1.0.2 + which-typed-array: ^1.1.15 + checksum: cc6410cb58ba90e3f0f84d83297c372ca545017b94e50fd0020119e82b26f0dbf9885c72335f0063b93669393c505712c6fe82bef7ae4d3d29d770c0dbfb1340 + languageName: node + linkType: hard + +"es-define-property@npm:^1.0.0": + version: 1.0.0 + resolution: "es-define-property@npm:1.0.0" + dependencies: + get-intrinsic: ^1.2.4 + checksum: f66ece0a887b6dca71848fa71f70461357c0e4e7249696f81bad0a1f347eed7b31262af4a29f5d726dc026426f085483b6b90301855e647aa8e21936f07293c6 + languageName: node + linkType: hard + +"es-errors@npm:^1.1.0, es-errors@npm:^1.2.1, es-errors@npm:^1.3.0": + version: 1.3.0 + resolution: "es-errors@npm:1.3.0" + checksum: ec1414527a0ccacd7f15f4a3bc66e215f04f595ba23ca75cdae0927af099b5ec865f9f4d33e9d7e86f512f252876ac77d4281a7871531a50678132429b1271b5 + languageName: node + linkType: hard + +"es-iterator-helpers@npm:^1.0.17": + version: 1.0.18 + resolution: "es-iterator-helpers@npm:1.0.18" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.0 + es-errors: ^1.3.0 + es-set-tostringtag: ^2.0.3 + function-bind: ^1.1.2 + get-intrinsic: ^1.2.4 + globalthis: ^1.0.3 + has-property-descriptors: ^1.0.2 + has-proto: ^1.0.3 + has-symbols: ^1.0.3 + internal-slot: ^1.0.7 + iterator.prototype: ^1.1.2 + safe-array-concat: ^1.1.2 + checksum: 1594324ff3ca8890fe30c98b2419d3007d2b14b35f9773f188114408ff973e13c526f6045d88209e932f58dc0c55fc9a4ae1554636f8938ed7d926ffc27d3e1a + languageName: node + linkType: hard + +"es-object-atoms@npm:^1.0.0": + version: 1.0.0 + resolution: "es-object-atoms@npm:1.0.0" + dependencies: + es-errors: ^1.3.0 + checksum: 26f0ff78ab93b63394e8403c353842b2272836968de4eafe97656adfb8a7c84b9099bf0fe96ed58f4a4cddc860f6e34c77f91649a58a5daa4a9c40b902744e3c + languageName: node + linkType: hard + +"es-set-tostringtag@npm:^2.0.1": + version: 2.0.2 + resolution: "es-set-tostringtag@npm:2.0.2" + dependencies: + get-intrinsic: ^1.2.2 + has-tostringtag: ^1.0.0 + hasown: ^2.0.0 + checksum: afcec3a4c9890ae14d7ec606204858441c801ff84f312538e1d1ccf1e5493c8b17bd672235df785f803756472cb4f2d49b87bde5237aef33411e74c22f194e07 + languageName: node + linkType: hard + +"es-set-tostringtag@npm:^2.0.3": + version: 2.0.3 + resolution: "es-set-tostringtag@npm:2.0.3" + dependencies: + get-intrinsic: ^1.2.4 + has-tostringtag: ^1.0.2 + hasown: ^2.0.1 + checksum: 7227fa48a41c0ce83e0377b11130d324ac797390688135b8da5c28994c0165be8b252e15cd1de41e1325e5a5412511586960213e88f9ab4a5e7d028895db5129 + 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-shim-unscopables@npm:^1.0.2": + version: 1.0.2 + resolution: "es-shim-unscopables@npm:1.0.2" + dependencies: + hasown: ^2.0.0 + checksum: 432bd527c62065da09ed1d37a3f8e623c423683285e6188108286f4a1e8e164a5bcbfbc0051557c7d14633cd2a41ce24c7048e6bbb66a985413fd32f1be72626 + 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, 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:4.0.0, 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 + +"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 + +"eslint-config-hypothesis@npm:2.6": + version: 2.6.0 + resolution: "eslint-config-hypothesis@npm:2.6.0" + peerDependencies: + eslint-plugin-mocha: ">=5.2.1" + eslint-plugin-react: ">=7.12.4" + eslint-plugin-react-hooks: ">=3.0.0" + checksum: 3d326860ced81e68938f230d41ed48efc63c86ea720d467acf7d994f9887ba5554c39754dd30553a1da7fcdd70891f6a5db1163c07a09a5c9a5de99a57b3a79a + languageName: node + linkType: hard + +"eslint-plugin-mocha@npm:^10.4.3": + version: 10.4.3 + resolution: "eslint-plugin-mocha@npm:10.4.3" + dependencies: + eslint-utils: ^3.0.0 + globals: ^13.24.0 + rambda: ^7.4.0 + peerDependencies: + eslint: ">=7.0.0" + checksum: 67176a889099cb68733d13ba17af5d13f48dc2a7ac9360b04abe94e81e5e9c35346ae2070aa50dce8a4c80dca4602f62375b074f3485369c3a66867fa683ba3c + languageName: node + linkType: hard + +"eslint-plugin-react-hooks@npm:^4.6.2": + version: 4.6.2 + resolution: "eslint-plugin-react-hooks@npm:4.6.2" + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + checksum: 395c433610f59577cfcf3f2e42bcb130436c8a0b3777ac64f441d88c5275f4fcfc89094cedab270f2822daf29af1079151a7a6579a8e9ea8cee66540ba0384c4 + languageName: node + linkType: hard + +"eslint-plugin-react@npm:^7.34.1": + version: 7.34.1 + resolution: "eslint-plugin-react@npm:7.34.1" + dependencies: + array-includes: ^3.1.7 + array.prototype.findlast: ^1.2.4 + array.prototype.flatmap: ^1.3.2 + array.prototype.toreversed: ^1.1.2 + array.prototype.tosorted: ^1.1.3 + doctrine: ^2.1.0 + es-iterator-helpers: ^1.0.17 + estraverse: ^5.3.0 + jsx-ast-utils: ^2.4.1 || ^3.0.0 + minimatch: ^3.1.2 + object.entries: ^1.1.7 + object.fromentries: ^2.0.7 + object.hasown: ^1.1.3 + object.values: ^1.1.7 + prop-types: ^15.8.1 + resolve: ^2.0.0-next.5 + semver: ^6.3.1 + string.prototype.matchall: ^4.0.10 + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + checksum: 82f391c5a093235c3bc2f664c54e009c49460778ee7d1b86c1536df9ac4d2a80d1dedc9241ac797df4a9dced936e955d9c89042fb3ac8d017b5359d1320d3c0f + 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": + 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": + version: 3.4.2 + resolution: "eslint-visitor-keys@npm:3.4.2" + checksum: 9e0e7e4aaea705c097ae37c97410e5f167d4d2193be2edcb1f0760762ede3df01545e4820ae314f42dcec687745f2c6dcaf6d83575c4a2a241eb0c8517d724f2 + languageName: node + linkType: hard + +"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@npm:^8.57.0": + version: 8.57.0 + resolution: "eslint@npm:8.57.0" + dependencies: + "@eslint-community/eslint-utils": ^4.2.0 + "@eslint-community/regexpp": ^4.6.1 + "@eslint/eslintrc": ^2.1.4 + "@eslint/js": 8.57.0 + "@humanwhocodes/config-array": ^0.11.14 + "@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: 3a48d7ff85ab420a8447e9810d8087aea5b1df9ef68c9151732b478de698389ee656fd895635b5f2871c89ee5a2652b3f343d11e9db6f8486880374ebc74a2d9 + 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 + +"esquery@npm:^1.4.2": + version: 1.4.2 + resolution: "esquery@npm:1.4.2" + dependencies: + estraverse: ^5.1.0 + checksum: 2f4ad89c5aafaca61cc2c15e256190f0d6deb4791cae6552d3cb4b1eb8867958cdf27a56aaa3272ff17435e3eaa19ee0d4129fac336ca6373d7354d7b5da7966 + 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:^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:^2.0.2": + version: 2.0.2 + resolution: "estree-walker@npm:2.0.2" + checksum: 6151e6f9828abe2259e57f5fd3761335bb0d2ebd76dc1a01048ccee22fabcfef3c0859300f6d83ff0d1927849368775ec5a6d265dde2f6de5a1be1721cd94efc + 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 + +"eventemitter3@npm:^4.0.0": + version: 4.0.7 + resolution: "eventemitter3@npm:4.0.7" + checksum: 1875311c42fcfe9c707b2712c32664a245629b42bb0a5a84439762dd0fd637fc54d078155ea83c2af9e0323c9ac13687e03cfba79b03af9f40c89b4960099374 + languageName: node + linkType: hard + +"expand-tilde@npm:^2.0.0, expand-tilde@npm:^2.0.2": + version: 2.0.2 + resolution: "expand-tilde@npm:2.0.2" + dependencies: + homedir-polyfill: ^1.0.1 + checksum: 2efe6ed407d229981b1b6ceb552438fbc9e5c7d6a6751ad6ced3e0aa5cf12f0b299da695e90d6c2ac79191b5c53c613e508f7149e4573abfbb540698ddb7301a + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 3d21519a4f8207c99f7457287291316306255a328770d320b401114ec8481986e4e467e854cb9914dd965e0a1ca810a23ccb559c642c88f4c7f55c55778a9b48 + languageName: node + linkType: hard + +"extend-shallow@npm:^3.0.2": + version: 3.0.2 + resolution: "extend-shallow@npm:3.0.2" + dependencies: + assign-symbols: ^1.0.0 + is-extendable: ^1.0.1 + checksum: a920b0cd5838a9995ace31dfd11ab5e79bf6e295aa566910ce53dff19f4b1c0fda2ef21f26b28586c7a2450ca2b42d97bd8c0f5cec9351a819222bf861e02461 + languageName: node + linkType: hard + +"extend@npm:^3.0.0, extend@npm:^3.0.2": + version: 3.0.2 + resolution: "extend@npm:3.0.2" + checksum: a50a8309ca65ea5d426382ff09f33586527882cf532931cb08ca786ea3146c0553310bda688710ff61d7668eba9f96b923fe1420cdf56a2c3eaf30fcab87b515 + languageName: node + linkType: hard + +"fancy-log@npm:^2.0.0": + version: 2.0.0 + resolution: "fancy-log@npm:2.0.0" + dependencies: + color-support: ^1.1.3 + checksum: 5652bf35e6a0be68bc011cf38706c78c7724808311e88905a3e4623d0e86168f084a9f38109dce2b2f78078ae704e4b55095effda743b4795c37f30ddb70497e + 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-fifo@npm:^1.1.0": + version: 1.3.2 + resolution: "fast-fifo@npm:1.3.2" + checksum: 6bfcba3e4df5af7be3332703b69a7898a8ed7020837ec4395bb341bd96cc3a6d86c3f6071dd98da289618cf2234c70d84b2a6f09a33dd6f988b1ff60d8e54275 + languageName: node + linkType: hard + +"fast-json-stable-stringify@npm:^2.0.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": + version: 2.0.6 + resolution: "fast-levenshtein@npm:2.0.6" + checksum: 92cfec0a8dfafd9c7a15fba8f2cc29cd0b62b85f056d99ce448bbcd9f708e18ab2764bda4dd5158364f4145a7c72788538994f0d1787b956ef0d1062b0f7c24c + languageName: node + linkType: hard + +"fast-levenshtein@npm:^3.0.0": + version: 3.0.0 + resolution: "fast-levenshtein@npm:3.0.0" + dependencies: + fastest-levenshtein: ^1.0.7 + checksum: 02732ba6c656797ca7e987c25f3e53718c8fcc39a4bfab46def78eef7a8729eb629632d4a7eca4c27a33e10deabffa9984839557e18a96e91ecf7ccaeedb9890 + languageName: node + linkType: hard + +"fastest-levenshtein@npm:^1.0.7": + version: 1.0.16 + resolution: "fastest-levenshtein@npm:1.0.16" + checksum: a78d44285c9e2ae2c25f3ef0f8a73f332c1247b7ea7fb4a191e6bb51aa6ee1ef0dfb3ed113616dcdc7023e18e35a8db41f61c8d88988e877cf510df8edafbc71 + languageName: node + linkType: hard + +"fastq@npm:^1.13.0": + version: 1.17.1 + resolution: "fastq@npm:1.17.1" + dependencies: + reusify: ^1.0.4 + checksum: a8c5b26788d5a1763f88bae56a8ddeee579f935a831c5fe7a8268cea5b0a91fbfe705f612209e02d639b881d7b48e461a50da4a10cfaa40da5ca7cc9da098d88 + languageName: node + linkType: hard + +"fastq@npm:^1.6.0": + version: 1.13.0 + resolution: "fastq@npm:1.13.0" + dependencies: + reusify: ^1.0.4 + checksum: 32cf15c29afe622af187d12fc9cd93e160a0cb7c31a3bb6ace86b7dea3b28e7b72acde89c882663f307b2184e14782c6c664fa315973c03626c7d4bff070bb0b + languageName: node + linkType: hard + +"fetch-mock@npm:^9.11.0": + version: 9.11.0 + resolution: "fetch-mock@npm:9.11.0" + dependencies: + "@babel/core": ^7.0.0 + "@babel/runtime": ^7.0.0 + core-js: ^3.0.0 + debug: ^4.1.1 + glob-to-regexp: ^0.4.0 + is-subset: ^0.1.1 + lodash.isequal: ^4.5.0 + path-to-regexp: ^2.2.1 + querystring: ^0.2.0 + whatwg-url: ^6.5.0 + peerDependencies: + node-fetch: "*" + peerDependenciesMeta: + node-fetch: + optional: true + checksum: debc4dd83bcda79b0aa71c38d08da6036906cdc49393343eb3426112314a7e57557255664f745d2e3f0b9b2a6e852bd3a564ae3f08332c27e422d3441bb865bd + 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 + +"fill-range@npm:^7.0.1": + version: 7.0.1 + resolution: "fill-range@npm:7.0.1" + dependencies: + to-regex-range: ^5.0.1 + checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 + languageName: node + linkType: hard + +"finalhandler@npm:1.1.2": + version: 1.1.2 + resolution: "finalhandler@npm:1.1.2" + 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 + checksum: 617880460c5138dd7ccfd555cb5dde4d8f170f4b31b8bd51e4b646bb2946c30f7db716428a1f2882d730d2b72afb47d1f67cc487b874cb15426f95753a88965e + languageName: node + linkType: hard + +"find-up@npm:5.0.0, 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 + +"findup-sync@npm:^5.0.0": + version: 5.0.0 + resolution: "findup-sync@npm:5.0.0" + dependencies: + detect-file: ^1.0.0 + is-glob: ^4.0.3 + micromatch: ^4.0.4 + resolve-dir: ^1.0.1 + checksum: 576716c77a0e8330b17ae9cba27d1fda8907c8cda7bf33a47f1999e16e089bfc6df4dd62933e0760f430736183c054348c34aa45dd882d49c8c098f55b89ee1d + languageName: node + linkType: hard + +"fined@npm:^2.0.0": + version: 2.0.0 + resolution: "fined@npm:2.0.0" + dependencies: + expand-tilde: ^2.0.2 + is-plain-object: ^5.0.0 + object.defaults: ^1.1.0 + object.pick: ^1.3.0 + parse-filepath: ^1.0.2 + checksum: 3c5125a5b4eabb9a9569a9bc55a629d4f463ea8926cca9ee0b54d0e0351715aaed7f245a5372defbb59a0aaccdfefae9dc1a9ac0c7b1167ba8537284db956852 + languageName: node + linkType: hard + +"flagged-respawn@npm:^2.0.0": + version: 2.0.0 + resolution: "flagged-respawn@npm:2.0.0" + checksum: 6c2b3fefbe6803953137c0d6033755b69b43dc6e0725b7f71bd90e69c912494a6e50d1c0188551c1c3b9214d7428a875f34f42a35518099c13995d8c471e475b + 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 + +"flat@npm:^5.0.2": + version: 5.0.2 + resolution: "flat@npm:5.0.2" + bin: + flat: cli.js + checksum: 12a1536ac746db74881316a181499a78ef953632ddd28050b7a3a43c62ef5462e3357c8c29d76072bb635f147f7a9a1f0c02efef6b4be28f8db62ceb3d5c7f5d + languageName: node + linkType: hard + +"flatted@npm:^3.1.0, flatted@npm:^3.2.4": + version: 3.2.4 + resolution: "flatted@npm:3.2.4" + checksum: 7d33846428ab337ec81ef9b8b9103894c1c81f5f67feb32bd4ed106fbc47da60d56edb42efd36c9f1f30a010272aeccd34ec1ffacfe9dfdff19673b1d4df481b + languageName: node + linkType: hard + +"follow-redirects@npm:^1.0.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 + +"for-in@npm:^1.0.1": + version: 1.0.2 + resolution: "for-in@npm:1.0.2" + checksum: 09f4ae93ce785d253ac963d94c7f3432d89398bf25ac7a24ed034ca393bf74380bdeccc40e0f2d721a895e54211b07c8fad7132e8157827f6f7f059b70b4043d + languageName: node + linkType: hard + +"for-own@npm:^1.0.0": + version: 1.0.0 + resolution: "for-own@npm:1.0.0" + dependencies: + for-in: ^1.0.1 + checksum: 233238f6e9060f61295a7f7c7e3e9de11aaef57e82a108e7f350dc92ae84fe2189848077ac4b8db47fd8edd45337ed8d9f66bd0b1efa4a6a1b3f38aa21b7ab2e + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0": + version: 3.1.1 + resolution: "foreground-child@npm:3.1.1" + dependencies: + cross-spawn: ^7.0.0 + signal-exit: ^4.0.1 + checksum: 139d270bc82dc9e6f8bc045fe2aae4001dc2472157044fdfad376d0a3457f77857fa883c1c8b21b491c6caade9a926a4bed3d3d2e8d3c9202b151a4cbbd0bcd5 + languageName: node + linkType: hard + +"fork-stream@npm:^0.0.4": + version: 0.0.4 + resolution: "fork-stream@npm:0.0.4" + checksum: 07e72ba6ec810724ae9fbb76bc966214347cac966f89cf9a56ab0f70162b7806eb2a5a4333d5a92ae045da2b55bb107afe7ef32011acffb65d1067c5c85b0e5a + languageName: node + linkType: hard + +"fraction.js@npm:^4.3.7": + version: 4.3.7 + resolution: "fraction.js@npm:4.3.7" + checksum: e1553ae3f08e3ba0e8c06e43a3ab20b319966dfb7ddb96fd9b5d0ee11a66571af7f993229c88ebbb0d4a816eb813a24ed48207b140d442a8f76f33763b8d1f3f + languageName: node + linkType: hard + +"fs-extra@npm:^10.0.0": + version: 10.0.0 + resolution: "fs-extra@npm:10.0.0" + dependencies: + graceful-fs: ^4.2.0 + jsonfile: ^6.0.1 + universalify: ^2.0.0 + checksum: 5285a3d8f34b917cf2b66af8c231a40c1623626e9d701a20051d3337be16c6d7cac94441c8b3732d47a92a2a027886ca93c69b6a4ae6aee3c89650d2a8880c0a + languageName: node + linkType: hard + +"fs-minipass@npm:^2.0.0": + version: 2.1.0 + resolution: "fs-minipass@npm:2.1.0" + dependencies: + minipass: ^3.0.0 + checksum: 1b8d128dae2ac6cc94230cc5ead341ba3e0efaef82dab46a33d171c044caaa6ca001364178d42069b2809c35a1c3c35079a32107c770e9ffab3901b59af8c8b1 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.2 + resolution: "fs-minipass@npm:3.0.2" + dependencies: + minipass: ^5.0.0 + checksum: e9cc0e1f2d01c6f6f62f567aee59530aba65c6c7b2ae88c5027bc34c711ebcfcfaefd0caf254afa6adfe7d1fba16bc2537508a6235196bac7276747d078aef0a + languageName: node + linkType: hard + +"fs-mkdirp-stream@npm:^2.0.1": + version: 2.0.1 + resolution: "fs-mkdirp-stream@npm:2.0.1" + dependencies: + graceful-fs: ^4.2.8 + streamx: ^2.12.0 + checksum: 9fefd9fa3d6985aea0935944288bd20215779f683ec3af3c157cf4d4d4b0c546caae8219219f47a05a1df3b23f6a605fe64bee6ee14e550f1a670db67359ff27 + 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": + 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": + 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-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 2b0ff4ce708d99715ad14a6d1f894e2a83242e4a52ccfcefaee5e40050562e5f6dafc1adbb4ce2d4ab47279a45dc736ab91ea5042d843c3c092820dfe032efb1 + 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 + +"function.prototype.name@npm:^1.1.6": + version: 1.1.6 + resolution: "function.prototype.name@npm:1.1.6" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + functions-have-names: ^1.2.3 + checksum: 7a3f9bd98adab09a07f6e1f03da03d3f7c26abbdeaeee15223f6c04a9fb5674792bdf5e689dac19b97ac71de6aad2027ba3048a9b883aa1b3173eed6ab07f479 + languageName: node + linkType: hard + +"functions-have-names@npm:^1.2.2, functions-have-names@npm:^1.2.3": + 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-func-name@npm:^2.0.1": + version: 2.0.2 + resolution: "get-func-name@npm:2.0.2" + checksum: 3f62f4c23647de9d46e6f76d2b3eafe58933a9b3830c60669e4180d6c601ce1b4aa310ba8366143f55e52b139f992087a9f0647274e8745621fa2af7e0acf13b + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.0, get-intrinsic@npm:^1.1.1": + version: 1.1.1 + resolution: "get-intrinsic@npm:1.1.1" + dependencies: + function-bind: ^1.1.1 + has: ^1.0.3 + has-symbols: ^1.0.1 + checksum: a9fe2ca8fa3f07f9b0d30fb202bcd01f3d9b9b6b732452e79c48e79f7d6d8d003af3f9e38514250e3553fdc83c61650851cb6870832ac89deaaceb08e3721a17 + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.1.3": + version: 1.1.3 + resolution: "get-intrinsic@npm:1.1.3" + dependencies: + function-bind: ^1.1.1 + has: ^1.0.3 + has-symbols: ^1.0.3 + checksum: 152d79e87251d536cf880ba75cfc3d6c6c50e12b3a64e1ea960e73a3752b47c69f46034456eae1b0894359ce3bc64c55c186f2811f8a788b75b638b06fab228a + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.2.0, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2": + version: 1.2.2 + resolution: "get-intrinsic@npm:1.2.2" + dependencies: + function-bind: ^1.1.2 + has-proto: ^1.0.1 + has-symbols: ^1.0.3 + hasown: ^2.0.0 + checksum: 447ff0724df26829908dc033b62732359596fcf66027bc131ab37984afb33842d9cd458fd6cecadfe7eac22fd8a54b349799ed334cf2726025c921c7250e7417 + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": + version: 1.2.4 + resolution: "get-intrinsic@npm:1.2.4" + dependencies: + es-errors: ^1.3.0 + function-bind: ^1.1.2 + has-proto: ^1.0.1 + has-symbols: ^1.0.3 + hasown: ^2.0.0 + checksum: 414e3cdf2c203d1b9d7d33111df746a4512a1aa622770b361dadddf8ed0b5aeb26c560f49ca077e24bfafb0acb55ca908d1f709216ccba33ffc548ec8a79a951 + 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 + +"get-symbol-description@npm:^1.0.2": + version: 1.0.2 + resolution: "get-symbol-description@npm:1.0.2" + dependencies: + call-bind: ^1.0.5 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.4 + checksum: e1cb53bc211f9dbe9691a4f97a46837a553c4e7caadd0488dc24ac694db8a390b93edd412b48dcdd0b4bbb4c595de1709effc75fc87c0839deedc6968f5bd973 + 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-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-stream@npm:^8.0.0": + version: 8.0.1 + resolution: "glob-stream@npm:8.0.1" + dependencies: + "@gulpjs/to-absolute-glob": ^4.0.0 + anymatch: ^3.1.3 + fastq: ^1.13.0 + glob-parent: ^6.0.2 + is-glob: ^4.0.3 + is-negated-glob: ^1.0.0 + normalize-path: ^3.0.0 + now-and-later: ^3.0.0 + streamx: ^2.12.5 + checksum: 0d57efdc07400c778fbd9adda9f29c97557a6ac96d508689ff22e15b95027c678dc8217d0475aa8739a8be7da8c31284b9d7ecc8e447fc923cc87cf9cafa3f50 + languageName: node + linkType: hard + +"glob-to-regexp@npm:^0.4.0": + version: 0.4.1 + resolution: "glob-to-regexp@npm:0.4.1" + checksum: e795f4e8f06d2a15e86f76e4d92751cf8bbfcf0157cea5c2f0f35678a8195a750b34096b1256e436f0cebc1883b5ff0888c47348443e69546a5a87f9e1eb1167 + languageName: node + linkType: hard + +"glob-watcher@npm:^6.0.0": + version: 6.0.0 + resolution: "glob-watcher@npm:6.0.0" + dependencies: + async-done: ^2.0.0 + chokidar: ^3.5.3 + checksum: b6d81f93435d2145a35a4eb605ed33020cb7ef4bb06bb30f9fbe8ac707b5463426c95af45f868764509eab6ebe8245279c190acd7b08ea0d579201badffed694 + languageName: node + linkType: hard + +"glob@npm:8.1.0": + 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 + +"glob@npm:^10.0.0": + version: 10.3.4 + resolution: "glob@npm:10.3.4" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^2.0.3 + minimatch: ^9.0.1 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + path-scurry: ^1.10.1 + bin: + glob: dist/cjs/src/bin.js + checksum: 176b97c124414401cb51329a93d2ba112cef8814adbed10348481916b9521b677773eee2691cb6b24d66632d8c8bb8913533f5ac4bfb2d0ef5454a1856082361 + languageName: node + linkType: hard + +"glob@npm:^10.2.2": + version: 10.3.3 + resolution: "glob@npm:10.3.3" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^2.0.3 + minimatch: ^9.0.1 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + path-scurry: ^1.10.1 + bin: + glob: dist/cjs/src/bin.js + checksum: 29190d3291f422da0cb40b77a72fc8d2c51a36524e99b8bf412548b7676a6627489528b57250429612b6eec2e6fe7826d328451d3e694a9d15e575389308ec53 + languageName: node + linkType: hard + +"glob@npm:^7.1.3, glob@npm:^7.1.7": + version: 7.2.0 + resolution: "glob@npm:7.2.0" + 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 + checksum: 78a8ea942331f08ed2e055cb5b9e40fe6f46f579d7fd3d694f3412fe5db23223d29b7fee1575440202e9a7ff9a72ab106a39fee39934c7bedafe5e5f8ae20134 + languageName: node + linkType: hard + +"glob@npm:^7.1.4": + 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.3": + version: 8.0.3 + resolution: "glob@npm:8.0.3" + dependencies: + fs.realpath: ^1.0.0 + inflight: ^1.0.4 + inherits: 2 + minimatch: ^5.0.1 + once: ^1.3.0 + checksum: 50bcdea19d8e79d8de5f460b1939ffc2b3299eac28deb502093fdca22a78efebc03e66bf54f0abc3d3d07d8134d19a32850288b7440d77e072aa55f9d33b18c5 + languageName: node + linkType: hard + +"global-modules@npm:^1.0.0": + version: 1.0.0 + resolution: "global-modules@npm:1.0.0" + dependencies: + global-prefix: ^1.0.1 + is-windows: ^1.0.1 + resolve-dir: ^1.0.0 + checksum: 10be68796c1e1abc1e2ba87ec4ea507f5629873b119ab0cd29c07284ef2b930f1402d10df01beccb7391dedd9cd479611dd6a24311c71be58937beaf18edf85e + languageName: node + linkType: hard + +"global-prefix@npm:^1.0.1": + version: 1.0.2 + resolution: "global-prefix@npm:1.0.2" + dependencies: + expand-tilde: ^2.0.2 + homedir-polyfill: ^1.0.1 + ini: ^1.3.4 + is-windows: ^1.0.1 + which: ^1.2.14 + checksum: 061b43470fe498271bcd514e7746e8a8535032b17ab9570517014ae27d700ff0dca749f76bbde13ba384d185be4310d8ba5712cb0e74f7d54d59390db63dd9a0 + 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": + version: 13.19.0 + resolution: "globals@npm:13.19.0" + dependencies: + type-fest: ^0.20.2 + checksum: a000dbd00bcf28f0941d8a29c3522b1c3b8e4bfe4e60e262c477a550c3cbbe8dbe2925a6905f037acd40f9a93c039242e1f7079c76b0fd184bc41dcc3b5c8e2e + languageName: node + linkType: hard + +"globals@npm:^13.24.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 + +"glogg@npm:^2.2.0": + version: 2.2.0 + resolution: "glogg@npm:2.2.0" + dependencies: + sparkles: ^2.1.0 + checksum: c2159222332f20873d8f9bc59a224f6ac83e79749fed004fab691d016eb0513fcb727266458bf233d18a3f15ecb0df00ee361a31561704580a29161236bcc8e3 + 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.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": + version: 4.2.9 + resolution: "graceful-fs@npm:4.2.9" + checksum: 68ea4e07ff2c041ada184f9278b830375f8e0b75154e3f080af6b70f66172fabb4108d19b3863a96b53fc068a310b9b6493d86d1291acc5f3861eb4b79d26ad6 + languageName: node + linkType: hard + +"graceful-fs@npm:^4.2.10, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.8": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 + 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 + +"gulp-changed@npm:^5.0.2": + version: 5.0.2 + resolution: "gulp-changed@npm:5.0.2" + dependencies: + change-file-extension: ^0.1.0 + gulp-plugin-extras: ^0.3.0 + touch: ^3.1.0 + peerDependencies: + gulp: ">=4" + peerDependenciesMeta: + gulp: + optional: true + checksum: 585237dcc556c9ccd0fd312b800e58c70d8f2bda7b282f3f3479fa16e724731a348b5b3ee0e304acdb8ea6251f203fc6b8244a12d2f5f46ce285851a997aa27f + languageName: node + linkType: hard + +"gulp-cli@npm:^3.0.0": + version: 3.0.0 + resolution: "gulp-cli@npm:3.0.0" + dependencies: + "@gulpjs/messages": ^1.1.0 + chalk: ^4.1.2 + copy-props: ^4.0.0 + gulplog: ^2.2.0 + interpret: ^3.1.1 + liftoff: ^5.0.0 + mute-stdout: ^2.0.0 + replace-homedir: ^2.0.0 + semver-greatest-satisfied-range: ^2.0.0 + string-width: ^4.2.3 + v8flags: ^4.0.0 + yargs: ^16.2.0 + bin: + gulp: bin/gulp.js + checksum: 90bef372b0831261c7b583ac9ad63b04ee52d7bb0a89f75dc9cf4378921842ddecc874f77d7dbc2ea30b04ce8083efaa0c6eea774ced0d44d1818facc2523db0 + languageName: node + linkType: hard + +"gulp-if@npm:^3.0.0": + version: 3.0.0 + resolution: "gulp-if@npm:3.0.0" + dependencies: + gulp-match: ^1.1.0 + ternary-stream: ^3.0.0 + through2: ^3.0.1 + checksum: 3316cc8c4b0c0fa2bf972aa459b28ab9ad00aebbb848eb1b5dbdfb7b73469dcc2d3bcb2107b013a8338f6ebf5a5a2587e7335771abc182b7cf04b17883b6b640 + languageName: node + linkType: hard + +"gulp-match@npm:^1.1.0": + version: 1.1.0 + resolution: "gulp-match@npm:1.1.0" + dependencies: + minimatch: ^3.0.3 + checksum: 1c0950be35013df1f6140ecca791b6cf475c88c81968b0bf7a2ea30ae36384d02ef49f5fb3e9a0cf01e8bdb845dc63179d4c04a63f1c224d8287e4e29954782b + languageName: node + linkType: hard + +"gulp-plugin-extras@npm:^0.3.0": + version: 0.3.0 + resolution: "gulp-plugin-extras@npm:0.3.0" + dependencies: + "@types/vinyl": ^2.0.9 + chalk: ^5.3.0 + easy-transform-stream: ^1.0.1 + checksum: 4252ff696529df643ddc4b2482e58ef0e4a865bba95a23d02ff82d6a4f7ec2c17619a52404a4cec88d0cc906ab6eb0773dd0088b235b9c93a52cbacff9336c21 + languageName: node + linkType: hard + +"gulp-svgmin@npm:^4.1.0": + version: 4.1.0 + resolution: "gulp-svgmin@npm:4.1.0" + dependencies: + lodash.clonedeep: ^4.5.0 + plugin-error: ^1.0.1 + svgo: ^2.7.0 + checksum: 51b15926190547cd80b67ea0d76b28c40edf16e5fa67d9997a72d3860e67623ca2a90e89f2a47b8627d68fb8ba4e8b89a58aeaa22c1c808ddd8089a304b00caa + languageName: node + linkType: hard + +"gulp@npm:^5.0.0": + version: 5.0.0 + resolution: "gulp@npm:5.0.0" + dependencies: + glob-watcher: ^6.0.0 + gulp-cli: ^3.0.0 + undertaker: ^2.0.0 + vinyl-fs: ^4.0.0 + bin: + gulp: bin/gulp.js + checksum: f5f45699f5c59078583d811fa8da70e030ace34744801765b3972403ec5ffee9702b8f2a65aeb945bf448f8b1a66c090ca66812bbd839ad712ecebb1b39e27c4 + languageName: node + linkType: hard + +"gulplog@npm:^2.2.0": + version: 2.2.0 + resolution: "gulplog@npm:2.2.0" + dependencies: + glogg: ^2.2.0 + checksum: 8a8c05e39ce2abe5589b8427484f26dd1e27367e0c730f822412de9884b9abd2872443d6c53868b421d80321a2c33455bafb03ec6fb13b465cf8b0452a2059e1 + languageName: node + linkType: hard + +"h@workspace:.": + version: 0.0.0-use.local + resolution: "h@workspace:." + dependencies: + "@babel/core": ^7.24.5 + "@babel/preset-env": ^7.24.5 + "@hypothesis/frontend-build": ^3.0.0 + "@rollup/plugin-babel": ^6.0.4 + "@rollup/plugin-commonjs": ^25.0.7 + "@rollup/plugin-node-resolve": ^15.2.3 + "@rollup/plugin-terser": ^0.4.4 + autoprefixer: ^10.4.19 + babel-plugin-mockable-imports: ^2.0.1 + bootstrap: ^4.6.2 + chai: ^5.1.0 + diff: ^5.2.0 + escape-html: ^1.0.3 + eslint: ^8.57.0 + eslint-config-hypothesis: 2.6 + eslint-plugin-mocha: ^10.4.3 + eslint-plugin-react: ^7.34.1 + eslint-plugin-react-hooks: ^4.6.2 + fetch-mock: ^9.11.0 + gulp: ^5.0.0 + gulp-changed: ^5.0.2 + gulp-cli: ^3.0.0 + gulp-if: ^3.0.0 + gulp-svgmin: ^4.1.0 + jquery: ^3.7.1 + karma: ^6.4.3 + karma-chrome-launcher: ^3.2.0 + karma-mocha: ^2.0.1 + karma-mocha-reporter: ^2.2.5 + karma-source-map-support: ^1.4.0 + mocha: ^10.4.0 + normalize.css: ^8.0.0 + popper.js: ^1.16.1 + postcss: ^8.4.38 + prettier: ^3.2.5 + raven-js: ^3.7.0 + rollup: ^4.17.2 + sass: ^1.76.0 + scroll-into-view: ^1.16.2 + sinon: ^17.0.1 + syn: ^0.2.2 + languageName: unknown + linkType: soft + +"has-bigints@npm:^1.0.1": + version: 1.0.1 + resolution: "has-bigints@npm:1.0.1" + checksum: 44ab55868174470065d2e0f8f6def1c990d12b82162a8803c679699fa8a39f966e336f2a33c185092fe8aea7e8bf2e85f1c26add5f29d98f2318bd270096b183 + languageName: node + linkType: hard + +"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-property-descriptors@npm:^1.0.2": + version: 1.0.2 + resolution: "has-property-descriptors@npm:1.0.2" + dependencies: + es-define-property: ^1.0.0 + checksum: fcbb246ea2838058be39887935231c6d5788babed499d0e9d0cc5737494c48aba4fe17ba1449e0d0fbbb1e36175442faa37f9c427ae357d6ccb1d895fbcd3de3 + 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-proto@npm:^1.0.3": + version: 1.0.3 + resolution: "has-proto@npm:1.0.3" + checksum: fe7c3d50b33f50f3933a04413ed1f69441d21d2d2944f81036276d30635cad9279f6b43bc8f32036c31ebdfcf6e731150f46c1907ad90c669ffe9b066c3ba5c4 + languageName: node + linkType: hard + +"has-symbols@npm:^1.0.1, has-symbols@npm:^1.0.2": + version: 1.0.2 + resolution: "has-symbols@npm:1.0.2" + checksum: 2309c426071731be792b5be43b3da6fb4ed7cbe8a9a6bcfca1862587709f01b33d575ce8f5c264c1eaad09fca2f9a8208c0a2be156232629daa2dd0c0740976b + languageName: node + linkType: hard + +"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-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" + dependencies: + has-symbols: ^1.0.3 + checksum: 999d60bb753ad714356b2c6c87b7fb74f32463b8426e159397da4bde5bca7e598ab1073f4d8d4deafac297f2eb311484cd177af242776bf05f0d11565680468d + 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 + +"hasown@npm:^2.0.0": + version: 2.0.0 + resolution: "hasown@npm:2.0.0" + dependencies: + function-bind: ^1.1.2 + checksum: 6151c75ca12554565098641c98a40f4cc86b85b0fd5b6fe92360967e4605a4f9610f7757260b4e8098dd1c2ce7f4b095f2006fe72a570e3b6d2d28de0298c176 + languageName: node + linkType: hard + +"hasown@npm:^2.0.1, hasown@npm:^2.0.2": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" + dependencies: + function-bind: ^1.1.2 + checksum: e8516f776a15149ca6c6ed2ae3110c417a00b62260e222590e54aa367cbcd6ed99122020b37b7fbdf05748df57b265e70095d7bf35a47660587619b15ffb93db + 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 + +"homedir-polyfill@npm:^1.0.1": + version: 1.0.3 + resolution: "homedir-polyfill@npm:1.0.3" + dependencies: + parse-passwd: ^1.0.0 + checksum: 18dd4db87052c6a2179d1813adea0c4bfcfa4f9996f0e226fefb29eb3d548e564350fa28ec46b0bf1fbc0a1d2d6922ceceb80093115ea45ff8842a4990139250 + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 + languageName: node + linkType: hard + +"http-errors@npm:1.7.2": + version: 1.7.2 + resolution: "http-errors@npm:1.7.2" + dependencies: + depd: ~1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.1 + statuses: ">= 1.5.0 < 2" + toidentifier: 1.0.0 + checksum: 5534b0ae08e77f5a45a2380f500e781f6580c4ff75b816cb1f09f99a290b57e78a518be6d866db1b48cca6b052c09da2c75fc91fb16a2fe3da3c44d9acbb9972 + 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@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 + +"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 + +"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 + +"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 + +"ieee754@npm:^1.2.1": + version: 1.2.1 + resolution: "ieee754@npm:1.2.1" + checksum: 5144c0c9815e54ada181d80a0b810221a253562422e7c6c3a60b1901154184f49326ec239d618c416c1c5945a2e197107aee8d986a3dd836b53dffefd99b5e7e + languageName: node + linkType: hard + +"ignore@npm:^5.2.0": + version: 5.2.0 + resolution: "ignore@npm:5.2.0" + checksum: 6b1f926792d614f64c6c83da3a1f9c83f6196c2839aa41e1e32dd7b8d174cef2e329d75caabb62cb61ce9dc432f75e67d07d122a037312db7caa73166a1bdb77 + languageName: node + linkType: hard + +"immutable@npm:^4.0.0": + version: 4.0.0 + resolution: "immutable@npm:4.0.0" + checksum: 4b5e9181e4d5fa06728a481835ec09c86367e5d03268666c95b522b7644ab891098022e4479a43c4c81a68f2ed82f10751ce5d33e208d7b873b6e7f9dfaf4d87 + languageName: node + linkType: hard + +"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 + +"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 + +"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.3, inherits@npm:^2.0.4": + 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:^1.3.4": + version: 1.3.8 + resolution: "ini@npm:1.3.8" + checksum: dfd98b0ca3a4fc1e323e38a6c8eb8936e31a97a918d3b377649ea15bdb15d481207a0dda1021efbd86b464cae29a0d33c1d7dcaf6c5672bee17fa849bc50a1b3 + languageName: node + linkType: hard + +"internal-slot@npm:^1.0.3": + version: 1.0.3 + resolution: "internal-slot@npm:1.0.3" + dependencies: + get-intrinsic: ^1.1.0 + has: ^1.0.3 + side-channel: ^1.0.4 + checksum: 1944f92e981e47aebc98a88ff0db579fd90543d937806104d0b96557b10c1f170c51fb777b97740a8b6ddeec585fca8c39ae99fd08a8e058dfc8ab70937238bf + languageName: node + linkType: hard + +"internal-slot@npm:^1.0.5": + version: 1.0.6 + resolution: "internal-slot@npm:1.0.6" + dependencies: + get-intrinsic: ^1.2.2 + hasown: ^2.0.0 + side-channel: ^1.0.4 + checksum: 7872454888047553ce97a3fa1da7cc054a28ec5400a9c2e9f4dbe4fe7c1d041cb8e8301467614b80d4246d50377aad2fb58860b294ed74d6700cc346b6f89549 + languageName: node + linkType: hard + +"internal-slot@npm:^1.0.7": + version: 1.0.7 + resolution: "internal-slot@npm:1.0.7" + dependencies: + es-errors: ^1.3.0 + hasown: ^2.0.0 + side-channel: ^1.0.4 + checksum: cadc5eea5d7d9bc2342e93aae9f31f04c196afebb11bde97448327049f492cd7081e18623ae71388aac9cd237b692ca3a105be9c68ac39c1dec679d7409e33eb + languageName: node + linkType: hard + +"interpret@npm:^3.1.1": + version: 3.1.1 + resolution: "interpret@npm:3.1.1" + checksum: 35cebcf48c7351130437596d9ab8c8fe131ce4038da4561e6d665f25640e0034702a031cf7e3a5cea60ac7ac548bf17465e0571ede126f3d3a6933152171ac82 + 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 + +"is-absolute@npm:^1.0.0": + version: 1.0.0 + resolution: "is-absolute@npm:1.0.0" + dependencies: + is-relative: ^1.0.0 + is-windows: ^1.0.1 + checksum: 9d16b2605eda3f3ce755410f1d423e327ad3a898bcb86c9354cf63970ed3f91ba85e9828aa56f5d6a952b9fae43d0477770f78d37409ae8ecc31e59ebc279b27 + languageName: node + linkType: hard + +"is-array-buffer@npm:^3.0.1, is-array-buffer@npm:^3.0.2": + version: 3.0.2 + resolution: "is-array-buffer@npm:3.0.2" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.2.0 + is-typed-array: ^1.1.10 + checksum: dcac9dda66ff17df9cabdc58214172bf41082f956eab30bb0d86bc0fab1e44b690fc8e1f855cf2481245caf4e8a5a006a982a71ddccec84032ed41f9d8da8c14 + languageName: node + linkType: hard + +"is-array-buffer@npm:^3.0.4": + version: 3.0.4 + resolution: "is-array-buffer@npm:3.0.4" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.2.1 + checksum: e4e3e6ef0ff2239e75371d221f74bc3c26a03564a22efb39f6bb02609b598917ddeecef4e8c877df2a25888f247a98198959842a5e73236bc7f22cabdf6351a7 + languageName: node + linkType: hard + +"is-async-function@npm:^2.0.0": + version: 2.0.0 + resolution: "is-async-function@npm:2.0.0" + dependencies: + has-tostringtag: ^1.0.0 + checksum: e3471d95e6c014bf37cad8a93f2f4b6aac962178e0a5041e8903147166964fdc1c5c1d2ef87e86d77322c370ca18f2ea004fa7420581fa747bcaf7c223069dbd + 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-builtin-module@npm:^3.2.1": + version: 3.2.1 + resolution: "is-builtin-module@npm:3.2.1" + dependencies: + builtin-modules: ^3.3.0 + checksum: e8f0ffc19a98240bda9c7ada84d846486365af88d14616e737d280d378695c8c448a621dcafc8332dbf0fcd0a17b0763b845400709963fa9151ddffece90ae88 + languageName: node + linkType: hard + +"is-callable@npm:^1.1.3, is-callable@npm:^1.2.7": + version: 1.2.7 + resolution: "is-callable@npm:1.2.7" + checksum: 61fd57d03b0d984e2ed3720fb1c7a897827ea174bd44402878e059542ea8c4aeedee0ea0985998aa5cc2736b2fa6e271c08587addb5b3959ac52cf665173d1ac + languageName: node + linkType: hard + +"is-callable@npm:^1.1.4, is-callable@npm:^1.2.4": + version: 1.2.4 + resolution: "is-callable@npm:1.2.4" + checksum: 1a28d57dc435797dae04b173b65d6d1e77d4f16276e9eff973f994eadcfdc30a017e6a597f092752a083c1103cceb56c91e3dadc6692fedb9898dfaba701575f + languageName: node + linkType: hard + +"is-core-module@npm:^2.13.0": + version: 2.13.1 + resolution: "is-core-module@npm:2.13.1" + dependencies: + hasown: ^2.0.0 + checksum: 256559ee8a9488af90e4bad16f5583c6d59e92f0742e9e8bb4331e758521ee86b810b93bae44f390766ffbc518a0488b18d9dab7da9a5ff997d499efc9403f7c + languageName: node + linkType: hard + +"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-data-view@npm:^1.0.1": + version: 1.0.1 + resolution: "is-data-view@npm:1.0.1" + dependencies: + is-typed-array: ^1.1.13 + checksum: 4ba4562ac2b2ec005fefe48269d6bd0152785458cd253c746154ffb8a8ab506a29d0cfb3b74af87513843776a88e4981ae25c89457bf640a33748eab1a7216b5 + 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-extendable@npm:^1.0.1": + version: 1.0.1 + resolution: "is-extendable@npm:1.0.1" + dependencies: + is-plain-object: ^2.0.4 + checksum: db07bc1e9de6170de70eff7001943691f05b9d1547730b11be01c0ebfe67362912ba743cf4be6fd20a5e03b4180c685dad80b7c509fe717037e3eee30ad8e84f + 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-finalizationregistry@npm:^1.0.2": + version: 1.0.2 + resolution: "is-finalizationregistry@npm:1.0.2" + dependencies: + call-bind: ^1.0.2 + checksum: 4f243a8e06228cd45bdab8608d2cb7abfc20f6f0189c8ac21ea8d603f1f196eabd531ce0bb8e08cbab047e9845ef2c191a3761c9a17ad5cabf8b35499c4ad35d + 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-generator-function@npm:^1.0.10": + version: 1.0.10 + resolution: "is-generator-function@npm:1.0.10" + dependencies: + has-tostringtag: ^1.0.0 + checksum: d54644e7dbaccef15ceb1e5d91d680eb5068c9ee9f9eb0a9e04173eb5542c9b51b5ab52c5537f5703e48d5fddfd376817c1ca07a84a407b7115b769d4bdde72b + 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-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": + 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-negated-glob@npm:^1.0.0": + version: 1.0.0 + resolution: "is-negated-glob@npm:1.0.0" + checksum: 2a767da06435b492daa98d3049480f0b7032abd5bfd3930ac01dbe9d6fcae04f2b3d883c6dca6b9c0c3f8a703952643c78540151c3eb1a2fe90fec543d61d241 + languageName: node + linkType: hard + +"is-negative-zero@npm:^2.0.1": + version: 2.0.1 + resolution: "is-negative-zero@npm:2.0.1" + checksum: a46f2e0cb5e16fdb8f2011ed488979386d7e68d381966682e3f4c98fc126efe47f26827912baca2d06a02a644aee458b9cba307fb389f6b161e759125db7a3b8 + 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-negative-zero@npm:^2.0.3": + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: c1e6b23d2070c0539d7b36022d5a94407132411d01aba39ec549af824231f3804b1aea90b5e4e58e807a65d23ceb538ed6e355ce76b267bdd86edb757ffcbdcd + languageName: node + linkType: hard + +"is-number-object@npm:^1.0.4": + version: 1.0.6 + resolution: "is-number-object@npm:1.0.6" + dependencies: + has-tostringtag: ^1.0.0 + checksum: c697704e8fc2027fc41cb81d29805de4e8b6dc9c3efee93741dbf126a8ecc8443fef85adbc581415ae7e55d325e51d0a942324ae35c829131748cce39cba55f3 + 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-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:^2.1.0": + version: 2.1.0 + resolution: "is-plain-obj@npm:2.1.0" + checksum: cec9100678b0a9fe0248a81743041ed990c2d4c99f893d935545cfbc42876cbe86d207f3b895700c690ad2fa520e568c44afc1605044b535a7820c1d40e38daa + 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-plain-object@npm:^5.0.0": + version: 5.0.0 + resolution: "is-plain-object@npm:5.0.0" + checksum: e32d27061eef62c0847d303125440a38660517e586f2f3db7c9d179ae5b6674ab0f469d519b2e25c147a1a3bc87156d0d5f4d8821e0ce4a9ee7fe1fcf11ce45c + languageName: node + linkType: hard + +"is-reference@npm:1.2.1": + version: 1.2.1 + resolution: "is-reference@npm:1.2.1" + dependencies: + "@types/estree": "*" + checksum: e7b48149f8abda2c10849ea51965904d6a714193d68942ad74e30522231045acf06cbfae5a4be2702fede5d232e61bf50b3183acdc056e6e3afe07fcf4f4b2bc + 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-relative@npm:^1.0.0": + version: 1.0.0 + resolution: "is-relative@npm:1.0.0" + dependencies: + is-unc-path: ^1.0.0 + checksum: 3271a0df109302ef5e14a29dcd5d23d9788e15ade91a40b942b035827ffbb59f7ce9ff82d036ea798541a52913cbf9d2d0b66456340887b51f3542d57b5a4c05 + languageName: node + linkType: hard + +"is-set@npm:^2.0.1": + version: 2.0.2 + resolution: "is-set@npm:2.0.2" + checksum: b64343faf45e9387b97a6fd32be632ee7b269bd8183701f3b3f5b71a7cf00d04450ed8669d0bd08753e08b968beda96fca73a10fd0ff56a32603f64deba55a57 + languageName: node + linkType: hard + +"is-shared-array-buffer@npm:^1.0.1": + version: 1.0.1 + resolution: "is-shared-array-buffer@npm:1.0.1" + checksum: 2ffb92533e64e2876e6cfe6906871d28400b6f1a53130fe652ec8007bc0e5044d05e7af8e31bdc992fbba520bd92938cfbeedd0f286be92f250c7c76191c4d90 + 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-shared-array-buffer@npm:^1.0.3": + version: 1.0.3 + resolution: "is-shared-array-buffer@npm:1.0.3" + dependencies: + call-bind: ^1.0.7 + checksum: a4fff602c309e64ccaa83b859255a43bb011145a42d3f56f67d9268b55bc7e6d98a5981a1d834186ad3105d6739d21547083fe7259c76c0468483fc538e716d8 + 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-subset@npm:^0.1.1": + version: 0.1.1 + resolution: "is-subset@npm:0.1.1" + checksum: 97b8d7852af165269b7495095691a6ce6cf20bdfa1f846f97b4560ee190069686107af4e277fbd93aa0845c4d5db704391460ff6e9014aeb73264ba87893df44 + 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.12, is-typed-array@npm:^1.1.9": + version: 1.1.12 + resolution: "is-typed-array@npm:1.1.12" + dependencies: + which-typed-array: ^1.1.11 + checksum: 4c89c4a3be07186caddadf92197b17fda663a9d259ea0d44a85f171558270d36059d1c386d34a12cba22dfade5aba497ce22778e866adc9406098c8fc4771796 + languageName: node + linkType: hard + +"is-typed-array@npm:^1.1.13": + version: 1.1.13 + resolution: "is-typed-array@npm:1.1.13" + dependencies: + which-typed-array: ^1.1.14 + checksum: 150f9ada183a61554c91e1c4290086d2c100b0dff45f60b028519be72a8db964da403c48760723bf5253979b8dffe7b544246e0e5351dcd05c5fdb1dcc1dc0f0 + languageName: node + linkType: hard + +"is-unc-path@npm:^1.0.0": + version: 1.0.0 + resolution: "is-unc-path@npm:1.0.0" + dependencies: + unc-path-regex: ^0.1.2 + checksum: e8abfde203f7409f5b03a5f1f8636e3a41e78b983702ef49d9343eb608cdfe691429398e8815157519b987b739bcfbc73ae7cf4c8582b0ab66add5171088eab6 + 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-valid-glob@npm:^1.0.0": + version: 1.0.0 + resolution: "is-valid-glob@npm:1.0.0" + checksum: 0155951e89291d405cbb2ff4e25a38ee7a88bc70b05f246c25d31a1d09f13d4207377e5860f67443bbda8e3e353da37047b60e586bd9c97a39c9301c30b67acb + 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.1": + version: 1.0.1 + resolution: "is-weakref@npm:1.0.1" + dependencies: + call-bind: ^1.0.0 + checksum: fdafb7b955671dd2f9658ff47c86e4025c0650fc68a3542a40e5a75898a763b1abd6b1e1f9f13207eed49541cdd76af67d73c44989ea358b201b70274cf8f6c1 + 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-windows@npm:^1.0.1": + version: 1.0.2 + resolution: "is-windows@npm:1.0.2" + checksum: 438b7e52656fe3b9b293b180defb4e448088e7023a523ec21a91a80b9ff8cdb3377ddb5b6e60f7c7de4fa8b63ab56e121b6705fe081b3cf1b828b0a380009ad7 + 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 + +"isbinaryfile@npm:^4.0.8": + version: 4.0.8 + resolution: "isbinaryfile@npm:4.0.8" + checksum: 606e3bb648d1a0dee23459d1d937bb2560e66a5281ec7c9ff50e585402d73321ac268d0f34cb7393125b3ebc4c7962d39e50a01cdb8904b52fce08b7ccd2bf9f + 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.0, isobject@npm:^3.0.1": + version: 3.0.1 + resolution: "isobject@npm:3.0.1" + checksum: db85c4c970ce30693676487cca0e61da2ca34e8d4967c2e1309143ff910c207133a969f9e4ddb2dc6aba670aabce4e0e307146c310350b298e74a31f7d464703 + languageName: node + linkType: hard + +"iterator.prototype@npm:^1.1.2": + version: 1.1.2 + resolution: "iterator.prototype@npm:1.1.2" + dependencies: + define-properties: ^1.2.1 + get-intrinsic: ^1.2.1 + has-symbols: ^1.0.3 + reflect.getprototypeof: ^1.0.4 + set-function-name: ^2.0.1 + checksum: d8a507e2ccdc2ce762e8a1d3f4438c5669160ac72b88b648e59a688eec6bc4e64b22338e74000518418d9e693faf2a092d2af21b9ec7dbf7763b037a54701168 + languageName: node + linkType: hard + +"jackspeak@npm:^2.0.3": + version: 2.2.2 + resolution: "jackspeak@npm:2.2.2" + dependencies: + "@isaacs/cliui": ^8.0.2 + "@pkgjs/parseargs": ^0.11.0 + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 7b1468dd910afc00642db87448f24b062346570b8b47531409aa9012bcb95fdf7ec2b1c48edbb8b57a938c08391f8cc01b5034fc335aa3a2e74dbcc0ee5c555a + languageName: node + linkType: hard + +"jquery@npm:^3.7.1": + version: 3.7.1 + resolution: "jquery@npm:3.7.1" + checksum: 4370b8139d6ae82867eb6f7f21d1edccf1d1bdf41c0840920ea80d366c2cd5dbe1ceebb110ee9772aa839b04400faa1572c5c560b507c688ed7b61cea26c0e27 + 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:4.1.0, 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 + +"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-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-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 + +"json5@npm:^2.2.2, json5@npm:^2.2.3": + 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 + +"jsx-ast-utils@npm:^2.4.1 || ^3.0.0": + version: 3.2.1 + resolution: "jsx-ast-utils@npm:3.2.1" + dependencies: + array-includes: ^3.1.3 + object.assign: ^4.1.2 + checksum: dcee22e6382ee5a6bd4187333a44b6420d9d079838119a07055d6e88d137dd0afadc97a2246152b0b65006bd5fc393112dc0cef01956a01a66c1713913953c66 + languageName: node + linkType: hard + +"just-extend@npm:^4.0.2": + version: 4.2.1 + resolution: "just-extend@npm:4.2.1" + checksum: ff9fdede240fad313efeeeb68a660b942e5586d99c0058064c78884894a2690dc09bba44c994ad4e077e45d913fef01a9240c14a72c657b53687ac58de53b39c + languageName: node + linkType: hard + +"karma-chrome-launcher@npm:^3.2.0": + version: 3.2.0 + resolution: "karma-chrome-launcher@npm:3.2.0" + dependencies: + which: ^1.2.1 + checksum: e1119e4f95dbcdaec937e5d15a9ffea1b7e5c1d7566f7074ff140161983d4a0821ad274d3dcc34aacfb792caf842a39c459ba9c263723faa6a060cca8692d9b7 + languageName: node + linkType: hard + +"karma-mocha-reporter@npm:^2.2.5": + version: 2.2.5 + resolution: "karma-mocha-reporter@npm:2.2.5" + dependencies: + chalk: ^2.1.0 + log-symbols: ^2.1.0 + strip-ansi: ^4.0.0 + peerDependencies: + karma: ">=0.13" + checksum: 8b9e43c64bc975d38c18958d7ba95baf9a8d23f11ee4641955fe0ae5e8bd563596c8965d6f290ce8c73c4832fb98bb7ed5fbbaa82b49273d2ca24aa7f3d0d5e5 + languageName: node + linkType: hard + +"karma-mocha@npm:^2.0.1": + version: 2.0.1 + resolution: "karma-mocha@npm:2.0.1" + dependencies: + minimist: ^1.2.3 + checksum: a09f4758758a899fb97836660624ccd1769325e05f6efca63c9132806cc8dfeb20eaf78b3bc4db7921dcb3c48384fbfd5cddfa3568ddaf00197c75852ec9b480 + languageName: node + linkType: hard + +"karma-source-map-support@npm:^1.4.0": + version: 1.4.0 + resolution: "karma-source-map-support@npm:1.4.0" + dependencies: + source-map-support: ^0.5.5 + checksum: 7a482bc836c70f8c1d9468382a9e1c887d032697f6ace97fac90b02e73d0523cb59fc0af8759356293e6bc4ce3a17bab59b331bad0560cab9dd77ac65b343de8 + languageName: node + linkType: hard + +"karma@npm:^6.4.3": + version: 6.4.3 + resolution: "karma@npm:6.4.3" + dependencies: + "@colors/colors": 1.5.0 + body-parser: ^1.19.0 + braces: ^3.0.2 + chokidar: ^3.5.1 + connect: ^3.7.0 + di: ^0.0.1 + dom-serialize: ^2.2.1 + glob: ^7.1.7 + graceful-fs: ^4.2.6 + http-proxy: ^1.18.1 + isbinaryfile: ^4.0.8 + lodash: ^4.17.21 + log4js: ^6.4.1 + mime: ^2.5.2 + minimatch: ^3.0.4 + mkdirp: ^0.5.5 + qjobs: ^1.2.0 + range-parser: ^1.2.1 + rimraf: ^3.0.2 + socket.io: ^4.7.2 + source-map: ^0.6.1 + tmp: ^0.2.1 + ua-parser-js: ^0.7.30 + yargs: ^16.1.1 + bin: + karma: bin/karma + checksum: 4eee6f52c7cf54d860bb35600b61eac3631647efa01282671c9f799dbe4ea80ac729946c8c82e53be778905b5920d221b527c86bd9bec73214ca2f84339aebbe + languageName: node + linkType: hard + +"last-run@npm:^2.0.0": + version: 2.0.0 + resolution: "last-run@npm:2.0.0" + checksum: a594c4bb4312258c625e3b40b760d5ce9ff183f90cd77a73dc509ff8d9f215ce7754755d843d8489ea97ef39cbe5975401889f29d0022a820321563dcd1ac184 + languageName: node + linkType: hard + +"lead@npm:^4.0.0": + version: 4.0.0 + resolution: "lead@npm:4.0.0" + checksum: 7117297c29b94e4846822e5ae0a25780af834586c0862b89ff899e44547f4f742d67801f19838b34611d36eec44868604c55525e12d2a1fb0c9496a9792ca396 + 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 + +"liftoff@npm:^5.0.0": + version: 5.0.0 + resolution: "liftoff@npm:5.0.0" + dependencies: + extend: ^3.0.2 + findup-sync: ^5.0.0 + fined: ^2.0.0 + flagged-respawn: ^2.0.0 + is-plain-object: ^5.0.0 + rechoir: ^0.8.0 + resolve: ^1.20.0 + checksum: ae6a1f3b734fbf0b8b5b7ca189e00fe04fa9966e436313c7e20e3444cec5ae9e4f472666aa02ac23557e412610f111d9d56ef78854cae1580d297d5e365738a8 + 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.clonedeep@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.clonedeep@npm:4.5.0" + checksum: 92c46f094b064e876a23c97f57f81fbffd5d760bf2d8a1c61d85db6d1e488c66b0384c943abee4f6af7debf5ad4e4282e74ff83177c9e63d8ff081a4837c3489 + languageName: node + linkType: hard + +"lodash.debounce@npm:^4.0.8": + version: 4.0.8 + resolution: "lodash.debounce@npm:4.0.8" + checksum: a3f527d22c548f43ae31c861ada88b2637eb48ac6aa3eb56e82d44917971b8aa96fbb37aa60efea674dc4ee8c42074f90f7b1f772e9db375435f6c83a19b3bc6 + languageName: node + linkType: hard + +"lodash.get@npm:^4.4.2": + version: 4.4.2 + resolution: "lodash.get@npm:4.4.2" + checksum: e403047ddb03181c9d0e92df9556570e2b67e0f0a930fcbbbd779370972368f5568e914f913e93f3b08f6d492abc71e14d4e9b7a18916c31fa04bd2306efe545 + 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.merge@npm:^4.6.2": + version: 4.6.2 + resolution: "lodash.merge@npm:4.6.2" + checksum: ad580b4bdbb7ca1f7abf7e1bce63a9a0b98e370cf40194b03380a46b4ed799c9573029599caebc1b14e3f24b111aef72b96674a56cfa105e0f5ac70546cdc005 + 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@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 + languageName: node + linkType: hard + +"log-symbols@npm:4.1.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-symbols@npm:^2.1.0": + version: 2.2.0 + resolution: "log-symbols@npm:2.2.0" + dependencies: + chalk: ^2.0.1 + checksum: 4c95e3b65f0352dbe91dc4989c10baf7a44e2ef5b0db7e6721e1476268e2b6f7090c3aa880d4f833a05c5c3ff18f4ec5215a09bd0099986d64a8186cfeb48ac8 + languageName: node + linkType: hard + +"log4js@npm:^6.4.1": + version: 6.4.1 + resolution: "log4js@npm:6.4.1" + dependencies: + date-format: ^4.0.3 + debug: ^4.3.3 + flatted: ^3.2.4 + rfdc: ^1.3.0 + streamroller: ^3.0.2 + checksum: 0614949662314573ec7dcd841769a4d23d8cb8268685458a40fcd94f2ae6ec628234cfb9a6bc17821fb6ea6ce3765e779b4966ba1cf918f393dc37155a3615cb + languageName: node + linkType: hard + +"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 + +"loupe@npm:^3.1.0": + version: 3.1.0 + resolution: "loupe@npm:3.1.0" + dependencies: + get-func-name: ^2.0.1 + checksum: e23814854ab2571e3f753b7c198bfe016c708f3a435501624dd6ff79b6a5544e14b0f28cfc0432eb22e9da9177b1533491871aca3f94d56b19fecc0d4a766e58 + 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.18.3 + resolution: "lru-cache@npm:7.18.3" + checksum: e550d772384709deea3f141af34b6d4fa392e2e418c1498c078de0ee63670f1f46f5eee746e8ef7e69e1c895af0d4224e62ee33e66a543a14763b0f2e74c1356 + languageName: node + linkType: hard + +"lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.0.0 + resolution: "lru-cache@npm:10.0.0" + checksum: 18f101675fe283bc09cda0ef1e3cc83781aeb8373b439f086f758d1d91b28730950db785999cd060d3c825a8571c03073e8c14512b6655af2188d623031baf50 + languageName: node + linkType: hard + +"magic-string@npm:^0.30.3": + version: 0.30.5 + resolution: "magic-string@npm:0.30.5" + dependencies: + "@jridgewell/sourcemap-codec": ^1.4.15 + checksum: da10fecff0c0a7d3faf756913ce62bd6d5e7b0402be48c3b27bfd651b90e29677e279069a63b764bcdc1b8ecdcdb898f29a5c5ec510f2323e8d62ee057a6eb18 + languageName: node + linkType: hard + +"make-fetch-happen@npm:^11.0.3": + version: 11.1.1 + resolution: "make-fetch-happen@npm:11.1.1" + dependencies: + agentkeepalive: ^4.2.1 + cacache: ^17.0.0 + http-cache-semantics: ^4.1.1 + http-proxy-agent: ^5.0.0 + https-proxy-agent: ^5.0.0 + is-lambda: ^1.0.1 + lru-cache: ^7.7.1 + minipass: ^5.0.0 + minipass-fetch: ^3.0.0 + 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: ^10.0.0 + checksum: 7268bf274a0f6dcf0343829489a4506603ff34bd0649c12058753900b0eb29191dce5dba12680719a5d0a983d3e57810f594a12f3c18494e93a1fbc6348a4540 + languageName: node + linkType: hard + +"map-cache@npm:^0.2.0": + version: 0.2.2 + resolution: "map-cache@npm:0.2.2" + checksum: 3067cea54285c43848bb4539f978a15dedc63c03022abeec6ef05c8cb6829f920f13b94bcaf04142fc6a088318e564c4785704072910d120d55dbc2e0c421969 + 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 + +"media-typer@npm:0.3.0": + version: 0.3.0 + resolution: "media-typer@npm:0.3.0" + checksum: af1b38516c28ec95d6b0826f6c8f276c58aec391f76be42aa07646b4e39d317723e869700933ca6995b056db4b09a78c92d5440dc23657e6764be5d28874bba1 + 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 + +"micromatch@npm:^4.0.4": + 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 + +"mime-db@npm:1.50.0": + version: 1.50.0 + resolution: "mime-db@npm:1.50.0" + checksum: 95fcc19c3664ae72391c8a7e4015dde7fb6817c98c951493ca3a1d48050feb8ee08810a372ce7d9e16310042d26e5bda168916f600583a9a583655eeea8ff5f5 + languageName: node + linkType: hard + +"mime-db@npm:1.52.0": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 0d99a03585f8b39d68182803b12ac601d9c01abfa28ec56204fa330bc9f3d1c5e14beb049bafadb3dbdf646dfb94b87e24d4ec7b31b7279ef906a8ea9b6a513f + languageName: node + linkType: hard + +"mime-types@npm:~2.1.24": + version: 2.1.33 + resolution: "mime-types@npm:2.1.33" + dependencies: + mime-db: 1.50.0 + checksum: 05f2a0b3f169fbc51d79bdc7674ceb379dd07dbeadb0143059a7def865224686ee9f9051aeb340e98b6c11dbc06794ce0122181db4312cb1ad054fd90b0d510e + languageName: node + linkType: hard + +"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:^2.5.2": + version: 2.5.2 + resolution: "mime@npm:2.5.2" + bin: + mime: cli.js + checksum: dd3c93d433d41a09f6a1cfa969b653b769899f3bd573e7bfcea33bdc8b0cc4eba57daa2f95937369c2bd2b6d39d62389b11a4309fe40d1d3a1b736afdedad0ff + languageName: node + linkType: hard + +"minimatch@npm:5.0.1": + version: 5.0.1 + resolution: "minimatch@npm:5.0.1" + dependencies: + brace-expansion: ^2.0.1 + checksum: b34b98463da4754bc526b244d680c69d4d6089451ebe512edaf6dd9eeed0279399cfa3edb19233513b8f830bf4bfcad911dddcdf125e75074100d52f724774f0 + languageName: node + linkType: hard + +"minimatch@npm:^3.0.3, 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.0 + resolution: "minimatch@npm:5.1.0" + dependencies: + brace-expansion: ^2.0.1 + checksum: 15ce53d31a06361e8b7a629501b5c75491bc2b59712d53e802b1987121d91b433d73fcc5be92974fde66b2b51d8fb28d75a9ae900d249feb792bb1ba2a4f0a90 + languageName: node + linkType: hard + +"minimatch@npm:^9.0.1": + version: 9.0.3 + resolution: "minimatch@npm:9.0.3" + dependencies: + brace-expansion: ^2.0.1 + checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5 + languageName: node + linkType: hard + +"minimist@npm:^1.2.3, minimist@npm:^1.2.5": + version: 1.2.6 + resolution: "minimist@npm:1.2.6" + checksum: d15428cd1e11eb14e1233bcfb88ae07ed7a147de251441d61158619dfb32c4d7e9061d09cab4825fdee18ecd6fce323228c8c47b5ba7cd20af378ca4048fb3fb + 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:^3.0.0": + version: 3.0.3 + resolution: "minipass-fetch@npm:3.0.3" + dependencies: + encoding: ^0.1.13 + minipass: ^5.0.0 + minipass-sized: ^1.0.3 + minizlib: ^2.1.2 + dependenciesMeta: + encoding: + optional: true + checksum: af5ab2552a16fcf505d35fd7ffb84b57f4a0eeb269e6e1d9a2a75824dda48b36e527083250b7cca4a4def21d9544e2ade441e4730e233c0bc2133f6abda31e18 + 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": + 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 + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0": + version: 7.0.2 + resolution: "minipass@npm:7.0.2" + checksum: 46776de732eb7cef2c7404a15fb28c41f5c54a22be50d47b03c605bf21f5c18d61a173c0a20b49a97e7a65f78d887245066410642551e45fffe04e9ac9e325bc + 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:^0.5.5": + version: 0.5.5 + resolution: "mkdirp@npm:0.5.5" + dependencies: + minimist: ^1.2.5 + bin: + mkdirp: bin/cmd.js + checksum: 3bce20ea525f9477befe458ab85284b0b66c8dc3812f94155af07c827175948cdd8114852ac6c6d82009b13c1048c37f6d98743eb019651ee25c39acc8aabe7d + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: a96865108c6c3b1b8e1d5e9f11843de1e077e57737602de1b82030815f311be11f96f09cce59bd5b903d0b29834733e5313f9301e3ed6d6f6fba2eae0df4298f + languageName: node + linkType: hard + +"mocha@npm:^10.4.0": + version: 10.4.0 + resolution: "mocha@npm:10.4.0" + dependencies: + ansi-colors: 4.1.1 + browser-stdout: 1.3.1 + chokidar: 3.5.3 + debug: 4.3.4 + diff: 5.0.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 8.1.0 + he: 1.2.0 + js-yaml: 4.1.0 + log-symbols: 4.1.0 + minimatch: 5.0.1 + ms: 2.1.3 + serialize-javascript: 6.0.0 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 6.2.1 + yargs: 16.2.0 + yargs-parser: 20.2.4 + yargs-unparser: 2.0.0 + bin: + _mocha: bin/_mocha + mocha: bin/mocha.js + checksum: 090771d6d42a65a934c7ed448d524bcc663836351af9f0678578caa69943b01a9535a73192d24fd625b3fdb5979cce5834dfe65e3e1ee982444d65e19975b81c + 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": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d + languageName: node + linkType: hard + +"mute-stdout@npm:^2.0.0": + version: 2.0.0 + resolution: "mute-stdout@npm:2.0.0" + checksum: b61db228cee454c07bab426701f1d64cd5f3375486607fd60bb01072f9728102820ab0838be18f362f3bca36f9529d4947e515c1478851c609f2d9b4472c4d5d + languageName: node + linkType: hard + +"nanocolors@npm:^0.1.12": + version: 0.1.12 + resolution: "nanocolors@npm:0.1.12" + checksum: 2ce58f57006ddd1d2680d05fe21f54d858db8ba81bd13381598ddc546f7637e33c4407da2ea7da40ea1c96794250e7c14a4d00358b48eeae4d917d6a92bafe4c + languageName: node + linkType: hard + +"nanoid@npm:^3.3.7": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" + bin: + nanoid: bin/nanoid.cjs + checksum: d36c427e530713e4ac6567d488b489a36582ef89da1d6d4e3b87eded11eb10d7042a877958c6f104929809b2ab0bafa17652b076cdf84324aa75b30b722204f2 + 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 + +"nise@npm:^5.1.5": + version: 5.1.5 + resolution: "nise@npm:5.1.5" + dependencies: + "@sinonjs/commons": ^2.0.0 + "@sinonjs/fake-timers": ^10.0.2 + "@sinonjs/text-encoding": ^0.7.1 + just-extend: ^4.0.2 + path-to-regexp: ^1.7.0 + checksum: c763dc62c5796cafa5c9268e14a5b34db6e6fa2f1dbc57a891fe5d7ea632a87868e22b5bb34965006f984630793ea11368351e94971163228d9e20b2e88edce8 + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 9.4.0 + resolution: "node-gyp@npm:9.4.0" + dependencies: + env-paths: ^2.2.0 + exponential-backoff: ^3.1.1 + glob: ^7.1.4 + graceful-fs: ^4.2.6 + make-fetch-happen: ^11.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: 78b404e2e0639d64e145845f7f5a3cb20c0520cdaf6dda2f6e025e9b644077202ea7de1232396ba5bde3fee84cdc79604feebe6ba3ec84d464c85d407bb5da99 + languageName: node + linkType: hard + +"node-releases@npm:^2.0.13": + version: 2.0.13 + resolution: "node-releases@npm:2.0.13" + checksum: 17ec8f315dba62710cae71a8dad3cd0288ba943d2ece43504b3b1aa8625bf138637798ab470b1d9035b0545996f63000a8a926e0f6d35d0996424f8b6d36dda3 + languageName: node + linkType: hard + +"node-releases@npm:^2.0.14": + version: 2.0.14 + resolution: "node-releases@npm:2.0.14" + checksum: 59443a2f77acac854c42d321bf1b43dea0aef55cd544c6a686e9816a697300458d4e82239e2d794ea05f7bbbc8a94500332e2d3ac3f11f52e4b16cbe638b3c41 + 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 + +"nopt@npm:~1.0.10": + version: 1.0.10 + resolution: "nopt@npm:1.0.10" + dependencies: + abbrev: 1 + bin: + nopt: ./bin/nopt.js + checksum: f62575aceaa3be43f365bf37a596b89bbac2e796b001b6d2e2a85c2140a4e378ff919e2753ccba959c4fd344776fc88c29b393bc167fa939fb1513f126f4cd45 + languageName: node + linkType: hard + +"normalize-path@npm:3.0.0, 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.css@npm:^8.0.0": + version: 8.0.1 + resolution: "normalize.css@npm:8.0.1" + checksum: 4698cae88ec35e3f3e82f9f9402e6ffb906c27ccd6373cad88e6b3f5634fc7a043cb38702472299e5edb73825cf8b18d5fd9283f58829eddda79ea97453049a2 + languageName: node + linkType: hard + +"now-and-later@npm:^3.0.0": + version: 3.0.0 + resolution: "now-and-later@npm:3.0.0" + dependencies: + once: ^1.4.0 + checksum: 3e7dfdef7d6e0d7a82bf78c98a33b272593e6c8bb0bcfd2c82e0ae58677fe9e95674eb3137fd3835256935adf06f144834524722e24abefcb208d25d4256603c + 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:^2.0.0": + version: 2.0.1 + resolution: "nth-check@npm:2.0.1" + dependencies: + boolbase: ^1.0.0 + checksum: 5386d035c48438ff304fe687704d93886397349d1bed136de97aeae464caba10e8ffac55a04b215b86b3bc8897f33e0a5aa1045a9d8b2f251ae61b2a3ad3e450 + languageName: node + linkType: hard + +"object-assign@npm:^4, object-assign@npm:^4.1.1": + version: 4.1.1 + resolution: "object-assign@npm:4.1.1" + checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f + languageName: node + linkType: hard + +"object-inspect@npm:^1.11.0, object-inspect@npm:^1.9.0": + version: 1.11.0 + resolution: "object-inspect@npm:1.11.0" + checksum: 8c64f89ce3a7b96b6925879ad5f6af71d498abc217e136660efecd97452991216f375a7eb47cb1cb50643df939bf0c7cc391567b7abc6a924d04679705e58e27 + languageName: node + linkType: hard + +"object-inspect@npm:^1.12.0, object-inspect@npm:^1.12.2": + version: 1.12.2 + resolution: "object-inspect@npm:1.12.2" + checksum: a534fc1b8534284ed71f25ce3a496013b7ea030f3d1b77118f6b7b1713829262be9e6243acbcb3ef8c626e2b64186112cb7f6db74e37b2789b9c789ca23048b2 + languageName: node + linkType: hard + +"object-inspect@npm:^1.13.1": + version: 1.13.1 + resolution: "object-inspect@npm:1.13.1" + checksum: 7d9fa9221de3311dcb5c7c307ee5dc011cdd31dc43624b7c184b3840514e118e05ef0002be5388304c416c0eb592feb46e983db12577fc47e47d5752fbbfb61f + languageName: node + linkType: hard + +"object-keys@npm:^1.0.12, 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.2": + version: 4.1.2 + resolution: "object.assign@npm:4.1.2" + dependencies: + call-bind: ^1.0.0 + define-properties: ^1.1.3 + has-symbols: ^1.0.1 + object-keys: ^1.1.1 + checksum: d621d832ed7b16ac74027adb87196804a500d80d9aca536fccb7ba48d33a7e9306a75f94c1d29cbfa324bc091bfc530bc24789568efdaee6a47fcfa298993814 + languageName: node + linkType: hard + +"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.assign@npm:^4.1.5": + version: 4.1.5 + resolution: "object.assign@npm:4.1.5" + dependencies: + call-bind: ^1.0.5 + define-properties: ^1.2.1 + has-symbols: ^1.0.3 + object-keys: ^1.1.1 + checksum: f9aeac0541661370a1fc86e6a8065eb1668d3e771f7dbb33ee54578201336c057b21ee61207a186dd42db0c62201d91aac703d20d12a79fc79c353eed44d4e25 + languageName: node + linkType: hard + +"object.defaults@npm:^1.1.0": + version: 1.1.0 + resolution: "object.defaults@npm:1.1.0" + dependencies: + array-each: ^1.0.1 + array-slice: ^1.0.0 + for-own: ^1.0.0 + isobject: ^3.0.0 + checksum: 25468e06132af866bffedf9889b8180a31b9915776dbb660106866c5dd70cd0c0ad54f17e34de8ab99e6f548d579678de2e558390f56bd4ee61899fa6057f946 + languageName: node + linkType: hard + +"object.entries@npm:^1.1.7": + version: 1.1.8 + resolution: "object.entries@npm:1.1.8" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: 5314877cb637ef3437a30bba61d9bacdb3ce74bf73ac101518be0633c37840c8cc67407edb341f766e8093b3d7516d5c3358f25adfee4a2c697c0ec4c8491907 + languageName: node + linkType: hard + +"object.fromentries@npm:^2.0.7": + version: 2.0.8 + resolution: "object.fromentries@npm:2.0.8" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + checksum: 29b2207a2db2782d7ced83f93b3ff5d425f901945f3665ffda1821e30a7253cd1fd6b891a64279976098137ddfa883d748787a6fea53ecdb51f8df8b8cec0ae1 + languageName: node + linkType: hard + +"object.hasown@npm:^1.1.3": + version: 1.1.3 + resolution: "object.hasown@npm:1.1.3" + dependencies: + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + checksum: 76bc17356f6124542fb47e5d0e78d531eafa4bba3fc2d6fc4b1a8ce8b6878912366c0d99f37ce5c84ada8fd79df7aa6ea1214fddf721f43e093ad2df51f27da1 + languageName: node + linkType: hard + +"object.pick@npm:^1.3.0": + version: 1.3.0 + resolution: "object.pick@npm:1.3.0" + dependencies: + isobject: ^3.0.1 + checksum: 77fb6eed57c67adf75e9901187e37af39f052ef601cb4480386436561357eb9e459e820762f01fd02c5c1b42ece839ad393717a6d1850d848ee11fbabb3e580a + languageName: node + linkType: hard + +"object.values@npm:^1.1.7": + version: 1.2.0 + resolution: "object.values@npm:1.2.0" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: 51fef456c2a544275cb1766897f34ded968b22adfc13ba13b5e4815fdaf4304a90d42a3aee114b1f1ede048a4890381d47a5594d84296f2767c6a0364b9da8fa + languageName: node + linkType: hard + +"on-finished@npm:~2.3.0": + version: 2.3.0 + resolution: "on-finished@npm:2.3.0" + dependencies: + ee-first: 1.1.1 + checksum: 1db595bd963b0124d6fa261d18320422407b8f01dc65863840f3ddaaf7bcad5b28ff6847286703ca53f4ec19595bd67a2f1253db79fc4094911ec6aa8df1671b + languageName: node + linkType: hard + +"once@npm:^1.3.0, once@npm:^1.4.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: 1 + checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 + 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 + +"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-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 + +"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-filepath@npm:^1.0.2": + version: 1.0.2 + resolution: "parse-filepath@npm:1.0.2" + dependencies: + is-absolute: ^1.0.0 + map-cache: ^0.2.0 + path-root: ^0.1.1 + checksum: 6794c3f38d3921f0f7cc63fb1fb0c4d04cd463356ad389c8ce6726d3c50793b9005971f4138975a6d7025526058d5e65e9bfe634d0765e84c4e2571152665a69 + languageName: node + linkType: hard + +"parse-passwd@npm:^1.0.0": + version: 1.0.0 + resolution: "parse-passwd@npm:1.0.0" + checksum: 4e55e0231d58f828a41d0f1da2bf2ff7bcef8f4cb6146e69d16ce499190de58b06199e6bd9b17fbf0d4d8aef9052099cdf8c4f13a6294b1a522e8e958073066e + languageName: node + linkType: hard + +"parseurl@npm:~1.3.3": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2 + 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-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 + 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-root-regex@npm:^0.1.0": + version: 0.1.2 + resolution: "path-root-regex@npm:0.1.2" + checksum: dcd75d1f8e93faabe35a58e875b0f636839b3658ff2ad8c289463c40bc1a844debe0dab73c3398ef9dc8f6ec6c319720aff390cf4633763ddcf3cf4b1bbf7e8b + languageName: node + linkType: hard + +"path-root@npm:^0.1.1": + version: 0.1.1 + resolution: "path-root@npm:0.1.1" + dependencies: + path-root-regex: ^0.1.0 + checksum: ff88aebfc1c59ace510cc06703d67692a11530989920427625e52b66a303ca9b3d4059b0b7d0b2a73248d1ad29bcb342b8b786ec00592f3101d38a45fd3b2e08 + languageName: node + linkType: hard + +"path-scurry@npm:^1.10.1": + version: 1.10.1 + resolution: "path-scurry@npm:1.10.1" + dependencies: + lru-cache: ^9.1.1 || ^10.0.0 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + checksum: e2557cff3a8fb8bc07afdd6ab163a92587884f9969b05bbbaf6fe7379348bfb09af9ed292af12ed32398b15fb443e81692047b786d1eeb6d898a51eb17ed7d90 + 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-to-regexp@npm:^2.2.1": + version: 2.4.0 + resolution: "path-to-regexp@npm:2.4.0" + checksum: 581175bf2968e51452f2b8c71f10e75c995693668b4ecf7d0b48962fbe0c56830661ca5dd5fd6d8e2f0cc9a045ce07e89af504ab133e1d21887c2712df85b1f4 + languageName: node + linkType: hard + +"pathval@npm:^2.0.0": + version: 2.0.0 + resolution: "pathval@npm:2.0.0" + checksum: 682b6a6289de7990909effef7dae9aa7bb6218c0426727bccf66a35b34e7bfbc65615270c5e44e3c9557a5cb44b1b9ef47fc3cb18bce6ad3ba92bcd28467ed7d + 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": + version: 2.3.0 + resolution: "picomatch@npm:2.3.0" + checksum: 16818720ea7c5872b6af110760dee856c8e4cd79aed1c7a006d076b1cc09eff3ae41ca5019966694c33fbd2e1cc6ea617ab10e4adac6df06556168f13be3fca2 + languageName: node + linkType: hard + +"picomatch@npm:^2.3.1": + version: 2.3.1 + resolution: "picomatch@npm:2.3.1" + checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf + languageName: node + linkType: hard + +"plugin-error@npm:^1.0.1": + version: 1.0.1 + resolution: "plugin-error@npm:1.0.1" + dependencies: + ansi-colors: ^1.0.1 + arr-diff: ^4.0.0 + arr-union: ^3.1.0 + extend-shallow: ^3.0.2 + checksum: 5cacd34372b909f07125829c2876707f4add64dcdf0dd8bd23d7ceac70eeb961c038a9707a998cc498bf8d478cc81f8d85b82584313926fe61a8fa294f79f3e4 + languageName: node + linkType: hard + +"popper.js@npm:^1.16.1": + version: 1.16.1 + resolution: "popper.js@npm:1.16.1" + checksum: c56ae5001ec50a77ee297a8061a0221d99d25c7348d2e6bcd3e45a0d0f32a1fd81bca29d46cb0d4bdf13efb77685bd6a0ce93f9eb3c608311a461f945fffedbe + languageName: node + linkType: hard + +"possible-typed-array-names@npm:^1.0.0": + version: 1.0.0 + resolution: "possible-typed-array-names@npm:1.0.0" + checksum: b32d403ece71e042385cc7856385cecf1cd8e144fa74d2f1de40d1e16035dba097bc189715925e79b67bdd1472796ff168d3a90d296356c9c94d272d5b95f3ae + languageName: node + linkType: hard + +"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:^8.4.38": + version: 8.4.38 + resolution: "postcss@npm:8.4.38" + dependencies: + nanoid: ^3.3.7 + picocolors: ^1.0.0 + source-map-js: ^1.2.0 + checksum: 649f9e60a763ca4b5a7bbec446a069edf07f057f6d780a5a0070576b841538d1ecf7dd888f2fbfd1f76200e26c969e405aeeae66332e6927dbdc8bdcb90b9451 + 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 + +"prettier@npm:^3.2.5": + version: 3.2.5 + resolution: "prettier@npm:3.2.5" + bin: + prettier: bin/prettier.cjs + checksum: 2ee4e1417572372afb7a13bb446b34f20f1bf1747db77cf6ccaf57a9be005f2f15c40f903d41a6b79eec3f57fff14d32a20fb6dee1f126da48908926fe43c311 + 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 + +"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 + +"punycode@npm:^2.1.0": + version: 2.1.1 + resolution: "punycode@npm:2.1.1" + checksum: 823bf443c6dd14f669984dea25757b37993f67e8d94698996064035edd43bed8a5a17a9f12e439c2b35df1078c6bec05a6c86e336209eb1061e8025c481168e8 + languageName: node + linkType: hard + +"qjobs@npm:^1.2.0": + version: 1.2.0 + resolution: "qjobs@npm:1.2.0" + checksum: eb64c00724d2fecaf9246383b4eebc3a4c34845b25d41921dd57f41b30a4310cef661543facac27ceb6911aab64a1acdf45b5d8f1d5e2838554d0c010ee56852 + languageName: node + linkType: hard + +"qs@npm:6.7.0": + version: 6.7.0 + resolution: "qs@npm:6.7.0" + checksum: dfd5f6adef50e36e908cfa70a6233871b5afe66fbaca37ecc1da352ba29eb2151a3797991948f158bb37fccde51bd57845cb619a8035287bfc24e4591172c347 + languageName: node + linkType: hard + +"querystring@npm:^0.2.0": + version: 0.2.1 + resolution: "querystring@npm:0.2.1" + checksum: 7b83b45d641e75fd39cd6625ddfd44e7618e741c61e95281b57bbae8fde0afcc12cf851924559e5cc1ef9baa3b1e06e22b164ea1397d65dd94b801f678d9c8ce + 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 + +"queue-tick@npm:^1.0.1": + version: 1.0.1 + resolution: "queue-tick@npm:1.0.1" + checksum: 57c3292814b297f87f792fbeb99ce982813e4e54d7a8bdff65cf53d5c084113913289d4a48ec8bbc964927a74b847554f9f4579df43c969a6c8e0f026457ad01 + languageName: node + linkType: hard + +"rambda@npm:^7.4.0": + version: 7.5.0 + resolution: "rambda@npm:7.5.0" + checksum: ad608a9a4160d0b6b0921047cea1329276bf239ff58d439135288712dcdbbf0df47c76591843ad249d89e7c5a9109ce86fe099aa54aef0dc0aa92a9b4dd1b8eb + 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.1": + version: 1.2.1 + resolution: "range-parser@npm:1.2.1" + checksum: 0a268d4fea508661cf5743dfe3d5f47ce214fd6b7dec1de0da4d669dd4ef3d2144468ebe4179049eff253d9d27e719c88dae55be64f954e80135a0cada804ec9 + languageName: node + linkType: hard + +"raven-js@npm:^3.7.0": + version: 3.27.2 + resolution: "raven-js@npm:3.27.2" + checksum: 561291123065f2c68e4e1b13a4e8484bb69240edf92b282f1659cde70ab5da69558778a1f146998a60aabd5b644635d5b5752e4327db54c4b715c6a9c45883f4 + languageName: node + linkType: hard + +"raw-body@npm:2.4.0": + version: 2.4.0 + resolution: "raw-body@npm:2.4.0" + dependencies: + bytes: 3.1.0 + http-errors: 1.7.2 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + checksum: 6343906939e018c6e633a34a938a5d6d1e93ffcfa48646e00207d53b418e941953b521473950c079347220944dc75ba10e7b3c08bf97e3ac72c7624882db09bb + languageName: node + linkType: hard + +"react-is@npm:^16.13.1": + version: 16.13.1 + resolution: "react-is@npm:16.13.1" + checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f + languageName: node + linkType: hard + +"readable-stream@npm:2 || 3, readable-stream@npm:^3.1.1": + 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 + +"readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" + dependencies: + inherits: ^2.0.3 + string_decoder: ^1.1.1 + util-deprecate: ^1.0.1 + checksum: bdcbe6c22e846b6af075e32cf8f4751c2576238c5043169a1c221c92ee2878458a816a4ea33f4c67623c0b6827c8a400409bfb3cf0bf3381392d0b1dfb52ac8d + 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 + +"rechoir@npm:^0.8.0": + version: 0.8.0 + resolution: "rechoir@npm:0.8.0" + dependencies: + resolve: ^1.20.0 + checksum: ad3caed8afdefbc33fbc30e6d22b86c35b3d51c2005546f4e79bcc03c074df804b3640ad18945e6bef9ed12caedc035655ec1082f64a5e94c849ff939dc0a788 + languageName: node + linkType: hard + +"reflect.getprototypeof@npm:^1.0.4": + version: 1.0.4 + resolution: "reflect.getprototypeof@npm:1.0.4" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + get-intrinsic: ^1.2.1 + globalthis: ^1.0.3 + which-builtin-type: ^1.1.3 + checksum: 16e2361988dbdd23274b53fb2b1b9cefeab876c3941a2543b4cadac6f989e3db3957b07a44aac46cfceb3e06e2871785ec2aac992d824f76292f3b5ee87f66f2 + languageName: node + linkType: hard + +"regenerate-unicode-properties@npm:^10.0.1": + version: 10.0.1 + resolution: "regenerate-unicode-properties@npm:10.0.1" + dependencies: + regenerate: ^1.4.2 + checksum: 1b638b7087d8143e5be3e20e2cda197ea0440fa0bc2cc49646b2f50c5a2b1acdc54b21e4215805a5a2dd487c686b2291accd5ad00619534098d2667e76247754 + 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.4": + version: 0.13.9 + resolution: "regenerator-runtime@npm:0.13.9" + checksum: 65ed455fe5afd799e2897baf691ca21c2772e1a969d19bb0c4695757c2d96249eb74ee3553ea34a91062b2a676beedf630b4c1551cc6299afb937be1426ec55e + languageName: node + linkType: hard + +"regenerator-transform@npm:^0.15.2": + version: 0.15.2 + resolution: "regenerator-transform@npm:0.15.2" + dependencies: + "@babel/runtime": ^7.8.4 + checksum: 20b6f9377d65954980fe044cfdd160de98df415b4bff38fbade67b3337efaf078308c4fed943067cd759827cc8cfeca9cb28ccda1f08333b85d6a2acbd022c27 + 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 + +"regexp.prototype.flags@npm:^1.5.1": + version: 1.5.1 + resolution: "regexp.prototype.flags@npm:1.5.1" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + set-function-name: ^2.0.0 + checksum: 869edff00288442f8d7fa4c9327f91d85f3b3acf8cbbef9ea7a220345cf23e9241b6def9263d2c1ebcf3a316b0aa52ad26a43a84aa02baca3381717b3e307f47 + languageName: node + linkType: hard + +"regexp.prototype.flags@npm:^1.5.2": + version: 1.5.2 + resolution: "regexp.prototype.flags@npm:1.5.2" + dependencies: + call-bind: ^1.0.6 + define-properties: ^1.2.1 + es-errors: ^1.3.0 + set-function-name: ^2.0.1 + checksum: d7f333667d5c564e2d7a97c56c3075d64c722c9bb51b2b4df6822b2e8096d623a5e63088fb4c83df919b6951ef8113841de8b47de7224872fa6838bc5d8a7d64 + languageName: node + linkType: hard + +"regexpu-core@npm:^5.1.0": + version: 5.1.0 + resolution: "regexpu-core@npm:5.1.0" + 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 + checksum: 7b4eb8d182d9d10537a220a93138df5bc7eaf4ed53e36b95e8427d33ed8a2b081468f1a15d3e5fcee66517e1df7f5ca180b999e046d060badd97150f2ffe87b2 + languageName: node + linkType: hard + +"regexpu-core@npm:^5.3.1": + version: 5.3.2 + resolution: "regexpu-core@npm:5.3.2" + dependencies: + "@babel/regjsgen": ^0.8.0 + regenerate: ^1.4.2 + regenerate-unicode-properties: ^10.1.0 + regjsparser: ^0.9.1 + unicode-match-property-ecmascript: ^2.0.0 + unicode-match-property-value-ecmascript: ^2.1.0 + checksum: 95bb97088419f5396e07769b7de96f995f58137ad75fac5811fb5fe53737766dfff35d66a0ee66babb1eb55386ef981feaef392f9df6d671f3c124812ba24da2 + languageName: node + linkType: hard + +"regjsgen@npm:^0.6.0": + version: 0.6.0 + resolution: "regjsgen@npm:0.6.0" + checksum: c5158ebd735e75074e41292ade1ff05d85566d205426cc61501e360c450a63baced8512ee3ae238e5c0a0e42969563c7875b08fa69d6f0402daf36bcb3e4d348 + languageName: node + linkType: hard + +"regjsparser@npm:^0.8.2": + version: 0.8.4 + resolution: "regjsparser@npm:0.8.4" + dependencies: + jsesc: ~0.5.0 + bin: + regjsparser: bin/parser + checksum: d069b932491761cda127ce11f6bd2729c3b1b394a35200ec33f1199e937423db28ceb86cf33f0a97c76ecd7c0f8db996476579eaf0d80a1f74c1934f4ca8b27a + 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 + +"remove-trailing-separator@npm:^1.1.0": + version: 1.1.0 + resolution: "remove-trailing-separator@npm:1.1.0" + checksum: d3c20b5a2d987db13e1cca9385d56ecfa1641bae143b620835ac02a6b70ab88f68f117a0021838db826c57b31373d609d52e4f31aca75fc490c862732d595419 + languageName: node + linkType: hard + +"replace-ext@npm:^2.0.0": + version: 2.0.0 + resolution: "replace-ext@npm:2.0.0" + checksum: ed640ac90d24cce4be977642847d138908d430049cc097633be33b072143515cc7d29699675a0c35f6dc3c3c73cb529ed352d59649cf15931740eb31ae083c1e + languageName: node + linkType: hard + +"replace-homedir@npm:^2.0.0": + version: 2.0.0 + resolution: "replace-homedir@npm:2.0.0" + checksum: 66030e85400b7b4af41aad5595a8a75d1344f768e9a773702a9e16e48bf12e56c006799007e59ea229a74398237b0934aca51795143b071d3578c23309d7e48b + 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 + +"requires-port@npm:^1.0.0": + version: 1.0.0 + resolution: "requires-port@npm:1.0.0" + checksum: eee0e303adffb69be55d1a214e415cf42b7441ae858c76dfc5353148644f6fd6e698926fc4643f510d5c126d12a705e7c8ed7e38061113bdf37547ab356797ff + languageName: node + linkType: hard + +"resolve-dir@npm:^1.0.0, resolve-dir@npm:^1.0.1": + version: 1.0.1 + resolution: "resolve-dir@npm:1.0.1" + dependencies: + expand-tilde: ^2.0.0 + global-modules: ^1.0.0 + checksum: ef736b8ed60d6645c3b573da17d329bfb50ec4e1d6c5ffd6df49e3497acef9226f9810ea6823b8ece1560e01dcb13f77a9f6180d4f242d00cc9a8f4de909c65c + 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-options@npm:^2.0.0": + version: 2.0.0 + resolution: "resolve-options@npm:2.0.0" + dependencies: + value-or-function: ^4.0.0 + checksum: b28584cc089099af42e36292c32bd9af8bc9e28e3ca73c172c0a172d7ed5afb01c75cc2275268c327dceba77a5555b33fbd55617be138874040279fe6ff02fbf + languageName: node + linkType: hard + +"resolve@npm:^1.14.2, 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:^1.20.0": + version: 1.22.8 + resolution: "resolve@npm:1.22.8" + dependencies: + is-core-module: ^2.13.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: f8a26958aa572c9b064562750b52131a37c29d072478ea32e129063e2da7f83e31f7f11e7087a18225a8561cfe8d2f0df9dbea7c9d331a897571c0a2527dbb4c + languageName: node + linkType: hard + +"resolve@npm:^2.0.0-next.5": + version: 2.0.0-next.5 + resolution: "resolve@npm:2.0.0-next.5" + dependencies: + is-core-module: ^2.13.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: a73ac69a1c4bd34c56b213d91f5b17ce390688fdb4a1a96ed3025cc7e08e7bfb90b3a06fcce461780cb0b589c958afcb0080ab802c71c01a7ecc8c64feafc89f + languageName: node + linkType: hard + +"resolve@patch:resolve@^1.14.2#~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@^1.20.0#~builtin": + version: 1.22.8 + resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin::version=1.22.8&hash=c3c19d" + dependencies: + is-core-module: ^2.13.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: 5479b7d431cacd5185f8db64bfcb7286ae5e31eb299f4c4f404ad8aa6098b77599563ac4257cb2c37a42f59dfc06a1bec2bcf283bb448f319e37f0feb9a09847 + languageName: node + linkType: hard + +"resolve@patch:resolve@^2.0.0-next.5#~builtin": + version: 2.0.0-next.5 + resolution: "resolve@patch:resolve@npm%3A2.0.0-next.5#~builtin::version=2.0.0-next.5&hash=c3c19d" + dependencies: + is-core-module: ^2.13.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: 064d09c1808d0c51b3d90b5d27e198e6d0c5dad0eb57065fd40803d6a20553e5398b07f76739d69cbabc12547058bec6b32106ea66622375fb0d7e8fca6a846c + 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 + +"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.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@npm:^4.17.2": + version: 4.17.2 + resolution: "rollup@npm:4.17.2" + dependencies: + "@rollup/rollup-android-arm-eabi": 4.17.2 + "@rollup/rollup-android-arm64": 4.17.2 + "@rollup/rollup-darwin-arm64": 4.17.2 + "@rollup/rollup-darwin-x64": 4.17.2 + "@rollup/rollup-linux-arm-gnueabihf": 4.17.2 + "@rollup/rollup-linux-arm-musleabihf": 4.17.2 + "@rollup/rollup-linux-arm64-gnu": 4.17.2 + "@rollup/rollup-linux-arm64-musl": 4.17.2 + "@rollup/rollup-linux-powerpc64le-gnu": 4.17.2 + "@rollup/rollup-linux-riscv64-gnu": 4.17.2 + "@rollup/rollup-linux-s390x-gnu": 4.17.2 + "@rollup/rollup-linux-x64-gnu": 4.17.2 + "@rollup/rollup-linux-x64-musl": 4.17.2 + "@rollup/rollup-win32-arm64-msvc": 4.17.2 + "@rollup/rollup-win32-ia32-msvc": 4.17.2 + "@rollup/rollup-win32-x64-msvc": 4.17.2 + "@types/estree": 1.0.5 + fsevents: ~2.3.2 + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: e6a2813fea25ea816ce582a04c2ffccc0b841ddc22842325c39353620214055bf827e0d7f6714e836170079faf0443ffc27966ccae27900ae3baa039aa36a8e1 + 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 + +"safe-array-concat@npm:^1.0.1": + version: 1.0.1 + resolution: "safe-array-concat@npm:1.0.1" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.2.1 + has-symbols: ^1.0.3 + isarray: ^2.0.5 + checksum: 001ecf1d8af398251cbfabaf30ed66e3855127fbceee178179524b24160b49d15442f94ed6c0db0b2e796da76bb05b73bf3cc241490ec9c2b741b41d33058581 + languageName: node + linkType: hard + +"safe-array-concat@npm:^1.1.2": + version: 1.1.2 + resolution: "safe-array-concat@npm:1.1.2" + dependencies: + call-bind: ^1.0.7 + get-intrinsic: ^1.2.4 + has-symbols: ^1.0.3 + isarray: ^2.0.5 + checksum: a3b259694754ddfb73ae0663829e396977b99ff21cbe8607f35a469655656da8e271753497e59da8a7575baa94d2e684bea3e10ddd74ba046c0c9b4418ffa0c4 + languageName: node + linkType: hard + +"safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 + languageName: node + linkType: hard + +"safe-buffer@npm:~5.1.1": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c + 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 + +"safe-regex-test@npm:^1.0.3": + version: 1.0.3 + resolution: "safe-regex-test@npm:1.0.3" + dependencies: + call-bind: ^1.0.6 + es-errors: ^1.3.0 + is-regex: ^1.1.4 + checksum: 6c7d392ff1ae7a3ae85273450ed02d1d131f1d2c76e177d6b03eb88e6df8fa062639070e7d311802c1615f351f18dc58f9454501c58e28d5ffd9b8f502ba6489 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 + languageName: node + linkType: hard + +"sass@npm:^1.76.0": + version: 1.76.0 + resolution: "sass@npm:1.76.0" + dependencies: + chokidar: ">=3.0.0 <4.0.0" + immutable: ^4.0.0 + source-map-js: ">=0.6.2 <2.0.0" + bin: + sass: sass.js + checksum: 5f3fa7e7a1be09b7cea842a397fb07b9413fa9903bf82ead2ea059aa56faea534c2a84ede5a140103ee18a1dec9162b2fa1413fe71bbe8f8074712bf3bd3a8c7 + languageName: node + linkType: hard + +"scroll-into-view@npm:^1.16.2": + version: 1.16.2 + resolution: "scroll-into-view@npm:1.16.2" + checksum: 57a434ab9e31da143c43c40bdc38039be97a8eaecb852a614bb7218e34c148f6cb0beadd230742a28d3ec6c9e479161e7527b0ccf0b7311c1664c64c40814649 + languageName: node + linkType: hard + +"semver-greatest-satisfied-range@npm:^2.0.0": + version: 2.0.0 + resolution: "semver-greatest-satisfied-range@npm:2.0.0" + dependencies: + sver: ^1.8.3 + checksum: 478a52a34fa4a265d7caf1f2279bf3f427abeee36175bfa03c29d48df65040f4d934ccdf5896b7ae6012f60f7364ec30826390ecb7c913f94109002dbd53a588 + languageName: node + linkType: hard + +"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.5": + version: 7.5.4 + resolution: "semver@npm:7.5.4" + dependencies: + lru-cache: ^6.0.0 + bin: + semver: bin/semver.js + checksum: 12d8ad952fa353b0995bf180cdac205a4068b759a140e5d3c608317098b3575ac2f1e09182206bf2eb26120e1c0ed8fb92c48c592f6099680de56bb071423ca3 + languageName: node + linkType: hard + +"serialize-javascript@npm:6.0.0": + version: 6.0.0 + resolution: "serialize-javascript@npm:6.0.0" + dependencies: + randombytes: ^2.1.0 + checksum: 56f90b562a1bdc92e55afb3e657c6397c01a902c588c0fe3d4c490efdcc97dcd2a3074ba12df9e94630f33a5ce5b76a74784a7041294628a6f4306e0ec84bf93 + languageName: node + linkType: hard + +"serialize-javascript@npm:^6.0.1": + version: 6.0.1 + resolution: "serialize-javascript@npm:6.0.1" + dependencies: + randombytes: ^2.1.0 + checksum: 3c4f4cb61d0893b988415bdb67243637333f3f574e9e9cc9a006a2ced0b390b0b3b44aef8d51c951272a9002ec50885eefdc0298891bc27eb2fe7510ea87dc4f + 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 + +"set-function-length@npm:^1.1.1": + version: 1.1.1 + resolution: "set-function-length@npm:1.1.1" + dependencies: + define-data-property: ^1.1.1 + get-intrinsic: ^1.2.1 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.0 + checksum: c131d7569cd7e110cafdfbfbb0557249b538477624dfac4fc18c376d879672fa52563b74029ca01f8f4583a8acb35bb1e873d573a24edb80d978a7ee607c6e06 + languageName: node + linkType: hard + +"set-function-length@npm:^1.2.1": + version: 1.2.2 + resolution: "set-function-length@npm:1.2.2" + dependencies: + define-data-property: ^1.1.4 + es-errors: ^1.3.0 + function-bind: ^1.1.2 + get-intrinsic: ^1.2.4 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.2 + checksum: a8248bdacdf84cb0fab4637774d9fb3c7a8e6089866d04c817583ff48e14149c87044ce683d7f50759a8c50fb87c7a7e173535b06169c87ef76f5fb276dfff72 + languageName: node + linkType: hard + +"set-function-name@npm:^2.0.0, set-function-name@npm:^2.0.1": + version: 2.0.1 + resolution: "set-function-name@npm:2.0.1" + dependencies: + define-data-property: ^1.0.1 + functions-have-names: ^1.2.3 + has-property-descriptors: ^1.0.0 + checksum: 4975d17d90c40168eee2c7c9c59d023429f0a1690a89d75656306481ece0c3c1fb1ebcc0150ea546d1913e35fbd037bace91372c69e543e51fc5d1f31a9fa126 + languageName: node + linkType: hard + +"set-function-name@npm:^2.0.2": + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" + dependencies: + define-data-property: ^1.1.4 + es-errors: ^1.3.0 + functions-have-names: ^1.2.3 + has-property-descriptors: ^1.0.2 + checksum: d6229a71527fd0404399fc6227e0ff0652800362510822a291925c9d7b48a1ca1a468b11b281471c34cd5a2da0db4f5d7ff315a61d26655e77f6e971e6d0c80f + languageName: node + linkType: hard + +"setprototypeof@npm:1.1.1": + version: 1.1.1 + resolution: "setprototypeof@npm:1.1.1" + checksum: a8bee29c1c64c245d460ce53f7460af8cbd0aceac68d66e5215153992cc8b3a7a123416353e0c642060e85cc5fd4241c92d1190eec97eda0dcb97436e8fcca3b + 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 + +"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 + +"side-channel@npm:^1.0.6": + version: 1.0.6 + resolution: "side-channel@npm:1.0.6" + dependencies: + call-bind: ^1.0.7 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.4 + object-inspect: ^1.13.1 + checksum: bfc1afc1827d712271453e91b7cd3878ac0efd767495fd4e594c4c2afaa7963b7b510e249572bfd54b0527e66e4a12b61b80c061389e129755f34c493aad9b97 + languageName: node + linkType: hard + +"signal-exit@npm:^3.0.7": + version: 3.0.7 + resolution: "signal-exit@npm:3.0.7" + checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549 + languageName: node + linkType: hard + +"sinon@npm:^17.0.1": + version: 17.0.1 + resolution: "sinon@npm:17.0.1" + dependencies: + "@sinonjs/commons": ^3.0.0 + "@sinonjs/fake-timers": ^11.2.2 + "@sinonjs/samsam": ^8.0.0 + diff: ^5.1.0 + nise: ^5.1.5 + supports-color: ^7.2.0 + checksum: a807c2997d6eabdcaa4409df9fd9816a3e839f96d7e5d76610a33f5e1b60cf37616c6288f0f580262da17ea4ee626c6d1600325bf423e30c5a7f0d9a203e26c0 + 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 + +"smob@npm:^1.0.0": + version: 1.4.0 + resolution: "smob@npm:1.4.0" + checksum: f693b42698c90262dee4324eae635ea2aa16782161274b47417f87e353880487cdea8e6d9d07fb9b2a0e0df472ef0c5a1bfc07395edd8acfad7062797c1293ca + languageName: node + linkType: hard + +"socket.io-adapter@npm:~2.5.2": + version: 2.5.4 + resolution: "socket.io-adapter@npm:2.5.4" + dependencies: + debug: ~4.3.4 + ws: ~8.11.0 + checksum: 7dea1d606a039d494f31fe06a9d84e4318704e3e61c1c5b917befe13f03dd9ee1a6564775a5ee92a444e8caaa83555e850e0da855cefa436d18cdbd638b3bb51 + languageName: node + linkType: hard + +"socket.io-parser@npm:~4.2.4": + version: 4.2.4 + resolution: "socket.io-parser@npm:4.2.4" + dependencies: + "@socket.io/component-emitter": ~3.1.0 + debug: ~4.3.1 + checksum: 61540ef99af33e6a562b9effe0fad769bcb7ec6a301aba5a64b3a8bccb611a0abdbe25f469933ab80072582006a78ca136bf0ad8adff9c77c9953581285e2263 + languageName: node + linkType: hard + +"socket.io@npm:^4.7.2": + version: 4.7.4 + resolution: "socket.io@npm:4.7.4" + dependencies: + accepts: ~1.3.4 + base64id: ~2.0.0 + cors: ~2.8.5 + debug: ~4.3.2 + engine.io: ~6.5.2 + socket.io-adapter: ~2.5.2 + socket.io-parser: ~4.2.4 + checksum: 63bb2b0c1168beb7a79b60541def09d4de23f10f206e2e36e7a1ec1ef3d1f2f3143264878e026ceacdd26b52a37da74606c44e95da6651b4980cad5bfcc291a9 + 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-map-js@npm:>=0.6.2 <2.0.0": + version: 1.0.2 + resolution: "source-map-js@npm:1.0.2" + checksum: c049a7fc4deb9a7e9b481ae3d424cc793cb4845daa690bc5a05d428bf41bf231ced49b4cf0c9e77f9d42fdb3d20d6187619fc586605f5eabe995a316da8d377c + languageName: node + linkType: hard + +"source-map-js@npm:^1.2.0": + version: 1.2.0 + resolution: "source-map-js@npm:1.2.0" + checksum: 791a43306d9223792e84293b00458bf102a8946e7188f3db0e4e22d8d530b5f80a4ce468eb5ec0bf585443ad55ebbd630bf379c98db0b1f317fd902500217f97 + languageName: node + linkType: hard + +"source-map-support@npm:^0.5.5, 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.0, source-map@npm:^0.6.1": + version: 0.6.1 + resolution: "source-map@npm:0.6.1" + checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2 + languageName: node + linkType: hard + +"sparkles@npm:^2.1.0": + version: 2.1.0 + resolution: "sparkles@npm:2.1.0" + checksum: 5243c388b3060762ac3ded676528be486e835c64996512a7e61e1be059c7da48ddf32d244b11b457c4dec2f5227da44963b59f51f772aa503c968f00aa19362d + languageName: node + linkType: hard + +"ssri@npm:^10.0.0": + version: 10.0.4 + resolution: "ssri@npm:10.0.4" + dependencies: + minipass: ^5.0.0 + checksum: fb14da9f8a72b04eab163eb13a9dda11d5962cd2317f85457c4e0b575e9a6e0e3a6a87b5bf122c75cb36565830cd5f263fb457571bf6f1587eb5f95d095d6165 + 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 + +"statuses@npm:>= 1.5.0 < 2, statuses@npm:~1.5.0": + version: 1.5.0 + resolution: "statuses@npm:1.5.0" + checksum: c469b9519de16a4bb19600205cffb39ee471a5f17b82589757ca7bd40a8d92ebb6ed9f98b5a540c5d302ccbc78f15dc03cc0280dd6e00df1335568a5d5758a5c + languageName: node + linkType: hard + +"stream-composer@npm:^1.0.2": + version: 1.0.2 + resolution: "stream-composer@npm:1.0.2" + dependencies: + streamx: ^2.13.2 + checksum: 338b8e088f2eb2c91b0e06907db436525da3620991b13499e57441548e62d3585be185505901b0380cad425889572794e5fe178dd326f5efde654b3ab26df3d3 + languageName: node + linkType: hard + +"stream-exhaust@npm:^1.0.2": + version: 1.0.2 + resolution: "stream-exhaust@npm:1.0.2" + checksum: ffac181a5c706db3a940d96f9a5be02df84cf03a4925bff10d210a2d791d65f6197d67a0a484cea128298e63737f46c08e51f9ebe64f25556b9d824b820c996d + languageName: node + linkType: hard + +"stream-shift@npm:^1.0.0": + version: 1.0.1 + resolution: "stream-shift@npm:1.0.1" + checksum: 59b82b44b29ec3699b5519a49b3cedcc6db58c72fb40c04e005525dfdcab1c75c4e0c180b923c380f204bed78211b9bad8faecc7b93dece4d004c3f6ec75737b + languageName: node + linkType: hard + +"streamroller@npm:^3.0.2": + version: 3.0.2 + resolution: "streamroller@npm:3.0.2" + dependencies: + date-format: ^4.0.3 + debug: ^4.1.1 + fs-extra: ^10.0.0 + checksum: 1f323824f0e81cc085c24f33addfd8ef00d0c15aafee520a8cf207ca6e2dc674fd852528c7b4450cc87f4335d1269ed18b3f0188853d45d7f0912c9a205d1fc1 + languageName: node + linkType: hard + +"streamx@npm:^2.12.0, streamx@npm:^2.12.5, streamx@npm:^2.13.2, streamx@npm:^2.14.0": + version: 2.16.1 + resolution: "streamx@npm:2.16.1" + dependencies: + bare-events: ^2.2.0 + fast-fifo: ^1.1.0 + queue-tick: ^1.0.1 + dependenciesMeta: + bare-events: + optional: true + checksum: 6bbb4c38c0ab6ddbe0857d55e72f71288f308f2a9f4413b7b07391cdf9f94232ffc2bbe40a1212d2e09634ecdbd5052b444c73cc8d67ae1c97e2b7e553dad559 + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, 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.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.10": + version: 4.0.11 + resolution: "string.prototype.matchall@npm:4.0.11" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + get-intrinsic: ^1.2.4 + gopd: ^1.0.1 + has-symbols: ^1.0.3 + internal-slot: ^1.0.7 + regexp.prototype.flags: ^1.5.2 + set-function-name: ^2.0.2 + side-channel: ^1.0.6 + checksum: 6ac6566ed065c0c8489c91156078ca077db8ff64d683fda97ae652d00c52dfa5f39aaab0a710d8243031a857fd2c7c511e38b45524796764d25472d10d7075ae + languageName: node + linkType: hard + +"string.prototype.trim@npm:^1.2.8": + version: 1.2.8 + resolution: "string.prototype.trim@npm:1.2.8" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + checksum: 49eb1a862a53aba73c3fb6c2a53f5463173cb1f4512374b623bcd6b43ad49dd559a06fb5789bdec771a40fc4d2a564411c0a75d35fb27e76bbe738c211ecff07 + languageName: node + linkType: hard + +"string.prototype.trim@npm:^1.2.9": + version: 1.2.9 + resolution: "string.prototype.trim@npm:1.2.9" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.0 + es-object-atoms: ^1.0.0 + checksum: ea2df6ec1e914c9d4e2dc856fa08228e8b1be59b59e50b17578c94a66a176888f417264bb763d4aac638ad3b3dad56e7a03d9317086a178078d131aa293ba193 + languageName: node + linkType: hard + +"string.prototype.trimend@npm:^1.0.4": + version: 1.0.4 + resolution: "string.prototype.trimend@npm:1.0.4" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.3 + checksum: 17e5aa45c3983f582693161f972c1c1fa4bbbdf22e70e582b00c91b6575f01680dc34e83005b98e31abe4d5d29e0b21fcc24690239c106c7b2315aade6a898ac + languageName: node + linkType: hard + +"string.prototype.trimend@npm:^1.0.5": + version: 1.0.5 + resolution: "string.prototype.trimend@npm:1.0.5" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.19.5 + checksum: d44f543833112f57224e79182debadc9f4f3bf9d48a0414d6f0cbd2a86f2b3e8c0ca1f95c3f8e5b32ae83e91554d79d932fc746b411895f03f93d89ed3dfb6bc + languageName: node + linkType: hard + +"string.prototype.trimend@npm:^1.0.7": + version: 1.0.7 + resolution: "string.prototype.trimend@npm:1.0.7" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + checksum: 2375516272fd1ba75992f4c4aa88a7b5f3c7a9ca308d963bcd5645adf689eba6f8a04ebab80c33e30ec0aefc6554181a3a8416015c38da0aa118e60ec896310c + languageName: node + linkType: hard + +"string.prototype.trimend@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimend@npm:1.0.8" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: cc3bd2de08d8968a28787deba9a3cb3f17ca5f9f770c91e7e8fa3e7d47f079bad70fadce16f05dda9f261788be2c6e84a942f618c3bed31e42abc5c1084f8dfd + languageName: node + linkType: hard + +"string.prototype.trimstart@npm:^1.0.4": + version: 1.0.4 + resolution: "string.prototype.trimstart@npm:1.0.4" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.3 + checksum: 3fb06818d3cccac5fa3f5f9873d984794ca0e9f6616fae6fcc745885d9efed4e17fe15f832515d9af5e16c279857fdbffdfc489ca4ed577811b017721b30302f + languageName: node + linkType: hard + +"string.prototype.trimstart@npm:^1.0.5": + version: 1.0.5 + resolution: "string.prototype.trimstart@npm:1.0.5" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + es-abstract: ^1.19.5 + checksum: a4857c5399ad709d159a77371eeaa8f9cc284469a0b5e1bfe405de16f1fd4166a8ea6f4180e55032f348d1b679b1599fd4301fbc7a8b72bdb3e795e43f7b1048 + languageName: node + linkType: hard + +"string.prototype.trimstart@npm:^1.0.7": + version: 1.0.7 + resolution: "string.prototype.trimstart@npm:1.0.7" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + checksum: 13d0c2cb0d5ff9e926fa0bec559158b062eed2b68cd5be777ffba782c96b2b492944e47057274e064549b94dd27cf81f48b27a31fee8af5b574cff253e7eb613 + 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 + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, 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:^4.0.0": + version: 4.0.0 + resolution: "strip-ansi@npm:4.0.0" + dependencies: + ansi-regex: ^3.0.0 + checksum: d9186e6c0cf78f25274f6750ee5e4a5725fb91b70fdd79aa5fe648eab092a0ec5b9621b22d69d4534a56319f75d8944efbd84e3afa8d4ad1b9a9491f12c84eca + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" + dependencies: + ansi-regex: ^6.0.1 + checksum: 859c73fcf27869c22a4e4d8c6acfe690064659e84bef9458aa6d13719d09ca88dcfd40cbf31fd0be63518ea1a643fe070b4827d353e09533a5b0b9fd4553d64d + languageName: node + linkType: hard + +"strip-json-comments@npm:3.1.1, 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 + +"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-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.1.0, supports-color@npm:^7.2.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-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 + +"sver@npm:^1.8.3": + version: 1.8.4 + resolution: "sver@npm:1.8.4" + dependencies: + semver: ^6.3.0 + dependenciesMeta: + semver: + optional: true + checksum: f6622470f8c574d509e95cbf94fbf1d67f2f7397fad73ffc9fbbeaacfcf8a359d4fe203cae50c34941b860efe6e87b43dd218f41aa2feb33021df7e6a925bfd3 + languageName: node + linkType: hard + +"svgo@npm:^2.7.0": + version: 2.7.0 + resolution: "svgo@npm:2.7.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 + nanocolors: ^0.1.12 + stable: ^0.1.8 + bin: + svgo: bin/svgo + checksum: 7da6574958185368356d1e0f50d7860afc01d9fffb0f75c8aab87d1af237d27d8a838c7f09e6829a0e81b1952cf6c4e12abe1bd3920a526ea0f0ca9dd1cd59c5 + languageName: node + linkType: hard + +"syn@npm:^0.2.2": + version: 0.2.2 + resolution: "syn@npm:0.2.2" + checksum: 936f7de14537e472ad089515740419a2e537ef4ab868395a1602e22894ea8ad98ba2d6c2457d7ea06b0f7ab171951da8f0181e9ac37276bb557ff9725471fab1 + 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 + +"teex@npm:^1.0.1": + version: 1.0.1 + resolution: "teex@npm:1.0.1" + dependencies: + streamx: ^2.12.5 + checksum: 36bf7ce8bb5eb428ad7b14b695ee7fb0a02f09c1a9d8181cc42531208543a920b299d711bf78dad4ff9bcf36ac437ae8e138053734746076e3e0e7d6d76eef64 + languageName: node + linkType: hard + +"ternary-stream@npm:^3.0.0": + version: 3.0.0 + resolution: "ternary-stream@npm:3.0.0" + dependencies: + duplexify: ^4.1.1 + fork-stream: ^0.0.4 + merge-stream: ^2.0.0 + through2: ^3.0.1 + checksum: 16dc329d2725edcd8ecb1379252b0cb8f24f7ebd7baf2351259e48e1d0deae5fd9a011e8502b54e9e35e27fab9cc421525198b862c3f6d82070b79781c3f2c24 + languageName: node + linkType: hard + +"terser@npm:^5.17.4": + version: 5.19.2 + resolution: "terser@npm:5.19.2" + dependencies: + "@jridgewell/source-map": ^0.3.3 + acorn: ^8.8.2 + commander: ^2.20.0 + source-map-support: ~0.5.20 + bin: + terser: bin/terser + checksum: e059177775b4d4f4cff219ad89293175aefbd1b081252270444dc83e42a2c5f07824eb2a85eae6e22ef6eb7ef04b21af36dd7d1dd7cfb93912310e57d416a205 + 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 + +"through2@npm:^3.0.1": + version: 3.0.2 + resolution: "through2@npm:3.0.2" + dependencies: + inherits: ^2.0.4 + readable-stream: 2 || 3 + checksum: 47c9586c735e7d9cbbc1029f3ff422108212f7cc42e06d5cc9fff7901e659c948143c790e0d0d41b1b5f89f1d1200bdd200c7b72ad34f42f9edbeb32ea49e8b7 + 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 + +"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 + +"to-through@npm:^3.0.0": + version: 3.0.0 + resolution: "to-through@npm:3.0.0" + dependencies: + streamx: ^2.12.5 + checksum: 404ad1a346babab53d75d3b4deb779916760fc9e605f4e64ec789366edf08e75ad592a262ca566e7864f77c03375151dcfac4744ff7fd52417cb2a2e9fc60795 + languageName: node + linkType: hard + +"toidentifier@npm:1.0.0": + version: 1.0.0 + resolution: "toidentifier@npm:1.0.0" + checksum: 199e6bfca1531d49b3506cff02353d53ec987c9ee10ee272ca6484ed97f1fc10fb77c6c009079ca16d5c5be4a10378178c3cacdb41ce9ec954c3297c74c6053e + languageName: node + linkType: hard + +"touch@npm:^3.1.0": + version: 3.1.0 + resolution: "touch@npm:3.1.0" + dependencies: + nopt: ~1.0.10 + bin: + nodetouch: ./bin/nodetouch.js + checksum: e0be589cb5b0e6dbfce6e7e077d4a0d5f0aba558ef769c6d9c33f635e00d73d5be49da6f8631db302ee073919d82b5b7f56da2987feb28765c95a7673af68647 + 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 + +"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-detect@npm:4.0.8, 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.20.2": + version: 0.20.2 + resolution: "type-fest@npm:0.20.2" + checksum: 4fb3272df21ad1c552486f8a2f8e115c09a521ad7a8db3d56d53718d0c907b62c6e9141ba5f584af3f6830d0872c521357e512381f24f7c44acae583ad517d73 + languageName: node + linkType: hard + +"type-is@npm:~1.6.17": + 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-buffer@npm:^1.0.0": + version: 1.0.0 + resolution: "typed-array-buffer@npm:1.0.0" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.2.1 + is-typed-array: ^1.1.10 + checksum: 3e0281c79b2a40cd97fe715db803884301993f4e8c18e8d79d75fd18f796e8cd203310fec8c7fdb5e6c09bedf0af4f6ab8b75eb3d3a85da69328f28a80456bd3 + languageName: node + linkType: hard + +"typed-array-buffer@npm:^1.0.2": + version: 1.0.2 + resolution: "typed-array-buffer@npm:1.0.2" + dependencies: + call-bind: ^1.0.7 + es-errors: ^1.3.0 + is-typed-array: ^1.1.13 + checksum: 02ffc185d29c6df07968272b15d5319a1610817916ec8d4cd670ded5d1efe72901541ff2202fcc622730d8a549c76e198a2f74e312eabbfb712ed907d45cbb0b + languageName: node + linkType: hard + +"typed-array-byte-length@npm:^1.0.0": + version: 1.0.0 + resolution: "typed-array-byte-length@npm:1.0.0" + dependencies: + call-bind: ^1.0.2 + for-each: ^0.3.3 + has-proto: ^1.0.1 + is-typed-array: ^1.1.10 + checksum: b03db16458322b263d87a702ff25388293f1356326c8a678d7515767ef563ef80e1e67ce648b821ec13178dd628eb2afdc19f97001ceae7a31acf674c849af94 + languageName: node + linkType: hard + +"typed-array-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "typed-array-byte-length@npm:1.0.1" + dependencies: + call-bind: ^1.0.7 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + checksum: f65e5ecd1cf76b1a2d0d6f631f3ea3cdb5e08da106c6703ffe687d583e49954d570cc80434816d3746e18be889ffe53c58bf3e538081ea4077c26a41055b216d + languageName: node + linkType: hard + +"typed-array-byte-offset@npm:^1.0.0": + version: 1.0.0 + resolution: "typed-array-byte-offset@npm:1.0.0" + dependencies: + available-typed-arrays: ^1.0.5 + call-bind: ^1.0.2 + for-each: ^0.3.3 + has-proto: ^1.0.1 + is-typed-array: ^1.1.10 + checksum: 04f6f02d0e9a948a95fbfe0d5a70b002191fae0b8fe0fe3130a9b2336f043daf7a3dda56a31333c35a067a97e13f539949ab261ca0f3692c41603a46a94e960b + languageName: node + linkType: hard + +"typed-array-byte-offset@npm:^1.0.2": + version: 1.0.2 + resolution: "typed-array-byte-offset@npm:1.0.2" + dependencies: + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + checksum: c8645c8794a621a0adcc142e0e2c57b1823bbfa4d590ad2c76b266aa3823895cf7afb9a893bf6685e18454ab1b0241e1a8d885a2d1340948efa4b56add4b5f67 + 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 + +"typed-array-length@npm:^1.0.5": + version: 1.0.6 + resolution: "typed-array-length@npm:1.0.6" + dependencies: + call-bind: ^1.0.7 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + possible-typed-array-names: ^1.0.0 + checksum: f0315e5b8f0168c29d390ff410ad13e4d511c78e6006df4a104576844812ee447fcc32daab1f3a76c9ef4f64eff808e134528b5b2439de335586b392e9750e5c + languageName: node + linkType: hard + +"ua-parser-js@npm:^0.7.30": + version: 0.7.33 + resolution: "ua-parser-js@npm:0.7.33" + checksum: 1510e9ec26fcaf0d8c6ae8f1078a8230e8816f083e1b5f453ea19d06b8ef2b8a596601c92148fd41899e8b3e5f83fa69c42332bd5729b931a721040339831696 + languageName: node + linkType: hard + +"unbox-primitive@npm:^1.0.1": + version: 1.0.1 + resolution: "unbox-primitive@npm:1.0.1" + dependencies: + function-bind: ^1.1.1 + has-bigints: ^1.0.1 + has-symbols: ^1.0.2 + which-boxed-primitive: ^1.0.2 + checksum: 89d950e18fb45672bc6b3c961f1e72c07beb9640c7ceed847b571ba6f7d2af570ae1a2584cfee268b9d9ea1e3293f7e33e0bc29eaeb9f8e8a0bab057ff9e6bba + 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 + +"unc-path-regex@npm:^0.1.2": + version: 0.1.2 + resolution: "unc-path-regex@npm:0.1.2" + checksum: a05fa2006bf4606051c10fc7968f08ce7b28fa646befafa282813aeb1ac1a56f65cb1b577ca7851af2726198d59475bb49b11776036257b843eaacee2860a4ec + languageName: node + linkType: hard + +"undertaker-registry@npm:^2.0.0": + version: 2.0.0 + resolution: "undertaker-registry@npm:2.0.0" + checksum: 5a26ac2bcddd5ffad9bcb1115968b19c18a3e8896610124c26592b44037bbb43f84b1252f7c5df730c2ad05c142b85bd564b2bc6b04fb1f9d53a75aa8067fd10 + languageName: node + linkType: hard + +"undertaker@npm:^2.0.0": + version: 2.0.0 + resolution: "undertaker@npm:2.0.0" + dependencies: + bach: ^2.0.1 + fast-levenshtein: ^3.0.0 + last-run: ^2.0.0 + undertaker-registry: ^2.0.0 + checksum: c952508f664a03bff20fd21211e7ee67fd8e86d9b26f1aefe30e126834e1730e1cc0a3691e76d099fa1b474721f24831c3f7586ff7aef3268e0b6ad2d8521bd9 + 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.0.0": + version: 2.0.0 + resolution: "unicode-match-property-value-ecmascript@npm:2.0.0" + checksum: 8fe6a09d9085a625cabcead5d95bdbc1a2d5d481712856092ce0347231e81a60b93a68f1b69e82b3076a07e415a72c708044efa2aa40ae23e2e7b5c99ed4a9ea + 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.0.0 + resolution: "unicode-property-aliases-ecmascript@npm:2.0.0" + checksum: dda4d39128cbbede2ac60fbb85493d979ec65913b8a486bf7cb7a375a2346fa48cbf9dc6f1ae23376e7e8e684c2b411434891e151e865a661b40a85407db51d0 + languageName: node + linkType: hard + +"unique-filename@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-filename@npm:3.0.0" + dependencies: + unique-slug: ^4.0.0 + checksum: 8e2f59b356cb2e54aab14ff98a51ac6c45781d15ceaab6d4f1c2228b780193dc70fae4463ce9e1df4479cb9d3304d7c2043a3fb905bdeca71cc7e8ce27e063df + languageName: node + linkType: hard + +"unique-slug@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-slug@npm:4.0.0" + dependencies: + imurmurhash: ^0.1.4 + checksum: 0884b58365af59f89739e6f71e3feacb5b1b41f2df2d842d0757933620e6de08eff347d27e9d499b43c40476cbaf7988638d3acb2ffbcb9d35fd035591adfd15 + 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 + +"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 + +"update-browserslist-db@npm:^1.0.11": + version: 1.0.11 + resolution: "update-browserslist-db@npm:1.0.11" + dependencies: + escalade: ^3.1.1 + picocolors: ^1.0.0 + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: b98327518f9a345c7cad5437afae4d2ae7d865f9779554baf2a200fdf4bac4969076b679b1115434bd6557376bdd37ca7583d0f9b8f8e302d7d4cc1e91b5f231 + languageName: node + linkType: hard + +"update-browserslist-db@npm:^1.0.13": + version: 1.0.13 + resolution: "update-browserslist-db@npm:1.0.13" + dependencies: + escalade: ^3.1.1 + picocolors: ^1.0.0 + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: 1e47d80182ab6e4ad35396ad8b61008ae2a1330221175d0abd37689658bdb61af9b705bfc41057fd16682474d79944fb2d86767c5ed5ae34b6276b9bed353322 + 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 + +"util-deprecate@npm:^1.0.1": + version: 1.0.2 + resolution: "util-deprecate@npm:1.0.2" + checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 + 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 + +"v8flags@npm:^4.0.0": + version: 4.0.1 + resolution: "v8flags@npm:4.0.1" + checksum: 69863ede75ff79579654951c78724c084bc337d0ebe1d9bffc6924f3f2bd0b40a9eb4c568fc795201d5eb72311b77e5d75a7e1544faa12355412360dc37d76e2 + languageName: node + linkType: hard + +"value-or-function@npm:^4.0.0": + version: 4.0.0 + resolution: "value-or-function@npm:4.0.0" + checksum: 16b6aed84b8f9732a7eb7a5035a1480be3689d097a73b1154fb827caf021d5f2b6f60c0dfe694bfc8c9605f06cfc093dc428efdc3d24cb2768fbe202ffd42ae1 + languageName: node + linkType: hard + +"vary@npm:^1": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: ae0123222c6df65b437669d63dfa8c36cee20a504101b2fcd97b8bf76f91259c17f9f2b4d70a1e3c6bbcee7f51b28392833adb6b2770b23b01abec84e369660b + languageName: node + linkType: hard + +"vinyl-contents@npm:^2.0.0": + version: 2.0.0 + resolution: "vinyl-contents@npm:2.0.0" + dependencies: + bl: ^5.0.0 + vinyl: ^3.0.0 + checksum: 10d72a032e6317bf89713565d616df8726ee41601a41c48c7d778e61ab557c0a5fdee883ceecbfb33da4a5e11ea80e76e5ae63c1d13fda61edbb5ef50445c8b2 + languageName: node + linkType: hard + +"vinyl-fs@npm:^4.0.0": + version: 4.0.0 + resolution: "vinyl-fs@npm:4.0.0" + dependencies: + fs-mkdirp-stream: ^2.0.1 + glob-stream: ^8.0.0 + graceful-fs: ^4.2.11 + iconv-lite: ^0.6.3 + is-valid-glob: ^1.0.0 + lead: ^4.0.0 + normalize-path: 3.0.0 + resolve-options: ^2.0.0 + stream-composer: ^1.0.2 + streamx: ^2.14.0 + to-through: ^3.0.0 + value-or-function: ^4.0.0 + vinyl: ^3.0.0 + vinyl-sourcemap: ^2.0.0 + checksum: 4cf83dea5123ac1f99e43e0710f22f5cb7524e6e13568cbac434a51015ae1d97965210feb9ff0787c4fa1cd79eb5f8538d86210cdafb76fd64c19bc3e755802a + languageName: node + linkType: hard + +"vinyl-sourcemap@npm:^2.0.0": + version: 2.0.0 + resolution: "vinyl-sourcemap@npm:2.0.0" + dependencies: + convert-source-map: ^2.0.0 + graceful-fs: ^4.2.10 + now-and-later: ^3.0.0 + streamx: ^2.12.5 + vinyl: ^3.0.0 + vinyl-contents: ^2.0.0 + checksum: c805fe46f586cf4435ac58d60818c1ae5d82f0c47498895f49842ca5d9f8b5167bfa88f6b4a84c0cb6761abf791d593ee580712685a57aaf3388122d22740afa + languageName: node + linkType: hard + +"vinyl@npm:^3.0.0": + version: 3.0.0 + resolution: "vinyl@npm:3.0.0" + dependencies: + clone: ^2.1.2 + clone-stats: ^1.0.0 + remove-trailing-separator: ^1.1.0 + replace-ext: ^2.0.0 + teex: ^1.0.1 + checksum: 29c563d6a027d49ec216bc8259b494bd048d1f9df39103aea6877e02af1d0a6956b11ad977206b5a807b331ef5431bed9f6b8890de5e55188389d31cf7af7fbe + languageName: node + linkType: hard + +"void-elements@npm:^2.0.0": + version: 2.0.1 + resolution: "void-elements@npm:2.0.1" + checksum: 700c07ba9cfa2dff88bb23974b3173118f9ad8107143db9e5d753552be15cf93380954d4e7f7d7bc80e7306c35c3a7fb83ab0ce4d4dcc18abf90ca8b31452126 + 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 + +"whatwg-url@npm:^6.5.0": + version: 6.5.0 + resolution: "whatwg-url@npm:6.5.0" + dependencies: + lodash.sortby: ^4.7.0 + tr46: ^1.0.1 + webidl-conversions: ^4.0.2 + checksum: a10bd5e29f4382cd19789c2a7bbce25416e606b6fefc241c7fe34a2449de5bc5709c165bd13634eda433942d917ca7386a52841780b82dc37afa8141c31a8ebd + 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-builtin-type@npm:^1.1.3": + version: 1.1.3 + resolution: "which-builtin-type@npm:1.1.3" + dependencies: + function.prototype.name: ^1.1.5 + has-tostringtag: ^1.0.0 + is-async-function: ^2.0.0 + is-date-object: ^1.0.5 + is-finalizationregistry: ^1.0.2 + is-generator-function: ^1.0.10 + is-regex: ^1.1.4 + is-weakref: ^1.0.2 + isarray: ^2.0.5 + which-boxed-primitive: ^1.0.2 + which-collection: ^1.0.1 + which-typed-array: ^1.1.9 + checksum: 43730f7d8660ff9e33d1d3f9f9451c4784265ee7bf222babc35e61674a11a08e1c2925019d6c03154fcaaca4541df43abe35d2720843b9b4cbcebdcc31408f36 + 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.11, which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.9": + version: 1.1.13 + resolution: "which-typed-array@npm:1.1.13" + dependencies: + available-typed-arrays: ^1.0.5 + call-bind: ^1.0.4 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-tostringtag: ^1.0.0 + checksum: 3828a0d5d72c800e369d447e54c7620742a4cc0c9baf1b5e8c17e9b6ff90d8d861a3a6dd4800f1953dbf80e5e5cec954a289e5b4a223e3bee4aeb1f8c5f33309 + languageName: node + linkType: hard + +"which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15": + version: 1.1.15 + resolution: "which-typed-array@npm:1.1.15" + dependencies: + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-tostringtag: ^1.0.2 + checksum: 65227dcbfadf5677aacc43ec84356d17b5500cb8b8753059bb4397de5cd0c2de681d24e1a7bd575633f976a95f88233abfd6549c2105ef4ebd58af8aa1807c75 + languageName: node + linkType: hard + +"which@npm:^1.2.1, which@npm:^1.2.14": + 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 + +"workerpool@npm:6.2.1": + version: 6.2.1 + resolution: "workerpool@npm:6.2.1" + checksum: c2c6eebbc5225f10f758d599a5c016fa04798bcc44e4c1dffb34050cd361d7be2e97891aa44419e7afe647b1f767b1dc0b85a5e046c409d890163f655028b09d + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, 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.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 + +"ws@npm:~8.11.0": + version: 8.11.0 + resolution: "ws@npm:8.11.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 316b33aba32f317cd217df66dbfc5b281a2f09ff36815de222bc859e3424d83766d9eb2bd4d667de658b6ab7be151f258318fb1da812416b30be13103e5b5c67 + 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 + +"yargs-parser@npm:20.2.4": + version: 20.2.4 + resolution: "yargs-parser@npm:20.2.4" + checksum: d251998a374b2743a20271c2fd752b9fbef24eb881d53a3b99a7caa5e8227fcafd9abf1f345ac5de46435821be25ec12189a11030c12ee6481fef6863ed8b924 + 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-unparser@npm:2.0.0": + version: 2.0.0 + resolution: "yargs-unparser@npm:2.0.0" + dependencies: + camelcase: ^6.0.0 + decamelize: ^4.0.0 + flat: ^5.0.2 + is-plain-obj: ^2.1.0 + checksum: 68f9a542c6927c3768c2f16c28f71b19008710abd6b8f8efbac6dcce26bbb68ab6503bed1d5994bdbc2df9a5c87c161110c1dfe04c6a3fe5c6ad1b0e15d9a8a3 + languageName: node + linkType: hard + +"yargs@npm:16.2.0, yargs@npm:^16.1.1, 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 + +"yocto-queue@npm:^0.1.0": + version: 0.1.0 + resolution: "yocto-queue@npm:0.1.0" + checksum: f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700 + languageName: node + linkType: hard