diff --git a/.cicsdev/sdv-sample.yml b/.cicsdev/sdv-sample.yml
new file mode 100644
index 0000000..df0a694
--- /dev/null
+++ b/.cicsdev/sdv-sample.yml
@@ -0,0 +1,21 @@
+name: cics-security-sdv-samples
+description: "Provides tooling to introduce Security testing into your CICS applications CI pipelines"
+learning_objective: |
+ Learn how to use the Galasa SDV manager to write role-based tests for your CICS applications, then how to adapt
+ the applications CI pipeline to detect changes in security definition usage following application code change
+ requests and initiate an approval process.
+product:
+ cicsts:
+ version:
+ minimum: 6.2
+ language: javascript,python,ansible
+
+build:
+ ide:
+ - VS Code
+ tools:
+ - Node
+ - Python
+ - Ansible
+ - GitHub
+ - Galasa
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
new file mode 100644
index 0000000..e5b1675
--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1,18 @@
+#
+# Copyright IBM Corp. 2024
+#
+FROM mcr.microsoft.com/devcontainers/base:jammy
+
+RUN apt update
+
+ENV LOG_LEVEL="trace"
+
+EXPOSE 3000
+EXPOSE 3001
+
+COPY initialise_dev_container.sh /post_script/initialise_dev_container.sh
+
+RUN mkdir -p /workspaces; \
+ chmod 755 /post_script/initialise_dev_container.sh
+
+WORKDIR /workspaces
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000..2fbb32b
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,54 @@
+{
+ "name": "cics-security-sdv-samples Container",
+ "build": {
+ "dockerfile": "Dockerfile"
+ },
+ "customizations": {
+ "vscode": {
+ "settings": {
+ "vsintellicode.java.completionsEnabled": false,
+ "vsintellicode.python.completionsEnabled": false,
+ "vsintellicode.sql.completionsEnabled": false,
+ "vsintellicode.typescript.completionsEnabled": false,
+ "vsintellicode.modify.editor.suggestSelection": "disabled",
+ "errorLens.onSave": true,
+ "errorLens.messageEnabled": true,
+ "versionlens.suggestions.showOnStartup": true,
+ "editor.formatOnSave": true,
+ "ansible.python.interpreterPath": "/usr/local/python/current/bin/python",
+ "pylint.interpreter": ["/usr/local/python/current/bin/python"]
+ },
+ "extensions": [
+ "dbaeumer.vscode-eslint",
+ "usernamehw.errorlens",
+ "igorsbitnev.error-gutters",
+ "wayou.vscode-todo-highlight",
+ "vscode-icons-team.vscode-icons",
+ "pflannery.vscode-versionlens",
+ "bierner.markdown-emoji",
+ "redhat.ansible",
+ "ms-python.flake8",
+ "gruntfuggly.todo-tree",
+ "ms-python.python",
+ "ms-python.pylint"
+ ]
+ }
+ },
+ "features": {
+ "ghcr.io/devcontainers/features/git:1": {},
+ "ghcr.io/devcontainers/features/common-utils:2": {},
+ "ghcr.io/devcontainers/features/node:1": {
+ "version": "18"
+ },
+ "ghcr.io/devcontainers/features/python:1": {
+ "version": "3.12"
+ }
+ },
+ "forwardPorts": [3000, 3001],
+ "privileged": true,
+ "remoteUser": "root",
+ "workspaceMount": "source=${localWorkspaceFolder},target=/workspaces,type=bind",
+ "workspaceFolder": "/workspaces",
+ "postStartCommand": "git config --global --add safe.directory /workspaces; git config commit.gpgsign false",
+ "postAttachCommand": "/post_script/initialise_dev_container.sh"
+}
\ No newline at end of file
diff --git a/.devcontainer/initialise_dev_container.sh b/.devcontainer/initialise_dev_container.sh
new file mode 100644
index 0000000..abc9b05
--- /dev/null
+++ b/.devcontainer/initialise_dev_container.sh
@@ -0,0 +1,19 @@
+#
+# Copyright IBM Corp. 2024
+#
+
+# Install approval bot dependencies
+npm install
+
+# Install docs dependencies
+cd docs
+npm install
+cd ..
+
+# Install Ansible tooling
+pip install ansible==10.2.0 ansible-lint==24.7.0 --root-user-action=ignore
+
+# Install ansible script dependencies
+cd ansible-sdv-pipeline
+pip install -r requirements.txt --root-user-action=ignore
+
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..6b308f2
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,5 @@
+*
+!lib/
+!index.js
+!package.json
+!package-lock.json
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..a83913e
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,14 @@
+# The ID of your GitHub App; You can find this in the About section of your Github app
+APP_ID=
+
+# The Webhook Secret; This is generated by you and then inputted in the settings of your Github app.
+WEBHOOK_SECRET=development
+
+# Use `trace` to get verbose logging or `info` to show less
+LOG_LEVEL=debug
+
+PRIVATE_KEY=""
+
+GHE_HOST=github.com
+
+CHECK_NAME=Security
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..4eb2283
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+text eol=lf
\ No newline at end of file
diff --git a/.github/workflows/ansible-lint.yml b/.github/workflows/ansible-lint.yml
new file mode 100644
index 0000000..1c64799
--- /dev/null
+++ b/.github/workflows/ansible-lint.yml
@@ -0,0 +1,27 @@
+name: Ansible
+
+on:
+ push:
+ branches: ["main"]
+ pull_request:
+ branches: ["main"]
+
+jobs:
+ Lint:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: "ansible-sdv-pipeline"
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python 3.x
+ uses: actions/setup-python@v3
+ with:
+ python-version: 3.x
+ - name: Install Ansible-lint
+ run: |
+ python -m pip install --upgrade pip
+ pip install ansible-lint
+ - name: Running Ansible-lint
+ run: ansible-lint ./*
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 0000000..2b53a8e
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,65 @@
+name: SDV Approval Bot Code QL
+
+on:
+ push:
+ branches: ["main"]
+ pull_request:
+ branches: ["main"]
+ schedule:
+ - cron: "17 13 * * 6"
+
+jobs:
+ code-ql:
+ name: Analyze (${{ matrix.language }})
+ runs-on: ubuntu-latest
+ permissions:
+ # required for all workflows
+ security-events: write
+
+ # required to fetch internal or private CodeQL packs
+ packages: read
+
+ # only required for workflows in private repositories
+ actions: read
+ contents: read
+
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - language: javascript-typescript
+ build-mode: none
+ - language: python
+ build-mode: none
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ languages: ${{ matrix.language }}
+ build-mode: ${{ matrix.build-mode }}
+
+ # If the analyze step fails for one of the languages you are analyzing with
+ # "We were unable to automatically build your code", modify the matrix above
+ # to set the build mode to "manual" for that language. Then modify this step
+ # to build your code.
+ # âšī¸ Command-line programs to run using the OS shell.
+ # đ See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+ - if: matrix.build-mode == 'manual'
+ shell: bash
+ run: |
+ echo 'If you are using a "manual" build mode for one or more of the' \
+ 'languages you are analyzing, replace this with the commands to build' \
+ 'your code, for example:'
+ echo ' make bootstrap'
+ echo ' make release'
+ exit 1
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
+ with:
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 0000000..417988a
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,71 @@
+name: SDV Documentation
+
+on:
+ push:
+ branches: ["main"]
+ pull_request:
+ branches: ["main"]
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: "docs"
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Use Node.js 18.x
+ uses: actions/setup-node@v3
+ with:
+ node-version: "18.x"
+ cache: "npm"
+ cache-dependency-path: "**/package-lock.json"
+
+ - name: Installing dependencies
+ run: npm ci
+
+ - name: Linting the docs code
+ run: npm run lint
+ working-directory: "docs"
+
+ - name: Setup Pages
+ uses: actions/configure-pages@v4
+ with:
+ static_site_generator: next
+
+ - name: Building docs
+ run: npm run build
+
+ - name: Uploading artifacts
+ if: ${{ github.ref == 'refs/heads/main' }}
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: ./docs/out
+
+ deploy:
+ if: ${{ github.ref == 'refs/heads/main' }}
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: "docs"
+ needs: build
+
+ steps:
+ - name: Publish to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml
new file mode 100644
index 0000000..492f7ba
--- /dev/null
+++ b/.github/workflows/node.js.yml
@@ -0,0 +1,30 @@
+name: SDV Approval Bot Build
+
+on:
+ push:
+ branches: ["main"]
+ pull_request:
+ branches: ["main"]
+
+jobs:
+ Test:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ - name: Use Node.js 18.x
+ uses: actions/setup-node@v3
+ with:
+ node-version: "18.x"
+ cache: "npm"
+ cache-dependency-path: "**/package-lock.json"
+ - name: Installing dependencies
+ run: npm ci
+ - name: Linting the commit message
+ run: npx commitlint -V --from=HEAD~1
+ - name: Linting the application code
+ run: npm run lint-bot
+ - name: Running unit tests
+ run: npm run unit-test
diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml
new file mode 100644
index 0000000..407d25f
--- /dev/null
+++ b/.github/workflows/pylint.yml
@@ -0,0 +1,31 @@
+name: Python
+
+on:
+ push:
+ branches: ["main"]
+ pull_request:
+ branches: ["main"]
+
+jobs:
+ Lint:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: "ansible-sdv-pipeline"
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python 3.x
+ uses: actions/setup-python@v3
+ with:
+ python-version: 3.x
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install pylint flake8
+ - name: Analysing the code with pylint
+ run: |
+ pylint $(git ls-files '*.py') --fail-under 5 --fail-on F,E,W,C,R
+ - name: Checking code styling
+ run: |
+ flake8 .
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9659b06
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+node_modules
+coverage
+.env
+.DS_Store
\ No newline at end of file
diff --git a/.husky/commit-msg b/.husky/commit-msg
new file mode 100755
index 0000000..fa859b0
--- /dev/null
+++ b/.husky/commit-msg
@@ -0,0 +1,4 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+npx --no -- commitlint --edit ""
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 0000000..d0612ad
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,4 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+npm run pre-commit
diff --git a/.jest/setEnvVars.js b/.jest/setEnvVars.js
new file mode 100644
index 0000000..c113914
--- /dev/null
+++ b/.jest/setEnvVars.js
@@ -0,0 +1,4 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+process.env.CHECK_NAME = 'Security';
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..8de1f65
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,37 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Launch Probot",
+ "program": "${workspaceFolder}/node_modules/probot/bin/probot-run.js",
+ "args": ["./lib/app.js"],
+ "console": "integratedTerminal",
+ "cwd": "${workspaceRoot}/",
+ "outFiles": [],
+ "sourceMaps": true,
+ "env": {
+ "LOG_LEVEL": "trace"
+ }
+ },
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Jest (current file)",
+ "program": "${workspaceFolder}/node_modules/jest/bin/jest",
+ "args": [
+ "${fileBasename}",
+ "--verbose",
+ "-i",
+ "--no-cache",
+ "--detectOpenHandles"
+ ],
+ "console": "integratedTerminal",
+ "internalConsoleOptions": "neverOpen",
+ "env": {
+ "NODE_OPTIONS": "--no-experimental-fetch"
+ }
+ },
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..46fff02
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "ansible.python.interpreterPath": "/Library/Developer/CommandLineTools/usr/bin/python3"
+}
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..ab8b987
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,15 @@
+# How to contribute
+
+Thank you for contributing to this project.
+
+We welcome bug reports, discussions about new function, and suggested updates to the documentation in the issue tracker.
+
+You should read these guidelines to help you contribute.
+
+## Reporting a bug
+
+Please raise bugs by raising a new issue using the Issues tab. When raising bugs, first check whether an issue for your problem already exists. Then try to give a good indication of the exact circumstances that provoked the bug. What were you doing? What did you expect to happen? What actually happened? What logs or other material can you provide to show the problem?
+
+## Requesting new features
+
+Please request new features or updates to the documentation in the issue tracker. When requesting features, try to show why you want the feature you're requesting.
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..3596fc3
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,19 @@
+#
+# Copyright IBM Corp. 2024
+#
+FROM registry.access.redhat.com/ubi8/nodejs-18-minimal
+
+USER root
+RUN microdnf update -y && microdnf -y clean all && rm -rf /var/cache/yum/*
+USER 1001
+
+COPY --chown=1001 . .
+
+RUN npm ci --production && npm cache clean --force
+
+ENV NODE_ENV="production"
+ENV LOG_LEVEL="debug"
+
+EXPOSE 3000
+
+CMD [ "npm", "start" ]
diff --git a/README.md b/README.md
index 751ec78..2bb8fcf 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,132 @@
# cics-security-sdv-samples
-CICS TS security discovery verification samples
+
+[![SDV Approval Bot Build](https://github.com/cicsdev/cics-security-sdv-samples/actions/workflows/node.js.yml/badge.svg)](https://github.com/cicsdev/cics-security-sdv-samples/actions/workflows/node.js.yml)
+[![SDV Documentation](https://github.com/cicsdev/cics-security-sdv-samples/actions/workflows/docs.yml/badge.svg)](https://github.com/cicsdev/cics-security-sdv-samples/actions/workflows/docs.yml)
+[![Ansible Lint](https://github.com/cicsdev/cics-security-sdv-samples/actions/workflows/ansible-lint.yml/badge.svg)](https://github.com/cicsdev/cics-security-sdv-samples/actions/workflows/ansible-lint.yml)
+[![Python Lint](https://github.com/cicsdev/cics-security-sdv-samples/actions/workflows/pylint.yml/badge.svg)](https://github.com/cicsdev/cics-security-sdv-samples/actions/workflows/pylint.yml)
+[![SDV Approval Bot Code QL](https://github.com/cicsdev/cics-security-sdv-samples/actions/workflows/codeql.yml/badge.svg)](https://github.com/cicsdev/cics-security-sdv-samples/actions/workflows/codeql.yml)
+
+
+This sample repository provides example tooling that contributes towards achieving **Security Definition Validation for CICS TS** in a CI/CD pipeline.
+
+## Contents
+
+Each of the tools contained within this repositiory live within their own folder. These tools include (along with folder locations):
+* **SDV Approval Bot** - located in `/`
+* **Ansible SDV Post-test Pipeline scripts** - located in `/ansible-sdv-pipeline`
+* **SDV Documentation** - `/docs`
+
+> [!NOTE]
+> These tools have been written spcifically for a pipeline using GitHub as its SCM, however the logic of these tools have been made open-source to show how SDV has been achieved, so it can be ported to pipelines using different technologies.
+
+## Prerequisites
+
+* CICS TS V6.2 or later
+* SCM tool (GitHub used in this sample)
+* CI Tool with Ansible installed in worker
+* Automated test framework ([**Galasa**](https://galasa.dev/) used in this sample)
+
+## Development
+
+This reposititory contains a **devcontainer** spec, therefore it would be beneficial to work on this repository using the [Microsoft VSCode IDE](https://code.visualstudio.com/), which will automatically open the repository within a container with all prerequistes installed, and the IDE fully configured.
+
+Please see the [`CONTRIBUTING.md`](/CONTRIBUTING.md) file for details on making contributions to this repository.
+
+Pull Requests and merges to `main` will cause a number of GitHub Actions to run. These actions include:
+* The automated test run for the **SDV Approval Bot**.
+* Code QL analysis against the **SDV Approval Bot** code.
+* Linting of the Ansible scripts.
+* Linting of the custom Python modules used by the Ansible scripts.
+* The Build and deployment of the SDV documentation.
+
+Pull requests cannot be merged if any of these tasks encounter issues.
+
+> [!NOTE]
+>Commit messages must follow the [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/master/@commitlint/config-conventional#type-enum) standard.
+
+## Documentation
+
+Full technical documentation can be viewed at https://cicsdev.github.io/cics-security-sdv-samples
+
+The source code for this documentation resides in the `/docs` folder. Any changes to documentation will be automatically deployed via a GitHub Action when delivered to the `main` branch.
+
+Please see the [`/docs/README.md`](/docs/README.md) file for more information on developing documentation changes.
+
+
+## SDV Approval Bot
+
+The **SDV Approval Bot** is a GitHub App built with [Probot](https://github.com/probot/probot), which is designed to continually run on a server, receiving webhooks from GitHub repositories when particular events (see [app.yml](/app.yml)) take place. The bot then runs required custom workflow logic following the event. As an example, an approved review within a pull request on the security repository would send out a webhook to the **SDV Approval Bot**, and the bot would then programatically pass the `Security` check in the application repository pull request. The bot will then merge both pull requests.
+
+### Configuration
+
+The bot is only active if:
+
+1. The bot is defined as a GitHub app in the GitHub UI, and is installed on the required organisations and repositories (this is any application, test, or security repository)
+1. An `.github/sdvapproval.yml` configuration file exists in every repository the SDV process should operate against (i.e. every application, test, or security repo), containing the following:
+
+ ```yaml
+ security_repo_owner:
+ security_repo_name:
+ ```
+ > [!NOTE]
+ > The Security repository must contain this file, even if it is just referencing itself!
+1. The bot will only act on branches from the Security repo following the format of: `//`
+
+
+The bot must be provided with the following required environment variables:
+
+| Name | Description |
+|------------------|---------------------------------------------------------------------------------|
+| `APP_ID` | The GH App ID, obtainable from the GH UI. |
+| `WEBHOOK_SECRET` | The GH App Webhook secret, set within the app's configuration in the GH UI. |
+| `PRIVATE_KEY` | The GH App Private Key, obtainable from the GH UI. |
+| `CHECK_NAME` | The name of the Security status check in GH, which blocks PRs (e.g. `Security`) |
+
+
+### Development of the bot
+
+
+Newly written code will be linted on file save. This will then be checked again as part of the build and on `npm test`.
+
+Before delivering new code, ensure all tests pass by running `npm test`.
+
+#### To create a development environment:
+
+1. Clone this repo to your local machine & open within the **dev container**.
+2. Copy `.env.example` to `.env`
+5. [Create a new Github App](https://www.github.com/settings/apps/new) for your personal development on GH
+ 1. For webhook url, find your development machines external IP via `ifconfig` combined with `PORT`, e.g. `http://x.x.xx.xxx:3000`.
+ 2. Use any secret for the webhook, setting to `development` is sufficient. Set this as `WEBHOOK_SECRET` in your `.env` file.
+ 3. Give the app the permissions specified in the [`app.yml` file](/app.yml):
+ 4. Save the app.
+ 5. Copy the provided `App ID`, and set as `APP_ID` in your `.env` file.
+ 6. Update the webhook secret.
+ 7. From the left-hand menu, select **Install App** and install onto your account, and on any test repository you own.
+ 6. In VSCode, open the `Run and Debug` view
+ 7. Run `Launch Probot`.
+
+You are now running your own local version of the app and can debug in VSCode.
+
+#### Testing
+
+To run the full test suite, run `npm test`.
+
+> [!NOTE]
+> Should the test suite fail due to a coverage threshold not being met, you must create new tests to reach that threshold.
+
+
+## Ansible SDV Post-test Pipeline
+
+This is an Ansible playbook called `security-approval.yaml` which contains all logic designed to be ran directly after the automated test suite has finished.
+
+The playbook has been written specifically to interact with **GitHub** and [**Galasa**](https://galasa.dev/), however the steps can be accessed here, and ported to pipelines using different technologies.
+
+Contained within the folder, as well as the playbook, is a number of Ansible sub-tasks, and Python custom modules. A number of checks are made against this code when creating a pull request on this repository, to ensure the code is of a good standard.
+
+The post-test scripts jobs are to:
+
+1. Fail the `Security` check in the app/test PR if testing failed
+1. Gather all security metadata for every test class ran
+1. Compare the gather security metadata against the baseline in the Security repository
+1. If differences found, create a pull request on the security repository changing existing security metadata, else pass the `Security` check in the app/test PR.
+1. Update the `Security` check with latest status.
diff --git a/ansible-sdv-pipeline/.gitignore b/ansible-sdv-pipeline/.gitignore
new file mode 100644
index 0000000..ed8ebf5
--- /dev/null
+++ b/ansible-sdv-pipeline/.gitignore
@@ -0,0 +1 @@
+__pycache__
\ No newline at end of file
diff --git a/ansible-sdv-pipeline/ansible.cfg b/ansible-sdv-pipeline/ansible.cfg
new file mode 100644
index 0000000..304400a
--- /dev/null
+++ b/ansible-sdv-pipeline/ansible.cfg
@@ -0,0 +1,4 @@
+[defaults]
+action_plugins=./plugins/action
+host_key_checking = False
+pipelining = False
\ No newline at end of file
diff --git a/ansible-sdv-pipeline/playbooks/library/fetch_galasa_security_data.py b/ansible-sdv-pipeline/playbooks/library/fetch_galasa_security_data.py
new file mode 100644
index 0000000..edbd75d
--- /dev/null
+++ b/ansible-sdv-pipeline/playbooks/library/fetch_galasa_security_data.py
@@ -0,0 +1,244 @@
+#!/usr/bin/python
+
+#
+# Copyright IBM Corp. 2024
+#
+
+'''
+Ansible module to download CICS Security metadata
+from Galasa tests
+'''
+from __future__ import (absolute_import, division, print_function)
+import json
+import os
+import re
+import requests
+
+from ansible.module_utils.basic import AnsibleModule
+# __metaclass__ = type
+
+
+def get_galasa_auth_token(
+ galasa_token,
+ galasa_ecosystem_url
+):
+ '''
+ Obtains a fresh Galasa auth token from the api using the provided
+ GALASA_TOKEN, which is a colon seperated client_id and refresh_token
+ '''
+ refresh_token, client_id = galasa_token.split(':', 1)
+
+ response = requests.post(
+ f'{galasa_ecosystem_url}/auth',
+ json={
+ 'client_id': client_id,
+ 'refresh_token': refresh_token
+ },
+ timeout=30
+ )
+ auth_token = response.json()['jwt']
+
+ return auth_token
+
+
+def get_test_run_id(
+ galasa_ecosystem_url,
+ test_run,
+ headers
+):
+ '''
+ Gets the internal run ID for the test run, which can then be
+ used to query for more detailed data for the run.
+ '''
+ response = requests.get(
+ f'{galasa_ecosystem_url}/ras/runs'
+ f'?runname={test_run["name"]}'
+ f'&bundle={test_run["bundle"]}'
+ f'&testname={test_run["class"]}'
+ f'&result=Passed',
+ headers=headers,
+ timeout=30
+ )
+ return response.json()['runs'][0]['runId']
+
+
+def get_security_metadata_artifact_list(
+ galasa_ecosystem_url,
+ headers,
+ run_id
+):
+ '''
+ Gets the list of stored artifacts for the test run,
+ then filters and returns just the security metadata.
+ '''
+ # Obtain the list of artifacts for the runId
+ response = requests.get(
+ f'{galasa_ecosystem_url}/ras/runs/{run_id}/artifacts',
+ headers=headers,
+ timeout=30
+ )
+ artifact_list = response.json()
+
+ # Filter list to list just security metadata
+ yaml_pattern = re.compile(r'.*\.cics\-security\.(yaml|yml)$')
+ yaml_artifact_path_list = [
+ artifact["path"] for artifact in artifact_list
+ if yaml_pattern.match(artifact['path'])
+ ]
+
+ return yaml_artifact_path_list
+
+
+def download_and_save_security_metadata_file(
+ galasa_ecosystem_url,
+ headers,
+ run_id,
+ metadata_folder,
+ yaml_artifact_path
+):
+ '''
+ Downloads a YAML Security metadata file from Galasa, then
+ saves it to a local folder
+ '''
+ # Download YAML
+ response = requests.get(
+ f'{galasa_ecosystem_url}/ras/runs/'
+ f'{run_id}/files{yaml_artifact_path}',
+ headers=headers,
+ timeout=30
+ )
+ yaml_string = response.text
+
+ # Store as a new text file
+ new_yaml_filename = metadata_folder + yaml_artifact_path.replace(
+ "/artifacts/sdv", ""
+ )
+ os.makedirs(os.path.dirname(new_yaml_filename), exist_ok=True)
+ with open(
+ new_yaml_filename,
+ "w",
+ encoding="utf8"
+ ) as new_yaml_file:
+ new_yaml_file.write(yaml_string)
+
+
+def fetch_galasa_security_data(
+ galasa_token,
+ test_report_path,
+ galasa_ecosystem_url,
+ metadata_folder
+):
+ '''
+ Using a Galasa JSON test report, downloads all of the CICS Security
+ metadata generated for each test run in an ecosystem, and saves into
+ a provided folder path.
+ '''
+ yaml_generated = False
+ headers = {}
+
+ # If a galasa_token is provided, use galasa authenticated.
+ # Obtain a fresh auth token for the Galasa REST API.
+ if galasa_token:
+ auth_token = get_galasa_auth_token(
+ galasa_token,
+ galasa_ecosystem_url
+ )
+ headers['Authorization'] = f'Bearer {auth_token}'
+
+ # Open the galasa test report
+ with open(test_report_path, "r", encoding="utf8") as test_report_file:
+ test_report_json = json.load(test_report_file)
+
+ # Loop through each galasa test run
+ for test_run in test_report_json['tests']:
+
+ # Obtain the runId for the test run
+ run_id = get_test_run_id(
+ galasa_ecosystem_url,
+ test_run,
+ headers
+ )
+
+ # Obtain the security metadata artifact list for the run
+ yaml_artifact_path_list = get_security_metadata_artifact_list(
+ galasa_ecosystem_url,
+ headers,
+ run_id
+ )
+
+ # Loop through each yaml
+ for yaml_artifact_path in yaml_artifact_path_list:
+ download_and_save_security_metadata_file(
+ galasa_ecosystem_url,
+ headers,
+ run_id,
+ metadata_folder,
+ yaml_artifact_path
+ )
+ yaml_generated = True
+
+ # Has YAML been generated by Galasa?
+ return yaml_generated
+
+
+def run_module():
+ '''Ansible specific setup'''
+ # define available arguments/parameters a user can pass to the module
+ module_args = {
+ 'test_report_path': {'type': 'str', 'required': True},
+ 'galasa_ecosystem_url': {'type': 'str', 'required': True},
+ 'metadata_folder': {'type': 'str', 'required': True},
+ 'state_changed': {'type': 'bool', 'required': False}
+ }
+
+ # seed the result dict in the object
+ # we primarily care about changed and state
+ # changed is if this module effectively modified the target
+ # state will include any data that you want your module to pass back
+ # for consumption, for example, in a subsequent task
+ result = {
+ 'changed': False
+ }
+
+ # the AnsibleModule object will be our abstraction working with Ansible
+ # this includes instantiation, a couple of common attr would be the
+ # args/params passed to the execution, as well as if the module
+ # supports check mode
+ module = AnsibleModule(
+ argument_spec=module_args,
+ supports_check_mode=True
+ )
+
+ # if the user is working with this module in only check mode we do not
+ # want to make any changes to the environment, just return the current
+ # state with no modifications
+ if module.check_mode:
+ module.exit_json(**result)
+
+ # Check for galasa token info in environment variables
+ if os.environ['GALASA_TOKEN']:
+ galasa_token = os.environ['GALASA_TOKEN']
+ else:
+ galasa_token = None
+
+ # manipulate or modify the state as needed (this is going to be the
+ # part where your module will do what it needs to do)
+ result['changed'] = fetch_galasa_security_data(
+ galasa_token,
+ module.params['test_report_path'],
+ module.params['galasa_ecosystem_url'],
+ module.params['metadata_folder']
+ )
+
+ # in the event of a successful module execution, you will want to
+ # simple AnsibleModule.exit_json(), passing the key/value results
+ module.exit_json(**result)
+
+
+def main():
+ '''The entry point for the module'''
+ run_module()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/ansible-sdv-pipeline/playbooks/security-approval.yaml b/ansible-sdv-pipeline/playbooks/security-approval.yaml
new file mode 100644
index 0000000..ea89b4d
--- /dev/null
+++ b/ansible-sdv-pipeline/playbooks/security-approval.yaml
@@ -0,0 +1,242 @@
+#
+# Copyright IBM Corp. 2024
+#
+
+- name: Security Definition Validation
+ hosts: localhost
+ gather_facts: false
+
+ vars_prompt:
+ - name: test_report_path
+ prompt: "Please enter the path of the Galasa test report Json"
+ private: false
+ - name: check_name
+ prompt: "Please enter the name of the PR check for this process"
+ private: false
+ default: "Security"
+ - name: source_repo_approval_bot_token_path
+ prompt: "Please enter the path of the file containing the token for the Approval Bot access on the source repo"
+ private: false
+ - name: scm_api_base_url
+ prompt: "Please enter the base URL for the scm's API"
+ private: false
+ - name: source_repo_owner
+ prompt: "Please enter the owner/org of the source repo of the change"
+ private: false
+ - name: source_repo_name
+ prompt: "Please enter the name of the source repo of the change"
+ private: false
+ - name: source_repo_branch
+ prompt: "Please enter the name of the branch on the source repo of the change"
+ private: false
+ - name: source_repo_commit_ref
+ prompt: "Please enter the commit sha"
+ private: false
+ - name: source_repo_pull_number
+ prompt: "Please enter the pull request number on the source repo of the change"
+ default: ""
+ private: false
+ - name: galasa_ecosystem_url
+ prompt: "Please enter the Galasa ecosystem URL"
+ private: false
+ - name: galasa_token_path
+ prompt: "Please enter the path of the file containing the token for Galasa"
+ private: false
+ - name: github_app_author_name_path
+ prompt: "Please enter path to the file containing the author name of the GitHub app that will commit to the security repo."
+ private: false
+ - name: github_app_author_email_path
+ prompt: "Please enter path to the file containing the email of the GitHub app that will commit to the security repo."
+ private: false
+ - name: security_repo_owner
+ prompt: "Please enter the owner of the security repo."
+ private: false
+ - name: security_repo_name
+ prompt: "Please enter the name of the security repo."
+ private: false
+ - name: target_branch
+ prompt: "Please enter the name of the branch both the source and the security repo will merge to."
+ private: false
+ - name: security_repo_approval_bot_token_path
+ prompt: "Please enter the path of the file containing the token for the security repo"
+ private: false
+ - name: security_repo_url
+ prompt: "Please enter the URL of the security repo"
+
+ vars:
+ test_results: "{{ lookup('file','{{ test_report_path }}') | from_json }}"
+ security_repo_new_branch: "{{ source_repo_owner }}/{{ source_repo_name }}/{{ source_repo_branch }}"
+ github_app_author_name: "{{ lookup('file','{{ github_app_author_name_path }}') }}"
+ github_app_author_email: "{{ lookup('file','{{ github_app_author_email_path }}') }}"
+ source_repo_approval_bot_token: "{{ lookup('file', '{{ source_repo_approval_bot_token_path }}') }}"
+ security_repo_approval_bot_token: "{{ lookup('file', '{{ security_repo_approval_bot_token_path }}') }}"
+ galasa_token: "{{ lookup('file', '{{ galasa_token_path }}') }}"
+
+ tasks:
+
+# ------------- Initialisation -------------
+
+ - name: Create GH Check
+ ansible.builtin.include_tasks: ../tasks/create_gh_check.yaml
+
+# ---------- Check we should run SDV -------
+ - name: Only run security if check set as required on branch protection for target branch
+ ansible.builtin.include_tasks: ../tasks/check_branch_protection.yaml
+
+ - name: If not all tests passed, gracefully end and update check
+ block:
+ - name: Check all tests passed
+ ansible.builtin.fail:
+ msg: Not all tests passed. Will not conduct SDV.
+ when: "test_results.tests | length != test_results | json_query('tests[?result == `Passed`]') | length"
+ rescue:
+ - name: Update GH Check
+ ansible.builtin.include_tasks: ../tasks/update_gh_check.yaml
+ vars:
+ check_conclusion: cancelled
+ check_title: "Failed: {{ ansible_failed_task.name }}"
+ check_summary: "{{ ansible_failed_result.msg }}"
+
+ - name: "{{ ansible_failed_task.name }}"
+ ansible.builtin.fail:
+ msg: "{{ ansible_failed_result.msg }}"
+
+# ------- Run SDV --------------------
+ - name: Attempt SDV, if anything fails, update check
+ block:
+ - name: Update GH Check
+ ansible.builtin.include_tasks: ../tasks/update_gh_check.yaml
+ vars:
+ check_status: in_progress
+ check_title: Cloning Security repo
+ check_summary: Cloning Security repo
+
+ - name: Create a temporary directory for processing
+ ansible.builtin.tempfile:
+ path: "/tmp"
+ state: directory
+ prefix: "ibm_security_verification."
+ register: temp_dir
+
+ - name: Set temp dir fact
+ ansible.builtin.set_fact:
+ security_repo_path: "{{ temp_dir.path }}/security"
+
+ - name: Clone the Security metadata repository
+ ansible.builtin.git:
+ repo: https://x-access-token:{{ security_repo_approval_bot_token }}@{{ security_repo_url }}
+ dest: "{{ security_repo_path }}"
+ single_branch: true
+ version: "{{ target_branch }}"
+
+ - name: Delete any existing branch in security repo
+ ansible.builtin.command:
+ cmd: "git branch -D {{ security_repo_new_branch }}"
+ chdir: "{{ security_repo_path }}"
+ ignore_errors: true
+ register: existing_branch_error
+ changed_when: existing_branch_error.rc == 0
+
+ - name: Create new branch in security repo linking to source repository & source branch # noqa: command-instead-of-module
+ ansible.builtin.command:
+ cmd: "git checkout -b {{ security_repo_new_branch }}"
+ chdir: "{{ security_repo_path }}"
+ register: branch_response
+ changed_when: "'Switched to a new branch' in branch_response.stdout"
+
+ - name: Delete the automated directory in security repo, if this is a default branch run
+ ansible.builtin.file:
+ path: "{{ security_repo_path }}/automated"
+ state: absent
+ when: source_repo_branch == target_branch
+
+ - name: Create automated directory in security repo, if it doesn't exist
+ ansible.builtin.file:
+ path: "{{ security_repo_path }}/automated"
+ state: directory
+ mode: "0777"
+
+# ------------ Grabbing data ------------
+
+ - name: Update GH Check
+ ansible.builtin.include_tasks: ../tasks/update_gh_check.yaml
+ vars:
+ check_status: in_progress
+ check_title: Fetching test metadata
+ check_summary: Fetching test metadata
+
+ - name: Grab security metadata from Galasa test run and place into security repo
+ fetch_galasa_security_data:
+ test_report_path: "{{ test_report_path }}"
+ galasa_ecosystem_url: "{{ galasa_ecosystem_url }}"
+ metadata_folder: "{{ security_repo_path }}/automated"
+ environment:
+ GALASA_TOKEN: "{{ galasa_token }}"
+ register: metadata_fetch_result
+
+# ----------- Process new data -----------
+
+ - name: Update GH Check
+ ansible.builtin.include_tasks: ../tasks/update_gh_check.yaml
+ vars:
+ check_status: in_progress
+ check_title: Processing new metadata
+ check_summary: Processing new metadata
+
+ - name: Stage metadata file changes # noqa: command-instead-of-module
+ ansible.builtin.command:
+ cmd: "git add ."
+ chdir: "{{ security_repo_path }}"
+ register: git_add_result
+ changed_when: git_add_result.rc == 0
+
+ - name: Check for changes in security metadata # noqa: command-instead-of-module
+ ansible.builtin.command:
+ cmd: "git diff --cached --exit-code --ignore-space-at-eol -b -w --ignore-blank-lines -G. -U4"
+ chdir: "{{ security_repo_path }}"
+ ignore_errors: true
+ register: git_diff_result
+ changed_when: git_diff_result.rc > 0
+
+# ----------- Approve source check & end, if no changes -----------
+ - name: Update GH Check
+ ansible.builtin.include_tasks: ../tasks/update_gh_check.yaml
+ vars:
+ check_conclusion: success
+ check_title: Security approved
+ check_summary: No security changes were found.
+ when: git_diff_result.rc == 0
+
+ - name: End run, no security changes found.
+ ansible.builtin.meta: end_play
+ when: git_diff_result.rc == 0
+
+# ----------- Security changes found, raise PR -----------
+
+ - name: Update GH Check
+ ansible.builtin.include_tasks: ../tasks/update_gh_check.yaml
+ vars:
+ check_status: in_progress
+ check_title: Deltas found, creating approval...
+ check_summary: Deltas found, creating approval...
+ when: git_diff_result.rc > 0
+
+ - name: Create Pull Request
+ ansible.builtin.include_tasks: ../tasks/create_pull_request.yaml
+ when: git_diff_result.rc > 0
+
+ rescue:
+ - name: Update GH Check
+ ansible.builtin.include_tasks: ../tasks/update_gh_check.yaml
+ vars:
+ check_conclusion: failure
+ check_title: "Failed: {{ ansible_failed_task.name }}"
+ check_summary: "{{ (ansible_failed_result | default({})).msg | default('') }} \
+ {{ (ansible_failed_result | default({})).stderr | default('') }} \
+ {{ (ansible_failed_result | default({})).stdout | default('') }}"
+
+ - name: "{{ ansible_failed_task.name }}"
+ ansible.builtin.fail:
+ msg: "{{ (ansible_failed_result | default({})).msg | default('') }} \
+ {{ (ansible_failed_result | default({})).stderr | default('') }} \
+ {{ (ansible_failed_result | default({})).stdout | default('') }}"
diff --git a/ansible-sdv-pipeline/requirements.txt b/ansible-sdv-pipeline/requirements.txt
new file mode 100644
index 0000000..04f8fbf
--- /dev/null
+++ b/ansible-sdv-pipeline/requirements.txt
@@ -0,0 +1,2 @@
+jmespath
+requests==2.32.3
\ No newline at end of file
diff --git a/ansible-sdv-pipeline/tasks/check_branch_protection.yaml b/ansible-sdv-pipeline/tasks/check_branch_protection.yaml
new file mode 100644
index 0000000..d9bbeae
--- /dev/null
+++ b/ansible-sdv-pipeline/tasks/check_branch_protection.yaml
@@ -0,0 +1,27 @@
+#
+# Copyright IBM Corp. 2024
+#
+
+- name: Obtain branch information for branch {{ target_branch }}
+ ansible.builtin.uri:
+ url: "{{ scm_api_base_url }}/repos/{{ source_repo_owner | urlencode }}/{{ source_repo_name | urlencode }}\
+ /branches/{{ target_branch | urlencode }}"
+ method: GET
+ headers:
+ authorization: "Bearer {{ source_repo_approval_bot_token }}"
+ register: branch_info_result
+
+- name: Handle if check not required on branch {{ target_branch }}
+ when: branch_info_result.json.protection.required_status_checks | json_query(branch_protect_json_query) | length == 0
+ vars:
+ branch_protect_json_query: 'checks[?context == `{{ check_name }}`]'
+ block:
+ - name: "Update check to skipped: {{ check_name }}"
+ ansible.builtin.include_tasks: ../tasks/update_gh_check.yaml
+ vars:
+ check_conclusion: skipped
+ check_title: "{{ check_name }} not required on {{ target_branch }} branch"
+ check_summary: "'{{ check_name }}' is not set as required in the '{{ target_branch }}' branch protection settings. Skipping process."
+
+ - name: End playbook
+ ansible.builtin.meta: end_play
diff --git a/ansible-sdv-pipeline/tasks/create_gh_check.yaml b/ansible-sdv-pipeline/tasks/create_gh_check.yaml
new file mode 100644
index 0000000..ef7348f
--- /dev/null
+++ b/ansible-sdv-pipeline/tasks/create_gh_check.yaml
@@ -0,0 +1,45 @@
+#
+# Copyright IBM Corp. 2024
+#
+
+# Try to get an existing check first, if exists, else create
+- name: Get GitHub check '{{ check_name }}'
+ ansible.builtin.uri:
+ url: "{{ scm_api_base_url }}/repos/{{ source_repo_owner | urlencode }}/{{ source_repo_name | urlencode }}/\
+ commits/{{ source_repo_commit_ref | urlencode }}/check-runs?check_name={{ check_name | urlencode }}"
+ method: GET
+ headers:
+ authorization: "Bearer {{ source_repo_approval_bot_token }}"
+ register: check_run_existing_info
+ ignore_errors: true
+ failed_when: check_run_existing_info.json.check_runs|length == 0
+
+- name: Set check_run_id as fact
+ ansible.builtin.set_fact:
+ check_run_id: "{{ check_run_existing_info.json.check_runs[0].id }}"
+ when: check_run_existing_info is succeeded
+
+- name: Create check
+ when: check_run_existing_info is failed
+ block:
+ - name: Create GitHub check '{{ check_name }}'
+ ansible.builtin.uri:
+ url: "{{ scm_api_base_url }}/repos/{{ source_repo_owner | urlencode }}/{{ source_repo_name | urlencode }}/check-runs"
+ method: POST
+ headers:
+ authorization: "Bearer {{ source_repo_approval_bot_token }}"
+ accept: application/vnd.github+json
+ status_code: [201]
+ body_format: json
+ body:
+ name: "{{ check_name | urlencode }}"
+ head_sha: "{{ source_repo_commit_ref | urlencode }}"
+ status: in_progress
+ output:
+ title: Starting Security checks...
+ summary: Starting Security checks...
+ register: new_check_run_info
+
+ - name: Set check_run_id as fact
+ ansible.builtin.set_fact:
+ check_run_id: "{{ new_check_run_info.json.id }}"
diff --git a/ansible-sdv-pipeline/tasks/create_pull_request.yaml b/ansible-sdv-pipeline/tasks/create_pull_request.yaml
new file mode 100644
index 0000000..6606cbe
--- /dev/null
+++ b/ansible-sdv-pipeline/tasks/create_pull_request.yaml
@@ -0,0 +1,115 @@
+#
+# Copyright IBM Corp. 2024
+#
+
+- name: Check we have a git author set up # noqa: command-instead-of-module
+ ansible.builtin.command:
+ cmd: git config user.name
+ register: git_username
+ ignore_errors: true
+ changed_when: git_username.rc == 0
+
+- name: Add Github App details as author
+ when: git_username.stdout == ""
+ block:
+ - name: Set user name # noqa: command-instead-of-module
+ ansible.builtin.command:
+ cmd: git config --global user.name "{{ github_app_author_name }}"
+ register: username_set
+ changed_when: username_set.rc == 0
+
+ - name: Set user email # noqa: command-instead-of-module
+ ansible.builtin.command:
+ cmd: git config --global user.email {{ github_app_author_email }}
+ register: email_set
+ changed_when: email_set.rc == 0
+
+- name: Create commit with PR link # noqa: command-instead-of-module
+ ansible.builtin.command:
+ cmd: "git commit -m 'update to security from {{ source_repo_owner }}/{{ source_repo_name }}#{{ source_repo_pull_number }}'"
+ chdir: "{{ security_repo_path }}"
+ when: source_repo_pull_number != ""
+ register: commit_result
+ changed_when: commit_result.rc == 0
+
+- name: Create commit for default branch # noqa: command-instead-of-module
+ ansible.builtin.command:
+ cmd: "git commit -m 'update to security on {{ source_repo_owner }}/{{ source_repo_name }} default branch'"
+ chdir: "{{ security_repo_path }}"
+ when: source_repo_pull_number == ""
+ register: commit_result
+ changed_when: commit_result.rc == 0
+
+- name: Update GH Check
+ ansible.builtin.include_tasks: ../tasks/update_gh_check.yaml
+ vars:
+ check_status: in_progress
+ check_title: Creating PR on security repo
+ check_summary: Creating PR on security repo
+
+- name: Push branch # noqa: command-instead-of-module
+ ansible.builtin.command:
+ cmd: "git push --set-upstream origin {{ security_repo_new_branch }} --force"
+ chdir: "{{ security_repo_path }}"
+ register: push_result
+ changed_when: push_result.rc == 0
+
+- name: See if Pull Request already exists
+ ansible.builtin.uri:
+ url: "{{ scm_api_base_url }}/repos/{{ security_repo_owner | urlencode }}/{{ security_repo_name | urlencode }}\
+ /pulls?state=open&base={{ target_branch | urlencode }}&head={{ security_repo_owner | urlencode }}:{{ security_repo_new_branch | urlencode }}"
+ method: GET
+ headers:
+ authorization: "Bearer {{ security_repo_approval_bot_token }}"
+ status_code: [200]
+ body_format: json
+ register: existing_pull_request_info
+
+- name: Create Pull Request
+ ansible.builtin.uri:
+ url: "{{ scm_api_base_url }}/repos/{{ security_repo_owner | urlencode }}/{{ security_repo_name | urlencode }}/pulls"
+ method: POST
+ headers:
+ authorization: "Bearer {{ security_repo_approval_bot_token }}"
+ body_format: json
+ body:
+ title: Security changes in {{ source_repo_owner }}/{{ source_repo_name }}
+ body: |
+ Changes to code have been proven to cause changes in security usage.
+ Please review the security changes in this pull request and either Approve or REJECT.
+
+ Source Org: {{ source_repo_owner }}
+ Source Repo: {{ source_repo_name }}
+ Pull Request: {{ source_repo_owner + '/' + source_repo_name + '#' + source_repo_pull_number
+ if source_repo_pull_number != '' else ' N/A - Changes found on default/release branch' }}
+ Author: {{ '@' + source_repo_pull_author if source_repo_pull_number != '' else ' N/A - Changes found on default/release branch' }}
+ head: "{{ security_repo_new_branch }}"
+ base: "{{ target_branch }}"
+ status_code: [201]
+ register: new_pull_request_info
+ when: existing_pull_request_info.json | length == 0
+
+- name: Rejig variable
+ ansible.builtin.set_fact:
+ pull_request_info: "{{ existing_pull_request_info.json[-1] }}"
+ when: existing_pull_request_info.json | length > 0
+
+- name: Rejig variable
+ ansible.builtin.set_fact:
+ pull_request_info: "{{ new_pull_request_info.json }}"
+ when: new_pull_request_info.json is defined
+
+- name: Print the gateway for each host when defined
+ ansible.builtin.debug:
+ msg: System {{ inventory_hostname }} has gateway {{ ansible_default_ipv4.gateway }}
+ when: ansible_default_ipv4.gateway is defined
+
+- name: Update GH Check
+ ansible.builtin.include_tasks: ../tasks/update_gh_check.yaml
+ vars:
+ check_status: in_progress
+ check_title: Awaiting full approval of security PR
+ check_summary: |
+ The changes in this PR will result in a change of security usage.
+
+ The security changes found are currently awaiting Security approval [here]({{ pull_request_info.html_url }}).
diff --git a/ansible-sdv-pipeline/tasks/update_gh_check.yaml b/ansible-sdv-pipeline/tasks/update_gh_check.yaml
new file mode 100644
index 0000000..cbc85fa
--- /dev/null
+++ b/ansible-sdv-pipeline/tasks/update_gh_check.yaml
@@ -0,0 +1,31 @@
+#
+# Copyright IBM Corp. 2024
+#
+
+- name: Update Check Run to {{ check_title }}
+ ansible.builtin.uri:
+ url: "{{ scm_api_base_url }}/repos/{{ source_repo_owner | urlencode }}/{{ source_repo_name | urlencode }}/check-runs/{{ check_run_id | urlencode }}"
+ method: PATCH
+ headers:
+ authorization: "Bearer {{ source_repo_approval_bot_token }}"
+ body_format: json
+ body:
+ status: "{{ check_status }}"
+ output:
+ title: "{{ check_title }}"
+ summary: "{{ check_summary }}"
+ when: check_status is defined
+
+- name: Update Check Run to {{ check_title }}
+ ansible.builtin.uri:
+ url: "{{ scm_api_base_url }}/repos/{{ source_repo_owner | urlencode }}/{{ source_repo_name | urlencode }}/check-runs/{{ check_run_id | urlencode }}"
+ method: PATCH
+ headers:
+ authorization: "Bearer {{ source_repo_approval_bot_token }}"
+ body_format: json
+ body:
+ conclusion: "{{ check_conclusion }}"
+ output:
+ title: "{{ check_title }}"
+ summary: "{{ check_summary }}"
+ when: check_conclusion is defined
diff --git a/app.yml b/app.yml
new file mode 100644
index 0000000..52370f4
--- /dev/null
+++ b/app.yml
@@ -0,0 +1,40 @@
+# This is a GitHub App Manifest. These settings will be used by default when
+# initially configuring your GitHub App.
+#
+# NOTE: changing this file will not update your GitHub App settings.
+# You must visit github.com/settings/apps/your-app-name to edit them.
+
+# The list of events the GitHub App subscribes to.
+# Uncomment the event names below to enable them.
+default_events:
+ - check_run
+ - delete
+ - pull_request
+ - pull_request_review
+ - status
+
+# The set of permissions needed by the GitHub App. The format of the object uses
+# the permission name for the key (for example, issues) and the access type for
+# the value (for example, write).
+# Valid values are `read`, `write`, and `none`
+default_permissions:
+
+ # Checks on code.
+ # https://developer.github.com/v3/apps/permissions/#permission-on-checks
+ checks: write
+
+ # Repository contents, commits, branches, downloads, releases, and merges.
+ # https://developer.github.com/v3/apps/permissions/#permission-on-contents
+ contents: write
+
+ # Search repositories, list collaborators, and access repository metadata.
+ # https://developer.github.com/v3/apps/permissions/#metadata-permissions
+ metadata: read
+
+ # Pull requests and related comments, assignees, labels, milestones, and merges.
+ # https://developer.github.com/v3/apps/permissions/#permission-on-pull-requests
+ pull_requests: write
+
+ # Commit statuses.
+ # https://developer.github.com/v3/apps/permissions/#permission-on-statuses
+ statuses: write
diff --git a/commitlint.config.js b/commitlint.config.js
new file mode 100644
index 0000000..d900335
--- /dev/null
+++ b/commitlint.config.js
@@ -0,0 +1,9 @@
+module.exports = {
+ extends: [
+ '@commitlint/config-conventional'
+ ],
+ rules: {
+ 'body-max-line-length': [0, 'always', 'Infinity'],
+ 'footer-max-line-length': [0, 'always', 'Infinity']
+ }
+};
diff --git a/docs/.eslintrc.json b/docs/.eslintrc.json
new file mode 100644
index 0000000..bffb357
--- /dev/null
+++ b/docs/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "next/core-web-vitals"
+}
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 0000000..a2b8d8d
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,37 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+node_modules
+.pnp
+.pnp.js
+.yarn/install-state.gz
+
+# testing
+/coverage
+
+# next.js
+.next
+**/.next
+out/
+
+# production
+build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..892f89a
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,15 @@
+# SDV Documentation
+
+This documentation is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
+
+## Getting Started
+
+First, run the development server:
+
+```bash
+npm run dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+You can start editing the page by modifying `src/app/page.js`. The page auto-updates as you edit the file.
diff --git a/docs/jsconfig.json b/docs/jsconfig.json
new file mode 100644
index 0000000..b8d6842
--- /dev/null
+++ b/docs/jsconfig.json
@@ -0,0 +1,7 @@
+{
+ "compilerOptions": {
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ }
+}
diff --git a/docs/next.config.mjs b/docs/next.config.mjs
new file mode 100644
index 0000000..2acd6d5
--- /dev/null
+++ b/docs/next.config.mjs
@@ -0,0 +1,12 @@
+/** @type {import('next').NextConfig} */
+
+const isProd = process.env.NODE_ENV === 'production';
+
+const nextConfig = {
+ output: "export",
+ basePath: isProd ? "/dummyNodeProj" : '',
+ reactStrictMode: true,
+ images: { unoptimized: true }
+};
+
+export default nextConfig;
diff --git a/docs/package-lock.json b/docs/package-lock.json
new file mode 100644
index 0000000..ca3905a
--- /dev/null
+++ b/docs/package-lock.json
@@ -0,0 +1,4788 @@
+{
+ "name": "docs",
+ "version": "0.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "docs",
+ "version": "0.1.0",
+ "dependencies": {
+ "@carbon/icons-react": "^11.45.0",
+ "@carbon/pictograms-react": "^11.63.0",
+ "@carbon/react": "^1.62.0",
+ "next": "14.2.5",
+ "react": "^18",
+ "react-dom": "^18",
+ "sass": "^1.77.8"
+ },
+ "devDependencies": {
+ "eslint": "^8",
+ "eslint-config-next": "14.2.5"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.24.8",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz",
+ "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==",
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@carbon/colors": {
+ "version": "11.23.0",
+ "resolved": "https://registry.npmjs.org/@carbon/colors/-/colors-11.23.0.tgz",
+ "integrity": "sha512-xXcD064+JPk/tFRN3e3UAOHYpayo9Z6MMcHTt2Vb4U5/+6UUxaDReMPnSL+UNSrf75d4epomB+GrpN0tbmgMCA==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@ibm/telemetry-js": "^1.5.0"
+ }
+ },
+ "node_modules/@carbon/feature-flags": {
+ "version": "0.20.0",
+ "resolved": "https://registry.npmjs.org/@carbon/feature-flags/-/feature-flags-0.20.0.tgz",
+ "integrity": "sha512-OEYrazJa0nEEHbBDyarXIz6kjWgqsJggjbNAcVOxx0Nvma1nZBd+SwXKwdbMkBZagSSC816dV12oZJtr+GIZZg==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@ibm/telemetry-js": "^1.5.0"
+ }
+ },
+ "node_modules/@carbon/grid": {
+ "version": "11.24.0",
+ "resolved": "https://registry.npmjs.org/@carbon/grid/-/grid-11.24.0.tgz",
+ "integrity": "sha512-1HYS5FhLqLBBsmHA/oWikRXVq0C639DUZf0VGw+Dl7Nl7UasHDzFkErN0W3pNyMXPVr/rxSZV3ihJJTBsgVuhg==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@carbon/layout": "^11.23.0",
+ "@ibm/telemetry-js": "^1.5.0"
+ }
+ },
+ "node_modules/@carbon/icon-helpers": {
+ "version": "10.49.0",
+ "resolved": "https://registry.npmjs.org/@carbon/icon-helpers/-/icon-helpers-10.49.0.tgz",
+ "integrity": "sha512-GSx22ch7ahJ3u/7ZRIykeO8h/uBx3Qruybz3VYi5JBIM+smHDLldXRpJTQk65JsXuSiPWWGepIb1FlhV99fgtw==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@ibm/telemetry-js": "^1.5.0"
+ }
+ },
+ "node_modules/@carbon/icons-react": {
+ "version": "11.45.0",
+ "resolved": "https://registry.npmjs.org/@carbon/icons-react/-/icons-react-11.45.0.tgz",
+ "integrity": "sha512-QTf+K4BT4Vn2e9c5HDZGqTOztVOXG+4k2dAxDgAyg+18zif/kJsZKPnaFJsthxVezzELJ9cbmlXC0acbiE/zjA==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@carbon/icon-helpers": "^10.49.0",
+ "@ibm/telemetry-js": "^1.5.0",
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "react": ">=16"
+ }
+ },
+ "node_modules/@carbon/layout": {
+ "version": "11.23.0",
+ "resolved": "https://registry.npmjs.org/@carbon/layout/-/layout-11.23.0.tgz",
+ "integrity": "sha512-7YFTFG9mqtvFp67h+qO2z2BG7QmbHc0jVgUevwtOHSCdVHRwhYqEFNGCCE4+MhMHetUjl/z3ut4rNfHleoyOWg==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@ibm/telemetry-js": "^1.5.0"
+ }
+ },
+ "node_modules/@carbon/motion": {
+ "version": "11.19.0",
+ "resolved": "https://registry.npmjs.org/@carbon/motion/-/motion-11.19.0.tgz",
+ "integrity": "sha512-lv8uBNbpciul9vBEOiFsGBkNsJJdfLEcQUFpiK2YyAtpkM4pD6uSw2kb4Pi+mx3htKfqH0/GS4iEtCUXf92w0Q==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@ibm/telemetry-js": "^1.5.0"
+ }
+ },
+ "node_modules/@carbon/pictograms-react": {
+ "version": "11.63.0",
+ "resolved": "https://registry.npmjs.org/@carbon/pictograms-react/-/pictograms-react-11.63.0.tgz",
+ "integrity": "sha512-porl/+MlRTcWNuk/mtGFbSb+WQZyfYb0opGxT2Pa0XgnSVhEOvANK9J60F427sHrifPbq7VhlJYZtKvkO220AA==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@carbon/icon-helpers": "^10.49.0",
+ "@ibm/telemetry-js": "^1.5.0",
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "react": ">=16"
+ }
+ },
+ "node_modules/@carbon/react": {
+ "version": "1.62.0",
+ "resolved": "https://registry.npmjs.org/@carbon/react/-/react-1.62.0.tgz",
+ "integrity": "sha512-vhN+Oz59ir4oF+MufuMOeTRxIAFcvoW/ExwLQ1bhyDbEImtz5ZD/iE4xVJ0uDfNH1pWLrSDXv5+Ft2ACw+lFww==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "@carbon/feature-flags": "^0.20.0",
+ "@carbon/icons-react": "^11.45.0",
+ "@carbon/layout": "^11.23.0",
+ "@carbon/styles": "^1.61.0",
+ "@floating-ui/react": "^0.26.0",
+ "@ibm/telemetry-js": "^1.5.0",
+ "classnames": "2.5.1",
+ "copy-to-clipboard": "^3.3.1",
+ "downshift": "8.5.0",
+ "flatpickr": "4.6.13",
+ "invariant": "^2.2.3",
+ "lodash.debounce": "^4.0.8",
+ "lodash.findlast": "^4.5.0",
+ "lodash.isequal": "^4.5.0",
+ "lodash.omit": "^4.5.0",
+ "lodash.throttle": "^4.1.1",
+ "prop-types": "^15.7.2",
+ "react-is": "^18.2.0",
+ "tabbable": "^6.2.0",
+ "use-resize-observer": "^6.0.0",
+ "window-or-global": "^1.0.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.6 || ^17.0.1 || ^18.2.0",
+ "react-dom": "^16.8.6 || ^17.0.1 || ^18.2.0",
+ "sass": "^1.33.0"
+ }
+ },
+ "node_modules/@carbon/react/node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
+ },
+ "node_modules/@carbon/styles": {
+ "version": "1.61.0",
+ "resolved": "https://registry.npmjs.org/@carbon/styles/-/styles-1.61.0.tgz",
+ "integrity": "sha512-9FPbAm7SySP8ktTMX+y8rW0/uSLV2n47E2vKAoAPN+CXIPMVkqZM/Ns/+UVuiBHjhTsVqKe4zEVCKAw25BqdRw==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@carbon/colors": "^11.23.0",
+ "@carbon/feature-flags": "^0.20.0",
+ "@carbon/grid": "^11.24.0",
+ "@carbon/layout": "^11.23.0",
+ "@carbon/motion": "^11.19.0",
+ "@carbon/themes": "^11.37.0",
+ "@carbon/type": "^11.28.0",
+ "@ibm/plex": "6.0.0-next.6",
+ "@ibm/telemetry-js": "^1.5.0"
+ },
+ "peerDependencies": {
+ "sass": "^1.33.0"
+ },
+ "peerDependenciesMeta": {
+ "sass": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@carbon/themes": {
+ "version": "11.37.0",
+ "resolved": "https://registry.npmjs.org/@carbon/themes/-/themes-11.37.0.tgz",
+ "integrity": "sha512-nGsU4x13190Mrm1beb6Oy9Vacv9NNKhRSX/9DYXa6uB9anMy14vzZMLBZ5L1ubL6Eh8GRD06y7TO9lq2xqEkvw==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@carbon/colors": "^11.23.0",
+ "@carbon/layout": "^11.23.0",
+ "@carbon/type": "^11.28.0",
+ "@ibm/telemetry-js": "^1.5.0",
+ "color": "^4.0.0"
+ }
+ },
+ "node_modules/@carbon/type": {
+ "version": "11.28.0",
+ "resolved": "https://registry.npmjs.org/@carbon/type/-/type-11.28.0.tgz",
+ "integrity": "sha512-c0iJXuZgsCr8WARe8h3aMzdYuxM7pW81b+j6AP2Ra2n+/13jK0zlDLLel4pp3U0UAd/qSrlk6PKlwVLH76eLEg==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@carbon/grid": "^11.24.0",
+ "@carbon/layout": "^11.23.0",
+ "@ibm/telemetry-js": "^1.5.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz",
+ "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@floating-ui/core": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.4.tgz",
+ "integrity": "sha512-a4IowK4QkXl4SCWTGUR0INAfEOX3wtsYw3rKK5InQEHMGObkR8Xk44qYQD9P4r6HHw0iIfK6GUKECmY8sTkqRA==",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.4"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.7.tgz",
+ "integrity": "sha512-wmVfPG5o2xnKDU4jx/m4w5qva9FWHcnZ8BvzEe90D/RpwsJaTAVYPEPdQ8sbr/N8zZTAHlZUTQdqg8ZUbzHmng==",
+ "dependencies": {
+ "@floating-ui/core": "^1.6.0",
+ "@floating-ui/utils": "^0.2.4"
+ }
+ },
+ "node_modules/@floating-ui/react": {
+ "version": "0.26.19",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.19.tgz",
+ "integrity": "sha512-Jk6zITdjjIvjO/VdQFvpRaD3qPwOHH6AoDHxjhpy+oK4KFgaSP871HYWUAPdnLmx1gQ+w/pB312co3tVml+BXA==",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.1.1",
+ "@floating-ui/utils": "^0.2.4",
+ "tabbable": "^6.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz",
+ "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==",
+ "dependencies": {
+ "@floating-ui/dom": "^1.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz",
+ "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA=="
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.14",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+ "deprecated": "Use @eslint/config-array instead",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.2",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "deprecated": "Use @eslint/object-schema instead",
+ "dev": true
+ },
+ "node_modules/@ibm/plex": {
+ "version": "6.0.0-next.6",
+ "resolved": "https://registry.npmjs.org/@ibm/plex/-/plex-6.0.0-next.6.tgz",
+ "integrity": "sha512-B3uGruTn2rS5gweynLmfSe7yCawSRsJguJJQHVQiqf4rh2RNgJFu8YLE2Zd/JHV0ZXoVMOslcXP2k3hMkxKEyA==",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@ibm/telemetry-js": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@ibm/telemetry-js/-/telemetry-js-1.6.0.tgz",
+ "integrity": "sha512-XXdsXhoZwKaJ1/24w/uCqx/YeDQeTu8SAl+7bHQxn62yiFUQ6/D20HhpQVdlG9/Jpv3nYJHFiDH0vGkQbXNFWg==",
+ "bin": {
+ "ibmtelemetry": "dist/collect.js"
+ }
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@next/env": {
+ "version": "14.2.5",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.5.tgz",
+ "integrity": "sha512-/zZGkrTOsraVfYjGP8uM0p6r0BDT6xWpkjdVbcz66PJVSpwXX3yNiRycxAuDfBKGWBrZBXRuK/YVlkNgxHGwmA=="
+ },
+ "node_modules/@next/eslint-plugin-next": {
+ "version": "14.2.5",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.5.tgz",
+ "integrity": "sha512-LY3btOpPh+OTIpviNojDpUdIbHW9j0JBYBjsIp8IxtDFfYFyORvw3yNq6N231FVqQA7n7lwaf7xHbVJlA1ED7g==",
+ "dev": true,
+ "dependencies": {
+ "glob": "10.3.10"
+ }
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "14.2.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.5.tgz",
+ "integrity": "sha512-/9zVxJ+K9lrzSGli1///ujyRfon/ZneeZ+v4ptpiPoOU+GKZnm8Wj8ELWU1Pm7GHltYRBklmXMTUqM/DqQ99FQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "14.2.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.5.tgz",
+ "integrity": "sha512-vXHOPCwfDe9qLDuq7U1OYM2wUY+KQ4Ex6ozwsKxp26BlJ6XXbHleOUldenM67JRyBfVjv371oneEvYd3H2gNSA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "14.2.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.5.tgz",
+ "integrity": "sha512-vlhB8wI+lj8q1ExFW8lbWutA4M2ZazQNvMWuEDqZcuJJc78iUnLdPPunBPX8rC4IgT6lIx/adB+Cwrl99MzNaA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "14.2.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.5.tgz",
+ "integrity": "sha512-NpDB9NUR2t0hXzJJwQSGu1IAOYybsfeB+LxpGsXrRIb7QOrYmidJz3shzY8cM6+rO4Aojuef0N/PEaX18pi9OA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "14.2.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.5.tgz",
+ "integrity": "sha512-8XFikMSxWleYNryWIjiCX+gU201YS+erTUidKdyOVYi5qUQo/gRxv/3N1oZFCgqpesN6FPeqGM72Zve+nReVXQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "14.2.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.5.tgz",
+ "integrity": "sha512-6QLwi7RaYiQDcRDSU/os40r5o06b5ue7Jsk5JgdRBGGp8l37RZEh9JsLSM8QF0YDsgcosSeHjglgqi25+m04IQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "14.2.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.5.tgz",
+ "integrity": "sha512-1GpG2VhbspO+aYoMOQPQiqc/tG3LzmsdBH0LhnDS3JrtDx2QmzXe0B6mSZZiN3Bq7IOMXxv1nlsjzoS1+9mzZw==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-ia32-msvc": {
+ "version": "14.2.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.5.tgz",
+ "integrity": "sha512-Igh9ZlxwvCDsu6438FXlQTHlRno4gFpJzqPjSIBZooD22tKeI4fE/YMRoHVJHmrQ2P5YL1DoZ0qaOKkbeFWeMg==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-x64-msvc": {
+ "version": "14.2.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.5.tgz",
+ "integrity": "sha512-tEQ7oinq1/CjSG9uSTerca3v4AZ+dFa+4Yu6ihaG8Ud8ddqLQgFGcnwYls13H5X5CPDPZJdYxyeMui6muOLd4g==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@rushstack/eslint-patch": {
+ "version": "1.10.3",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz",
+ "integrity": "sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==",
+ "dev": true
+ },
+ "node_modules/@swc/counter": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz",
+ "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==",
+ "dependencies": {
+ "@swc/counter": "^0.1.3",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz",
+ "integrity": "sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "7.2.0",
+ "@typescript-eslint/types": "7.2.0",
+ "@typescript-eslint/typescript-estree": "7.2.0",
+ "@typescript-eslint/visitor-keys": "7.2.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz",
+ "integrity": "sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.2.0",
+ "@typescript-eslint/visitor-keys": "7.2.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.2.0.tgz",
+ "integrity": "sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==",
+ "dev": true,
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz",
+ "integrity": "sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.2.0",
+ "@typescript-eslint/visitor-keys": "7.2.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "9.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz",
+ "integrity": "sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.2.0",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+ "dev": true
+ },
+ "node_modules/acorn": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
+ "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/aria-query": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz",
+ "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==",
+ "dev": true,
+ "dependencies": {
+ "deep-equal": "^2.0.5"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
+ "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz",
+ "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array.prototype.findlast": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
+ "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz",
+ "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
+ "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
+ "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.tosorted": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
+ "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3",
+ "es-errors": "^1.3.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz",
+ "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ast-types-flow": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
+ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
+ "dev": true
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/axe-core": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz",
+ "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz",
+ "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==",
+ "dev": true,
+ "dependencies": {
+ "deep-equal": "^2.0.5"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dependencies": {
+ "streamsearch": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001642",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz",
+ "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/classnames": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
+ },
+ "node_modules/client-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
+ },
+ "node_modules/color": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
+ "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
+ "dependencies": {
+ "color-convert": "^2.0.1",
+ "color-string": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=12.5.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "node_modules/compute-scroll-into-view": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz",
+ "integrity": "sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg=="
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/copy-to-clipboard": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
+ "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==",
+ "dependencies": {
+ "toggle-selection": "^1.0.6"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/damerau-levenshtein": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+ "dev": true
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
+ "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz",
+ "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz",
+ "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.5",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
+ "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-equal": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz",
+ "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "call-bind": "^1.0.5",
+ "es-get-iterator": "^1.1.3",
+ "get-intrinsic": "^1.2.2",
+ "is-arguments": "^1.1.1",
+ "is-array-buffer": "^3.0.2",
+ "is-date-object": "^1.0.5",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "isarray": "^2.0.5",
+ "object-is": "^1.1.5",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.5.1",
+ "side-channel": "^1.0.4",
+ "which-boxed-primitive": "^1.0.2",
+ "which-collection": "^1.0.1",
+ "which-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/downshift": {
+ "version": "8.5.0",
+ "resolved": "https://registry.npmjs.org/downshift/-/downshift-8.5.0.tgz",
+ "integrity": "sha512-BAr/KAZX8GGARwWl4aER6ABv8aAaRXZcVKP0m1oFPKpSIXCGuoqnhi6nRf87glHhYDd/CCPp9RVUK27JKJD/Fw==",
+ "dependencies": {
+ "@babel/runtime": "^7.22.15",
+ "compute-scroll-into-view": "^3.0.3",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0",
+ "tslib": "^2.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.12.0"
+ }
+ },
+ "node_modules/downshift/node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz",
+ "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.23.3",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz",
+ "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==",
+ "dev": true,
+ "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.8",
+ "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.6",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.15"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-get-iterator": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
+ "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.3",
+ "has-symbols": "^1.0.3",
+ "is-arguments": "^1.1.1",
+ "is-map": "^2.0.2",
+ "is-set": "^2.0.2",
+ "is-string": "^1.0.7",
+ "isarray": "^2.0.5",
+ "stop-iteration-iterator": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-iterator-helpers": {
+ "version": "1.0.19",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz",
+ "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
+ "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
+ "dev": true,
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz",
+ "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.4",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
+ "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
+ "dev": true,
+ "dependencies": {
+ "hasown": "^2.0.0"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
+ "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-next": {
+ "version": "14.2.5",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.5.tgz",
+ "integrity": "sha512-zogs9zlOiZ7ka+wgUnmcM0KBEDjo4Jis7kxN1jvC0N4wynQ2MIx/KBkg4mVF63J5EK4W0QMCn7xO3vNisjaAoA==",
+ "dev": true,
+ "dependencies": {
+ "@next/eslint-plugin-next": "14.2.5",
+ "@rushstack/eslint-patch": "^1.3.3",
+ "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-import-resolver-typescript": "^3.5.2",
+ "eslint-plugin-import": "^2.28.1",
+ "eslint-plugin-jsx-a11y": "^6.7.1",
+ "eslint-plugin-react": "^7.33.2",
+ "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705"
+ },
+ "peerDependencies": {
+ "eslint": "^7.23.0 || ^8.0.0",
+ "typescript": ">=3.3.1"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
+ "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.13.0",
+ "resolve": "^1.22.4"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-import-resolver-typescript": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz",
+ "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.3.4",
+ "enhanced-resolve": "^5.12.0",
+ "eslint-module-utils": "^2.7.4",
+ "fast-glob": "^3.3.1",
+ "get-tsconfig": "^4.5.0",
+ "is-core-module": "^2.11.0",
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts"
+ },
+ "peerDependencies": {
+ "eslint": "*",
+ "eslint-plugin-import": "*"
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz",
+ "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.29.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz",
+ "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.7",
+ "array.prototype.findlastindex": "^1.2.3",
+ "array.prototype.flat": "^1.3.2",
+ "array.prototype.flatmap": "^1.3.2",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "eslint-module-utils": "^2.8.0",
+ "hasown": "^2.0.0",
+ "is-core-module": "^2.13.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.7",
+ "object.groupby": "^1.0.1",
+ "object.values": "^1.1.7",
+ "semver": "^6.3.1",
+ "tsconfig-paths": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-jsx-a11y": {
+ "version": "6.9.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz",
+ "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==",
+ "dev": true,
+ "dependencies": {
+ "aria-query": "~5.1.3",
+ "array-includes": "^3.1.8",
+ "array.prototype.flatmap": "^1.3.2",
+ "ast-types-flow": "^0.0.8",
+ "axe-core": "^4.9.1",
+ "axobject-query": "~3.1.1",
+ "damerau-levenshtein": "^1.0.8",
+ "emoji-regex": "^9.2.2",
+ "es-iterator-helpers": "^1.0.19",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^3.3.5",
+ "language-tags": "^1.0.9",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "safe-regex-test": "^1.0.3",
+ "string.prototype.includes": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-react": {
+ "version": "7.35.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz",
+ "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.8",
+ "array.prototype.findlast": "^1.2.5",
+ "array.prototype.flatmap": "^1.3.2",
+ "array.prototype.tosorted": "^1.1.4",
+ "doctrine": "^2.1.0",
+ "es-iterator-helpers": "^1.0.19",
+ "estraverse": "^5.3.0",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.8",
+ "object.fromentries": "^2.0.8",
+ "object.values": "^1.2.0",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.5",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.11",
+ "string.prototype.repeat": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz",
+ "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/resolve": {
+ "version": "2.0.0-next.5",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
+ "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatpickr": {
+ "version": "4.6.13",
+ "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz",
+ "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw=="
+ },
+ "node_modules/flatted": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
+ "dev": true
+ },
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz",
+ "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
+ "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "functions-have-names": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz",
+ "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-tsconfig": {
+ "version": "4.7.6",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz",
+ "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==",
+ "dev": true,
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
+ "node_modules/glob": {
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.5",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/glob/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dev": true,
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+ "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/immutable": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz",
+ "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ=="
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/internal-slot": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
+ "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==",
+ "dev": true,
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.0",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "dependencies": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "node_modules/is-arguments": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+ "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
+ "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
+ },
+ "node_modules/is-async-function": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
+ "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.15.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz",
+ "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==",
+ "dev": true,
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz",
+ "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==",
+ "dev": true,
+ "dependencies": {
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-finalizationregistry": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz",
+ "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-set": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz",
+ "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==",
+ "dev": true,
+ "dependencies": {
+ "which-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakmap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakset": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz",
+ "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/iterator.prototype": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
+ "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==",
+ "dev": true,
+ "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"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+ "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+ "dev": true,
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/language-subtag-registry": {
+ "version": "0.3.23",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
+ "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==",
+ "dev": true
+ },
+ "node_modules/language-tags": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
+ "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
+ "dev": true,
+ "dependencies": {
+ "language-subtag-registry": "^0.3.20"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
+ },
+ "node_modules/lodash.findlast": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.findlast/-/lodash.findlast-4.6.0.tgz",
+ "integrity": "sha512-+OGwb1FVKjhc2aIEQ9vKqNDW1a0/HaCLr0iCIK10jfVif3dBE0nhQD0jOZNZLh7zOlmFUTrk+vt85eXoH4vKuA=="
+ },
+ "node_modules/lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/lodash.omit": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz",
+ "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg=="
+ },
+ "node_modules/lodash.throttle": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
+ "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
+ "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/next": {
+ "version": "14.2.5",
+ "resolved": "https://registry.npmjs.org/next/-/next-14.2.5.tgz",
+ "integrity": "sha512-0f8aRfBVL+mpzfBjYfQuLWh2WyAwtJXCRfkPF4UJ5qd2YwrHczsrSzXU4tRMV0OAxR8ZJZWPFn6uhSC56UTsLA==",
+ "dependencies": {
+ "@next/env": "14.2.5",
+ "@swc/helpers": "0.5.5",
+ "busboy": "1.6.0",
+ "caniuse-lite": "^1.0.30001579",
+ "graceful-fs": "^4.2.11",
+ "postcss": "8.4.31",
+ "styled-jsx": "5.1.1"
+ },
+ "bin": {
+ "next": "dist/bin/next"
+ },
+ "engines": {
+ "node": ">=18.17.0"
+ },
+ "optionalDependencies": {
+ "@next/swc-darwin-arm64": "14.2.5",
+ "@next/swc-darwin-x64": "14.2.5",
+ "@next/swc-linux-arm64-gnu": "14.2.5",
+ "@next/swc-linux-arm64-musl": "14.2.5",
+ "@next/swc-linux-x64-gnu": "14.2.5",
+ "@next/swc-linux-x64-musl": "14.2.5",
+ "@next/swc-win32-arm64-msvc": "14.2.5",
+ "@next/swc-win32-ia32-msvc": "14.2.5",
+ "@next/swc-win32-x64-msvc": "14.2.5"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.1.0",
+ "@playwright/test": "^1.41.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "sass": "^1.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@playwright/test": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
+ "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-is": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
+ "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
+ "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz",
+ "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
+ "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.groupby": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
+ "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz",
+ "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
+ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew=="
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/possible-typed-array-names": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
+ "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/reflect.getprototypeof": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
+ "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.1",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "globalthis": "^1.0.3",
+ "which-builtin-type": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
+ "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "set-function-name": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resize-observer-polyfill": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+ "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rimraf/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz",
+ "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "get-intrinsic": "^1.2.4",
+ "has-symbols": "^1.0.3",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz",
+ "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.1.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/sass": {
+ "version": "1.77.8",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz",
+ "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==",
+ "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"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+ "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
+ "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stop-iteration-iterator": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
+ "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==",
+ "dev": true,
+ "dependencies": {
+ "internal-slot": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/string-width/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/string-width/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/string.prototype.includes": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz",
+ "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz",
+ "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.repeat": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
+ "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz",
+ "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz",
+ "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/styled-jsx": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
+ "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
+ "dependencies": {
+ "client-only": "0.0.1"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tabbable": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
+ "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
+ },
+ "node_modules/tapable": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toggle-selection": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
+ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
+ },
+ "node_modules/ts-api-utils": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
+ "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
+ "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
+ "dev": true,
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz",
+ "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz",
+ "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz",
+ "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
+ "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/use-resize-observer": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-6.1.0.tgz",
+ "integrity": "sha512-SiPcWHiIQ1CnHmb6PxbYtygqiZXR0U9dNkkbpX9VYnlstUwF8+QqpUTrzh13pjPwcjMVGR+QIC+nvF5ujfFNng==",
+ "dependencies": {
+ "resize-observer-polyfill": "^1.5.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-builtin-type": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz",
+ "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+ "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+ "dev": true,
+ "dependencies": {
+ "is-map": "^2.0.3",
+ "is-set": "^2.0.3",
+ "is-weakmap": "^2.0.2",
+ "is-weakset": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz",
+ "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/window-or-global": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/window-or-global/-/window-or-global-1.0.1.tgz",
+ "integrity": "sha512-tE12J/NenOv4xdVobD+AD3fT06T4KNqnzRhkv5nBIu7K+pvOH2oLCEgYP+i+5mF2jtI6FEADheOdZkA8YWET9w=="
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/docs/package.json b/docs/package.json
new file mode 100644
index 0000000..b3a3c13
--- /dev/null
+++ b/docs/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "docs",
+ "version": "0.1.0",
+ "homepage": "https://Mark-J-Lawrence.github.io/DummyNodeProj",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "NODE_ENV=production next build",
+ "start": "next start",
+ "lint": "next lint ./src"
+ },
+ "dependencies": {
+ "@carbon/icons-react": "^11.45.0",
+ "@carbon/pictograms-react": "^11.63.0",
+ "@carbon/react": "^1.62.0",
+ "next": "14.2.5",
+ "react": "^18",
+ "react-dom": "^18",
+ "sass": "^1.77.8"
+ },
+ "devDependencies": {
+ "eslint": "^8",
+ "eslint-config-next": "14.2.5"
+ }
+}
diff --git a/docs/src/app/components/Info/Info.js b/docs/src/app/components/Info/Info.js
new file mode 100644
index 0000000..e2be918
--- /dev/null
+++ b/docs/src/app/components/Info/Info.js
@@ -0,0 +1,36 @@
+import { Grid, Column } from '@carbon/react';
+
+// Take in a phrase and separate the third word in an array
+function createArrayFromPhrase(phrase) {
+ const splitPhrase = phrase.split(' ');
+ const thirdWord = splitPhrase.pop();
+ return [splitPhrase.join(' '), thirdWord];
+}
+
+const InfoSection = (props) => (
+
+
+ {props.heading}
+
+ {props.children}
+
+);
+
+const InfoCard = (props) => {
+ const splitHeading = createArrayFromPhrase(props.heading);
+
+ return (
+
+
+
+ {`${splitHeading[0]} `}
+ {splitHeading[1]}
+
+
{props.body}
+
+ {props.icon()}
+
+ );
+};
+
+export { InfoSection, InfoCard };
diff --git a/docs/src/app/components/Info/_info.scss b/docs/src/app/components/Info/_info.scss
new file mode 100644
index 0000000..518027b
--- /dev/null
+++ b/docs/src/app/components/Info/_info.scss
@@ -0,0 +1,86 @@
+@use '@carbon/react/scss/type' as *;
+@use '@carbon/react/scss/spacing' as *;
+@use '@carbon/react/scss/breakpoint' as *;
+@use '@carbon/react/scss/theme' as *;
+
+.info-section__heading {
+ @include type-style('heading-01');
+ padding-bottom: $spacing-08;
+}
+
+.info-card {
+ margin-top: $spacing-09;
+ display: flex;
+ flex-direction: column;
+ padding-left: 1rem;
+
+ svg {
+ margin-top: $spacing-09;
+ }
+
+ @include breakpoint(sm) {
+ padding-left: 0;
+ }
+
+ div {
+ flex-grow: 1; // fill space so icons are bottom aligned
+ }
+
+ // top border in only small breakpoints to prevent overrides
+ @include breakpoint-down(lg) {
+ padding-left: 0;
+ margin-top: 0;
+ flex-direction: row-reverse;
+
+ &:not(:nth-child(2)) {
+ padding-top: $spacing-10;
+ }
+
+ svg {
+ margin-top: -0.25rem;
+ margin-right: 2rem;
+ min-width: 48px;
+ min-height: 48px;
+ }
+ }
+
+ @include breakpoint(lg) {
+ margin-top: 0;
+ padding-left: 0;
+
+ &:not(:nth-child(2)) {
+ border-left: 1px solid $border-subtle-01;
+ padding-left: 1rem;
+ }
+
+ svg {
+ margin-top: $spacing-12;
+ }
+ }
+
+ // left border in all items
+ @include breakpoint(xlg) {
+ margin-top: 0;
+ border-left: 1px solid $border-subtle-01;
+ padding-left: 1rem;
+
+ svg {
+ margin-top: $spacing-12;
+ }
+ }
+}
+
+.info-card__heading {
+ @include type-style('productive-heading-03');
+}
+
+.info-card__body {
+ margin-top: $spacing-06;
+ flex-grow: 1; // fill space so pictograms are bottom aligned
+ @include type-style('body-long-01');
+
+ // prevent large line lengths between small and medium viewports
+ @include breakpoint-between(321px, md) {
+ max-width: 75%;
+ }
+}
\ No newline at end of file
diff --git a/docs/src/app/components/SdvHeader/SdvHeader.js b/docs/src/app/components/SdvHeader/SdvHeader.js
new file mode 100644
index 0000000..b221d98
--- /dev/null
+++ b/docs/src/app/components/SdvHeader/SdvHeader.js
@@ -0,0 +1,96 @@
+import {
+ Header,
+ HeaderContainer,
+ HeaderName,
+ HeaderNavigation,
+ HeaderMenuButton,
+ HeaderMenuItem,
+ HeaderGlobalBar,
+ HeaderGlobalAction,
+ SkipToContent,
+ SideNav,
+ SideNavItems,
+ HeaderSideNavItems,
+} from '@carbon/react';
+
+import Link from 'next/link';
+
+import { Switcher, Notification, UserAvatar } from '@carbon/icons-react';
+
+const SdvHeader = () => (
+ (
+
+
+ {/* */}
+
+
+ CICS TS
+
+
+
+ {/*
+
+ Problem
+
+
+ Concepts
+
+
+ Demo
+
+
+ How
+
+ */}
+ {/*
+
+
+
+ Problem
+
+
+ Concepts
+
+
+ Demo
+
+
+ How
+
+
+
+ */}
+ {/*
+
+
+
+
+
+
+
+
+
+ */}
+
+ )}
+ />
+);
+
+export default SdvHeader;
\ No newline at end of file
diff --git a/docs/src/app/components/SdvHeader/sdv-header.scss b/docs/src/app/components/SdvHeader/sdv-header.scss
new file mode 100644
index 0000000..c568065
--- /dev/null
+++ b/docs/src/app/components/SdvHeader/sdv-header.scss
@@ -0,0 +1,18 @@
+@use '@carbon/react/scss/colors';
+
+// overriding header tooltip bg color
+// because the navigation is dark themed while the content is white
+// which means the dark theme tooltip bg blends into the white content bg
+.cds--header__global .cds--popover-content {
+ background-color: colors.$gray-20;
+}
+
+.cds--header__global .cds--popover-caret {
+ background-color: colors.$gray-20;
+}
+
+@media (max-width: 320px) {
+ .action-icons {
+ display: none;
+ }
+}
\ No newline at end of file
diff --git a/docs/src/app/concepts/_concepts-page.scss b/docs/src/app/concepts/_concepts-page.scss
new file mode 100644
index 0000000..e69de29
diff --git a/docs/src/app/concepts/page.js b/docs/src/app/concepts/page.js
new file mode 100644
index 0000000..2254377
--- /dev/null
+++ b/docs/src/app/concepts/page.js
@@ -0,0 +1,5 @@
+`use client`;
+
+export default function ConceptsPage() {
+ return CONCEPTS PAGE
;
+}
diff --git a/docs/src/app/demo/_demo-page.scss b/docs/src/app/demo/_demo-page.scss
new file mode 100644
index 0000000..bffe47b
--- /dev/null
+++ b/docs/src/app/demo/_demo-page.scss
@@ -0,0 +1,17 @@
+@use '@carbon/react/scss/spacing' as *;
+@use '@carbon/react/scss/type' as *;
+@use '@carbon/react/scss/breakpoint' as *;
+@use '@carbon/react/scss/theme' as *;
+@use './mixins.scss' as *;
+@use './overrides.scss';
+
+html {
+ background-color: $layer-01;
+}
+
+.demo-page__banner {
+ padding-top: $spacing-05;
+ padding-bottom: $spacing-07 * 4;
+ padding-left: $spacing-06;
+ @include demo-page-background;
+}
\ No newline at end of file
diff --git a/docs/src/app/demo/_mixins.scss b/docs/src/app/demo/_mixins.scss
new file mode 100644
index 0000000..117b434
--- /dev/null
+++ b/docs/src/app/demo/_mixins.scss
@@ -0,0 +1,7 @@
+@use '@carbon/react/scss/spacing' as *;
+@use '@carbon/react/scss/theme' as *;
+
+@mixin demo-page-background() {
+ background-color: $layer-01;
+ position: relative;
+}
\ No newline at end of file
diff --git a/docs/src/app/demo/_overrides.scss b/docs/src/app/demo/_overrides.scss
new file mode 100644
index 0000000..859badf
--- /dev/null
+++ b/docs/src/app/demo/_overrides.scss
@@ -0,0 +1,18 @@
+.demo-page__r2 .cds--tabs--scrollable {
+ transform: translateZ(0);
+ justify-content: flex-end;
+}
+
+.demo-page__r2 .cds--tab-content {
+ padding: 0;
+}
+
+.cds--tab--list {
+ justify-content: flex-end;
+ padding-right: 1rem;
+}
+
+.cds--subgrid--wide {
+ //fix needed to keep the subgrid from scrolling horizontally
+ margin-right: 1rem;
+}
\ No newline at end of file
diff --git a/docs/src/app/demo/page.js b/docs/src/app/demo/page.js
new file mode 100644
index 0000000..a2aebbc
--- /dev/null
+++ b/docs/src/app/demo/page.js
@@ -0,0 +1,35 @@
+'use client';
+
+import {
+ Breadcrumb,
+ BreadcrumbItem,
+ Button,
+ Tabs,
+ Tab,
+ TabList,
+ TabPanels,
+ TabPanel,
+ Grid,
+ Column,
+} from '@carbon/react';
+
+import Image from 'next/image';
+import Link from 'next/link';
+
+export default function DemoPage() {
+ return (
+
+
+
+
+ Getting started
+
+
+ Security Definition Validation (SDV)
+
+
+ VIDEO
+
+
+ );
+}
diff --git a/docs/src/app/favicon.ico b/docs/src/app/favicon.ico
new file mode 100644
index 0000000..ea36456
Binary files /dev/null and b/docs/src/app/favicon.ico differ
diff --git a/docs/src/app/globals.scss b/docs/src/app/globals.scss
new file mode 100644
index 0000000..cc4b349
--- /dev/null
+++ b/docs/src/app/globals.scss
@@ -0,0 +1,39 @@
+@use '@carbon/react';
+@use '@carbon/react/scss/breakpoint' as *;
+
+@use './components/SdvHeader/sdv-header';
+@use './components/Info/info';
+
+@use './concepts/concepts-page';
+@use './demo/demo-page';
+@use './home/landing-page';
+@use './how/how-page';
+@use './problem/problem-page';
+
+
+/// Remove overrides once Carbon bugs are fixed upstream.
+/// Need grid option to not add page gutters at large viewports, to also use when nesting grids
+/// @link https://github.com/carbon-design-system/carbon/issues/2792
+@media (min-width: 42rem) {
+ .cds--grid--no-gutter {
+ padding-left: 1rem;
+ padding-right: 1rem;
+ }
+}
+
+/// Padding was introduced in 10.3.0, needs an option to let grid set the viewport gutter
+/// @link https://github.com/carbon-design-system/carbon/issues/3010
+.cds--content {
+ margin-top: 3rem;
+ padding: 0;
+ background: var(--cds-background);
+}
+
+.cds--content .cds--css-grid {
+ max-width: 100%;
+ @include breakpoint(md) {
+ padding-left: 20px;
+ padding-right: 20px;
+ }
+}
+
diff --git a/docs/src/app/home/_landing-page.scss b/docs/src/app/home/_landing-page.scss
new file mode 100644
index 0000000..cfbd75b
--- /dev/null
+++ b/docs/src/app/home/_landing-page.scss
@@ -0,0 +1,107 @@
+@use '@carbon/react/scss/spacing' as *;
+@use '@carbon/react/scss/type' as *;
+@use '@carbon/react/scss/breakpoint' as *;
+@use '@carbon/react/scss/theme' as *;
+@use '@carbon/motion';
+@use './mixins.scss' as *;
+@use './overrides.scss';
+
+html {
+ background-color: $layer-01;
+}
+
+.landing-page__illo {
+ max-width: 100%;
+ float: inline-end;
+ height: auto;
+}
+
+.landing-page__banner {
+ padding-top: $spacing-05;
+ padding-bottom: $spacing-07 * 4;
+ padding-left: $spacing-06;
+ @include landing-page-background;
+}
+
+.landing-page__heading {
+ @include type-style('productive-heading-05');
+}
+
+.landing-page__r2 {
+ margin-top: -40px;
+}
+
+.tabs-group-content {
+ padding: $spacing-10 0 $spacing-10 $spacing-06;
+}
+
+.landing-page__subheading {
+ @include type-style('productive-heading-03');
+
+ font-weight: 600;
+}
+
+.landing-page__p {
+ @include type-style('productive-heading-03');
+ margin-top: $spacing-06;
+ margin-bottom: $spacing-08;
+
+ @include breakpoint-between((320px + 1), md) {
+ max-width: 75%;
+ }
+}
+
+.tabs-group {
+ background-color: $layer-01;
+ padding: 0 $spacing-03;
+}
+
+.landing-page__r3 {
+ padding-top: $spacing-08;
+ padding-bottom: $spacing-08;
+ padding-left: $spacing-06;
+ @include landing-page-background;
+}
+
+.landing-page__label {
+ @include type-style('heading-01');
+
+ @include breakpoint-down(md) {
+ padding-bottom: 1.5rem;
+ }
+}
+
+.landing-page__title {
+ padding-bottom: 0.5rem;
+}
+
+.landing-page__banner,
+.landing-page__r2,
+.landing-page__r3 {
+ margin-left: -20px;
+ margin-right: -20px;
+
+ @include breakpoint-down(md) {
+ margin-left: 0;
+ margin-right: 0;
+ }
+}
+
+@media (max-width: 672px) {
+ .landing-page__illo {
+ width: 528px;
+ width: 100%;
+ height: auto;
+ float: inline-start;
+ }
+}
+
+@media (max-width: 320px) {
+ .landing-page__illo {
+ display: none;
+ }
+
+ .landing-page__banner {
+ padding-bottom: $spacing-05 * 4;
+ }
+}
diff --git a/docs/src/app/home/_mixins.scss b/docs/src/app/home/_mixins.scss
new file mode 100644
index 0000000..b396b02
--- /dev/null
+++ b/docs/src/app/home/_mixins.scss
@@ -0,0 +1,7 @@
+@use '@carbon/react/scss/spacing' as *;
+@use '@carbon/react/scss/theme' as *;
+
+@mixin landing-page-background() {
+ background-color: $layer-01;
+ position: relative;
+}
\ No newline at end of file
diff --git a/docs/src/app/home/_overrides.scss b/docs/src/app/home/_overrides.scss
new file mode 100644
index 0000000..075209a
--- /dev/null
+++ b/docs/src/app/home/_overrides.scss
@@ -0,0 +1,18 @@
+.landing-page__r2 .cds--tabs--scrollable {
+ transform: translateZ(0);
+ justify-content: flex-end;
+}
+
+.landing-page__r2 .cds--tab-content {
+ padding: 0;
+}
+
+.cds--tab--list {
+ justify-content: flex-end;
+ padding-right: 1rem;
+}
+
+.cds--subgrid--wide {
+ //fix needed to keep the subgrid from scrolling horizontally
+ margin-right: 1rem;
+}
\ No newline at end of file
diff --git a/docs/src/app/home/page.js b/docs/src/app/home/page.js
new file mode 100644
index 0000000..aef604f
--- /dev/null
+++ b/docs/src/app/home/page.js
@@ -0,0 +1,247 @@
+'use client';
+
+import {
+ Breadcrumb,
+ BreadcrumbItem,
+ Button,
+ Tabs,
+ Tab,
+ TabList,
+ TabPanels,
+ TabPanel,
+ Grid,
+ Column,
+ ProgressIndicator,
+ ProgressStep,
+ CodeSnippet
+} from '@carbon/react';
+
+import {
+ ZeroTrust,
+ DataPrivacy,
+ AppModernization,
+} from '@carbon/pictograms-react';
+
+import Image from 'next/image';
+import Link from 'next/link';
+
+import { InfoSection, InfoCard } from '../components/Info/Info';
+
+import tabilloPng from './tab-illo.png';
+
+import sdvFlowPng from './sdv_flow.png';
+
+export default function LandingPage() {
+ return (
+
+
+ {/*
+
+ Getting started
+
+ */}
+
+
+ Security definition validation for CICS TS (SDV)
+
+
+
+
+ Problem
+ Concepts
+ Demo
+ How
+
+
+
+
+
+ What is Security definition validation?
+
+
+ SDV is an example implementation of a full CI pipeline that utilises CICS TS 6.2 feature Security Definition Capture (SDC)
+ within its automated testing stage and initiates an approval process, which must be successfully completed if changes to
+ security are identified.
+
+
+
+ Application code change requests are blocked until security changes are approved by an authority (e.g. Sys prog, Security
+ Admin).
+
+
+
+ All key tools that make SDV possible will be available open-source.
+
+
+ Next: Concepts
+
+
+
+
+
+
+
+
+
+ What are the concepts?
+
+
+ Identifies developers desired changes to security before the code is delivered, as far-left in the pipeline as possible, reducing costs.
+
+
+
+ 1. Developer raises application code change in GitHub (PR)
+ 2. A GitHub PR hook then triggers a Tekton CI pipeline
+ 3. As part of the CI pipeline, an automated test suite would run against the application compiled with proposed changes, collecting the security and dumping to a file for each test case, in YAML format.
+ 4. The CI pipeline would then run an Ansible script which extracts all the newly found security YAMLs, and compares them against a baseline previously collected from the test run on the default branch (stored in a separate 'Security' repo in GitHub).
+ 5. If deltas are found, the Ansible script would then push the new security YAML files to a branch on the 'Security' repo, and create a Pull Request, with the 'Security Admin' team being set as reviewers.
+ 6. Use of 'GitHub checks' would cause blockages on all PRs involved, meaning no PR could be merged until the 'Security Admin' approves.
+ 7. A GitHub App would be developed, acting as the synchroniser between the 'application' PR, and the 'Security' PR (e.g. if the Security PR is approved, then the bot would update the check in the application PR to passed.)
+ 8. Once all PRs involved were in a mergeable state (aka, no blocks), the GitHub App would then auto merge both PRs.
+
+
+
+ Brings Security testing into the development lifecycle much earlier, typically only first seen at preprod.
+
+
+ Provides an unbreakable quality gate owned by Security Admins on developer code changes.
+
+
+ Speeds up the process of getting Security changes made to the database.
+
+
+ Automatically done as part of automated test. Only the approval and updating of the Security DB is manual.
+
+
+ Stops unwanted security changes making it into the codebase.
+
+
+ Identifies security definitions that are no longer required.
+
+
+ Contributes towards a greater DevSecOps goal.
+
+
+ Next: Demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ alert(`Clicked index ${stepIndex}`)} spaceEqually='true'>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fhuerhfguehfesauofhesaufhesapfueisafjhueasjhf
+ fjeushfaeshfusehafuhefsuah
+
+
+
+ fhuerhfguehfesauofhesaufhesapfueisafjhueasjhf
+ fjeushfaeshfusehafuhefsuah
+
+
+
+
+ Tekton
+ Jenkins
+
+
+
+
+ {`a load of bash`}
+
+
+
+
+ {`a load of jenkins stuff`}
+
+
+
+
+
+
+
+
+
+ fhuerhfguehfesauofhesaufhesapfueisafjhueasjhf
+ fjeushfaeshfusehafuhefsuah
+
+
+ fhuerhfguehfesauofhesaufhesapfueisafjhueasjhf
+ fjeushfaeshfusehafuhefsuah
+
+
+ fhuerhfguehfesauofhesaufhesapfueisafjhueasjhf
+ fjeushfaeshfusehafuhefsuah
+
+
+
+
+
+
+
+
+
+
+ }
+ />
+ }
+ />
+ }
+ />
+
+
+
+ );
+}
diff --git a/docs/src/app/home/sdv_flow.png b/docs/src/app/home/sdv_flow.png
new file mode 100644
index 0000000..f8f72e3
Binary files /dev/null and b/docs/src/app/home/sdv_flow.png differ
diff --git a/docs/src/app/home/tab-illo.png b/docs/src/app/home/tab-illo.png
new file mode 100644
index 0000000..736f59d
Binary files /dev/null and b/docs/src/app/home/tab-illo.png differ
diff --git a/docs/src/app/how/_how-page.scss b/docs/src/app/how/_how-page.scss
new file mode 100644
index 0000000..e69de29
diff --git a/docs/src/app/how/page.js b/docs/src/app/how/page.js
new file mode 100644
index 0000000..bfb81c9
--- /dev/null
+++ b/docs/src/app/how/page.js
@@ -0,0 +1,5 @@
+`use client`;
+
+export default function HowPage() {
+ return HOW PAGE
;
+}
diff --git a/docs/src/app/layout.js b/docs/src/app/layout.js
new file mode 100644
index 0000000..3385f95
--- /dev/null
+++ b/docs/src/app/layout.js
@@ -0,0 +1,17 @@
+import './globals.scss';
+import { Providers } from './providers';
+
+export const metadata = {
+ title: 'IBM CICS - Security Definition Validation',
+ description: 'IBM CICS SDV documentation',
+};
+
+export default function RootLayout({ children }) {
+ return (
+
+
+ {children}
+
+
+ );
+}
\ No newline at end of file
diff --git a/docs/src/app/page.js b/docs/src/app/page.js
new file mode 100644
index 0000000..08135e7
--- /dev/null
+++ b/docs/src/app/page.js
@@ -0,0 +1,8 @@
+'use client';
+import LandingPage from './home/page';
+
+export default function Home() {
+ return (
+
+ );
+}
diff --git a/docs/src/app/page.module.css b/docs/src/app/page.module.css
new file mode 100644
index 0000000..5c4b1e6
--- /dev/null
+++ b/docs/src/app/page.module.css
@@ -0,0 +1,230 @@
+.main {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ align-items: center;
+ padding: 6rem;
+ min-height: 100vh;
+}
+
+.description {
+ display: inherit;
+ justify-content: inherit;
+ align-items: inherit;
+ font-size: 0.85rem;
+ max-width: var(--max-width);
+ width: 100%;
+ z-index: 2;
+ font-family: var(--font-mono);
+}
+
+.description a {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.description p {
+ position: relative;
+ margin: 0;
+ padding: 1rem;
+ background-color: rgba(var(--callout-rgb), 0.5);
+ border: 1px solid rgba(var(--callout-border-rgb), 0.3);
+ border-radius: var(--border-radius);
+}
+
+.code {
+ font-weight: 700;
+ font-family: var(--font-mono);
+}
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(4, minmax(25%, auto));
+ max-width: 100%;
+ width: var(--max-width);
+}
+
+.card {
+ padding: 1rem 1.2rem;
+ border-radius: var(--border-radius);
+ background: rgba(var(--card-rgb), 0);
+ border: 1px solid rgba(var(--card-border-rgb), 0);
+ transition: background 200ms, border 200ms;
+}
+
+.card span {
+ display: inline-block;
+ transition: transform 200ms;
+}
+
+.card h2 {
+ font-weight: 600;
+ margin-bottom: 0.7rem;
+}
+
+.card p {
+ margin: 0;
+ opacity: 0.6;
+ font-size: 0.9rem;
+ line-height: 1.5;
+ max-width: 30ch;
+ text-wrap: balance;
+}
+
+.center {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ position: relative;
+ padding: 4rem 0;
+}
+
+.center::before {
+ background: var(--secondary-glow);
+ border-radius: 50%;
+ width: 480px;
+ height: 360px;
+ margin-left: -400px;
+}
+
+.center::after {
+ background: var(--primary-glow);
+ width: 240px;
+ height: 180px;
+ z-index: -1;
+}
+
+.center::before,
+.center::after {
+ content: "";
+ left: 50%;
+ position: absolute;
+ filter: blur(45px);
+ transform: translateZ(0);
+}
+
+.logo {
+ position: relative;
+}
+/* Enable hover only on non-touch devices */
+@media (hover: hover) and (pointer: fine) {
+ .card:hover {
+ background: rgba(var(--card-rgb), 0.1);
+ border: 1px solid rgba(var(--card-border-rgb), 0.15);
+ }
+
+ .card:hover span {
+ transform: translateX(4px);
+ }
+}
+
+@media (prefers-reduced-motion) {
+ .card:hover span {
+ transform: none;
+ }
+}
+
+/* Mobile */
+@media (max-width: 700px) {
+ .content {
+ padding: 4rem;
+ }
+
+ .grid {
+ grid-template-columns: 1fr;
+ margin-bottom: 120px;
+ max-width: 320px;
+ text-align: center;
+ }
+
+ .card {
+ padding: 1rem 2.5rem;
+ }
+
+ .card h2 {
+ margin-bottom: 0.5rem;
+ }
+
+ .center {
+ padding: 8rem 0 6rem;
+ }
+
+ .center::before {
+ transform: none;
+ height: 300px;
+ }
+
+ .description {
+ font-size: 0.8rem;
+ }
+
+ .description a {
+ padding: 1rem;
+ }
+
+ .description p,
+ .description div {
+ display: flex;
+ justify-content: center;
+ position: fixed;
+ width: 100%;
+ }
+
+ .description p {
+ align-items: center;
+ inset: 0 0 auto;
+ padding: 2rem 1rem 1.4rem;
+ border-radius: 0;
+ border: none;
+ border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
+ background: linear-gradient(
+ to bottom,
+ rgba(var(--background-start-rgb), 1),
+ rgba(var(--callout-rgb), 0.5)
+ );
+ background-clip: padding-box;
+ backdrop-filter: blur(24px);
+ }
+
+ .description div {
+ align-items: flex-end;
+ pointer-events: none;
+ inset: auto 0 0;
+ padding: 2rem;
+ height: 200px;
+ background: linear-gradient(
+ to bottom,
+ transparent 0%,
+ rgb(var(--background-end-rgb)) 40%
+ );
+ z-index: 1;
+ }
+}
+
+/* Tablet and Smaller Desktop */
+@media (min-width: 701px) and (max-width: 1120px) {
+ .grid {
+ grid-template-columns: repeat(2, 50%);
+ }
+}
+
+@media (prefers-color-scheme: dark) {
+ .vercelLogo {
+ filter: invert(1);
+ }
+
+ .logo {
+ filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
+ }
+}
+
+@keyframes rotate {
+ from {
+ transform: rotate(360deg);
+ }
+ to {
+ transform: rotate(0deg);
+ }
+}
diff --git a/docs/src/app/problem/_problem-page.scss b/docs/src/app/problem/_problem-page.scss
new file mode 100644
index 0000000..e69de29
diff --git a/docs/src/app/problem/page.js b/docs/src/app/problem/page.js
new file mode 100644
index 0000000..6f27449
--- /dev/null
+++ b/docs/src/app/problem/page.js
@@ -0,0 +1,5 @@
+`use client`;
+
+export default function ProblemPage() {
+ return PROBLEM PAGE
;
+}
diff --git a/docs/src/app/providers.js b/docs/src/app/providers.js
new file mode 100644
index 0000000..cb9c313
--- /dev/null
+++ b/docs/src/app/providers.js
@@ -0,0 +1,16 @@
+'use client';
+import { Content, Theme } from '@carbon/react';
+
+import SdvHeader from './components/SdvHeader/SdvHeader';
+
+
+export function Providers({ children }) {
+ return (
+
+
+
+
+ {children}
+
+ );
+}
\ No newline at end of file
diff --git a/lib/.eslintrc.json b/lib/.eslintrc.json
new file mode 100644
index 0000000..e452b1e
--- /dev/null
+++ b/lib/.eslintrc.json
@@ -0,0 +1,20 @@
+{
+ "env": {
+ "commonjs": true,
+ "es2021": true,
+ "node": true,
+ "jest/globals": true
+ },
+ "plugins": [
+ "jest"
+ ],
+ "extends": [
+ "airbnb-base"
+ ],
+ "rules": {
+ "no-restricted-syntax": ["off"],
+ "no-unused-vars": ["error", { "varsIgnorePattern": "_ignore", "argsIgnorePattern": "^_$" }],
+ "comma-dangle": ["error", "never"],
+ "no-warning-comments": ["warn"]
+ }
+}
diff --git a/lib/__tests__/CheckRunActions.test.js b/lib/__tests__/CheckRunActions.test.js
new file mode 100644
index 0000000..cd012d7
--- /dev/null
+++ b/lib/__tests__/CheckRunActions.test.js
@@ -0,0 +1,1642 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const fetch = require('node-fetch');
+const nock = require('nock');
+
+const {
+ Probot, ProbotOctokit
+} = require('probot');
+
+globalThis.fetch = fetch;
+
+const sdvApprovalApp = require('../app');
+
+const getRouter = () => ({
+ use: jest.fn(),
+ get: jest.fn()
+});
+
+describe('Check run event tests.', () => {
+ let probot;
+
+ const reposOwner = 'cics-sdv';
+ const appTestsRepoName = 'galasa-tests-repo';
+ const appTestHeadRef = 'newBranchChange';
+ const securityRepoName = 'application-security';
+ const appTestPrNumber = 12;
+ const securityPrNumber = 86;
+ const appTestHeadSha = 'abcd1234';
+ const securityHeadSha = 'blah78657';
+ const securityPrUrl = 'http://github.com/123';
+
+ const sdvConfigYaml = `security_repo_owner: ${reposOwner}\nsecurity_repo_name: ${securityRepoName}`;
+
+ beforeEach(async () => {
+ nock.disableNetConnect();
+
+ probot = new Probot({
+ githubToken: 'test',
+ // Disable throttling & retrying requests for easier testing
+ Octokit: ProbotOctokit.defaults({
+ retry: { enabled: false },
+ throttle: { enabled: false }
+ })
+ });
+ sdvApprovalApp(probot, { getRouter });
+ });
+
+ /*
+ if a check run completes on the app/test PR, but the
+ Security check has not, no actions should be taken
+ */
+ test('App/Test PR - A non-Security check run completes and branch protection is blocking due to Security not passing yet', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get App/Test PR Object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ },
+ mergeable_state: 'blocked'
+ });
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Build',
+ conclusion: 'success',
+ head_sha: appTestHeadSha,
+ check_suite: {
+ head_branch: appTestHeadRef
+ },
+ pull_requests: [
+ {
+ number: appTestPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ If by chance an app/test PR check finishes after the Security check passes,
+ and nothing has merged, it should attempt to auto merge.
+ */
+ test('App/Test PR - A non-Security check run completes and Security check & all others have passed, and not already merged', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get App/Test PR Object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ },
+ mergeable_state: 'has_hooks'
+ });
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide Security branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, {
+ name: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ });
+
+ // Get Security PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: securityPrNumber
+ }
+ ]);
+
+ // Provide Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'has_hooks'
+ });
+
+ // Merge App/Test & Security PR
+ nock('https://api.github.com')
+ .put(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}/merge`)
+ .reply(200);
+ nock('https://api.github.com')
+ .put(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/merge`)
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Build',
+ conclusion: 'success',
+ head_sha: appTestHeadSha,
+ check_suite: {
+ head_branch: appTestHeadRef
+ },
+ pull_requests: [
+ {
+ number: appTestPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ If by chance an app/test PR check finishes after the Security check passes,
+ and the PRs are already merged, it should not try to merge again.
+ */
+ test('App/Test PR - A non-Security check run completes and Security check & all others have passed, but is already merged', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get App/Test PR Object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ merged: true,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ },
+ mergeable_state: ''
+ });
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide Security branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, {
+ name: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ });
+
+ // Get Security PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: securityPrNumber
+ }
+ ]);
+
+ // Provide Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: false,
+ merged: true,
+ mergeable_state: ''
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Build',
+ conclusion: 'success',
+ head_sha: appTestHeadSha,
+ check_suite: {
+ head_branch: appTestHeadRef
+ },
+ pull_requests: [
+ {
+ number: appTestPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ This should auto merge.
+ */
+ test('App/Test PR - The Security check run completes for a feature branch PR, and all other checks passed', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get App/Test PR Object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ },
+ mergeable_state: 'has_hooks'
+ });
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide Security branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, {
+ name: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ });
+
+ // Get Security PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: securityPrNumber
+ }
+ ]);
+
+ // Provide Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'has_hooks'
+ });
+
+ // Merge App/Test & Security PR
+ nock('https://api.github.com')
+ .put(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}/merge`)
+ .reply(200);
+
+ nock('https://api.github.com')
+ .put(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/merge`)
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Security',
+ conclusion: 'success',
+ head_sha: appTestHeadSha,
+ check_suite: {
+ head_branch: appTestHeadRef
+ },
+ pull_requests: [
+ {
+ number: appTestPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ If the Security PR is raised against the app/test default branch, there is
+ no app/test PR. Therefore, if Security check passes on the commit, reviews
+ have approved it, so merge Security PR without a matching app/test PR.
+ */
+ test('App/Test PR - The Security check run completes for an overnight build on the default branch, and all other checks pass', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Get Security PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2Fmain`)
+ .reply(200, [
+ {
+ number: securityPrNumber
+ }
+ ]);
+
+ // Provide Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'has_hooks'
+ });
+
+ // Merge Security PR
+ nock('https://api.github.com')
+ .put(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/merge`)
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Security',
+ conclusion: 'success',
+ head_sha: appTestHeadSha,
+ check_suite: {
+ head_branch: 'main'
+ },
+ pull_requests: []
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ If the Security check fails, don't take any action
+ */
+ test('App/Test PR - The Security check run fails for an overnight build on the default branch, and all other checks pass', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Security',
+ conclusion: 'failed',
+ head_sha: appTestHeadSha,
+ check_suite: {
+ head_branch: 'main'
+ },
+ pull_requests: []
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ If a user sets up checks on the Security repo, checks should be made to see
+ if it is auto mergable when those checks complete.
+ */
+ test('Security PR - A random Check passes for feature branch PR, but required reviews have not yet been approved', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'blocked',
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ }
+ });
+
+ // Provide app/test branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`
+ });
+
+ // Get App/Test PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls?head=${reposOwner}%3A${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: appTestPrNumber,
+ base: {
+ ref: 'main'
+ }
+ }
+ ]);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Get App/Test PR Object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'has_hooks',
+ base: {
+ ref: 'main'
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'RandomCheck',
+ conclusion: 'success',
+ head_sha: securityHeadSha,
+ check_suite: {
+ head_branch: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ },
+ pull_requests: [
+ {
+ number: securityPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ If a user sets up checks on the Security repo, checks should be made to see
+ if it is auto mergable when those checks complete.
+ */
+ test('Security PR - A random Check passes for feature branch PR, and approving required review present', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'has_hooks',
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ }
+ });
+
+ // Provide app/test branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`
+ });
+
+ // Get App/Test PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls?head=${reposOwner}%3A${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: appTestPrNumber,
+ base: {
+ ref: 'main'
+ }
+ }
+ ]);
+
+ // Get App/Test PR Object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'has_hooks'
+ });
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Merge App/Test & Security PR
+ nock('https://api.github.com')
+ .put(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}/merge`)
+ .reply(200);
+ nock('https://api.github.com')
+ .put(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/merge`)
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'RandomCheck',
+ conclusion: 'success',
+ head_sha: securityHeadSha,
+ check_suite: {
+ head_branch: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ },
+ pull_requests: [
+ {
+ number: securityPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ If a user sets up checks on the Security repo, checks should be made to see
+ if it is auto mergable when those checks complete.
+ */
+ test('Security PR - A random Check passes for default branch PR, but required reviews have not yet been approved', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'blocked',
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/main`
+ }
+ });
+
+ // Provide app/test branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get App/Test PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls?head=${reposOwner}%3Amain`)
+ .reply(200, []);
+
+ // Get app/test commit Security check
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: 123,
+ status: 'in_progress'
+ }
+ ],
+ total_count: 1
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'RandomCheck',
+ conclusion: 'success',
+ head_sha: securityHeadSha,
+ check_suite: {
+ head_branch: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ },
+ pull_requests: [
+ {
+ number: securityPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ If a user sets up checks on the Security repo, checks should be made to see
+ if it is auto mergable when those checks complete.
+ */
+ test('Security PR - A random Check passes for default branch PR, and approving required review present', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'has_hooks',
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/main`
+ }
+ });
+
+ // Provide app/test branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get App/Test PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls?head=${reposOwner}%3Amain`)
+ .reply(200, []);
+
+ // Get app/test commit Security check
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: 123,
+ status: 'in_progress'
+ }
+ ],
+ total_count: 1
+ });
+
+ // Merge Security PR
+ nock('https://api.github.com')
+ .put(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/merge`)
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'RandomCheck',
+ conclusion: 'success',
+ head_sha: securityHeadSha,
+ check_suite: {
+ head_branch: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ },
+ pull_requests: [
+ {
+ number: securityPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Security PR - No config exists', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(404);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'RandomCheck',
+ conclusion: 'success',
+ head_sha: securityHeadSha,
+ check_suite: {
+ head_branch: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ },
+ pull_requests: [
+ {
+ number: securityPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ This would indicate that the repo has some form of checks on feature branches (a
+ dev deployment of a feature branch perhaps?) and the dev has just pushed a commit
+ */
+ test('App/test PR - A random check passes for a feature branch with no PR', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Dev Deploy',
+ conclusion: 'success',
+ head_sha: 'aNewFeatureSha123',
+ check_suite: {
+ head_branch: 'aNewFeature'
+ },
+ pull_requests: []
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ A check completes but in draft state, no action taken
+ */
+ test('App/Test PR - A check run completes but PR is in draft state', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get App/Test PR Object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: true,
+ head: {
+ ref: appTestHeadRef
+ },
+ mergeable_state: 'has_hooks'
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Build',
+ conclusion: 'success',
+ head_sha: appTestHeadSha,
+ check_suite: {
+ head_branch: appTestHeadRef
+ },
+ pull_requests: [
+ {
+ number: appTestPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ A check completes but in draft state, no action taken
+ */
+ test('Security PR - A check run completes but PR is in draft state', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get Security PR Object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: true,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ },
+ mergeable_state: 'has_hooks'
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Build',
+ conclusion: 'success',
+ head_sha: securityHeadSha,
+ check_suite: {
+ head_branch: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ },
+ pull_requests: [
+ {
+ number: securityPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ Takes no action, this is a PR being merged to a branch where Security isn't required.
+ The App/Test PR will have a skipped security check
+ */
+ test('App/test PR - A check run completes, but the target branch does not have Security as a required check', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get App/Test PR Object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'someOddBranch'
+ },
+ mergeable_state: 'has_hooks'
+ });
+
+ // Provide App/Test someOddBranch branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/someOddBranch`)
+ .reply(200, {
+ name: 'someOddBranch',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: []
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Security',
+ conclusion: 'success',
+ head_sha: appTestHeadSha,
+ check_suite: {
+ head_branch: appTestHeadRef
+ },
+ pull_requests: [
+ {
+ number: appTestPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ This will merge as branch 1.0.0 has 'Security' as required check on branch protection
+ */
+ test('App/test PR - A check run completes on overnight release branch 1.0.0, which has Security as a required check', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test 1.0.0 branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/1.0.0`)
+ .reply(200, {
+ name: '1.0.0',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Build',
+ app_id: null
+ },
+ {
+ context: 'Test',
+ app_id: null
+ },
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Get Security PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F1%2E0%2E0`)
+ .reply(200, [
+ {
+ number: securityPrNumber
+ }
+ ]);
+
+ // Provide Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'has_hooks'
+ });
+
+ // Merge Security PR
+ nock('https://api.github.com')
+ .put(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/merge`)
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Security',
+ conclusion: 'success',
+ head_sha: appTestHeadSha,
+ check_suite: {
+ head_branch: '1.0.0'
+ },
+ pull_requests: []
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ No action taken, the feature branch does not have branch protection turned on.
+ */
+ test('App/test PR - A check run completes on overnight build of feature branch, which has no branch protection', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Build',
+ conclusion: 'success',
+ head_sha: appTestHeadSha,
+ check_suite: {
+ head_branch: 'someOddBranch'
+ },
+ pull_requests: []
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ No action taken, the feature branch does not have 'Security' as a required check.
+ */
+ test('App/test PR - A check run completes on overnight build of a random branch, which has a form of branch protection, but Security is not required', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Build',
+ conclusion: 'success',
+ head_sha: appTestHeadSha,
+ check_suite: {
+ head_branch: 'someOddBranch'
+ },
+ pull_requests: []
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ No action taken, the feature branch does not have 'Security' as a required check.
+ */
+ test('App/test PR - A check run completes on overnight build of a random branch, which has a form of branch protection, but Security is not required - yet is somehow ran!', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test someOddBranch branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/someOddBranch`)
+ .reply(200, {
+ name: 'someOddBranch',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Build',
+ app_id: null
+ },
+ {
+ context: 'Test',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'Security',
+ conclusion: 'success',
+ head_sha: appTestHeadSha,
+ check_suite: {
+ head_branch: 'someOddBranch'
+ },
+ pull_requests: []
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ Nothing will happen because the target branch of the app/test
+ PR does not have 'Security' as a required check
+ */
+ test('Security PR - A check run completes, but the target branch for the app/test PR does not have Security as a required check', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'has_hooks',
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ }
+ });
+
+ // Provide app/test branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`
+ });
+
+ // Get App/Test PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls?head=${reposOwner}%3A${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: appTestPrNumber,
+ base: {
+ ref: 'someUnprotectedBranch'
+ }
+ }
+ ]);
+
+ // Provide App/Test someUnprotectedBranch branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/someUnprotectedBranch`)
+ .reply(200, {
+ name: 'someUnprotectedBranch',
+ protection: {
+ enabled: false,
+ required_status_checks: {
+ checks: []
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'RandomCheck',
+ conclusion: 'success',
+ head_sha: securityHeadSha,
+ check_suite: {
+ head_branch: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ },
+ pull_requests: [
+ {
+ number: securityPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ Nothing happens, no processing is done for Security checks,
+ unless part of a PR that can affect an app/test PR
+ */
+ test('Security PR - A check run completes, but is happening on a release branch, and app/test branch is branch protected', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'RandomCheck',
+ conclusion: 'success',
+ head_sha: securityHeadSha,
+ check_suite: {
+ head_branch: `${reposOwner}/${appTestsRepoName}/1.0.0`
+ },
+ pull_requests: []
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ Does nothing, won't even get as far as checking the branch protection of the app/test PR target
+ branch because we don't process checks on the security repo which aren't part of a PR
+ */
+ test('Security PR - A check run completes, but is happening on a random feature branch, and app/test branch is not branch protected', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'RandomCheck',
+ conclusion: 'success',
+ head_sha: securityHeadSha,
+ check_suite: {
+ head_branch: 'userRandomBranch'
+ },
+ pull_requests: []
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ Does nothing, won't even get as far as checking the branch protection of the app/test PR target
+ branch because we don't process checks on the security repo which aren't part of a PR
+ */
+ test('Security PR - A check run completes, but is happening on a random feature branch, with no corresponding app/test branch', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'RandomCheck',
+ conclusion: 'success',
+ head_sha: securityHeadSha,
+ check_suite: {
+ head_branch: 'userRandomBranch'
+ },
+ pull_requests: []
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ It will get as far as seeing that a matching branch
+ doesn't exist in the app/test repo, then exit
+ */
+ test('Security PR - A check run completes on a branch the sec admin as managed to manually create and be of the correct format, & then created a PR for', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'has_hooks',
+ html_url: securityPrUrl,
+ head: {
+ ref: 'cics-sdv/galasa-tests-repo/somethingWild'
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'check_run',
+ payload: {
+ action: 'completed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ check_run: {
+ name: 'RandomCheck',
+ conclusion: 'success',
+ head_sha: securityHeadSha,
+ check_suite: {
+ head_branch: 'cics-sdv/galasa-tests-repo/somethingWild'
+ },
+ pull_requests: [
+ {
+ number: securityPrNumber
+ }
+ ]
+ }
+ }
+ });
+ }, 10000);
+
+ afterEach(() => {
+ if (!nock.isDone()) {
+ throw new Error(
+ `Not all nock interceptors were used: ${JSON.stringify(
+ nock.pendingMocks()
+ )}`
+ );
+ }
+
+ nock.cleanAll();
+ nock.enableNetConnect();
+ });
+});
diff --git a/lib/__tests__/DeleteActions.test.js b/lib/__tests__/DeleteActions.test.js
new file mode 100644
index 0000000..b8e459b
--- /dev/null
+++ b/lib/__tests__/DeleteActions.test.js
@@ -0,0 +1,293 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const fetch = require('node-fetch');
+const nock = require('nock');
+
+const {
+ Probot, ProbotOctokit
+} = require('probot');
+
+globalThis.fetch = fetch;
+
+const sdvApprovalApp = require('../app');
+
+const getRouter = () => ({
+ use: jest.fn(),
+ get: jest.fn()
+});
+
+describe('Delete event tests.', () => {
+ let probot;
+
+ const reposOwner = 'cics-sdv';
+ const appTestsRepoName = 'galasa-tests-repo';
+ const appTestHeadRef = 'newBranchChange';
+ const securityRepoName = 'application-security';
+ // const appTestPrNumber = 12;
+ // const securityPrNumber = 86;
+ // const appTestHeadSha = 'abcd1234';
+ const securityHeadSha = 'blah78657';
+ // const securityPrUrl = 'http://github.com/123';
+
+ const sdvConfigYaml = `security_repo_owner: ${reposOwner}\nsecurity_repo_name: ${securityRepoName}`;
+
+ beforeEach(async () => {
+ nock.disableNetConnect();
+
+ probot = new Probot({
+ githubToken: 'test',
+ // Disable throttling & retrying requests for easier testing
+ Octokit: ProbotOctokit.defaults({
+ retry: { enabled: false },
+ throttle: { enabled: false }
+ })
+ });
+ sdvApprovalApp(probot, { getRouter });
+ });
+
+ /*
+ Deleting the app/test branch at any point, should simply
+ delete the assoicated Security branch, if it exists.
+ */
+ test('App/Test - Delete feature branch', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get Security branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, {
+ name: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ commit: {
+ sha: securityHeadSha
+ }
+ });
+
+ // Delete Security branch
+ nock('https://api.github.com')
+ .delete(`/repos/${reposOwner}/${securityRepoName}/git/refs/heads%2F${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(204);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'delete',
+ payload: {
+ ref_type: 'branch',
+ ref: appTestHeadRef,
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ Deleting the app/test branch at any point, should simply
+ delete the assoicated Security branch, if it exists.
+ */
+ test('App/Test - Delete feature branch, but no Security branch exists', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get Security branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(404);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'delete',
+ payload: {
+ ref_type: 'branch',
+ ref: appTestHeadRef,
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ If the Security branch is deleted, if there are any associated app/test PRs,
+ their Security checks should fail
+ */
+ test('Security PR - Delete feature branch with associated app/test PR live & Security check in_progress', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest Security Check
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadRef}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: 1,
+ status: 'in_progress'
+ }
+ ],
+ total_count: 1
+ });
+
+ // Created the Security Check
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${appTestsRepoName}/check-runs/1`, {
+ status: 'completed',
+ conclusion: 'failure',
+ output: {
+ title: 'Security PR closed',
+ summary: 'Security PR closed due to removed associated branch.'
+ }
+ })
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'delete',
+ payload: {
+ ref_type: 'branch',
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('App/Test PR - No config exists', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(404);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'delete',
+ payload: {
+ ref_type: 'branch',
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ Deleting a branch not linked to a PR, could be a dev simplying deleting a
+ feature branch they've done nothing with, so no action should be taken.
+ */
+ test('App/Test - Delete feature branch with no linked PR', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get Security branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2FaRandomNewFeature`)
+ .reply(404);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'delete',
+ payload: {
+ ref_type: 'branch',
+ ref: 'aRandomNewFeature',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ Security check is skipped, and remains skipped.
+ */
+ test('Security PR - Deleted branch, but the app/test PR has a "skipped" Security check', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest Security Check
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadRef}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: 1,
+ status: 'completed',
+ conclusion: 'skipped'
+ }
+ ],
+ total_count: 1
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'delete',
+ payload: {
+ ref_type: 'branch',
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ afterEach(() => {
+ if (!nock.isDone()) {
+ throw new Error(
+ `Not all nock interceptors were used: ${JSON.stringify(
+ nock.pendingMocks()
+ )}`
+ );
+ }
+
+ nock.cleanAll();
+ nock.enableNetConnect();
+ });
+});
diff --git a/lib/__tests__/appTestRepoPullRequestActions.test.js b/lib/__tests__/appTestRepoPullRequestActions.test.js
new file mode 100644
index 0000000..b134117
--- /dev/null
+++ b/lib/__tests__/appTestRepoPullRequestActions.test.js
@@ -0,0 +1,1871 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const fetch = require('node-fetch');
+const nock = require('nock');
+
+const {
+ Probot, ProbotOctokit
+} = require('probot');
+
+globalThis.fetch = fetch;
+
+const sdvApprovalApp = require('../app');
+
+const getRouter = () => ({
+ use: jest.fn(),
+ get: jest.fn()
+});
+
+describe('App/Test Repository Pull Request event tests', () => {
+ let probot;
+
+ const reposOwner = 'cics-sdv';
+ const appTestsRepoName = 'galasa-tests-repo';
+ const appTestHeadRef = 'newBranchChange';
+ const securityRepoName = 'application-security';
+ const appTestPrNumber = 12;
+ const securityPrNumber = 86;
+ const appTestHeadSha = 'abcd1234';
+
+ const sdvConfigYaml = `security_repo_owner: ${reposOwner}\nsecurity_repo_name: ${securityRepoName}`;
+
+ beforeEach(async () => {
+ nock.disableNetConnect();
+
+ probot = new Probot({
+ githubToken: 'test',
+ // Disable throttling & retrying requests for easier testing
+ Octokit: ProbotOctokit.defaults({
+ retry: { enabled: false },
+ throttle: { enabled: false }
+ })
+ });
+ sdvApprovalApp(probot, { getRouter });
+ });
+
+ /*
+ When this happens, no action is taken in GHE
+ */
+ test('Application/Test PR - is opened', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'opened',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ });
+
+ test('Application/Test PR - is closed, with existing Security PR', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide pulls list on Security Repo
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?state=open&head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: securityPrNumber
+ }
+ ]);
+
+ // Mock the patch to close the security PR
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`, {
+ state: 'closed'
+ })
+ .reply(200);
+
+ // Mock the patch to create close comment in Security PR
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/issues/${securityPrNumber}/comments`, {
+ body: 'Closed due to corresponding app/test PR being closed without merge.'
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'closed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ });
+
+ /*
+ When this happens, the bot attempts to close any
+ open Security PR
+ */
+ test('Application/Test PR - is closed, with no existing Security PR', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide pulls list on Security Repo
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?state=open&head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, []);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'closed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ });
+
+ /*
+ When this happens, no action is taken. GHE will restart a fresh pipeline
+ */
+ test('Application/Test PR - is reopened', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'reopened',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ });
+
+ /*
+ When this happens, an auto merge attempt will be conducted
+ */
+ test('Application/Test PR - is approved, Security PR is NOT approved', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide source PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ },
+ mergeable_state: 'has_hooks'
+ });
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide Security PR branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, {
+ name: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ });
+
+ // Provide Security PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: securityPrNumber
+ }
+ ]);
+
+ // Provide Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'blocked'
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'submitted',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, an auto merge attempt will be conducted for both PRs
+ */
+ test('Application/Test PR - is approved, Security PR IS approved', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide source PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ },
+ mergeable_state: 'has_hooks'
+ });
+
+ // Provide Security PR branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, {
+ name: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ });
+
+ // Provide Security PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: securityPrNumber
+ }
+ ]);
+
+ // Provide Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ state: 'open',
+ draft: false,
+ mergeable_state: 'has_hooks'
+ });
+
+ // Merge App/Test & Security PR
+ nock('https://api.github.com')
+ .put(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}/merge`)
+ .reply(200);
+
+ nock('https://api.github.com')
+ .put(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/merge`)
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'submitted',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, an auto merge attempt will be conducted for app/Test PR
+ */
+ test('Application/Test PR - is approved, but no security branch exists due to zero deltas found', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide source PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ },
+ mergeable_state: 'has_hooks'
+ });
+
+ // Provide Security PR branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(404);
+
+ // Get checks for App/Test PR ref
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ conclusion: 'success'
+ }
+ ],
+ total_count: 1
+ });
+
+ // Merge App/Test & Security PR
+ nock('https://api.github.com')
+ .put(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}/merge`)
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'submitted',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ }
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, an auto merge attempt will not happen
+ */
+ test('Application/Test PR - is approved, but no security branch exists and the Security check is still in_progress due to bad state', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide source PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ },
+ mergeable_state: 'has_hooks'
+ });
+
+ // Provide Security PR branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(404);
+
+ // Get checks for App/Test PR ref
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'in_progress'
+ }
+ ],
+ total_count: 1
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'submitted',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, an auto merge attempt will be conducted for app/Test PR
+ */
+ test('Application/Test PR - is approved, but although security branch exists, there is no PR', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide source PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ },
+ mergeable_state: 'has_hooks'
+ });
+
+ // Provide Security PR branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, {
+ name: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ });
+
+ // Provide Security PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, []);
+
+ // Get checks for App/Test PR ref
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ conclusion: 'success'
+ }
+ ],
+ total_count: 1
+ });
+
+ // Merge App/Test & Security PR
+ nock('https://api.github.com')
+ .put(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}/merge`)
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'submitted',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, an auto merge attempt will not happen as we don't know the state.
+ You would expect the Security check to still be in_progress
+ */
+ test('Application/Test PR - is approved, but although security branch exists, there is no PR due to some horrible state', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide source PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ },
+ mergeable_state: 'has_hooks'
+ });
+
+ // Provide Security PR branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, {
+ name: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ });
+
+ // Provide Security PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, []);
+
+ // Get checks for App/Test PR ref
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'in_progress'
+ }
+ ],
+ total_count: 1
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'submitted',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Application/Test PR - is rejected', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide source PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ },
+ mergeable_state: 'blocked'
+ });
+
+ // Provide Security PR branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, {
+ name: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ });
+
+ // Provide Security PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, []);
+
+ // Get checks for App/Test PR ref
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ conclusion: 'success'
+ }
+ ],
+ total_count: 1
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'submitted',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Application/Test PR - is commented on type 1', async () => {
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review_comment',
+ payload: {
+ action: 'created',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Application/Test PR - comment thread resolved', async () => {
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review_thread',
+ payload: {
+ action: 'resolved',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, it closes any currently open Security PR. It will expect
+ the security branch to be force pushed with new upcoming updates
+ */
+ test('Application/Test PR - has update branch button pressed / new commit pushed', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide Security PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?state=open&head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: securityPrNumber
+ }
+ ]);
+
+ // Update Security PR to closed
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`, {
+ state: 'closed'
+ })
+ .reply(200);
+
+ // Add comment to Security PR indicating why
+ // it has been closed
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/issues/${securityPrNumber}/comments`, {
+ body: 'Closed due to corresponding app/test PR being updated with new code commit, which may change security.\n\nA new Security will be created, if required.'
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'synchronize',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ draft: false,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, an existing Security PR is closed
+ */
+ test('Application/Test PR - has demote to draft button pressed', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide Security PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?state=open&head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: securityPrNumber
+ }
+ ]);
+
+ // Update Security PR to closed
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`, {
+ state: 'closed'
+ })
+ .reply(200);
+
+ // Add comment to Security PR indicating why
+ // it has been closed
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/issues/${securityPrNumber}/comments`, {
+ body: 'Closed due to corresponding app/test PR being moved to a draft state.'
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'converted_to_draft',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ draft: false,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Application/Test PR - has promote from draft button pressed', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'ready_for_review',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ draft: false,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Application/Test PR - has review dismissed', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Provide source PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls/${appTestPrNumber}`)
+ .reply(200, {
+ number: appTestPrNumber,
+ state: 'open',
+ draft: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'main'
+ },
+ mergeable_state: 'blocked'
+ });
+
+ // Provide Security PR branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/branches/${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, {
+ name: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`
+ });
+
+ // Provide Security PR list
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls?head=${reposOwner}%3A${reposOwner}%2F${appTestsRepoName}%2F${appTestHeadRef}`)
+ .reply(200, []);
+
+ // Get checks for App/Test PR ref
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ conclusion: 'success'
+ }
+ ],
+ total_count: 1
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'dismissed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ draft: false,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Application/Test PR - An action on a PR which is already merged', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'ready_for_review',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ draft: false,
+ merged: true,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Application/Test PR - No config exists', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(404);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'opened',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ draft: false,
+ merged: true,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Application/Test PR - PR has a new push, but is in draft state', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'synchronize',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ draft: true,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Application/Test PR - PR is opened, but is in draft state', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'opened',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ draft: true,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Application/Test PR - PR is reopened, but is in draft state', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'reopened',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ draft: true,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'main'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ No action.
+ */
+ test('Application/Test PR - PR is closed, but target branch does not have Security as a required check', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test someOddBranch branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/someOddBranch`)
+ .reply(200, {
+ name: 'someOddBranch',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: []
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'closed',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ draft: false,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'someOddBranch'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ Do nothing, let the CI pipeline deal with everything.
+ */
+ test('Application/Test PR - PR is reopened, but target branch does not have Security as a required check', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/someOddBranch`)
+ .reply(200, {
+ name: 'someOddBranch',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: []
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'reopened',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ merged: false,
+ head: {
+ ref: appTestHeadRef
+ },
+ base: {
+ ref: 'someOddBranch'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ Do nothing, target branch doesn't have 'Security' as a required check,
+ so SDV is switched off, so there shouldn't be a related Security PR.
+ */
+ test('Application/Test PR - PR has new push, but target branch does not have Security as a required check', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/someOddBranch`)
+ .reply(200, {
+ name: 'someOddBranch',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: []
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'synchronize',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ draft: false,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'someOddBranch'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ Do nothing, target branch doesn't have 'Security' as a required check,
+ so SDV is switched off, so there shouldn't be a related Security PR.
+ */
+ test('Application/Test PR - PR is converted to draft, but target branch does not have Security as a required check', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/someOddBranch`)
+ .reply(200, {
+ name: 'someOddBranch',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: []
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'converted_to_draft',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ draft: false,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'someOddBranch'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ Do nothing, CI pipeline will handle things
+ */
+ test('Application/Test PR - PR is promoted from draft, but target branch does not have Security as a required check', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/someOddBranch`)
+ .reply(200, {
+ name: 'someOddBranch',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: []
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'ready_for_review',
+ repository: {
+ name: appTestsRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: appTestPrNumber,
+ draft: false,
+ merged: false,
+ head: {
+ ref: appTestHeadRef,
+ sha: appTestHeadSha
+ },
+ base: {
+ ref: 'someOddBranch'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ afterEach(() => {
+ if (!nock.isDone()) {
+ throw new Error(
+ `Not all nock interceptors were used: ${JSON.stringify(
+ nock.pendingMocks()
+ )}`
+ );
+ }
+
+ nock.cleanAll();
+ nock.enableNetConnect();
+ });
+});
diff --git a/lib/__tests__/securityRepoPullRequestActions.test.js b/lib/__tests__/securityRepoPullRequestActions.test.js
new file mode 100644
index 0000000..751785c
--- /dev/null
+++ b/lib/__tests__/securityRepoPullRequestActions.test.js
@@ -0,0 +1,2548 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const fetch = require('node-fetch');
+const nock = require('nock');
+
+const {
+ Probot, ProbotOctokit
+} = require('probot');
+
+globalThis.fetch = fetch;
+
+const sdvApprovalApp = require('../app');
+
+const getRouter = () => ({
+ use: jest.fn(),
+ get: jest.fn()
+});
+
+describe('Security Repository Pull Request event tests', () => {
+ let probot;
+
+ const reposOwner = 'cics-sdv';
+ const appTestsRepoName = 'galasa-tests-repo';
+ const appTestHeadRef = 'newBranchChange';
+ const securityRepoName = 'application-security';
+ const appTestPrNumber = 12;
+ const securityPrNumber = 86;
+ const appTestHeadSha = 'abcd1234';
+ const securityHeadSha = 'blah78657';
+ const securityPrUrl = 'http://github.com/123';
+
+ const sdvConfigYaml = `security_repo_owner: ${reposOwner}\nsecurity_repo_name: ${securityRepoName}`;
+
+ beforeEach(async () => {
+ nock.disableNetConnect();
+
+ probot = new Probot({
+ githubToken: 'test',
+ // Disable throttling & retrying requests for easier testing
+ Octokit: ProbotOctokit.defaults({
+ retry: { enabled: false },
+ throttle: { enabled: false }
+ })
+ });
+ sdvApprovalApp(probot, { getRouter });
+ });
+
+ /*
+ When this happens, it should create a Security check
+ */
+ test('Security PR - is opened for a branch that is related to SDV and a Security check does not already exist.', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Create Security PR Up-To-Date Check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/check-runs`, {
+ head_sha: securityHeadSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ })
+ .reply(201);
+
+ // Get AppTest Security Check
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [],
+ total_count: 0
+ });
+
+ // Created the Security Check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${appTestsRepoName}/check-runs`, {
+ name: 'Security',
+ head_sha: appTestHeadSha,
+ status: 'in_progress',
+ output: {
+ title: 'Awaiting approval of security PR',
+ summary: 'Awaiting approval of security PR'
+ }
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'opened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ html_url: securityPrUrl,
+ draft: false,
+ merged: false,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, it should update the appTest PR Security check to in progress
+ */
+ test('Security PR - is opened for a branch that is related to SDV and a Security check does already exist.', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Create Security PR Up-To-Date Check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/check-runs`, {
+ head_sha: securityHeadSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ })
+ .reply(201);
+
+ // Get AppTest Security Check
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'in_progress'
+ }
+ ],
+ total_count: 1
+ });
+
+ // Created the Security Check
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${appTestsRepoName}/check-runs/1`, {
+ status: 'in_progress',
+ output: {
+ title: 'Awaiting approval of security PR',
+ summary: 'Awaiting approval of security PR'
+ }
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'opened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ html_url: securityPrUrl,
+ draft: false,
+ merged: false,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken, this is happening
+ outside the SDV process
+ */
+ test('Security PR - is opened for a non-SDV created branch', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'opened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ html_url: securityPrUrl,
+ draft: false,
+ merged: false,
+ head: {
+ ref: 'randomBranch',
+ sha: 'gfghdghrdgrg'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken, this is happening
+ outside the SDV process
+ */
+ test('Security PR - is closed and its NOT an SDV created PR.', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'closed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ html_url: securityPrUrl,
+ draft: false,
+ merged: false,
+ head: {
+ ref: 'randomBranch',
+ sha: 'gfghdghrdgrg'
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, it should update the appTest PR Security check to failed
+ */
+ test('Security PR - is closed and it IS an SDV created PR.', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get AppTest PR Security Check
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'in_progress'
+ }
+ ],
+ total_count: 1
+ });
+
+ // Close the Security Check
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${appTestsRepoName}/check-runs/1`, {
+ status: 'completed',
+ conclusion: 'failure',
+ output: {
+ title: 'Security PR closed',
+ summary: 'Security PR closed'
+ }
+ })
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'closed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ html_url: securityPrUrl,
+ draft: false,
+ merged: false,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, set app/test Security check to 'in progress' and waiting
+ */
+ test('Security PR - is reopened in draft WITH an associated app/test PR existing', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get pull request list from App/Test repo
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls?state=open&head=${reposOwner}%3A${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: appTestPrNumber,
+ base: {
+ ref: 'main'
+ }
+ }
+ ]);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Create Up-to-date check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/check-runs`, {
+ head_sha: securityHeadSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ })
+ .reply(201);
+
+ // Get Security Check on AppTest commit
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'completed',
+ conclusion: 'failure',
+ head_sha: appTestHeadSha
+ }
+ ],
+ total_count: 1
+ });
+
+ // Create new check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${appTestsRepoName}/check-runs`, {
+ head_sha: appTestHeadSha,
+ name: 'Security',
+ status: 'in_progress',
+ output: {
+ title: 'Awaiting full approval of security PR',
+ summary: `The changes in this PR will result in a change of security usage.\n\nThe security changes found are currently awaiting a Security approval [here](${securityPrUrl}).\n\n#### Review status\nAwaiting for reviewers to be assigned.`
+ }
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'reopened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: true,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, set app/test Security check to 'in progress' and revaulates all
+ existing reviews
+ */
+ test('Security PR - is reopened not in draft with no existing review comments, WITH an associated app/test PR existing', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get pull request list from App/Test repo
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls?state=open&head=${reposOwner}%3A${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: appTestPrNumber,
+ base: {
+ ref: 'main'
+ }
+ }
+ ]);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Create Up-to-date check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/check-runs`, {
+ head_sha: securityHeadSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ })
+ .reply(201);
+
+ // Get Security Check on AppTest commit
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'completed',
+ conclusion: 'failure',
+ head_sha: appTestHeadSha
+ }
+ ],
+ total_count: 1
+ });
+
+ // Get list of requested reviewers on the Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/requested_reviewers`)
+ .reply(200, {
+ users: [
+ {
+ id: '1',
+ login: 'justADev'
+ }
+ ],
+ teams: [
+ {
+ id: 2,
+ name: 'security-admins'
+ }
+ ]
+ });
+
+ // Get list of reviews against Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews`)
+ .reply(200, []);
+
+ // Create new check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${appTestsRepoName}/check-runs`, {
+ head_sha: appTestHeadSha,
+ name: 'Security',
+ status: 'in_progress',
+ output: {
+ title: 'Awaiting full approval of security PR',
+ summary: `The changes in this PR will result in a change of security usage.\n\nThe security changes found are currently awaiting Security approval [here](${securityPrUrl}).\n\n#### Review status\n Reviewer Status Details \n \n\nTeam: \`security-admins\` \n\n \n\n:clock1:\n\n Awaiting review... \n \n\n@justADev\n\n \n\n:clock1:\n\n Awaiting review... \n
\n`
+ }
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'reopened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, set app/test Security check to 'in progress' and revaulates all
+ existing reviews
+ */
+ test('Security PR - is reopened not in draft state and with previous rejecting review comments, WITH an associated app/test PR existing', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get pull request list from App/Test repo
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls?state=open&head=${reposOwner}%3A${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: appTestPrNumber,
+ base: {
+ ref: 'main'
+ }
+ }
+ ]);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Create Up-to-date check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/check-runs`, {
+ head_sha: securityHeadSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ })
+ .reply(201);
+
+ // Get Security Check on AppTest commit
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'completed',
+ conclusion: 'failure',
+ head_sha: appTestHeadSha
+ }
+ ],
+ total_count: 1
+ });
+
+ // Get list of requested reviewers on the Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/requested_reviewers`)
+ .reply(200, {
+ users: [],
+ teams: []
+ });
+
+ // Get list of reviews against Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews`)
+ .reply(200, [
+ {
+ id: 123,
+ user: {
+ login: 'securityAdminUser'
+ },
+ body: 'bad change',
+ state: 'CHANGES_REQUESTED'
+ }
+ ]);
+
+ // Get comments for each review
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews/123/comments`)
+ .reply(200, [
+ {
+ id: 7657,
+ body: 'this is the comment body of a bad change'
+ }
+ ]);
+
+ // Update existing check
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${appTestsRepoName}/check-runs/1`, {
+ status: 'completed',
+ output: {
+ title: 'Security reviewer concerns',
+ summary: '#### Review status\n Reviewer Status Details \n \n\n@securityAdminUser\n\n \n\n:x:\n\n \n\nbad change\n\n\n* this is the comment body of a bad change\n\n\n \n
\n'
+ },
+ conclusion: 'failure'
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'reopened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, set app/test Security check to 'in progress' and revaulates all
+ existing reviews
+ */
+ test('Security PR - is reopened not in draft state and with previous approving review comments with all other checks passed, WITH an associated app/test PR existing', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get pull request list from App/Test repo
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls?state=open&head=${reposOwner}%3A${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: appTestPrNumber,
+ base: {
+ ref: 'main'
+ }
+ }
+ ]);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Create Up-to-date check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/check-runs`, {
+ head_sha: securityHeadSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ })
+ .reply(201);
+
+ // Get Security Check on AppTest commit
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'completed',
+ conclusion: 'failure',
+ head_sha: appTestHeadSha
+ }
+ ],
+ total_count: 1
+ });
+
+ // Get list of requested reviewers on the Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/requested_reviewers`)
+ .reply(200, {
+ users: [],
+ teams: []
+ });
+
+ // Get list of reviews against Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews`)
+ .reply(200, [
+ {
+ id: 123,
+ user: {
+ login: 'securityAdminUser'
+ },
+ body: 'great change',
+ state: 'APPROVED'
+ }
+ ]);
+
+ // Get comments for each review
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews/123/comments`)
+ .reply(200, [
+ {
+ id: 7657,
+ body: 'this is the comment body of a great change'
+ }
+ ]);
+
+ // Get Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ mergeable_state: 'has_hooks'
+ });
+
+ // Update existing check
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${appTestsRepoName}/check-runs/1`, {
+ status: 'completed',
+ output: {
+ title: 'Security approved',
+ summary: '#### Review status\n Reviewer Status Details \n \n\n@securityAdminUser\n\n \n\n:white_check_mark:\n\n \n\ngreat change\n\n* this is the comment body of a great change\n\n\n \n
\n'
+ },
+ conclusion: 'success'
+ })
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'reopened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Security PR - is reopened not in draft state and with previous approving review comments WITHOUT all other checks passed, WITH an associated app/test PR existing', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get pull request list from App/Test repo
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls?state=open&head=${reposOwner}%3A${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: appTestPrNumber,
+ base: {
+ ref: 'main'
+ }
+ }
+ ]);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Create Up-to-date check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/check-runs`, {
+ head_sha: securityHeadSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ })
+ .reply(201);
+
+ // Get Security Check on AppTest commit
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'completed',
+ conclusion: 'failure',
+ head_sha: appTestHeadSha
+ }
+ ],
+ total_count: 1
+ });
+
+ // Get list of requested reviewers on the Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/requested_reviewers`)
+ .reply(200, {
+ users: [],
+ teams: []
+ });
+
+ // Get list of reviews against Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews`)
+ .reply(200, [
+ {
+ id: 123,
+ user: {
+ login: 'securityAdminUser'
+ },
+ body: 'great change',
+ state: 'APPROVED'
+ }
+ ]);
+
+ // Get comments for each review
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews/123/comments`)
+ .reply(200, [
+ {
+ id: 7657,
+ body: 'this is the comment body of a great change'
+ }
+ ]);
+
+ // Get Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ mergeable_state: 'blocked'
+ });
+
+ // Update existing check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${appTestsRepoName}/check-runs`, {
+ name: 'Security',
+ head_sha: appTestHeadSha,
+ status: 'in_progress',
+ output: {
+ title: 'Awaiting full approval of security PR',
+ summary: `The changes in this PR will result in a change of security usage.\n\nThe security changes found are currently awaiting a Security approval [here](${securityPrUrl}).\n\n#### Review status\nAwaiting for reviewers to be assigned.`
+ }
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'reopened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, if there is no matching App/Test PR, then the security
+ PR just reopened is useless. Immediately close it again.
+ */
+ test('Security PR - is reopened WITHOUT an associated app/test PR existing', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get pull request list from App/Test repo
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls?state=open&head=${reposOwner}%3A${appTestHeadRef}`)
+ .reply(200, []);
+
+ // Close Security PR
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`, {
+ state: 'closed'
+ })
+ .reply(200);
+
+ // Add comment to Security PR
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/issues/${securityPrNumber}/comments`, {
+ body: 'Closed due to no corresponding open app/test PR existing requiring review.'
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'reopened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Security PR - an approved review is submitted with App/Test PR Security check waiting.', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get App/Test PR Security check
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'in_progress',
+ head_sha: appTestHeadSha
+ }
+ ],
+ total_count: 1
+ });
+
+ // Get list of requested reviewers on the Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/requested_reviewers`)
+ .reply(200, {
+ users: [],
+ teams: []
+ });
+
+ // Get list of reviews against Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews`)
+ .reply(200, [
+ {
+ id: 123,
+ user: {
+ login: 'securityAdminUser'
+ },
+ body: 'great change',
+ state: 'APPROVED'
+ }
+ ]);
+
+ // Get comments for each review
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews/123/comments`)
+ .reply(200, [
+ {
+ id: 7657,
+ body: 'this is the comment body of a great change'
+ }
+ ]);
+
+ // Get Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ mergeable_state: 'has_hooks'
+ });
+
+ // Update existing check
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${appTestsRepoName}/check-runs/1`, {
+ status: 'completed',
+ output: {
+ title: 'Security approved',
+ summary: '#### Review status\n Reviewer Status Details \n \n\n@securityAdminUser\n\n \n\n:white_check_mark:\n\n \n\ngreat change\n\n* this is the comment body of a great change\n\n\n \n
\n'
+ },
+ conclusion: 'success'
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'submitted',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, the App/Test PR Security check should still be failed,
+ however, the check text will display the reviews from both users.
+ */
+ test('Security PR - an approved review is submitted with App/Test PR Security check waiting, but with an existing rejected review by another user.', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get App/Test PR Security check
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'in_progress',
+ head_sha: appTestHeadSha
+ }
+ ],
+ total_count: 1
+ });
+
+ // Get list of requested reviewers on the Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/requested_reviewers`)
+ .reply(200, {
+ users: [],
+ teams: []
+ });
+
+ // Get list of reviews against Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews`)
+ .reply(200, [
+ {
+ id: 123,
+ user: {
+ login: 'securityAdminUser'
+ },
+ body: 'great change',
+ state: 'APPROVED'
+ },
+ {
+ id: 6546,
+ user: {
+ login: 'SecondSecurityAdminUser'
+ },
+ body: 'bad change',
+ state: 'CHANGES_REQUESTED'
+ }
+ ]);
+
+ // Get comments for each review
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews/123/comments`)
+ .reply(200, [
+ {
+ id: 7657,
+ body: 'this is the comment body of a great change'
+ }
+ ]);
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews/6546/comments`)
+ .reply(200, [
+ {
+ id: 754747,
+ body: 'this needs serious work'
+ }
+ ]);
+
+ // Update existing check
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${appTestsRepoName}/check-runs/1`, {
+ status: 'completed',
+ output: {
+ title: 'Security reviewer concerns',
+ summary: '#### Review status\n Reviewer Status Details \n \n\n@SecondSecurityAdminUser\n\n \n\n:x:\n\n \n\nbad change\n\n\n* this needs serious work\n\n\n \n \n\n@securityAdminUser\n\n \n\n:white_check_mark:\n\n \n\ngreat change\n\n* this is the comment body of a great change\n\n\n \n
\n'
+ },
+ conclusion: 'failure'
+ })
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'submitted',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, the App/Test PR Security check should pass,
+ the previous rejected review should be considered old, thus ignored.
+ */
+ test('Security PR - an approved review is submitted with App/Test PR Security check waiting, but a rejected review by the same user exists.', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get App/Test PR Security check
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'in_progress',
+ head_sha: appTestHeadSha
+ }
+ ],
+ total_count: 1
+ });
+
+ // Get list of requested reviewers on the Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/requested_reviewers`)
+ .reply(200, {
+ users: [],
+ teams: []
+ });
+
+ // Get list of reviews against Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews`)
+ .reply(200, [
+ {
+ id: 6546,
+ user: {
+ login: 'securityAdminUser'
+ },
+ body: 'bad change',
+ state: 'CHANGES_REQUESTED'
+ },
+ {
+ id: 123,
+ user: {
+ login: 'securityAdminUser'
+ },
+ body: 'great change',
+ state: 'APPROVED'
+ }
+ ]);
+
+ // Get comments for each review
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews/123/comments`)
+ .reply(200, [
+ {
+ id: 7657,
+ body: 'this is the comment body of a great change'
+ }
+ ]);
+
+ // Get Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ mergeable_state: 'has_hooks'
+ });
+
+ // Update existing check
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${appTestsRepoName}/check-runs/1`, {
+ status: 'completed',
+ output: {
+ title: 'Security approved',
+ summary: '#### Review status\n Reviewer Status Details \n \n\n@securityAdminUser\n\n \n\n:white_check_mark:\n\n \n\ngreat change\n\n* this is the comment body of a great change\n\n\n \n
\n'
+ },
+ conclusion: 'success'
+ })
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'submitted',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, the App/Test PR Security check should fail,
+ the previous approved review should be considered old, thus ignored.
+ */
+ test('Security PR - a rejected review is submitted with App/Test PR Security check waiting, but an approved review by the same user exists.', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get App/Test PR Security check
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'in_progress',
+ head_sha: appTestHeadSha
+ }
+ ],
+ total_count: 1
+ });
+
+ // Get list of requested reviewers on the Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/requested_reviewers`)
+ .reply(200, {
+ users: [],
+ teams: []
+ });
+
+ // Get list of reviews against Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews`)
+ .reply(200, [
+ {
+ id: 123,
+ user: {
+ login: 'securityAdminUser'
+ },
+ body: 'great change',
+ state: 'APPROVED'
+ },
+ {
+ id: 6546,
+ user: {
+ login: 'securityAdminUser'
+ },
+ body: 'bad change',
+ state: 'CHANGES_REQUESTED'
+ }
+ ]);
+
+ // Get comments for each review
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews/6546/comments`)
+ .reply(200, [
+ {
+ id: 6546,
+ body: 'this is the comment body of a bad change'
+ }
+ ]);
+
+ // Update existing check
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${appTestsRepoName}/check-runs/1`, {
+ status: 'completed',
+ output: {
+ title: 'Security reviewer concerns',
+ summary: '#### Review status\n Reviewer Status Details \n \n\n@securityAdminUser\n\n \n\n:x:\n\n \n\nbad change\n\n\n* this is the comment body of a bad change\n\n\n \n
\n'
+ },
+ conclusion: 'failure'
+ })
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'submitted',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, the App/Test PR Security check should fail,
+ the check text shows all the review information for all users.
+ */
+ test('Security PR - an rejected review is submitted with App/Test PR Security check waiting, with many other rejected reviews by other users.', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get App/Test PR Security check
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'in_progress',
+ head_sha: appTestHeadSha
+ }
+ ],
+ total_count: 1
+ });
+
+ // Get list of requested reviewers on the Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/requested_reviewers`)
+ .reply(200, {
+ users: [],
+ teams: []
+ });
+
+ // Get list of reviews against Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews`)
+ .reply(200, [
+ {
+ id: 123,
+ user: {
+ login: 'securityAdminUser'
+ },
+ body: 'bad change',
+ state: 'CHANGES_REQUESTED'
+ },
+ {
+ id: 6546,
+ user: {
+ login: 'secondSecurityAdminUser'
+ },
+ body: 'bad change 2',
+ state: 'CHANGES_REQUESTED'
+ },
+ {
+ id: 76575,
+ user: {
+ login: 'thirdSecurityAdminUser'
+ },
+ body: 'bad change 3',
+ state: 'CHANGES_REQUESTED'
+ }
+ ]);
+
+ // Get comments for each review
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews/6546/comments`)
+ .reply(200, [
+ {
+ id: 6546,
+ body: 'this is the comment body of a bad change 2'
+ }
+ ]);
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews/123/comments`)
+ .reply(200, [
+ {
+ id: 654734,
+ body: 'this is the comment body of a bad change'
+ }
+ ]);
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews/76575/comments`)
+ .reply(200, [
+ {
+ id: 654752534,
+ body: 'this is the comment body of a bad change 3'
+ }
+ ]);
+
+ // Update existing check
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${appTestsRepoName}/check-runs/1`, {
+ status: 'completed',
+ output: {
+ title: 'Security reviewer concerns',
+ summary: '#### Review status\n Reviewer Status Details \n \n\n@securityAdminUser\n\n \n\n:x:\n\n \n\nbad change\n\n\n* this is the comment body of a bad change\n\n\n \n \n\n@secondSecurityAdminUser\n\n \n\n:x:\n\n \n\nbad change 2\n\n\n* this is the comment body of a bad change 2\n\n\n \n \n\n@thirdSecurityAdminUser\n\n \n\n:x:\n\n \n\nbad change 3\n\n\n* this is the comment body of a bad change 3\n\n\n \n
\n'
+ },
+ conclusion: 'failure'
+ })
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'submitted',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken. A full review is the only
+ way comments are send back to the app/test PR.
+ */
+ test('Security PR - is commented on', async () => {
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review_comment',
+ payload: {
+ action: 'created',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ merged: false,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ });
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Security PR - has update branch button pressed/commit pushed', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Create Security PR Up-To-Date Check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/check-runs`, {
+ head_sha: securityHeadSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'synchronize',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ merged: false,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Security PR - has demote to draft button pressed', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'converted_to_draft',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, it will reassess the review status based on any
+ previously existing reviews. If there are none, it makes the Security
+ check 'in progress'.
+ */
+ test('Security PR - has promote from draft button pressed, and app/test branch exists', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Create Security PR Up-To-Date Check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/check-runs`, {
+ head_sha: securityHeadSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ })
+ .reply(201);
+
+ // Get Security Check on AppTest commit
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'in_progress',
+ head_sha: appTestHeadSha
+ }
+ ],
+ total_count: 1
+ });
+
+ // Get list of requested reviewers on the Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/requested_reviewers`)
+ .reply(200, {
+ users: [],
+ teams: []
+ });
+
+ // Get list of reviews against Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews`)
+ .reply(200, []);
+
+ // Get Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ mergeable_state: 'blocked'
+ });
+
+ // Update existing check
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${appTestsRepoName}/check-runs/1`, {
+ status: 'in_progress',
+ output: {
+ title: 'Awaiting full approval of security PR',
+ summary: `The changes in this PR will result in a change of security usage.\n\nThe security changes found are currently awaiting a Security approval [here](${securityPrUrl}).\n\n#### Review status\nAwaiting for reviewers to be assigned.`
+ }
+ })
+ .reply(200);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'ready_for_review',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, it will immediately close the Security PR.
+ */
+ test('Security PR - has promote from draft button pressed, but no app/test branch exists', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(404);
+
+ // Close Security PR
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`, {
+ state: 'closed'
+ })
+ .reply(200);
+
+ // Create comment on the Security PR
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/issues/${securityPrNumber}/comments`, {
+ body: 'Closed due to no corresponding app/test branch existing.'
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'ready_for_review',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, it will reasses the Security check status
+ by rechecking remaining reviews, there are none, therefore updates
+ the app/test PR Security checked from Failed to in progress.
+ */
+ test('Security PR - has a sole rejected review dismissed', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get Security Check on AppTest commit
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'completed',
+ conclusion: 'failed',
+ head_sha: appTestHeadSha
+ }
+ ],
+ total_count: 1
+ });
+
+ // Get list of requested reviewers on the Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/requested_reviewers`)
+ .reply(200, {
+ users: [],
+ teams: []
+ });
+
+ // Get list of reviews against Security PR
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}/reviews`)
+ .reply(200, [
+ {
+ id: 123,
+ user: {
+ login: 'securityAdminUser'
+ },
+ body: 'bad change',
+ state: 'DISMISSED'
+ }
+ ]);
+
+ // Get Security PR object
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`)
+ .reply(200, {
+ number: securityPrNumber,
+ mergeable_state: 'blocked'
+ });
+
+ // Update existing check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${appTestsRepoName}/check-runs`, {
+ name: 'Security',
+ head_sha: appTestHeadSha,
+ status: 'in_progress',
+ output: {
+ title: 'Awaiting full approval of security PR',
+ summary: 'The changes in this PR will result in a change of security usage.\n\nThe security changes found are currently awaiting a Security approval [here](http://github.com/123).\n\n#### Review status\nAwaiting for reviewers to be assigned.'
+ }
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'dismissed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ });
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Security PR - No config exists', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(404);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'opened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: true,
+ head: {
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, it will immediately close the Security PR.
+ */
+ test('Security PR - PR is opened with no matching branch, but in draft state', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(404);
+
+ // Close Security PR
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`, {
+ state: 'closed'
+ })
+ .reply(200);
+
+ // Create comment on the Security PR
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/issues/${securityPrNumber}/comments`, {
+ body: 'Closed due to no corresponding app/test branch existing.'
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'opened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: true,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, it will immediately close the Security PR.
+ */
+ test('Security PR - PR is reopened with no matching branch, but in draft state', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(404);
+
+ // Close Security PR
+ nock('https://api.github.com')
+ .patch(`/repos/${reposOwner}/${securityRepoName}/pulls/${securityPrNumber}`, {
+ state: 'closed'
+ })
+ .reply(200);
+
+ // Create comment on the Security PR
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/issues/${securityPrNumber}/comments`, {
+ body: 'Closed due to no corresponding app/test branch existing.'
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'reopened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: true,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, it will immediately close the Security PR.
+ */
+ test('Security PR - PR is reopened with a matching branch, but in draft state', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get pull request list from App/Test repo
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls?state=open&head=${reposOwner}%3A${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: appTestPrNumber,
+ base: {
+ ref: 'main'
+ }
+ }
+ ]);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: [
+ {
+ context: 'Security',
+ app_id: null
+ }
+ ]
+ }
+ }
+ });
+
+ // Create Security PR Up-To-Date Check
+ nock('https://api.github.com')
+ .post(`/repos/${reposOwner}/${securityRepoName}/check-runs`, {
+ head_sha: securityHeadSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ })
+ .reply(201);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'reopened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: true,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ When this happens, no action is taken
+ */
+ test('Security PR - an approved review is submitted with PR in draft state.', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request_review',
+ payload: {
+ action: 'submitted',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: true,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ Nothing happens, the 'Security' check is not required on
+ the app/test PR target branch, so SDV process is not active.
+ */
+ test('Security PR - PR is reopened, but the target branch for the app/test PR does not have Security as a required check', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get pull request list from App/Test repo
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/pulls?state=open&head=${reposOwner}%3A${appTestHeadRef}`)
+ .reply(200, [
+ {
+ number: appTestPrNumber,
+ base: {
+ ref: 'main'
+ }
+ }
+ ]);
+
+ // Provide App/Test main branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/main`)
+ .reply(200, {
+ name: 'main',
+ protection: {
+ enabled: true,
+ required_status_checks: {
+ checks: []
+ }
+ }
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'reopened',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ draft: false,
+ merged: false,
+ html_url: securityPrUrl,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ /*
+ This should never happen, but it could if someone wanted to break
+ things, either way, a skipped 'Security' check indicates that the
+ 'Security' check is not set as required on the target branch.
+ Therefore, don't take any action.
+ */
+ test('Security PR - PR is closed, but the app/test PR has its Security check as skipped', async () => {
+ // Provide sdvapproval.yml
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${securityRepoName}/contents/.github%2Fsdvapproval.yml`)
+ .matchHeader('accept', 'application/vnd.github.v3.raw')
+ .reply(200, sdvConfigYaml);
+
+ // Get AppTest branch
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/branches/${appTestHeadRef}`)
+ .reply(200, {
+ name: `${appTestHeadRef}`,
+ commit: {
+ sha: appTestHeadSha
+ }
+ });
+
+ // Get AppTest PR Security Check
+ nock('https://api.github.com')
+ .get(`/repos/${reposOwner}/${appTestsRepoName}/commits/${appTestHeadSha}/check-runs`)
+ .query({
+ check_name: 'Security',
+ filter: 'latest'
+ })
+ .reply(200, {
+ check_runs: [
+ {
+ id: '1',
+ status: 'completed',
+ conclusion: 'skipped'
+ }
+ ],
+ total_count: 1
+ });
+
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request',
+ payload: {
+ action: 'closed',
+ repository: {
+ name: securityRepoName,
+ owner: {
+ login: reposOwner
+ }
+ },
+ pull_request: {
+ number: securityPrNumber,
+ html_url: securityPrUrl,
+ draft: false,
+ merged: false,
+ head: {
+ ref: `${reposOwner}/${appTestsRepoName}/${appTestHeadRef}`,
+ sha: securityHeadSha
+ }
+ }
+ }
+ });
+ }, 10000);
+
+ afterEach(() => {
+ if (!nock.isDone()) {
+ throw new Error(
+ `Not all nock interceptors were used: ${JSON.stringify(
+ nock.pendingMocks()
+ )}`
+ );
+ }
+
+ nock.cleanAll();
+ nock.enableNetConnect();
+ });
+});
diff --git a/lib/actions/appTestDeleteAction.js b/lib/actions/appTestDeleteAction.js
new file mode 100644
index 0000000..11fdfba
--- /dev/null
+++ b/lib/actions/appTestDeleteAction.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+async function processAppTestDeleteAction(app, context, config) {
+ const owner = context.payload.repository.owner.login;
+ const repo = context.payload.repository.name;
+ const branch = context.payload.ref;
+
+ const logData = {
+ owner,
+ repo,
+ branch
+ };
+
+ try {
+ app.log.debug(logData, 'APP/TEST DELETE WEBHOOK RECEIVED:\n');
+
+ // Check if branch exists on Security repo
+ let securityBranch = null;
+ try {
+ securityBranch = await context.octokit.repos.getBranch({
+ owner: config.security_repo_owner,
+ repo: config.security_repo_name,
+ branch: `${owner}/${repo}/${branch}`
+ })
+ .then((result) => result.data);
+ } catch (exception) {
+ app.log.debug(logData, `No open Security PR found for branch ${owner}/${repo}/${branch}`);
+ }
+
+ // If found, delete the branch
+ if (securityBranch) {
+ await context.octokit.git.deleteRef({
+ owner: config.security_repo_owner,
+ repo: config.security_repo_name,
+ ref: `heads/${owner}/${repo}/${branch}`
+ });
+ }
+
+ app.log.debug(logData, 'SUCCESSFULLY COMPLETED APP/TEST DELETE WEBHOOK');
+ } catch (exception) {
+ app.log.error(logData, exception.stack);
+ throw exception;
+ }
+}
+
+module.exports = {
+ processAppTestDeleteAction
+};
diff --git a/lib/actions/appTestPrAction.js b/lib/actions/appTestPrAction.js
new file mode 100644
index 0000000..8e94751
--- /dev/null
+++ b/lib/actions/appTestPrAction.js
@@ -0,0 +1,223 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+async function processAppTestPrAction(app, context, config) {
+ const owner = context.payload.repository.owner.login;
+ const repo = context.payload.repository.name;
+ const branch = context.payload.pull_request.head.ref;
+ const prNumber = context.payload.pull_request.number;
+ const targetBranch = context.payload.pull_request.base.ref;
+
+ const logData = {
+ owner,
+ repo,
+ prNumber,
+ branch
+ };
+
+ try {
+ app.log.debug(logData, 'APP/TEST PR REVIEW WEBHOOK RECEIVED:\n');
+
+ // Get branch protection info of target
+ let appTestTargetBranchInfo = null;
+ try {
+ appTestTargetBranchInfo = await context.octokit.repos.getBranch({
+ owner,
+ repo,
+ branch: targetBranch
+ })
+ .then((result) => result.data);
+ } catch (exception) {
+ app.log.debug(logData, `Branch ${targetBranch} not found in repo ${owner}/${repo}`);
+ }
+
+ // Only process if target branch has the 'Security' check
+ // set to 'required' on branch protection
+ if (appTestTargetBranchInfo
+ && appTestTargetBranchInfo.protection.enabled
+ && appTestTargetBranchInfo.protection.required_status_checks.checks.some(
+ (e) => e.context === process.env.CHECK_NAME
+ )
+ ) {
+ // Only process if this is a PR that isn't already
+ // merged.
+ if (!context.payload.pull_request.merged) {
+ switch (context.payload.action) {
+ case 'closed': {
+ // The App or Test Pr has been closed.
+ // This could have been manually done by a user, or
+ // happened as part of the merge of a PR.
+ // Try to close any related Security PR.
+ app.log.debug(logData, `'close' action for pull request ${prNumber} intercepted.`);
+
+ // Check PR exists in security repo
+ let securityPR = null;
+ try {
+ securityPR = await context.octokit.pulls.list({
+ owner: config.security_repo_owner,
+ repo: config.security_repo_name,
+ state: 'open',
+ head: `${config.security_repo_owner}:${owner}/${repo}/${branch}`
+ })
+ .then((result) => {
+ if (result.data.length > 0) {
+ return result.data[0];
+ }
+ return null;
+ });
+ } catch (exception) {
+ app.log.debug(logData, `No open Security PR found for branch ${owner}/${repo}/${branch}`);
+ }
+
+ if (securityPR) {
+ // Close security PR
+ await context.octokit.pulls.update({
+ owner: config.security_repo_owner,
+ repo: config.security_repo_name,
+ pull_number: securityPR.number,
+ state: 'closed'
+ });
+
+ // Add comment
+ await context.octokit.rest.issues.createComment({
+ owner: config.security_repo_owner,
+ repo: config.security_repo_name,
+ issue_number: securityPR.number,
+ body: 'Closed due to corresponding app/test PR being closed without merge.'
+ });
+ }
+ break;
+ }
+ case 'reopened': {
+ // If an App or Test PR is reopened, do nothing.
+ // The pipeline for the PR will re-run all checks, including
+ // a new Security check, which will recreate a Security PR if
+ // required.
+ // Trying to reopen a related Security PR would just cause problems &
+ // is pointless.
+ // i.e. the security PR may contain stale data, & the Sec Admin may
+ // approve it, only to be overwritten by the new Security that will run as
+ // part of the build.
+ app.log.debug(logData, `'reopened' action for pull request ${prNumber} intercepted.`);
+ break;
+ }
+ case 'synchronize':
+ // If a user adds a new commit to their App or Test PR, or
+ // clicks 'Update Branch' because it is behind, it immediately
+ // invalidates any assoicated, open Security PR.
+ // In which case, just close any associated Security PR, and let the
+ // new build run a new Security check, which will create a fresh Security PR
+ // with updated data.
+ app.log.debug(logData, `'synchronise' action for pull request ${prNumber} intercepted.`);
+
+ if (!context.payload.pull_request.draft) {
+ let securityPR = null;
+ try {
+ securityPR = await context.octokit.pulls.list({
+ owner: config.security_repo_owner,
+ repo: config.security_repo_name,
+ state: 'open',
+ head: `${config.security_repo_owner}:${owner}/${repo}/${branch}`
+ })
+ .then((result) => {
+ if (result.data.length > 0) {
+ return result.data[0];
+ }
+ return null;
+ });
+ } catch (exception) {
+ app.log.debug(logData, `No open Security PR found for branch ${owner}/${repo}/${branch}`);
+ }
+
+ if (securityPR) {
+ // Close security PR
+ await context.octokit.pulls.update({
+ owner: config.security_repo_owner,
+ repo: config.security_repo_name,
+ pull_number: securityPR.number,
+ state: 'closed'
+ });
+
+ // Add comment
+ await context.octokit.rest.issues.createComment({
+ owner: config.security_repo_owner,
+ repo: config.security_repo_name,
+ issue_number: securityPR.number,
+ body: 'Closed due to corresponding app/test PR being updated with new code commit, which may change security.\n\nA new Security will be created, if required.'
+ });
+ }
+ } else {
+ app.log.debug(logData, 'Skipping, this PR is a draft.');
+ }
+ break;
+ case 'converted_to_draft': {
+ // A user has downgraded their App or Test PR to a draft.
+ // Getting a Sec Admin to review its security now is pointless, so
+ // close any associated Security PR.
+ // When the user takes their PR out of draft, the pipeline will
+ // run a new Security check and will create a new Security PR if required.
+ app.log.debug(logData, `'converted_to_draft' action for pull request ${prNumber} intercepted.`);
+
+ // Check PR exists in security repo
+ let securityPR = null;
+ try {
+ securityPR = await context.octokit.pulls.list({
+ owner: config.security_repo_owner,
+ repo: config.security_repo_name,
+ state: 'open',
+ head: `${config.security_repo_owner}:${owner}/${repo}/${branch}`
+ })
+ .then((result) => {
+ if (result.data.length > 0) {
+ return result.data[0];
+ }
+ return null;
+ });
+ } catch (exception) {
+ app.log.debug(logData, `No open Security PR found for branch ${owner}/${repo}/${branch}`);
+ }
+
+ if (securityPR) {
+ // Close security PR
+ await context.octokit.pulls.update({
+ owner: config.security_repo_owner,
+ repo: config.security_repo_name,
+ pull_number: securityPR.number,
+ state: 'closed'
+ });
+
+ // Add comment
+ await context.octokit.rest.issues.createComment({
+ owner: config.security_repo_owner,
+ repo: config.security_repo_name,
+ issue_number: securityPR.number,
+ body: 'Closed due to corresponding app/test PR being moved to a draft state.'
+ });
+ }
+ break;
+ }
+ case 'ready_for_review':
+ // Do nothing, the App or Test pipeline will run a new Security check.
+ app.log.debug(logData, `'ready_for_review' action for pull request ${prNumber} intercepted.`);
+ break;
+ default:
+ // Do nothing
+ }
+ } else {
+ app.log.debug(logData, 'Skipping, this PR is already merged.');
+ }
+ } else {
+ app.log.debug(logData, 'Skipping, target branch does not have necessary branch protection.');
+ }
+
+ app.log.debug(logData, 'SUCCESSFULLY COMPLETED APP/TEST PR WEBHOOK');
+ } catch (exception) {
+ app.log.error(logData, exception.stack);
+
+ throw exception;
+ }
+}
+
+module.exports = {
+ processAppTestPrAction
+};
diff --git a/lib/actions/autoMerge.js b/lib/actions/autoMerge.js
new file mode 100644
index 0000000..967ae47
--- /dev/null
+++ b/lib/actions/autoMerge.js
@@ -0,0 +1,411 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const {
+ GITHUB_SECURITY_BRANCH_REGEX
+} = require('../common/constants');
+
+async function autoMerge(app, context, config) {
+ const sourceOwner = context.payload.repository.owner.login;
+ const sourceRepo = context.payload.repository.name;
+ let targetOwner = null;
+ let targetRepo = null;
+
+ let sourcePrNumber = null;
+
+ if (context.payload.pull_request) {
+ sourcePrNumber = context.payload.pull_request.number;
+ } else if (context.payload.check_run.pull_requests.length > 0) {
+ sourcePrNumber = context.payload.check_run.pull_requests[0].number;
+ }
+
+ if (sourcePrNumber) {
+ const sourceHeadSha = (context.payload.pull_request)
+ ? context.payload.pull_request.head.sha
+ : context.payload.check_run.head_sha;
+
+ app.log.debug({}, 'Attempting to auto-merge app/test and corresponding Security PRs...');
+
+ let targetPrObj = null;
+ const sourcePrObj = await context.octokit.pulls.get({
+ owner: sourceOwner,
+ repo: sourceRepo,
+ pull_number: sourcePrNumber
+ })
+ .then((result) => {
+ if (result.data) {
+ return result.data;
+ }
+ return null;
+ });
+
+ if (sourcePrObj && sourcePrObj.state === 'open') {
+ const logData = {
+ owner: sourceOwner,
+ repo: sourceRepo,
+ sourcePrNumber,
+ sourceHeadSha
+ };
+
+ if (!sourcePrObj.draft) {
+ if (sourceOwner === config.security_repo_owner
+ && sourceRepo === config.security_repo_name) {
+ // This is a Security repo hook
+
+ // does branch follow standard?
+ if (sourcePrObj.head.ref.match(GITHUB_SECURITY_BRANCH_REGEX)) {
+ [targetOwner, targetRepo] = sourcePrObj.head.ref.split('/');
+ const targetBranch = sourcePrObj.head.ref.split('/')[2];
+
+ // Does branch exist for corresponding repo?
+ let appTestBranch = null;
+ try {
+ appTestBranch = await context.octokit.repos.getBranch({
+ owner: targetOwner,
+ repo: targetRepo,
+ branch: targetBranch
+ })
+ .then((result) => result.data);
+ } catch (exception) {
+ app.log.debug(logData, `Branch ${targetBranch} not found in repo ${targetOwner}/${targetRepo}`);
+ }
+
+ if (appTestBranch) {
+ // get PR obj for app/test repo
+ targetPrObj = await context.octokit.pulls.list({
+ owner: targetOwner,
+ repo: targetRepo,
+ head: `${targetOwner}:${appTestBranch.name}`
+ })
+ .then((result) => {
+ if (result.data.length > 0) {
+ return result.data[0];
+ }
+ return null;
+ });
+ if (targetPrObj) {
+ // Does the target branch of the app/Test PR have 'Security' as a
+ // required check on the branch protection? If not, then don't do
+ // anything & exit
+ let appTestTargetBranch = null;
+ try {
+ appTestTargetBranch = await context.octokit.repos.getBranch({
+ owner: targetOwner,
+ repo: targetRepo,
+ branch: targetPrObj.base.ref
+ })
+ .then((result) => result.data);
+ } catch (exception) {
+ app.log.debug(logData, `Branch ${targetPrObj.base.ref} not found in repo ${targetOwner}/${targetRepo}`);
+ }
+
+ if (appTestTargetBranch
+ && appTestTargetBranch.protection.enabled
+ && appTestTargetBranch.protection.required_status_checks.checks.some(
+ (e) => e.context === process.env.CHECK_NAME
+ )
+ ) {
+ // Get a more detailed PR object that contains the
+ // mergable_state attribute
+ targetPrObj = await context.octokit.pulls.get({
+ owner: targetOwner,
+ repo: targetRepo,
+ pull_number: targetPrObj.number
+ })
+ .then((result) => result.data);
+ } else {
+ targetPrObj = null;
+ app.log.debug(logData, 'Skipping, app/test PR target branch does not have necessary branch protection.');
+ }
+ } else {
+ // This is could potentially be an approved Security PR
+ // against the default branch via an overnight run.
+ // If it is approved, then just merge without worrying about
+ // a corresponding app/test PR to merge also, though, update
+ // the commit Security check!
+
+ let appTestSecurityApprovalCheckRun = null;
+ try {
+ appTestSecurityApprovalCheckRun = await context
+ .octokit.rest.checks.listForRef({
+ owner: targetOwner,
+ repo: targetRepo,
+ ref: appTestBranch.commit.sha,
+ check_name: process.env.CHECK_NAME,
+ filter: 'latest'
+ })
+ .then((result) => {
+ if (result.data.total_count > 0) {
+ return result.data.check_runs[0];
+ }
+ return null;
+ });
+ } catch (e) {
+ app.log.debug(logData, `Could not find checks or branch for ${targetOwner}/${targetRepo} - ${appTestBranch.commit.sha}`);
+ }
+
+ if (appTestSecurityApprovalCheckRun) {
+ if (['clean', 'has_hooks', 'unstable'].includes(sourcePrObj.mergeable_state)) {
+ // Merge PR
+ try {
+ await context.octokit.rest.pulls.merge({
+ owner: sourceOwner,
+ repo: sourceRepo,
+ pull_number: sourcePrObj.number
+ });
+ return;
+ } catch (e) {
+ app.log.error({}, 'Could not merge PR', e);
+ throw e;
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // App/test repo hook
+
+ // Does the target branch of this app/Test PR have 'Security' as a
+ // required check on the branch protection? If not, don't do anything
+ // and exit
+ let appTestTargetBranch = null;
+ try {
+ appTestTargetBranch = await context.octokit.repos.getBranch({
+ owner: sourceOwner,
+ repo: sourceRepo,
+ branch: sourcePrObj.base.ref
+ })
+ .then((result) => result.data);
+ } catch (exception) {
+ app.log.debug(logData, `Branch ${sourcePrObj.base.ref} not found in repo ${sourceOwner}/${sourceRepo}`);
+ }
+
+ if (appTestTargetBranch && appTestTargetBranch.protection.enabled
+ && appTestTargetBranch.protection.required_status_checks.checks.some(
+ (e) => e.context === process.env.CHECK_NAME
+ )
+ ) {
+ targetOwner = config.security_repo_owner;
+ targetRepo = config.security_repo_name;
+
+ // Does branch exist for corresponding repo?
+ let securityBranch = null;
+ try {
+ securityBranch = await context.octokit.repos.getBranch({
+ owner: targetOwner,
+ repo: targetRepo,
+ branch: `${sourceOwner}/${sourceRepo}/${sourcePrObj.head.ref}`
+ })
+ .then((result) => result.data);
+ } catch (exception) {
+ app.log.debug(logData, `Branch ${securityBranch} not found in repo ${targetOwner}/${targetRepo}`);
+ }
+
+ if (securityBranch) {
+ // get PR obj for Security repo
+ targetPrObj = await context.octokit.pulls.list({
+ owner: targetOwner,
+ repo: targetRepo,
+ head: `${targetOwner}:${securityBranch.name}`
+ })
+ .then((result) => {
+ if (result.data.length > 0) {
+ return result.data[0];
+ }
+ return null;
+ });
+ if (targetPrObj) {
+ targetPrObj = await context.octokit.pulls.get({
+ owner: targetOwner,
+ repo: targetRepo,
+ pull_number: targetPrObj.number
+ })
+ .then((result) => result.data);
+ } else {
+ // There isn't a security PR for this, but the Security check passed on the app/test
+ // Merge it.
+ let appTestSecurityApprovalCheckRun = null;
+ try {
+ appTestSecurityApprovalCheckRun = await context
+ .octokit.rest.checks.listForRef({
+ owner: sourceOwner,
+ repo: sourceRepo,
+ ref: sourceHeadSha,
+ check_name: process.env.CHECK_NAME,
+ filter: 'latest'
+ })
+ .then((result) => {
+ if (result.data.total_count > 0) {
+ return result.data.check_runs[0];
+ }
+ return null;
+ });
+ } catch (e) {
+ app.log.debug(logData, `Could not find checks or branch for ${sourceRepo}/${sourceRepo} - ${sourceHeadSha}`);
+ }
+
+ if (appTestSecurityApprovalCheckRun && appTestSecurityApprovalCheckRun.conclusion === 'success') {
+ if (['clean', 'has_hooks', 'unstable'].includes(sourcePrObj.mergeable_state)) {
+ // Merge PR
+ try {
+ await context.octokit.rest.pulls.merge({
+ owner: sourceOwner,
+ repo: sourceRepo,
+ pull_number: sourcePrObj.number
+ });
+ return;
+ } catch (e) {
+ app.log.error({}, 'Could not merge PR', e);
+ throw e;
+ }
+ }
+ }
+ }
+ } else {
+ // This app/test PR doesn't have an associated PR in Security.
+ // If however, if the app PR has a Security Check and is approved,
+ // it means a security check was made but no changes were found.
+ // The app/test PR should be merged.
+ let appTestSecurityApprovalCheckRun = null;
+ try {
+ appTestSecurityApprovalCheckRun = await context.octokit.checks.listForRef({
+ owner: sourceOwner,
+ repo: sourceRepo,
+ ref: sourceHeadSha,
+ check_name: process.env.CHECK_NAME,
+ filter: 'latest'
+ })
+ .then((result) => {
+ if (result.data.total_count > 0) {
+ return result.data.check_runs[0];
+ }
+ return null;
+ });
+ } catch (e) {
+ app.log.debug(logData, `Could not find checks or branch for ${sourceOwner}/${sourceRepo} - ${sourcePrObj.head.ref}`);
+ }
+
+ if (appTestSecurityApprovalCheckRun && appTestSecurityApprovalCheckRun.conclusion === 'success') {
+ if (['clean', 'has_hooks', 'unstable'].includes(sourcePrObj.mergeable_state)) {
+ // Merge PR
+ try {
+ await context.octokit.rest.pulls.merge({
+ owner: sourceOwner,
+ repo: sourceRepo,
+ pull_number: sourcePrObj.number
+ });
+ return;
+ } catch (e) {
+ app.log.error({}, 'Could not merge PR', e);
+ throw e;
+ }
+ }
+ }
+ }
+ } else {
+ app.log.debug(logData, 'Skipping, app/test PR target branch does not have necessary branch protection.');
+ }
+ }
+ } else {
+ app.log.debug(logData, 'Skipping, this is a draft PR.');
+ }
+ } else {
+ app.log.debug({}, 'Skipping, could not find PR.');
+ }
+
+ if (sourcePrObj && targetPrObj) {
+ // Are both PR objects mergable?
+ if (['clean', 'has_hooks', 'unstable'].includes(sourcePrObj.mergeable_state) && ['clean', 'has_hooks', 'unstable'].includes(targetPrObj.mergeable_state)) {
+ // Merge both PRs
+ try {
+ await Promise.all([
+ context.octokit.rest.pulls.merge({
+ owner: sourceOwner,
+ repo: sourceRepo,
+ pull_number: sourcePrObj.number
+ }),
+ context.octokit.rest.pulls.merge({
+ owner: targetOwner,
+ repo: targetRepo,
+ pull_number: targetPrObj.number
+ })
+ ]);
+ } catch (e) {
+ app.log.warn({}, 'Could not merge PRs', e);
+ throw e;
+ }
+ }
+ }
+ } else if (context.payload.check_run.name === process.env.CHECK_NAME && context.payload.check_run.conclusion === 'success') {
+ // If we get here, it means a 'Security' check was completed, which wasn't within a
+ // PR, and is potentially running on a main/release branch, probably following a PR merge.
+ // Check for the above, & if an open PR is found on the security repo, merge it.
+ let appTestBranch = null;
+ try {
+ appTestBranch = await context.octokit.repos.getBranch({
+ owner: sourceOwner,
+ repo: sourceRepo,
+ branch: context.payload.check_run.check_suite.head_branch
+ })
+ .then((result) => result.data);
+ } catch (exception) {
+ app.log.debug(`Branch ${context.payload.check_run.check_suite.head_branch} not found in repo ${sourceOwner}/${sourceRepo}`);
+ }
+
+ if (appTestBranch
+ && appTestBranch.protection.enabled
+ && appTestBranch.protection.required_status_checks.checks.some(
+ (e) => e.context === process.env.CHECK_NAME
+ )
+ ) {
+ targetOwner = config.security_repo_owner;
+ targetRepo = config.security_repo_name;
+
+ // get PR obj for Security repo
+ let securityPrObj = await context.octokit.pulls.list({
+ owner: targetOwner,
+ repo: targetRepo,
+ head: `${targetOwner}:${sourceOwner}/${sourceRepo}/${context.payload.check_run.check_suite.head_branch}`
+ })
+ .then((result) => {
+ if (result.data.length > 0) {
+ return result.data[0];
+ }
+ return null;
+ });
+ if (securityPrObj) {
+ securityPrObj = await context.octokit.pulls.get({
+ owner: targetOwner,
+ repo: targetRepo,
+ pull_number: securityPrObj.number
+ })
+ .then((result) => result.data);
+ }
+
+ if (securityPrObj) {
+ if (['clean', 'has_hooks', 'unstable'].includes(securityPrObj.mergeable_state)) {
+ // Merge PR
+ try {
+ await context.octokit.rest.pulls.merge({
+ owner: targetOwner,
+ repo: targetRepo,
+ pull_number: securityPrObj.number
+ });
+ } catch (e) {
+ app.log.error({}, 'Could not merge PR', e);
+ throw e;
+ }
+ }
+ }
+ } else {
+ app.log.debug('Skipping, app/test PR target branch does not have necessary branch protection.');
+ }
+ } else {
+ app.log.debug({}, 'Skipping, not a PR.');
+ }
+}
+
+module.exports = {
+ autoMerge
+};
diff --git a/lib/actions/securityDeleteAction.js b/lib/actions/securityDeleteAction.js
new file mode 100644
index 0000000..362f1f2
--- /dev/null
+++ b/lib/actions/securityDeleteAction.js
@@ -0,0 +1,74 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const { GITHUB_SECURITY_BRANCH_REGEX } = require('../common/constants');
+
+async function processSecurityDeleteAction(app, context) {
+ const owner = context.payload.repository.owner.login;
+ const repo = context.payload.repository.name;
+ const branch = context.payload.ref;
+
+ const logData = {
+ owner,
+ repo,
+ branch
+ };
+
+ if (context.payload.ref.match(GITHUB_SECURITY_BRANCH_REGEX)) {
+ const appTestRepoOwner = context.payload.ref.split('/')[0];
+ const appTestRepoName = context.payload.ref.split('/')[1];
+ const appTestRepoBranch = context.payload.ref.split('/')[2];
+
+ try {
+ app.log.debug(logData, 'SECURITY DELETE WEBHOOK RECEIVED:\n');
+
+ // Get App/Test repo PR Security check ID
+ let appTestCheckRun = null;
+ try {
+ appTestCheckRun = await context.octokit.rest.checks.listForRef({
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ ref: appTestRepoBranch,
+ check_name: process.env.CHECK_NAME,
+ filter: 'latest'
+ })
+ .then((result) => {
+ if (result.data.total_count > 0) {
+ return result.data.check_runs[0];
+ }
+ return null;
+ });
+ } catch (e) {
+ app.log.debug(logData, `Could not find checks or branch for ${appTestRepoOwner}/${appTestRepoName} - ${appTestRepoBranch}`);
+ }
+
+ // Fail Security check in app/test repo PR if its in progress
+ if (appTestCheckRun && appTestCheckRun.status === 'in_progress') {
+ await context.octokit.checks.update({
+ mediaType: {
+ previews: ['antiope-preview']
+ },
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ check_run_id: appTestCheckRun.id,
+ status: 'completed',
+ conclusion: 'failure',
+ output: {
+ title: 'Security PR closed',
+ summary: 'Security PR closed due to removed associated branch.'
+ }
+ });
+ }
+
+ app.log.debug(logData, 'SUCCESSFULLY COMPLETED SECURITY DELETE WEBHOOK');
+ } catch (exception) {
+ app.log.error(logData, exception.stack);
+
+ throw exception;
+ }
+ }
+}
+
+module.exports = {
+ processSecurityDeleteAction
+};
diff --git a/lib/actions/securityPrAction.js b/lib/actions/securityPrAction.js
new file mode 100644
index 0000000..4c3f3a6
--- /dev/null
+++ b/lib/actions/securityPrAction.js
@@ -0,0 +1,403 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const {
+ GITHUB_SECURITY_BRANCH_REGEX
+} = require('../common/constants');
+
+const {
+ updateSecurityApprovalBasedOnReviews,
+ resetSecurityCheckToWaiting
+} = require('../common/reviewProcessing');
+
+async function processSecurityPrAction(app, context) {
+ const owner = context.payload.repository.owner.login;
+ const repo = context.payload.repository.name;
+ const headSha = context.payload.pull_request.head.sha;
+ const prNumber = context.payload.pull_request.number;
+ const securityPrUrl = context.payload.pull_request.html_url;
+
+ const logData = {
+ owner,
+ repo,
+ prNumber,
+ headSha
+ };
+
+ app.log.debug(logData, 'SECURITY PR WEBHOOK RECEIVED:\n');
+
+ // Only process if this is a PR that is not already merged
+ if (!context.payload.pull_request.merged) {
+ // Check branch name follows standard, if not, ignore
+ if (context.payload.pull_request.head.ref.match(GITHUB_SECURITY_BRANCH_REGEX)) {
+ const appTestRepoOwner = context.payload.pull_request.head.ref.split('/')[0];
+ const appTestRepoName = context.payload.pull_request.head.ref.split('/')[1];
+ const appTestRepoBranch = context.payload.pull_request.head.ref.split('/')[2];
+
+ // Check branch exists in app/test repo
+ let appTestBranch = null;
+ try {
+ appTestBranch = await context.octokit.repos.getBranch({
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ branch: appTestRepoBranch
+ })
+ .then((result) => result.data);
+ } catch (exception) {
+ app.log.debug(logData, `Branch ${appTestRepoBranch} not found in repo ${appTestRepoOwner}/${appTestRepoName}`);
+ }
+
+ try {
+ switch (context.payload.action) {
+ case 'opened': {
+ // Security PR is opened.
+ // The check should already be put in place by the app / test pipeline,
+ // but incase not, ths code will update an existing one to the correct
+ // state, or will create one if there isn't one.
+
+ // Firstly, there must be a matching app / test branch,
+ // if there isn't, close this Security PR.
+ if (appTestBranch) {
+ // Create 'up-to-date' check
+ await context.octokit.rest.checks.create({
+ owner,
+ repo,
+ head_sha: headSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ });
+
+ // Security checks shouldn't be updated when the PR is in a draft state
+ if (!context.payload.pull_request.draft) {
+ // Get App/Test repo PR Security check ID
+ let appTestCheckRun = null;
+ try {
+ appTestCheckRun = await context.octokit.rest.checks.listForRef({
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ ref: appTestBranch.commit.sha,
+ check_name: process.env.CHECK_NAME,
+ filter: 'latest'
+ })
+ .then((result) => {
+ if (result.data.total_count > 0) {
+ return result.data.check_runs[0];
+ }
+ return null;
+ });
+ } catch (e) {
+ app.log.debug(logData, `Could not find checks or branch for ${appTestRepoOwner}/${appTestRepoName} - ${appTestRepoBranch}`);
+ }
+
+ if (appTestCheckRun && !appTestCheckRun.conclusion) {
+ // Update Security check in app/test repo PR
+ await context.octokit.checks.update({
+ mediaType: {
+ previews: ['antiope-preview']
+ },
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ check_run_id: appTestCheckRun.id,
+ status: 'in_progress',
+ output: {
+ title: 'Awaiting approval of security PR',
+ summary: 'Awaiting approval of security PR'
+ }
+ });
+ } else {
+ // Create Security check in app/test repo PR
+ await context.octokit.checks.create({
+ name: process.env.CHECK_NAME,
+ mediaType: {
+ previews: ['antiope-preview']
+ },
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ head_sha: appTestBranch.commit.sha,
+ status: 'in_progress',
+ output: {
+ title: 'Awaiting approval of security PR',
+ summary: 'Awaiting approval of security PR'
+ }
+ });
+ }
+ }
+ } else {
+ // There is no matching app / test PR for this Security PR,
+ // So close it.
+ await context.octokit.pulls.update({
+ owner,
+ repo,
+ pull_number: prNumber,
+ state: 'closed'
+ });
+ await context.octokit.rest.issues.createComment({
+ owner,
+ repo,
+ issue_number: prNumber,
+ body: 'Closed due to no corresponding app/test branch existing.'
+ });
+ }
+ break;
+ }
+ case 'closed': {
+ // If the Security Repo PR has been closed, regardless of any approvals,
+ // the security metadata changes will not be commited to the repo, therefore
+ // the app/test PR should have its Security check failed, to stop
+ // the app/test code changes from being merged.
+
+ if (appTestBranch) {
+ // Get App/Test repo PR Security check ID
+ let appTestCheckRun = null;
+ try {
+ appTestCheckRun = await context.octokit.rest.checks.listForRef({
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ ref: appTestBranch.commit.sha,
+ check_name: process.env.CHECK_NAME,
+ filter: 'latest'
+ })
+ .then((result) => {
+ if (result.data.total_count > 0) {
+ return result.data.check_runs[0];
+ }
+ return null;
+ });
+ } catch (e) {
+ app.log.debug(logData, `Could not find checks or branch for ${appTestRepoOwner}/${appTestRepoName} - ${appTestRepoBranch}`);
+ }
+
+ // Fail Security check in app/test repo PR
+ if (appTestCheckRun && appTestCheckRun.conclusion !== 'skipped') {
+ await context.octokit.checks.update({
+ mediaType: {
+ previews: ['antiope-preview']
+ },
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ check_run_id: appTestCheckRun.id,
+ status: 'completed',
+ conclusion: 'failure',
+ output: {
+ title: 'Security PR closed',
+ summary: 'Security PR closed'
+ }
+ });
+ }
+ }
+ break;
+ }
+ case 'reopened': {
+ // If a Security repo PR is re-opened from a closed state, its possible it still
+ // contains approvals on the commit therefore the app/test PR should have a Security
+ // Approval check approved.
+ // If there are no existing approvals, the app/test PR should have a Security check
+ // created as 'in progress'.
+ // If the Security repo PR is re-opened, yet there is no corresponding app/test
+ // PR any more, security metadata may be commited that isn't true. In this case it
+ // should likely be immediately closed again.
+
+ if (appTestBranch) {
+ // If there is no open associated app /test PR,
+ // then immediately close.
+ const appTestOpenPullRequest = await context.octokit.pulls.list({
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ state: 'open',
+ head: `${appTestRepoOwner}:${appTestBranch.name}`
+ })
+ .then((result) => {
+ if (result.data.length > 0) {
+ return result.data[0];
+ }
+ return null;
+ });
+
+ if (appTestOpenPullRequest) {
+ // Does the target branch of the app/Test PR have 'Security' as a
+ // required check on the branch protection? If not, then don't do
+ // anything & exit
+ let appTestTargetBranchInfo = null;
+ if (appTestBranch) {
+ try {
+ appTestTargetBranchInfo = await context.octokit.repos.getBranch({
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ branch: appTestOpenPullRequest.base.ref
+ })
+ .then((result) => result.data);
+ } catch (exception) {
+ app.log.debug(logData, `Branch ${appTestOpenPullRequest.base.ref} not found in repo ${appTestRepoOwner}/${appTestRepoName}`);
+ }
+ }
+
+ if (appTestTargetBranchInfo
+ && appTestTargetBranchInfo.protection.enabled
+ && appTestTargetBranchInfo.protection.required_status_checks.checks.some(
+ (e) => e.context === process.env.CHECK_NAME
+ )
+ ) {
+ // Create 'up-to-date' check
+ await context.octokit.rest.checks.create({
+ owner,
+ repo,
+ head_sha: headSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ });
+ if (!context.payload.pull_request.draft) {
+ await updateSecurityApprovalBasedOnReviews(
+ app,
+ context,
+ owner,
+ repo,
+ prNumber,
+ appTestRepoOwner,
+ appTestRepoName,
+ appTestBranch.commit.sha,
+ securityPrUrl
+ );
+ } else {
+ // if reopening a draft, simply reopen the security check
+ // but don't re-evaulate Security check status. That will
+ // be done when it comes out of draft
+ await resetSecurityCheckToWaiting(
+ app,
+ context,
+ appTestRepoOwner,
+ appTestRepoName,
+ appTestBranch.commit.sha,
+ securityPrUrl
+ );
+ }
+ } else {
+ app.log.debug(logData, 'Skipping, app/test PR target branch does not have necessary branch protection.');
+ }
+ } else {
+ // There is no matching app / test PR for this Security PR,
+ // So close it.
+ await context.octokit.pulls.update({
+ owner,
+ repo,
+ pull_number: prNumber,
+ state: 'closed'
+ });
+ await context.octokit.rest.issues.createComment({
+ owner,
+ repo,
+ issue_number: prNumber,
+ body: 'Closed due to no corresponding open app/test PR existing requiring review.'
+ });
+ }
+ } else {
+ // There is no matching app / test PR for this Security PR,
+ // So close it.
+ await context.octokit.pulls.update({
+ owner,
+ repo,
+ pull_number: prNumber,
+ state: 'closed'
+ });
+ await context.octokit.rest.issues.createComment({
+ owner,
+ repo,
+ issue_number: prNumber,
+ body: 'Closed due to no corresponding app/test branch existing.'
+ });
+ }
+ break;
+ }
+ case 'synchronize': {
+ // This could be caused by:
+ // 1. the Security Admin delivering a change on the branch
+ // 2. as a result of another Security PR merging, the 'Update branch'
+ // button was pressed to update the Security PR.
+ // 3. the app / test pipeline has ran again and has force pushed the latest updates
+ //
+ // In either of these cases we don't want to do anything, reasoning for each:
+ // 1. They shouldn't do this, and if they do, it will cause a Security PR
+ // when 'main' runs to reverse it.
+ // 2. As a result of other PRs merging, it means the app code has changed,
+ // the app PR should rebuild again when the 'Update Branch' button is pressed.
+ // Causing the Security PR to immediately close, and a new PR be created later.
+ // 3. This is fine. do nothing
+
+ // Despite the above, if a new commit is pushed, the
+ // Up-To-Date check should pass, otherwise the PR cannot
+ // merge
+ if (appTestBranch) {
+ // Create 'up-to-date' check
+ await context.octokit.rest.checks.create({
+ owner,
+ repo,
+ head_sha: headSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ });
+ }
+ break;
+ }
+ case 'converted_to_draft':
+ // Do nothing
+ break;
+ case 'ready_for_review':
+ if (appTestBranch) {
+ // Create 'up-to-date' check
+ await context.octokit.rest.checks.create({
+ owner,
+ repo,
+ head_sha: headSha,
+ name: 'Up-to-date',
+ conclusion: 'success'
+ });
+
+ await updateSecurityApprovalBasedOnReviews(
+ app,
+ context,
+ owner,
+ repo,
+ prNumber,
+ appTestRepoOwner,
+ appTestRepoName,
+ appTestBranch.commit.sha,
+ securityPrUrl
+ );
+ } else {
+ // There is no matching app / test PR for this Security PR,
+ // So close it.
+ await context.octokit.pulls.update({
+ owner,
+ repo,
+ pull_number: prNumber,
+ state: 'closed'
+ });
+ await context.octokit.rest.issues.createComment({
+ owner,
+ repo,
+ issue_number: prNumber,
+ body: 'Closed due to no corresponding app/test branch existing.'
+ });
+ }
+ break;
+ default:
+ // Do nothing
+ break;
+ }
+ } catch (exception) {
+ app.log.error(logData, exception.stack);
+
+ throw exception;
+ }
+
+ app.log.debug(logData, 'SUCCESSFULLY COMPLETED SECURITY PR WEBHOOK');
+ } else {
+ app.log.debug(logData, 'Skipping, branch naming convention doest follow standrd for SDV.');
+ }
+ } else {
+ app.log.debug(logData, 'Skipping, this PR is already merged.');
+ }
+}
+
+module.exports = {
+ processSecurityPrAction
+};
diff --git a/lib/actions/securityReviewAction.js b/lib/actions/securityReviewAction.js
new file mode 100644
index 0000000..9fb782d
--- /dev/null
+++ b/lib/actions/securityReviewAction.js
@@ -0,0 +1,76 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const {
+ GITHUB_SECURITY_BRANCH_REGEX
+} = require('../common/constants');
+const { updateSecurityApprovalBasedOnReviews } = require('../common/reviewProcessing');
+
+async function processSecurityReviewAction(app, context) {
+ // Context coming in is from the Security repo
+ const owner = context.payload.repository.owner.login;
+ const repo = context.payload.repository.name;
+ const headSha = context.payload.pull_request.head.sha;
+ const prNumber = context.payload.pull_request.number;
+ const securityPrUrl = context.payload.pull_request.html_url;
+
+ const logData = {
+ owner,
+ repo,
+ prNumber,
+ headSha
+ };
+
+ app.log.debug(logData, 'SECURITY REVIEW WEBHOOK RECEIVED:\n');
+
+ if (!context.payload.pull_request.draft && !context.payload.pull_request.merged) {
+ // Check branch name follows standard, if not, ignore
+ if (context.payload.pull_request.head.ref.match(GITHUB_SECURITY_BRANCH_REGEX)) {
+ const appTestRepoOwner = context.payload.pull_request.head.ref.split('/')[0];
+ const appTestRepoName = context.payload.pull_request.head.ref.split('/')[1];
+ const appTestRepoBranch = context.payload.pull_request.head.ref.split('/')[2];
+
+ // Check branch exists in app/test repo
+ let appTestBranch = null;
+ try {
+ appTestBranch = await context.octokit.repos.getBranch({
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ branch: appTestRepoBranch
+ })
+ .then((result) => result.data);
+ } catch (exception) {
+ app.log.debug(logData, `Branch ${appTestRepoBranch} not found in repo ${appTestRepoOwner}/${appTestRepoName}`);
+ }
+
+ if (appTestBranch) {
+ try {
+ await updateSecurityApprovalBasedOnReviews(
+ app,
+ context,
+ owner,
+ repo,
+ prNumber,
+ appTestRepoOwner,
+ appTestRepoName,
+ appTestBranch.commit.sha,
+ securityPrUrl
+ );
+ } catch (exception) {
+ app.log.error(logData, exception.stack);
+ throw exception;
+ }
+ }
+
+ app.log.debug(logData, 'SUCCESSFULLY COMPLETED SECURITY REVIEW WEBHOOK');
+ } else {
+ app.log.debug(logData, 'Skipping, branch naming convention doest follow standrd for SDV.');
+ }
+ } else {
+ app.log.debug(logData, 'Skipping, this is a draft PR.');
+ }
+}
+
+module.exports = {
+ processSecurityReviewAction
+};
diff --git a/lib/app.js b/lib/app.js
new file mode 100644
index 0000000..95f0723
--- /dev/null
+++ b/lib/app.js
@@ -0,0 +1,71 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const express = require('express');
+
+const { handlePrEvents } = require('./handlers/handlePrEvents');
+const { handleReviewEvents } = require('./handlers/handleReviewEvents');
+const { handleCompletedCheckRunEvents } = require('./handlers/handleCompletedCheckRunEvents');
+const { handleDeleteEvents } = require('./handlers/handleDeleteEvents');
+
+if (!process.env.CHECK_NAME) {
+ throw Error('CHECK_NAME has not been provided in the environment variables');
+}
+
+module.exports = async (app, { getRouter }) => {
+ app.on(
+ [
+ 'pull_request.opened',
+ 'pull_request.reopened',
+ 'pull_request.closed',
+ 'pull_request.synchronize',
+ 'pull_request.converted_to_draft',
+ 'pull_request.ready_for_review'
+ ],
+ handlePrEvents.bind(null, app)
+ );
+
+ app.on(
+ [
+ 'pull_request_review',
+ 'pull_request.review_requested',
+ 'pull_request.review_request_removed'
+ ],
+ handleReviewEvents.bind(null, app)
+ );
+
+ // As we plan to auto-merge the app/test and security PRs, we must monitor
+ // for both the status of reviews & 'checks'.
+ // Only when all reviews are approved, and all required checks have passed,
+ // (aka github has put PRs mergable_state to something other than 'blocked') should PRs
+ // auto merge.
+ app.on(
+ [
+ 'check_run.completed'
+ ],
+ handleCompletedCheckRunEvents.bind(null, app)
+ );
+
+ // It's possible there could be a big build up of branches on the Security repo
+ // if PRs are not merged and are closed and forgotten about. After a period of time,
+ // the associated App / Test repo branches wouldn't exist anymore, yet the Security
+ // ones would still remain. This is just a helper function so that when an app / test
+ // repo branch is deleted, if there is an assosciated one on the Securtity repo,
+ // it is deleted also.
+ app.on(
+ [
+ 'delete'
+ ],
+ handleDeleteEvents.bind(null, app)
+ );
+
+ // Get an express router to expose
+ // new routes
+ const router = getRouter('/sdv-approval-bot');
+ router.use(express.static('public'));
+
+ router.get('/healthz', async (req, res) => {
+ app.log.debug('/healthz call made.');
+ res.sendStatus(200);
+ });
+};
diff --git a/lib/common/constants.js b/lib/common/constants.js
new file mode 100644
index 0000000..dfd022b
--- /dev/null
+++ b/lib/common/constants.js
@@ -0,0 +1,8 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const GITHUB_SECURITY_BRANCH_REGEX = '^[\\w\\-\\.]+\\/[\\w\\-\\.]+\\/[\\w\\-\\.]+$';
+
+module.exports = {
+ GITHUB_SECURITY_BRANCH_REGEX
+};
diff --git a/lib/common/reviewProcessing.js b/lib/common/reviewProcessing.js
new file mode 100644
index 0000000..0a090c4
--- /dev/null
+++ b/lib/common/reviewProcessing.js
@@ -0,0 +1,302 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const updateSecurityApprovalCheck = async (
+ context,
+ appTestSecurityApprovalCheckRun,
+ appTestRepoOwner,
+ appTestRepoName,
+ status,
+ output,
+ conclusion = ''
+) => {
+ // Check 'Security' check state. If conclusion & wanting to
+ // update to in_progress, create a new check, otherwise, update.
+ if (!conclusion && appTestSecurityApprovalCheckRun.conclusion) {
+ await context.octokit.checks.create({
+ name: process.env.CHECK_NAME,
+ mediaType: {
+ previews: ['antiope-preview']
+ },
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ head_sha: appTestSecurityApprovalCheckRun.head_sha,
+ status,
+ output
+ });
+ } else {
+ const body = {
+ mediaType: {
+ previews: ['antiope-preview']
+ },
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ check_run_id: appTestSecurityApprovalCheckRun.id,
+ status,
+ output
+ };
+ if (conclusion) {
+ body.conclusion = conclusion;
+ }
+ await context.octokit.checks.update(body);
+ }
+};
+
+const getLatestReviewForReviewers = async (
+ context,
+ owner,
+ repo,
+ prNumber
+) => {
+ // get list of all reviews for PR
+ const allPrReviews = await context.octokit.paginate(context.octokit.rest.pulls.listReviews, {
+ owner,
+ repo,
+ pull_number: prNumber
+ })
+ .then((result) => result);
+
+ return allPrReviews.reduce((finalList, review) => {
+ const key = `${review.user.login}`;
+ return {
+ ...finalList,
+ [key]: { ...review }
+ };
+ }, []);
+};
+
+const updateSecurityApprovalBasedOnReviews = async (
+ app,
+ context,
+ securityRepoOwner,
+ securityRepoName,
+ securityRepoPrNumber,
+ appTestRepoOwner,
+ appTestRepoName,
+ appTestRepoSha,
+ securityPrUrl
+) => {
+ // Get Security check on app/test PR
+ let appTestSecurityApprovalCheckRun = null;
+ try {
+ appTestSecurityApprovalCheckRun = await context.octokit.rest.checks.listForRef({
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ ref: appTestRepoSha,
+ check_name: process.env.CHECK_NAME,
+ filter: 'latest'
+ })
+ .then((result) => {
+ if (result.data.total_count > 0) {
+ return result.data.check_runs[0];
+ }
+ return null;
+ });
+ } catch (e) {
+ app.log.debug({}, `Could not find checks or branch for ${appTestRepoOwner}/${appTestRepoName} - commit ${appTestRepoSha}`);
+ }
+
+ if (appTestSecurityApprovalCheckRun && appTestSecurityApprovalCheckRun.conclusion !== 'skipped') {
+ // Get list of pending reviewers for security PR
+ const pendingReviewerList = await context.octokit.pulls.listRequestedReviewers({
+ owner: securityRepoOwner,
+ repo: securityRepoName,
+ pull_number: securityRepoPrNumber
+ })
+ .then((result) => result.data);
+
+ // Get list unique reviews and their latest review for security PR
+ const latestReviewForReviewers = await getLatestReviewForReviewers(
+ context,
+ securityRepoOwner,
+ securityRepoName,
+ securityRepoPrNumber
+ );
+
+ const currentFailedReviews = Object.values(latestReviewForReviewers).filter((item) => item.state === 'CHANGES_REQUESTED');
+ const currentApprovedReviews = Object.values(latestReviewForReviewers).filter((item) => item.state === 'APPROVED');
+
+ let reviewText = '#### Review status\n Reviewer Status Details \n';
+ for (let i = 0; i < currentFailedReviews.length; i += 1) {
+ /* eslint-disable no-await-in-loop */
+ const commentsList = await context.octokit
+ .paginate(context.octokit.pulls.listCommentsForReview, {
+ owner: securityRepoOwner,
+ repo: securityRepoName,
+ pull_number: securityRepoPrNumber,
+ review_id: currentFailedReviews[i].id
+ })
+ .then((result) => result);
+ /* eslint-enable no-await-in-loop */
+
+ let failureComments = '';
+ commentsList.forEach((comment) => {
+ failureComments += `* ${comment.body}\n`;
+ });
+
+ reviewText += ` \n\n@${currentFailedReviews[i].user.login}\n\n \n\n:x:\n\n \n\n${currentFailedReviews[i].body}\n\n\n${failureComments}\n\n \n`;
+ }
+ for (let i = 0; i < currentApprovedReviews.length; i += 1) {
+ /* eslint-disable no-await-in-loop */
+ const commentsList = await context.octokit
+ .paginate(context.octokit.pulls.listCommentsForReview, {
+ owner: securityRepoOwner,
+ repo: securityRepoName,
+ pull_number: securityRepoPrNumber,
+ review_id: currentApprovedReviews[i].id
+ })
+ .then((result) => result);
+ /* eslint-enable no-await-in-loop */
+
+ let approvalComments = '';
+ commentsList.forEach((comment) => {
+ approvalComments += `* ${comment.body}\n`;
+ });
+
+ reviewText += ` \n\n@${currentApprovedReviews[i].user.login}\n\n \n\n:white_check_mark:\n\n \n\n${currentApprovedReviews[i].body}\n\n${approvalComments}\n\n \n`;
+ }
+ for (let i = 0; i < pendingReviewerList.teams.length; i += 1) {
+ reviewText += ` \n\nTeam: \`${pendingReviewerList.teams[i].name}\` \n\n \n\n:clock1:\n\n Awaiting review... \n`;
+ }
+ for (let i = 0; i < pendingReviewerList.users.length; i += 1) {
+ reviewText += ` \n\n@${pendingReviewerList.users[i].login}\n\n \n\n:clock1:\n\n Awaiting review... \n`;
+ }
+ reviewText += '
\n';
+
+ if (currentFailedReviews.length > 0) {
+ // No matter what, if at least one rejected review is found,
+ // fail the Security check.
+
+ // Fail the Security check
+ await updateSecurityApprovalCheck(
+ context,
+ appTestSecurityApprovalCheckRun,
+ appTestRepoOwner,
+ appTestRepoName,
+ 'completed',
+ {
+ title: 'Security reviewer concerns',
+ summary: reviewText
+ },
+ 'failure'
+ );
+ } else if (pendingReviewerList.teams.length > 0 || pendingReviewerList.users.length > 0) {
+ // If we get to here, there are no rejected approvals, but if we have any
+ // reviews we are waiting for, the Security check must remain in progress.
+
+ const summaryText = `The changes in this PR will result in a change of security usage.\n\nThe security changes found are currently awaiting Security approval [here](${securityPrUrl}).\n\n${reviewText}`;
+ await updateSecurityApprovalCheck(
+ context,
+ appTestSecurityApprovalCheckRun,
+ appTestRepoOwner,
+ appTestRepoName,
+ 'in_progress',
+ {
+ title: 'Awaiting full approval of security PR',
+ summary: summaryText
+ }
+ );
+ } else {
+ // Get full PR object to test mergability
+ const securityRepoPullRequest = await context.octokit.pulls.get({
+ owner: securityRepoOwner,
+ repo: securityRepoName,
+ pull_number: securityRepoPrNumber
+ })
+ .then((result) => result.data);
+
+ if (['clean', 'has_hooks', 'unstable'].includes(securityRepoPullRequest.mergeable_state)) {
+ // If we get to this point, then either:
+ // 1. the PR is approved by all reviewers.
+ // 2. there are no currently active reviews on the PR, nor are any requested.
+ //
+ // Regardless of which is true, the actions are still the same. We will rely on
+ // the branch protection set up in GitHub to decide if the PR is mergable or not.
+ //
+ // The PR could still be potentially blocked from merging if not
+ // all Checks have passed, or if none of the reviewers are a codeowner
+ // of the Security metadata Repo.
+ // It could also be that branch protection has been switched off, so we should not enforce
+ // a review must be approved.
+
+ // Pass Security check in app/test repo PR
+ await updateSecurityApprovalCheck(
+ context,
+ appTestSecurityApprovalCheckRun,
+ appTestRepoOwner,
+ appTestRepoName,
+ 'completed',
+ {
+ title: 'Security approved',
+ summary: reviewText
+ },
+ 'success'
+ );
+ } else {
+ // See last comment
+ const summaryText = `The changes in this PR will result in a change of security usage.\n\nThe security changes found are currently awaiting a Security approval [here](${securityPrUrl}).\n\n#### Review status\nAwaiting for reviewers to be assigned.`;
+ await updateSecurityApprovalCheck(
+ context,
+ appTestSecurityApprovalCheckRun,
+ appTestRepoOwner,
+ appTestRepoName,
+ 'in_progress',
+ {
+ title: 'Awaiting full approval of security PR',
+ summary: summaryText
+ }
+ );
+ }
+ }
+ }
+};
+
+const resetSecurityCheckToWaiting = async (
+ app,
+ context,
+ appTestRepoOwner,
+ appTestRepoName,
+ appTestRepoSha,
+ securityPrUrl
+) => {
+ // Get Security check on app/test PR
+ let appTestSecurityApprovalCheckRun = null;
+ try {
+ appTestSecurityApprovalCheckRun = await context.octokit.rest.checks.listForRef({
+ owner: appTestRepoOwner,
+ repo: appTestRepoName,
+ ref: appTestRepoSha,
+ check_name: process.env.CHECK_NAME,
+ filter: 'latest'
+ })
+ .then((result) => {
+ if (result.data.total_count > 0) {
+ return result.data.check_runs[0];
+ }
+ return null;
+ });
+ } catch (e) {
+ app.log.debug({}, `Could not find checks or branch for ${appTestRepoOwner}/${appTestRepoName} - commit ${appTestRepoSha}`);
+ }
+
+ if (appTestSecurityApprovalCheckRun) {
+ const summaryText = `The changes in this PR will result in a change of security usage.\n\nThe security changes found are currently awaiting a Security approval [here](${securityPrUrl}).\n\n#### Review status\nAwaiting for reviewers to be assigned.`;
+ await updateSecurityApprovalCheck(
+ context,
+ appTestSecurityApprovalCheckRun,
+ appTestRepoOwner,
+ appTestRepoName,
+ 'in_progress',
+ {
+ title: 'Awaiting full approval of security PR',
+ summary: summaryText
+ }
+ );
+ }
+};
+
+module.exports = {
+ getLatestReviewForReviewers,
+ updateSecurityApprovalBasedOnReviews,
+ resetSecurityCheckToWaiting
+};
diff --git a/lib/handlers/handleCompletedCheckRunEvents.js b/lib/handlers/handleCompletedCheckRunEvents.js
new file mode 100644
index 0000000..9deeab7
--- /dev/null
+++ b/lib/handlers/handleCompletedCheckRunEvents.js
@@ -0,0 +1,26 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const { autoMerge } = require('../actions/autoMerge');
+
+async function handleCompletedCheckRunEvents(app, context) {
+ const owner = context.payload.repository.owner.login;
+ const repo = context.payload.repository.name;
+
+ // Get config from default branch
+ let config = null;
+ try {
+ config = await context.config('sdvapproval.yml');
+ } catch (exception) {
+ app.log.warn(`No SDV configuration file found in repo ${owner}/${repo}. Will not process.`);
+ }
+
+ // only continue if a config found
+ if (config) {
+ await autoMerge(app, context, config);
+ }
+}
+
+module.exports = {
+ handleCompletedCheckRunEvents
+};
diff --git a/lib/handlers/handleDeleteEvents.js b/lib/handlers/handleDeleteEvents.js
new file mode 100644
index 0000000..02a25b7
--- /dev/null
+++ b/lib/handlers/handleDeleteEvents.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const { processAppTestDeleteAction } = require('../actions/appTestDeleteAction');
+const { processSecurityDeleteAction } = require('../actions/securityDeleteAction');
+
+async function handleDeleteEvents(app, context) {
+ if (context.payload.ref_type === 'branch') {
+ const owner = context.payload.repository.owner.login;
+ const repo = context.payload.repository.name;
+
+ // Get config from default branch
+ let config = null;
+ try {
+ config = await context.config('sdvapproval.yml');
+ } catch (exception) {
+ app.log.warn(`No SDV configuration file found in repo ${owner}/${repo}. Will not process.`);
+ }
+
+ // only continue if a config found
+ if (config) {
+ if (owner === config.security_repo_owner && repo === config.security_repo_name) {
+ await processSecurityDeleteAction(app, context, config);
+ } else {
+ await processAppTestDeleteAction(app, context, config);
+ }
+ }
+ }
+}
+
+module.exports = {
+ handleDeleteEvents
+};
diff --git a/lib/handlers/handlePrEvents.js b/lib/handlers/handlePrEvents.js
new file mode 100644
index 0000000..35ac2ee
--- /dev/null
+++ b/lib/handlers/handlePrEvents.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const { processSecurityPrAction } = require('../actions/securityPrAction');
+const { processAppTestPrAction } = require('../actions/appTestPrAction');
+
+async function handlePrEvents(app, context) {
+ const owner = context.payload.repository.owner.login;
+ const repo = context.payload.repository.name;
+
+ // Get config from default branch
+ let config = null;
+ try {
+ config = await context.config('sdvapproval.yml');
+ } catch (exception) {
+ app.log.warn(`No SDV configuration file found in repo ${owner}/${repo}. Will not process.`);
+ }
+
+ // only continue if a config found
+ if (config) {
+ if (owner === config.security_repo_owner && repo === config.security_repo_name) {
+ await processSecurityPrAction(app, context);
+ } else {
+ await processAppTestPrAction(app, context, config);
+ }
+ }
+}
+
+module.exports = {
+ handlePrEvents
+};
diff --git a/lib/handlers/handleReviewEvents.js b/lib/handlers/handleReviewEvents.js
new file mode 100644
index 0000000..75e75f8
--- /dev/null
+++ b/lib/handlers/handleReviewEvents.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright IBM Corp. 2024
+ */
+const { autoMerge } = require('../actions/autoMerge');
+const { processSecurityReviewAction } = require('../actions/securityReviewAction');
+
+async function handleReviewEvents(app, context) {
+ const owner = context.payload.repository.owner.login;
+ const repo = context.payload.repository.name;
+
+ // Get config from default branch
+ let config = null;
+ try {
+ config = await context.config('sdvapproval.yml');
+ } catch (exception) {
+ app.log.warn(`No SDV configuration file found in repo ${owner}/${repo}. Will not process.`);
+ }
+
+ // only continue if a config found
+ if (config) {
+ if (owner === config.security_repo_owner && repo === config.security_repo_name) {
+ await processSecurityReviewAction(app, context);
+ } else {
+ await autoMerge(app, context, config);
+ }
+ }
+}
+
+module.exports = {
+ handleReviewEvents
+};
diff --git a/logo.png b/logo.png
new file mode 100644
index 0000000..22d1e74
Binary files /dev/null and b/logo.png differ
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..ddc420f
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,9250 @@
+{
+ "name": "sdv-approval-bot",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "sdv-approval-bot",
+ "version": "1.0.0",
+ "hasInstallScript": true,
+ "license": "EPL-2.0",
+ "dependencies": {
+ "@octokit/rest": "20.0.2",
+ "express": "4.19.2",
+ "octokit-auth-probot": "2.0.0",
+ "per-env": "1.0.2",
+ "probot": "13.2.0"
+ },
+ "devDependencies": {
+ "@commitlint/cli": "18.4.3",
+ "@commitlint/config-conventional": "18.4.3",
+ "@types/jest": "29.5.11",
+ "eslint": "8.55.0",
+ "eslint-config-airbnb-base": "15.0.0",
+ "eslint-plugin-import": "2.29.0",
+ "eslint-plugin-jest": "27.6.0",
+ "husky": "8.0.3",
+ "jest": "29.7.0",
+ "nock": "13.5.4",
+ "node-fetch": "2.7.0",
+ "pino": "8.17.0"
+ },
+ "engines": {
+ "node": ">= 18.17.0"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz",
+ "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.24.7",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz",
+ "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz",
+ "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.24.7",
+ "@babel/generator": "^7.24.7",
+ "@babel/helper-compilation-targets": "^7.24.7",
+ "@babel/helper-module-transforms": "^7.24.7",
+ "@babel/helpers": "^7.24.7",
+ "@babel/parser": "^7.24.7",
+ "@babel/template": "^7.24.7",
+ "@babel/traverse": "^7.24.7",
+ "@babel/types": "^7.24.7",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz",
+ "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.24.7",
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz",
+ "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.24.7",
+ "@babel/helper-validator-option": "^7.24.7",
+ "browserslist": "^4.22.2",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz",
+ "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz",
+ "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.24.7",
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz",
+ "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz",
+ "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/traverse": "^7.24.7",
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz",
+ "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.24.7",
+ "@babel/helper-module-imports": "^7.24.7",
+ "@babel/helper-simple-access": "^7.24.7",
+ "@babel/helper-split-export-declaration": "^7.24.7",
+ "@babel/helper-validator-identifier": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz",
+ "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz",
+ "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/traverse": "^7.24.7",
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz",
+ "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz",
+ "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz",
+ "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz",
+ "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz",
+ "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.24.7",
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz",
+ "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.24.7",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz",
+ "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==",
+ "dev": true,
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz",
+ "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz",
+ "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz",
+ "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.24.7",
+ "@babel/parser": "^7.24.7",
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz",
+ "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.24.7",
+ "@babel/generator": "^7.24.7",
+ "@babel/helper-environment-visitor": "^7.24.7",
+ "@babel/helper-function-name": "^7.24.7",
+ "@babel/helper-hoist-variables": "^7.24.7",
+ "@babel/helper-split-export-declaration": "^7.24.7",
+ "@babel/parser": "^7.24.7",
+ "@babel/types": "^7.24.7",
+ "debug": "^4.3.1",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz",
+ "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.24.7",
+ "@babel/helper-validator-identifier": "^7.24.7",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true
+ },
+ "node_modules/@commitlint/cli": {
+ "version": "18.4.3",
+ "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-18.4.3.tgz",
+ "integrity": "sha512-zop98yfB3A6NveYAZ3P1Mb6bIXuCeWgnUfVNkH4yhIMQpQfzFwseadazOuSn0OOfTt0lWuFauehpm9GcqM5lww==",
+ "dev": true,
+ "dependencies": {
+ "@commitlint/format": "^18.4.3",
+ "@commitlint/lint": "^18.4.3",
+ "@commitlint/load": "^18.4.3",
+ "@commitlint/read": "^18.4.3",
+ "@commitlint/types": "^18.4.3",
+ "execa": "^5.0.0",
+ "lodash.isfunction": "^3.0.9",
+ "resolve-from": "5.0.0",
+ "resolve-global": "1.0.0",
+ "yargs": "^17.0.0"
+ },
+ "bin": {
+ "commitlint": "cli.js"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/config-conventional": {
+ "version": "18.4.3",
+ "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-18.4.3.tgz",
+ "integrity": "sha512-729eRRaNta7JZF07qf6SAGSghoDEp9mH7yHU0m7ff0q89W97wDrWCyZ3yoV3mcQJwbhlmVmZPTkPcm7qiAu8WA==",
+ "dev": true,
+ "dependencies": {
+ "conventional-changelog-conventionalcommits": "^7.0.2"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/config-validator": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-18.6.1.tgz",
+ "integrity": "sha512-05uiToBVfPhepcQWE1ZQBR/Io3+tb3gEotZjnI4tTzzPk16NffN6YABgwFQCLmzZefbDcmwWqJWc2XT47q7Znw==",
+ "dev": true,
+ "dependencies": {
+ "@commitlint/types": "^18.6.1",
+ "ajv": "^8.11.0"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/ensure": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-18.6.1.tgz",
+ "integrity": "sha512-BPm6+SspyxQ7ZTsZwXc7TRQL5kh5YWt3euKmEIBZnocMFkJevqs3fbLRb8+8I/cfbVcAo4mxRlpTPfz8zX7SnQ==",
+ "dev": true,
+ "dependencies": {
+ "@commitlint/types": "^18.6.1",
+ "lodash.camelcase": "^4.3.0",
+ "lodash.kebabcase": "^4.1.1",
+ "lodash.snakecase": "^4.1.1",
+ "lodash.startcase": "^4.4.0",
+ "lodash.upperfirst": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/execute-rule": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-18.6.1.tgz",
+ "integrity": "sha512-7s37a+iWyJiGUeMFF6qBlyZciUkF8odSAnHijbD36YDctLhGKoYltdvuJ/AFfRm6cBLRtRk9cCVPdsEFtt/2rg==",
+ "dev": true,
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/format": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-18.6.1.tgz",
+ "integrity": "sha512-K8mNcfU/JEFCharj2xVjxGSF+My+FbUHoqR+4GqPGrHNqXOGNio47ziiR4HQUPKtiNs05o8/WyLBoIpMVOP7wg==",
+ "dev": true,
+ "dependencies": {
+ "@commitlint/types": "^18.6.1",
+ "chalk": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/is-ignored": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-18.6.1.tgz",
+ "integrity": "sha512-MOfJjkEJj/wOaPBw5jFjTtfnx72RGwqYIROABudOtJKW7isVjFe9j0t8xhceA02QebtYf4P/zea4HIwnXg8rvA==",
+ "dev": true,
+ "dependencies": {
+ "@commitlint/types": "^18.6.1",
+ "semver": "7.6.0"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/lint": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-18.6.1.tgz",
+ "integrity": "sha512-8WwIFo3jAuU+h1PkYe5SfnIOzp+TtBHpFr4S8oJWhu44IWKuVx6GOPux3+9H1iHOan/rGBaiacicZkMZuluhfQ==",
+ "dev": true,
+ "dependencies": {
+ "@commitlint/is-ignored": "^18.6.1",
+ "@commitlint/parse": "^18.6.1",
+ "@commitlint/rules": "^18.6.1",
+ "@commitlint/types": "^18.6.1"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/load": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-18.6.1.tgz",
+ "integrity": "sha512-p26x8734tSXUHoAw0ERIiHyW4RaI4Bj99D8YgUlVV9SedLf8hlWAfyIFhHRIhfPngLlCe0QYOdRKYFt8gy56TA==",
+ "dev": true,
+ "dependencies": {
+ "@commitlint/config-validator": "^18.6.1",
+ "@commitlint/execute-rule": "^18.6.1",
+ "@commitlint/resolve-extends": "^18.6.1",
+ "@commitlint/types": "^18.6.1",
+ "chalk": "^4.1.0",
+ "cosmiconfig": "^8.3.6",
+ "cosmiconfig-typescript-loader": "^5.0.0",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.merge": "^4.6.2",
+ "lodash.uniq": "^4.5.0",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/message": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-18.6.1.tgz",
+ "integrity": "sha512-VKC10UTMLcpVjMIaHHsY1KwhuTQtdIKPkIdVEwWV+YuzKkzhlI3aNy6oo1eAN6b/D2LTtZkJe2enHmX0corYRw==",
+ "dev": true,
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/parse": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-18.6.1.tgz",
+ "integrity": "sha512-eS/3GREtvVJqGZrwAGRwR9Gdno3YcZ6Xvuaa+vUF8j++wsmxrA2En3n0ccfVO2qVOLJC41ni7jSZhQiJpMPGOQ==",
+ "dev": true,
+ "dependencies": {
+ "@commitlint/types": "^18.6.1",
+ "conventional-changelog-angular": "^7.0.0",
+ "conventional-commits-parser": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/read": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-18.6.1.tgz",
+ "integrity": "sha512-ia6ODaQFzXrVul07ffSgbZGFajpe8xhnDeLIprLeyfz3ivQU1dIoHp7yz0QIorZ6yuf4nlzg4ZUkluDrGN/J/w==",
+ "dev": true,
+ "dependencies": {
+ "@commitlint/top-level": "^18.6.1",
+ "@commitlint/types": "^18.6.1",
+ "git-raw-commits": "^2.0.11",
+ "minimist": "^1.2.6"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/resolve-extends": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-18.6.1.tgz",
+ "integrity": "sha512-ifRAQtHwK+Gj3Bxj/5chhc4L2LIc3s30lpsyW67yyjsETR6ctHAHRu1FSpt0KqahK5xESqoJ92v6XxoDRtjwEQ==",
+ "dev": true,
+ "dependencies": {
+ "@commitlint/config-validator": "^18.6.1",
+ "@commitlint/types": "^18.6.1",
+ "import-fresh": "^3.0.0",
+ "lodash.mergewith": "^4.6.2",
+ "resolve-from": "^5.0.0",
+ "resolve-global": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/rules": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-18.6.1.tgz",
+ "integrity": "sha512-kguM6HxZDtz60v/zQYOe0voAtTdGybWXefA1iidjWYmyUUspO1zBPQEmJZ05/plIAqCVyNUTAiRPWIBKLCrGew==",
+ "dev": true,
+ "dependencies": {
+ "@commitlint/ensure": "^18.6.1",
+ "@commitlint/message": "^18.6.1",
+ "@commitlint/to-lines": "^18.6.1",
+ "@commitlint/types": "^18.6.1",
+ "execa": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/to-lines": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-18.6.1.tgz",
+ "integrity": "sha512-Gl+orGBxYSNphx1+83GYeNy5N0dQsHBQ9PJMriaLQDB51UQHCVLBT/HBdOx5VaYksivSf5Os55TLePbRLlW50Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/top-level": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-18.6.1.tgz",
+ "integrity": "sha512-HyiHQZUTf0+r0goTCDs/bbVv/LiiQ7AVtz6KIar+8ZrseB9+YJAIo8HQ2IC2QT1y3N1lbW6OqVEsTHjbT6hGSw==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@commitlint/types": {
+ "version": "18.6.1",
+ "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-18.6.1.tgz",
+ "integrity": "sha512-gwRLBLra/Dozj2OywopeuHj2ac26gjGkz2cZ+86cTJOdtWfiRRr4+e77ZDAGc6MDWxaWheI+mAV5TLWWRwqrFg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=v18"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz",
+ "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.55.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz",
+ "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@hapi/bourne": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.1.0.tgz",
+ "integrity": "sha512-i1BpaNDVLJdRBEKeJWkVO6tYX6DMFBuwMhSuWqLsY4ufeTKGVuV5rBsUhxPayXqnnWHgXUAmWK16H/ykO5Wj4Q=="
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.14",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+ "deprecated": "Use @eslint/config-array instead",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.2",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "deprecated": "Use @eslint/object-schema instead",
+ "dev": true
+ },
+ "node_modules/@ioredis/commands": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
+ "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="
+ },
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/console": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
+ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
+ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/reporters": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-changed-files": "^29.7.0",
+ "jest-config": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-resolve-dependencies": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
+ "dev": true,
+ "dependencies": {
+ "expect": "^29.7.0",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+ "dev": true,
+ "dependencies": {
+ "jest-get-type": "^29.6.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
+ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
+ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
+ "dev": true,
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^6.0.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
+ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
+ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
+ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@octokit/auth-app": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-6.1.1.tgz",
+ "integrity": "sha512-VrTtzRpyuT5nYGUWeGWQqH//hqEZDV+/yb6+w5wmWpmmUA1Tx950XsAc2mBBfvusfcdF2E7w8jZ1r1WwvfZ9pA==",
+ "dependencies": {
+ "@octokit/auth-oauth-app": "^7.1.0",
+ "@octokit/auth-oauth-user": "^4.1.0",
+ "@octokit/request": "^8.3.1",
+ "@octokit/request-error": "^5.1.0",
+ "@octokit/types": "^13.1.0",
+ "deprecation": "^2.3.1",
+ "lru-cache": "^10.0.0",
+ "universal-github-app-jwt": "^1.1.2",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/auth-app/node_modules/lru-cache": {
+ "version": "10.2.2",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz",
+ "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==",
+ "engines": {
+ "node": "14 || >=16.14"
+ }
+ },
+ "node_modules/@octokit/auth-oauth-app": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-7.1.0.tgz",
+ "integrity": "sha512-w+SyJN/b0l/HEb4EOPRudo7uUOSW51jcK1jwLa+4r7PA8FPFpoxEnHBHMITqCsc/3Vo2qqFjgQfz/xUUvsSQnA==",
+ "dependencies": {
+ "@octokit/auth-oauth-device": "^6.1.0",
+ "@octokit/auth-oauth-user": "^4.1.0",
+ "@octokit/request": "^8.3.1",
+ "@octokit/types": "^13.0.0",
+ "@types/btoa-lite": "^1.0.0",
+ "btoa-lite": "^1.0.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/auth-oauth-device": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-6.1.0.tgz",
+ "integrity": "sha512-FNQ7cb8kASufd6Ej4gnJ3f1QB5vJitkoV1O0/g6e6lUsQ7+VsSNRHRmFScN2tV4IgKA12frrr/cegUs0t+0/Lw==",
+ "dependencies": {
+ "@octokit/oauth-methods": "^4.1.0",
+ "@octokit/request": "^8.3.1",
+ "@octokit/types": "^13.0.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/auth-oauth-user": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-4.1.0.tgz",
+ "integrity": "sha512-FrEp8mtFuS/BrJyjpur+4GARteUCrPeR/tZJzD8YourzoVhRics7u7we/aDcKv+yywRNwNi/P4fRi631rG/OyQ==",
+ "dependencies": {
+ "@octokit/auth-oauth-device": "^6.1.0",
+ "@octokit/oauth-methods": "^4.1.0",
+ "@octokit/request": "^8.3.1",
+ "@octokit/types": "^13.0.0",
+ "btoa-lite": "^1.0.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/auth-token": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
+ "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/auth-unauthenticated": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-5.0.1.tgz",
+ "integrity": "sha512-oxeWzmBFxWd+XolxKTc4zr+h3mt+yofn4r7OfoIkR/Cj/o70eEGmPsFbueyJE2iBAGpjgTnEOKM3pnuEGVmiqg==",
+ "dependencies": {
+ "@octokit/request-error": "^5.0.0",
+ "@octokit/types": "^12.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/auth-unauthenticated/node_modules/@octokit/types": {
+ "version": "12.6.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
+ "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
+ "dependencies": {
+ "@octokit/openapi-types": "^20.0.0"
+ }
+ },
+ "node_modules/@octokit/auth-unauthenticated/node_modules/@octokit/types/node_modules/@octokit/openapi-types": {
+ "version": "20.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
+ "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
+ },
+ "node_modules/@octokit/core": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz",
+ "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==",
+ "dependencies": {
+ "@octokit/auth-token": "^4.0.0",
+ "@octokit/graphql": "^7.1.0",
+ "@octokit/request": "^8.3.1",
+ "@octokit/request-error": "^5.1.0",
+ "@octokit/types": "^13.0.0",
+ "before-after-hook": "^2.2.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/endpoint": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz",
+ "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==",
+ "dependencies": {
+ "@octokit/types": "^13.1.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/graphql": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz",
+ "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==",
+ "dependencies": {
+ "@octokit/request": "^8.3.0",
+ "@octokit/types": "^13.0.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/oauth-authorization-url": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-6.0.2.tgz",
+ "integrity": "sha512-CdoJukjXXxqLNK4y/VOiVzQVjibqoj/xHgInekviUJV73y/BSIcwvJ/4aNHPBPKcPWFnd4/lO9uqRV65jXhcLA==",
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/oauth-methods": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-4.1.0.tgz",
+ "integrity": "sha512-4tuKnCRecJ6CG6gr0XcEXdZtkTDbfbnD5oaHBmLERTjTMZNi2CbfEHZxPU41xXLDG4DfKf+sonu00zvKI9NSbw==",
+ "dependencies": {
+ "@octokit/oauth-authorization-url": "^6.0.2",
+ "@octokit/request": "^8.3.1",
+ "@octokit/request-error": "^5.1.0",
+ "@octokit/types": "^13.0.0",
+ "btoa-lite": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/openapi-types": {
+ "version": "22.2.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz",
+ "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg=="
+ },
+ "node_modules/@octokit/plugin-enterprise-compatibility": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-compatibility/-/plugin-enterprise-compatibility-4.1.0.tgz",
+ "integrity": "sha512-a8QehVu9Iy4k+m2XgG2rrF4m9vhlRIaefOMr0yJzgQCt4KpiTj5mZVrzSwagyOovkJdD0yDolQazBQZqPWTFSQ==",
+ "dependencies": {
+ "@octokit/request-error": "^5.0.0",
+ "@octokit/types": "^12.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/plugin-enterprise-compatibility/node_modules/@octokit/types": {
+ "version": "12.6.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
+ "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
+ "dependencies": {
+ "@octokit/openapi-types": "^20.0.0"
+ }
+ },
+ "node_modules/@octokit/plugin-enterprise-compatibility/node_modules/@octokit/types/node_modules/@octokit/openapi-types": {
+ "version": "20.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
+ "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
+ },
+ "node_modules/@octokit/plugin-paginate-rest": {
+ "version": "9.2.1",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz",
+ "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==",
+ "dependencies": {
+ "@octokit/types": "^12.6.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "@octokit/core": "5"
+ }
+ },
+ "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
+ "version": "20.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
+ "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
+ },
+ "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
+ "version": "12.6.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
+ "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
+ "dependencies": {
+ "@octokit/openapi-types": "^20.0.0"
+ }
+ },
+ "node_modules/@octokit/plugin-request-log": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz",
+ "integrity": "sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==",
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "@octokit/core": "5"
+ }
+ },
+ "node_modules/@octokit/plugin-rest-endpoint-methods": {
+ "version": "10.4.1",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz",
+ "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==",
+ "dependencies": {
+ "@octokit/types": "^12.6.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "@octokit/core": "5"
+ }
+ },
+ "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
+ "version": "20.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
+ "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
+ },
+ "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
+ "version": "12.6.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
+ "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
+ "dependencies": {
+ "@octokit/openapi-types": "^20.0.0"
+ }
+ },
+ "node_modules/@octokit/plugin-retry": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.0.1.tgz",
+ "integrity": "sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog==",
+ "dependencies": {
+ "@octokit/request-error": "^5.0.0",
+ "@octokit/types": "^12.0.0",
+ "bottleneck": "^2.15.3"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "@octokit/core": ">=5"
+ }
+ },
+ "node_modules/@octokit/plugin-retry/node_modules/@octokit/types": {
+ "version": "12.6.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
+ "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
+ "dependencies": {
+ "@octokit/openapi-types": "^20.0.0"
+ }
+ },
+ "node_modules/@octokit/plugin-retry/node_modules/@octokit/types/node_modules/@octokit/openapi-types": {
+ "version": "20.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
+ "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
+ },
+ "node_modules/@octokit/request": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.0.tgz",
+ "integrity": "sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==",
+ "dependencies": {
+ "@octokit/endpoint": "^9.0.1",
+ "@octokit/request-error": "^5.1.0",
+ "@octokit/types": "^13.1.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/request-error": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz",
+ "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==",
+ "dependencies": {
+ "@octokit/types": "^13.1.0",
+ "deprecation": "^2.0.0",
+ "once": "^1.4.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/rest": {
+ "version": "20.0.2",
+ "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz",
+ "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==",
+ "dependencies": {
+ "@octokit/core": "^5.0.0",
+ "@octokit/plugin-paginate-rest": "^9.0.0",
+ "@octokit/plugin-request-log": "^4.0.0",
+ "@octokit/plugin-rest-endpoint-methods": "^10.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/types": {
+ "version": "13.5.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz",
+ "integrity": "sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==",
+ "dependencies": {
+ "@octokit/openapi-types": "^22.2.0"
+ }
+ },
+ "node_modules/@octokit/webhooks": {
+ "version": "12.2.0",
+ "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-12.2.0.tgz",
+ "integrity": "sha512-CyuLJ0/P7bKZ+kIYw+fnkeVdhUzNuDKgNSI7pU/m7Nod0T7kP+s4s2f0pNmG9HL8/RZN1S0ZWTDll3VTMrFLAw==",
+ "dependencies": {
+ "@octokit/request-error": "^5.0.0",
+ "@octokit/webhooks-methods": "^4.1.0",
+ "@octokit/webhooks-types": "7.4.0",
+ "aggregate-error": "^3.1.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/webhooks-methods": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-4.1.0.tgz",
+ "integrity": "sha512-zoQyKw8h9STNPqtm28UGOYFE7O6D4Il8VJwhAtMHFt2C4L0VQT1qGKLeefUOqHNs1mNRYSadVv7x0z8U2yyeWQ==",
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/webhooks-types": {
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-7.4.0.tgz",
+ "integrity": "sha512-FE2V+QZ2UYlh+9wWd5BPLNXG+J/XUD/PPq0ovS+nCcGX4+3qVbi3jYOmCTW48hg9SBBLtInx9+o7fFt4H5iP0Q=="
+ },
+ "node_modules/@probot/get-private-key": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@probot/get-private-key/-/get-private-key-1.1.2.tgz",
+ "integrity": "sha512-yVgyCdTyooGX6+czDLkJahEcwgBWZsKH9xbjvjDNVFjY3QtiI/tHRiB3zjgJCQMZehXxv2CFHZQSpWRXdr6CeQ=="
+ },
+ "node_modules/@probot/octokit-plugin-config": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@probot/octokit-plugin-config/-/octokit-plugin-config-2.0.1.tgz",
+ "integrity": "sha512-aWQYzPY2xiKscTVTKveghtbglqZ+W4eBLIdK1C/cNiFIofy3AxKogWgEZj29PjIe5ZRYx0sRHAPc/pkcXyOmTQ==",
+ "dependencies": {
+ "js-yaml": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@octokit/core": ">=5"
+ }
+ },
+ "node_modules/@probot/pino": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@probot/pino/-/pino-2.3.5.tgz",
+ "integrity": "sha512-IiyiNZonMw1dHC4EAdD55y5owV733d9Gll/IKsrLikB7EJ54+eMCOtL/qo+OmgWN9XV3NTDfziEQF2og/OBKog==",
+ "dependencies": {
+ "@sentry/node": "^6.0.0",
+ "pino-pretty": "^6.0.0",
+ "pump": "^3.0.0",
+ "readable-stream": "^3.6.0",
+ "split2": "^4.0.0"
+ },
+ "bin": {
+ "pino-probot": "cli.js"
+ }
+ },
+ "node_modules/@probot/pino/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@sentry/core": {
+ "version": "6.19.7",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz",
+ "integrity": "sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw==",
+ "dependencies": {
+ "@sentry/hub": "6.19.7",
+ "@sentry/minimal": "6.19.7",
+ "@sentry/types": "6.19.7",
+ "@sentry/utils": "6.19.7",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/hub": {
+ "version": "6.19.7",
+ "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz",
+ "integrity": "sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==",
+ "dependencies": {
+ "@sentry/types": "6.19.7",
+ "@sentry/utils": "6.19.7",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/minimal": {
+ "version": "6.19.7",
+ "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz",
+ "integrity": "sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==",
+ "dependencies": {
+ "@sentry/hub": "6.19.7",
+ "@sentry/types": "6.19.7",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/node": {
+ "version": "6.19.7",
+ "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.19.7.tgz",
+ "integrity": "sha512-gtmRC4dAXKODMpHXKfrkfvyBL3cI8y64vEi3fDD046uqYcrWdgoQsffuBbxMAizc6Ez1ia+f0Flue6p15Qaltg==",
+ "dependencies": {
+ "@sentry/core": "6.19.7",
+ "@sentry/hub": "6.19.7",
+ "@sentry/types": "6.19.7",
+ "@sentry/utils": "6.19.7",
+ "cookie": "^0.4.1",
+ "https-proxy-agent": "^5.0.0",
+ "lru_map": "^0.3.3",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/node/node_modules/cookie": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
+ "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/@sentry/types": {
+ "version": "6.19.7",
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz",
+ "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/utils": {
+ "version": "6.19.7",
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz",
+ "integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==",
+ "dependencies": {
+ "@sentry/types": "6.19.7",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.8",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+ "dev": true
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "dev": true,
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.6.8",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz",
+ "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.6",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz",
+ "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.5",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
+ "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/btoa-lite": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.2.tgz",
+ "integrity": "sha512-ZYbcE2x7yrvNFJiU7xJGrpF/ihpkM7zKgw8bha3LNJSesvTtUNxbpzaT7WXBIryf6jovisrxTBvymxMeLLj1Mg=="
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.38",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
+ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/express": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
+ "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.33",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "4.19.5",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz",
+ "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
+ "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA=="
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "dev": true
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "dev": true,
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/jest": {
+ "version": "29.5.11",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz",
+ "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==",
+ "dev": true,
+ "dependencies": {
+ "expect": "^29.0.0",
+ "pretty-format": "^29.0.0"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
+ "node_modules/@types/jsonwebtoken": {
+ "version": "9.0.6",
+ "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz",
+ "integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/mime": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
+ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
+ },
+ "node_modules/@types/minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "20.14.9",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz",
+ "integrity": "sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==",
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@types/normalize-package-data": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
+ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
+ "dev": true
+ },
+ "node_modules/@types/qs": {
+ "version": "6.9.15",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz",
+ "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg=="
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
+ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="
+ },
+ "node_modules/@types/semver": {
+ "version": "7.5.8",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
+ "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
+ "dev": true
+ },
+ "node_modules/@types/send": {
+ "version": "0.17.4",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
+ "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
+ "dependencies": {
+ "@types/mime": "^1",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "1.15.7",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz",
+ "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==",
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/node": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "dev": true
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.32",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz",
+ "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==",
+ "dev": true,
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz",
+ "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/visitor-keys": "5.62.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz",
+ "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz",
+ "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/visitor-keys": "5.62.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz",
+ "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@types/json-schema": "^7.0.9",
+ "@types/semver": "^7.3.12",
+ "@typescript-eslint/scope-manager": "5.62.0",
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/typescript-estree": "5.62.0",
+ "eslint-scope": "^5.1.1",
+ "semver": "^7.3.7"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz",
+ "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+ "dev": true
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz",
+ "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz",
+ "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.4.1"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+ },
+ "node_modules/args": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/args/-/args-5.0.3.tgz",
+ "integrity": "sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==",
+ "dependencies": {
+ "camelcase": "5.0.0",
+ "chalk": "2.4.2",
+ "leven": "2.1.0",
+ "mri": "1.1.4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/args/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/args/node_modules/camelcase": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
+ "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/args/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/args/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/args/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "node_modules/args/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/args/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/args/node_modules/leven": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
+ "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/args/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
+ "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
+ },
+ "node_modules/array-ify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz",
+ "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==",
+ "dev": true
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz",
+ "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz",
+ "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
+ "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
+ "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz",
+ "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/atomic-sleep": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
+ "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/babel-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
+ "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.8.3",
+ "@babel/plugin-syntax-import-meta": "^7.8.3",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.8.3",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-top-level-await": "^7.8.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "dev": true,
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/before-after-hook": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
+ "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
+ "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.5",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.11.0",
+ "raw-body": "2.5.2",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/body-parser/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/body-parser/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/bottleneck": {
+ "version": "2.19.5",
+ "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
+ "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.23.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz",
+ "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001629",
+ "electron-to-chromium": "^1.4.796",
+ "node-releases": "^2.0.14",
+ "update-browserslist-db": "^1.0.16"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "node_modules/btoa-lite": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz",
+ "integrity": "sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA=="
+ },
+ "node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase-keys": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
+ "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "map-obj": "^4.0.0",
+ "quick-lru": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001637",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001637.tgz",
+ "integrity": "sha512-1x0qRI1mD1o9e+7mBI7XtzFAP4XszbHaVWsMiGbSPLYekKTJF7K+FNk6AsXH4sUpc+qrsI3pVgf1Jdl/uGkuSQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz",
+ "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==",
+ "dev": true
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cluster-key-slot": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
+ "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true,
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
+ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==",
+ "dev": true
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/colorette": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
+ "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g=="
+ },
+ "node_modules/commander": {
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+ "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/compare-func": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz",
+ "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==",
+ "dev": true,
+ "dependencies": {
+ "array-ify": "^1.0.0",
+ "dot-prop": "^5.1.0"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/confusing-browser-globals": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz",
+ "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==",
+ "dev": true
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/conventional-changelog-angular": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz",
+ "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==",
+ "dev": true,
+ "dependencies": {
+ "compare-func": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/conventional-changelog-conventionalcommits": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz",
+ "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==",
+ "dev": true,
+ "dependencies": {
+ "compare-func": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/conventional-commits-parser": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz",
+ "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==",
+ "dev": true,
+ "dependencies": {
+ "is-text-path": "^2.0.0",
+ "JSONStream": "^1.3.5",
+ "meow": "^12.0.1",
+ "split2": "^4.0.0"
+ },
+ "bin": {
+ "conventional-commits-parser": "cli.mjs"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true
+ },
+ "node_modules/cookie": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+ },
+ "node_modules/cosmiconfig": {
+ "version": "8.3.6",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
+ "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
+ "dev": true,
+ "dependencies": {
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0",
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/cosmiconfig-typescript-loader": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz",
+ "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==",
+ "dev": true,
+ "dependencies": {
+ "jiti": "^1.19.1"
+ },
+ "engines": {
+ "node": ">=v16"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "cosmiconfig": ">=8.2",
+ "typescript": ">=4"
+ }
+ },
+ "node_modules/create-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
+ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "prompts": "^2.0.1"
+ },
+ "bin": {
+ "create-jest": "bin/create-jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/dargs": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz",
+ "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
+ "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz",
+ "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz",
+ "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/dateformat": {
+ "version": "4.6.3",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
+ "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.5",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
+ "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/decamelize-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz",
+ "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==",
+ "dev": true,
+ "dependencies": {
+ "decamelize": "^1.1.0",
+ "map-obj": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/decamelize-keys/node_modules/map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/dedent": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
+ "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==",
+ "dev": true,
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/denque": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
+ "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/deprecation": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
+ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/diff-sequences": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dot-prop": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
+ "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
+ "dev": true,
+ "dependencies": {
+ "is-obj": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "16.4.5",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
+ "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.812",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.812.tgz",
+ "integrity": "sha512-7L8fC2Ey/b6SePDFKR2zHAy4mbdp1/38Yk5TsARO66W3hC5KEaeKMMHoxwtuH+jcu2AYLSn9QX04i95t6Fl1Hg==",
+ "dev": true
+ },
+ "node_modules/emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.23.3",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz",
+ "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==",
+ "dev": true,
+ "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.8",
+ "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.6",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.15"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
+ "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
+ "dev": true,
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz",
+ "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.4",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
+ "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
+ "dev": true,
+ "dependencies": {
+ "hasown": "^2.0.0"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
+ "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.55.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz",
+ "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.55.0",
+ "@humanwhocodes/config-array": "^0.11.13",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-airbnb-base": {
+ "version": "15.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz",
+ "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==",
+ "dev": true,
+ "dependencies": {
+ "confusing-browser-globals": "^1.0.10",
+ "object.assign": "^4.1.2",
+ "object.entries": "^1.1.5",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^7.32.0 || ^8.2.0",
+ "eslint-plugin-import": "^2.25.2"
+ }
+ },
+ "node_modules/eslint-config-airbnb-base/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
+ "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.13.0",
+ "resolve": "^1.22.4"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz",
+ "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.29.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz",
+ "integrity": "sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.7",
+ "array.prototype.findlastindex": "^1.2.3",
+ "array.prototype.flat": "^1.3.2",
+ "array.prototype.flatmap": "^1.3.2",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "eslint-module-utils": "^2.8.0",
+ "hasown": "^2.0.0",
+ "is-core-module": "^2.13.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.7",
+ "object.groupby": "^1.0.1",
+ "object.values": "^1.1.7",
+ "semver": "^6.3.1",
+ "tsconfig-paths": "^3.14.2"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-jest": {
+ "version": "27.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.0.tgz",
+ "integrity": "sha512-MTlusnnDMChbElsszJvrwD1dN3x6nZl//s4JD23BxB6MgR66TZlL064su24xEIS3VACfAoHV1vgyMgPw8nkdng==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/utils": "^5.10.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0",
+ "eslint": "^7.0.0 || ^8.0.0",
+ "jest": "*"
+ },
+ "peerDependenciesMeta": {
+ "@typescript-eslint/eslint-plugin": {
+ "optional": true
+ },
+ "jest": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/eslint/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/eventsource": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz",
+ "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/expect-utils": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.19.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
+ "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.2",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.6.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.2.0",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.11.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.18.0",
+ "serve-static": "1.15.0",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/express/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/express/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fast-redact": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz",
+ "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/fast-safe-stringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
+ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "dev": true,
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
+ "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/finalhandler/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/finalhandler/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
+ "dev": true
+ },
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
+ "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "functions-have-names": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz",
+ "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/git-raw-commits": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz",
+ "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==",
+ "dev": true,
+ "dependencies": {
+ "dargs": "^7.0.0",
+ "lodash": "^4.17.15",
+ "meow": "^8.0.0",
+ "split2": "^3.0.0",
+ "through2": "^4.0.0"
+ },
+ "bin": {
+ "git-raw-commits": "cli.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/git-raw-commits/node_modules/meow": {
+ "version": "8.1.2",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz",
+ "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==",
+ "dev": true,
+ "dependencies": {
+ "@types/minimist": "^1.2.0",
+ "camelcase-keys": "^6.2.2",
+ "decamelize-keys": "^1.1.0",
+ "hard-rejection": "^2.1.0",
+ "minimist-options": "4.1.0",
+ "normalize-package-data": "^3.0.0",
+ "read-pkg-up": "^7.0.1",
+ "redent": "^3.0.0",
+ "trim-newlines": "^3.0.0",
+ "type-fest": "^0.18.0",
+ "yargs-parser": "^20.2.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/git-raw-commits/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/git-raw-commits/node_modules/split2": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
+ "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "^3.0.0"
+ }
+ },
+ "node_modules/git-raw-commits/node_modules/type-fest": {
+ "version": "0.18.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz",
+ "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/git-raw-commits/node_modules/yargs-parser": {
+ "version": "20.2.9",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
+ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/global-dirs": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
+ "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==",
+ "dev": true,
+ "dependencies": {
+ "ini": "^1.3.4"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "node_modules/hard-rejection": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
+ "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+ "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hosted-git-info": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+ "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/hosted-git-info/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/hosted-git-info/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/husky": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
+ "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==",
+ "dev": true,
+ "bin": {
+ "husky": "lib/bin.js"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/typicode"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/ignore": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-fresh/node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/import-local": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+ "dev": true,
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true
+ },
+ "node_modules/internal-slot": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
+ "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==",
+ "dev": true,
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.0",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ioredis": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz",
+ "integrity": "sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==",
+ "dependencies": {
+ "@ioredis/commands": "^1.1.1",
+ "cluster-key-slot": "^1.1.0",
+ "debug": "^4.3.4",
+ "denque": "^2.1.0",
+ "lodash.defaults": "^4.2.0",
+ "lodash.isarguments": "^3.1.0",
+ "redis-errors": "^1.2.0",
+ "redis-parser": "^3.0.0",
+ "standard-as-callback": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=12.22.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/ioredis"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
+ "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.14.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz",
+ "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz",
+ "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==",
+ "dev": true,
+ "dependencies": {
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-obj": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-text-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz",
+ "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==",
+ "dev": true,
+ "dependencies": {
+ "text-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz",
+ "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==",
+ "dev": true,
+ "dependencies": {
+ "which-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz",
+ "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.23.9",
+ "@babel/parser": "^7.23.9",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
+ "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
+ "dev": true,
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
+ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.7.0"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-changed-files": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
+ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
+ "dev": true,
+ "dependencies": {
+ "execa": "^5.0.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
+ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^1.0.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.7.0",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.7.0",
+ "pure-rand": "^6.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-cli": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
+ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "create-jest": "^29.7.0",
+ "exit": "^0.1.2",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-config": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
+ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.7.0",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-circus": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-diff": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-docblock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
+ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
+ "dev": true,
+ "dependencies": {
+ "detect-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-each": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
+ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-environment-node": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
+ }
+ },
+ "node_modules/jest-leak-detector": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
+ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
+ "dev": true,
+ "dependencies": {
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-pnp-resolver": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
+ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^2.0.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve-dependencies": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
+ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
+ "dev": true,
+ "dependencies": {
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
+ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/environment": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-leak-detector": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-resolve": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runtime": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
+ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/globals": "^29.7.0",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
+ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@babel/generator": "^7.7.2",
+ "@babel/plugin-syntax-jsx": "^7.7.2",
+ "@babel/plugin-syntax-typescript": "^7.7.2",
+ "@babel/types": "^7.3.3",
+ "@jest/expect-utils": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.7.0",
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-watcher": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
+ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
+ "dev": true,
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.7.0",
+ "string-length": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "1.21.6",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
+ "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
+ "dev": true,
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
+ "node_modules/jmespath": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz",
+ "integrity": "sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/joycon": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz",
+ "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "node_modules/json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
+ "dev": true,
+ "engines": [
+ "node >= 0.2.0"
+ ]
+ },
+ "node_modules/JSONStream": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
+ "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+ "dev": true,
+ "dependencies": {
+ "jsonparse": "^1.2.0",
+ "through": ">=2.2.7 <3"
+ },
+ "bin": {
+ "JSONStream": "bin.js"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/jsonwebtoken": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
+ "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
+ "dependencies": {
+ "jws": "^3.2.2",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=12",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/jwa": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
+ "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
+ "dependencies": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/jws": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
+ "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+ "dependencies": {
+ "jwa": "^1.4.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true
+ },
+ "node_modules/load-json-file": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz",
+ "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==",
+ "dependencies": {
+ "graceful-fs": "^4.1.15",
+ "parse-json": "^4.0.0",
+ "pify": "^4.0.1",
+ "strip-bom": "^3.0.0",
+ "type-fest": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/load-json-file/node_modules/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+ "dependencies": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/load-json-file/node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/load-json-file/node_modules/type-fest": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz",
+ "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+ "dev": true
+ },
+ "node_modules/lodash.defaults": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+ "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
+ },
+ "node_modules/lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
+ },
+ "node_modules/lodash.isarguments": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="
+ },
+ "node_modules/lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
+ },
+ "node_modules/lodash.isfunction": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
+ "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==",
+ "dev": true
+ },
+ "node_modules/lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
+ },
+ "node_modules/lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
+ },
+ "node_modules/lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
+ },
+ "node_modules/lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
+ },
+ "node_modules/lodash.kebabcase": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
+ "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==",
+ "dev": true
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/lodash.mergewith": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
+ "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
+ "dev": true
+ },
+ "node_modules/lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
+ },
+ "node_modules/lodash.snakecase": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
+ "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==",
+ "dev": true
+ },
+ "node_modules/lodash.startcase": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz",
+ "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==",
+ "dev": true
+ },
+ "node_modules/lodash.uniq": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
+ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
+ "dev": true
+ },
+ "node_modules/lodash.upperfirst": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz",
+ "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==",
+ "dev": true
+ },
+ "node_modules/lru_map": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
+ "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ=="
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "node_modules/map-obj": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz",
+ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/meow": {
+ "version": "12.1.1",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz",
+ "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==",
+ "dev": true,
+ "engines": {
+ "node": ">=16.10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
+ "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/min-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
+ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minimist-options": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
+ "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
+ "dev": true,
+ "dependencies": {
+ "arrify": "^1.0.1",
+ "is-plain-obj": "^1.1.0",
+ "kind-of": "^6.0.3"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/mri": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz",
+ "integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/nock": {
+ "version": "13.5.4",
+ "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.4.tgz",
+ "integrity": "sha512-yAyTfdeNJGGBFxWdzSKCBYxs5FxLbCg5X5Q4ets974hcQzG1+qCxvIyOo4j2Ry6MUlhWVMX4OoYDefAIIwupjw==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.0",
+ "json-stringify-safe": "^5.0.1",
+ "propagate": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 10.13"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dev": true,
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "dev": true
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.14",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
+ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
+ "dev": true
+ },
+ "node_modules/normalize-package-data": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
+ "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^4.0.1",
+ "is-core-module": "^2.5.0",
+ "semver": "^7.3.4",
+ "validate-npm-package-license": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
+ "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
+ "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz",
+ "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
+ "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.groupby": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
+ "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz",
+ "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/octokit-auth-probot": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/octokit-auth-probot/-/octokit-auth-probot-2.0.0.tgz",
+ "integrity": "sha512-bxidVIyxYJ+hWkG24pchPrN6mJdQrklZ2Acu+oGmZlh9aRONsIrw0KNW5W7QC2VlkxsFQwb9lnV+vH0BcEhnLQ==",
+ "dependencies": {
+ "@octokit/auth-app": "^6.0.1",
+ "@octokit/auth-token": "^4.0.0",
+ "@octokit/auth-unauthenticated": "^5.0.1",
+ "@octokit/types": "^12.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@octokit/core": ">=5"
+ }
+ },
+ "node_modules/octokit-auth-probot/node_modules/@octokit/openapi-types": {
+ "version": "20.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
+ "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
+ },
+ "node_modules/octokit-auth-probot/node_modules/@octokit/types": {
+ "version": "12.6.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
+ "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
+ "dependencies": {
+ "@octokit/openapi-types": "^20.0.0"
+ }
+ },
+ "node_modules/on-exit-leak-free": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
+ "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/per-env": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/per-env/-/per-env-1.0.2.tgz",
+ "integrity": "sha512-ShJSJb8a1YVRJnN6Acdbj4xayfUjpj3nLTcfsjZ+bYCGWceUiRDZb5H3sijcc4hVzLlZiRK/H/NaXGMxyEULpA==",
+ "bin": {
+ "per-env": "bin/per-env"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
+ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pino": {
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/pino/-/pino-8.17.0.tgz",
+ "integrity": "sha512-ey+Mku+PVPhvxglLXMg1l1zQMwSHuNrKC3MD40EDZbkckJmmuY7DYZLIOwwjZ8ix/Nvhe9dZt5H99cgkot9bAw==",
+ "dependencies": {
+ "atomic-sleep": "^1.0.0",
+ "fast-redact": "^3.1.1",
+ "on-exit-leak-free": "^2.1.0",
+ "pino-abstract-transport": "v1.1.0",
+ "pino-std-serializers": "^6.0.0",
+ "process-warning": "^2.0.0",
+ "quick-format-unescaped": "^4.0.3",
+ "real-require": "^0.2.0",
+ "safe-stable-stringify": "^2.3.1",
+ "sonic-boom": "^3.7.0",
+ "thread-stream": "^2.0.0"
+ },
+ "bin": {
+ "pino": "bin.js"
+ }
+ },
+ "node_modules/pino-abstract-transport": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz",
+ "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==",
+ "dependencies": {
+ "readable-stream": "^4.0.0",
+ "split2": "^4.0.0"
+ }
+ },
+ "node_modules/pino-http": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/pino-http/-/pino-http-9.0.0.tgz",
+ "integrity": "sha512-Q9QDNEz0vQmbJtMFjOVr2c9yL92vHudjmr3s3m6J1hbw3DBGFZJm3TIj9TWyynZ4GEsEA9SOtni4heRUr6lNOg==",
+ "dependencies": {
+ "get-caller-file": "^2.0.5",
+ "pino": "^8.17.1",
+ "pino-std-serializers": "^6.2.2",
+ "process-warning": "^3.0.0"
+ }
+ },
+ "node_modules/pino-http/node_modules/pino": {
+ "version": "8.21.0",
+ "resolved": "https://registry.npmjs.org/pino/-/pino-8.21.0.tgz",
+ "integrity": "sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==",
+ "dependencies": {
+ "atomic-sleep": "^1.0.0",
+ "fast-redact": "^3.1.1",
+ "on-exit-leak-free": "^2.1.0",
+ "pino-abstract-transport": "^1.2.0",
+ "pino-std-serializers": "^6.0.0",
+ "process-warning": "^3.0.0",
+ "quick-format-unescaped": "^4.0.3",
+ "real-require": "^0.2.0",
+ "safe-stable-stringify": "^2.3.1",
+ "sonic-boom": "^3.7.0",
+ "thread-stream": "^2.6.0"
+ },
+ "bin": {
+ "pino": "bin.js"
+ }
+ },
+ "node_modules/pino-http/node_modules/pino-abstract-transport": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz",
+ "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==",
+ "dependencies": {
+ "readable-stream": "^4.0.0",
+ "split2": "^4.0.0"
+ }
+ },
+ "node_modules/pino-http/node_modules/process-warning": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz",
+ "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ=="
+ },
+ "node_modules/pino-pretty": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-6.0.0.tgz",
+ "integrity": "sha512-jyeR2fXXWc68st1DTTM5NhkHlx8p+1fKZMfm84Jwq+jSw08IwAjNaZBZR6ts69hhPOfOjg/NiE1HYW7vBRPL3A==",
+ "dependencies": {
+ "@hapi/bourne": "^2.0.0",
+ "args": "^5.0.1",
+ "colorette": "^1.3.0",
+ "dateformat": "^4.5.1",
+ "fast-safe-stringify": "^2.0.7",
+ "jmespath": "^0.15.0",
+ "joycon": "^3.0.0",
+ "pump": "^3.0.0",
+ "readable-stream": "^3.6.0",
+ "rfdc": "^1.3.0",
+ "split2": "^3.1.1",
+ "strip-json-comments": "^3.1.1"
+ },
+ "bin": {
+ "pino-pretty": "bin.js"
+ }
+ },
+ "node_modules/pino-pretty/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pino-pretty/node_modules/split2": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
+ "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
+ "dependencies": {
+ "readable-stream": "^3.0.0"
+ }
+ },
+ "node_modules/pino-std-serializers": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz",
+ "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA=="
+ },
+ "node_modules/pirates": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-conf": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz",
+ "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==",
+ "dependencies": {
+ "find-up": "^3.0.0",
+ "load-json-file": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-conf/node_modules/find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dependencies": {
+ "locate-path": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-conf/node_modules/locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dependencies": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-conf/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-conf/node_modules/p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dependencies": {
+ "p-limit": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-conf/node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/possible-typed-array-names": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
+ "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/probot": {
+ "version": "13.2.0",
+ "resolved": "https://registry.npmjs.org/probot/-/probot-13.2.0.tgz",
+ "integrity": "sha512-9fONmImU9aUmcbgEg/JtQwwEvM6IA6ds4ZRlshhjVB2fw5ijKXCH0M26H9kzVFeNZcmRDxK/MvCSc1CnHehxfA==",
+ "dependencies": {
+ "@octokit/core": "^5.0.2",
+ "@octokit/plugin-enterprise-compatibility": "^4.0.1",
+ "@octokit/plugin-paginate-rest": "^9.1.4",
+ "@octokit/plugin-rest-endpoint-methods": "^10.1.5",
+ "@octokit/plugin-retry": "^6.0.1",
+ "@octokit/plugin-throttling": "^8.1.3",
+ "@octokit/request": "^8.1.6",
+ "@octokit/types": "^12.3.0",
+ "@octokit/webhooks": "^12.0.10",
+ "@probot/get-private-key": "^1.1.2",
+ "@probot/octokit-plugin-config": "^2.0.1",
+ "@probot/pino": "^2.3.5",
+ "@types/express": "^4.17.21",
+ "bottleneck": "^2.19.5",
+ "commander": "^12.0.0",
+ "deepmerge": "^4.3.1",
+ "dotenv": "^16.3.1",
+ "eventsource": "^2.0.2",
+ "express": "^4.18.2",
+ "ioredis": "^5.3.2",
+ "js-yaml": "^4.1.0",
+ "lru-cache": "^10.0.3",
+ "octokit-auth-probot": "^2.0.0",
+ "pino": "^8.16.1",
+ "pino-http": "^9.0.0",
+ "pkg-conf": "^3.1.0",
+ "resolve": "^1.22.8",
+ "update-dotenv": "^1.1.1"
+ },
+ "bin": {
+ "probot": "bin/probot.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/probot/node_modules/@octokit/plugin-throttling": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-8.2.0.tgz",
+ "integrity": "sha512-nOpWtLayKFpgqmgD0y3GqXafMFuKcA4tRPZIfu7BArd2lEZeb1988nhWhwx4aZWmjDmUfdgVf7W+Tt4AmvRmMQ==",
+ "dependencies": {
+ "@octokit/types": "^12.2.0",
+ "bottleneck": "^2.15.3"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "@octokit/core": "^5.0.0"
+ }
+ },
+ "node_modules/probot/node_modules/@octokit/types": {
+ "version": "12.6.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
+ "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
+ "dependencies": {
+ "@octokit/openapi-types": "^20.0.0"
+ }
+ },
+ "node_modules/probot/node_modules/@octokit/types/node_modules/@octokit/openapi-types": {
+ "version": "20.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
+ "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
+ },
+ "node_modules/probot/node_modules/lru-cache": {
+ "version": "10.2.2",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz",
+ "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==",
+ "engines": {
+ "node": "14 || >=16.14"
+ }
+ },
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/process-warning": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.3.2.tgz",
+ "integrity": "sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA=="
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/propagate": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz",
+ "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
+ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ]
+ },
+ "node_modules/qs": {
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
+ "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/quick-format-unescaped": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
+ "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="
+ },
+ "node_modules/quick-lru": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
+ "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "dev": true
+ },
+ "node_modules/read-pkg": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+ "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+ "dev": true,
+ "dependencies": {
+ "@types/normalize-package-data": "^2.4.0",
+ "normalize-package-data": "^2.5.0",
+ "parse-json": "^5.0.0",
+ "type-fest": "^0.6.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+ "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^4.1.0",
+ "read-pkg": "^5.2.0",
+ "type-fest": "^0.8.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg/node_modules/hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
+ "node_modules/read-pkg/node_modules/normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "node_modules/read-pkg/node_modules/semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/read-pkg/node_modules/type-fest": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+ "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
+ "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "buffer": "^6.0.3",
+ "events": "^3.3.0",
+ "process": "^0.11.10",
+ "string_decoder": "^1.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/real-require": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
+ "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==",
+ "engines": {
+ "node": ">= 12.13.0"
+ }
+ },
+ "node_modules/redent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
+ "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
+ "dev": true,
+ "dependencies": {
+ "indent-string": "^4.0.0",
+ "strip-indent": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/redis-errors": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
+ "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/redis-parser": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
+ "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
+ "dependencies": {
+ "redis-errors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
+ "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "set-function-name": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-global": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz",
+ "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==",
+ "dev": true,
+ "dependencies": {
+ "global-dirs": "^0.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve.exports": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz",
+ "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rfdc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz",
+ "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "get-intrinsic": "^1.2.4",
+ "has-symbols": "^1.0.3",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz",
+ "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.1.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-stable-stringify": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz",
+ "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "node_modules/semver": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+ "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ },
+ "node_modules/send": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
+ "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/send/node_modules/debug/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/send/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/serve-static": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
+ "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+ "dependencies": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.18.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+ "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/sonic-boom": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz",
+ "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==",
+ "dependencies": {
+ "atomic-sleep": "^1.0.0"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/spdx-correct": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+ "dev": true,
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
+ "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
+ "dev": true
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.18",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz",
+ "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==",
+ "dev": true
+ },
+ "node_modules/split2": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
+ "engines": {
+ "node": ">= 10.x"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true
+ },
+ "node_modules/stack-utils": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
+ "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/stack-utils/node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/standard-as-callback": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
+ "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="
+ },
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "dependencies": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz",
+ "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz",
+ "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-indent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
+ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+ "dev": true,
+ "dependencies": {
+ "min-indent": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/text-extensions": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz",
+ "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/thread-stream": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz",
+ "integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==",
+ "dependencies": {
+ "real-require": "^0.2.0"
+ }
+ },
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+ "dev": true
+ },
+ "node_modules/through2": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
+ "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "3"
+ }
+ },
+ "node_modules/through2/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true
+ },
+ "node_modules/to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "dev": true
+ },
+ "node_modules/trim-newlines": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
+ "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
+ "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
+ "dev": true,
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tsconfig-paths/node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/tsconfig-paths/node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz",
+ "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz",
+ "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz",
+ "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz",
+ "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
+ },
+ "node_modules/universal-github-app-jwt": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-1.1.2.tgz",
+ "integrity": "sha512-t1iB2FmLFE+yyJY9+3wMx0ejB+MQpEVkH0gQv7dR6FZyltyq+ZZO0uDpbopxhrZ3SLEO4dCEkIujOMldEQ2iOA==",
+ "dependencies": {
+ "@types/jsonwebtoken": "^9.0.0",
+ "jsonwebtoken": "^9.0.2"
+ }
+ },
+ "node_modules/universal-user-agent": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz",
+ "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.16",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz",
+ "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.1.2",
+ "picocolors": "^1.0.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/update-dotenv": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/update-dotenv/-/update-dotenv-1.1.1.tgz",
+ "integrity": "sha512-3cIC18In/t0X/yH793c00qqxcKD8jVCgNOPif/fGQkFpYMGecM9YAc+kaAKXuZsM2dE9I9wFI7KvAuNX22SGMQ==",
+ "peerDependencies": {
+ "dotenv": "*"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/v8-to-istanbul": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "dev": true
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dev": true,
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz",
+ "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..ac6b2ce
--- /dev/null
+++ b/package.json
@@ -0,0 +1,70 @@
+{
+ "name": "sdv-approval-bot",
+ "version": "1.0.0",
+ "description": "",
+ "author": "Mark Lawrence <15652599+Mark-J-Lawrence@users.noreply.github.com>",
+ "license": "EPL-2.0",
+ "homepage": "https://github.com/cicsdev/cics-security-sdv-samples",
+ "scripts": {
+ "postinstall": "per-env",
+ "postinstall:development": "husky install",
+ "postinstall:staging": "",
+ "postinstall:production": "",
+ "clean": "rm -rf ./coverage",
+ "lint-bot": "eslint ./lib",
+ "lint-docs": "cd docs && npm run lint",
+ "lint-ansible": "ansible-lint ./ansible-sdv-pipeline/*",
+ "lint-flake8-python": "flake8 ./ansible-sdv-pipeline/",
+ "lint-pylint": "pylint ./ansible-sdv-pipeline --fail-under 5 --fail-on F,E,W,C,R",
+ "lint-all": "git config --global --add safe.directory /workspace/git-workspace; commitlint -V --from=HEAD~1 && npm run lint-bot && npm run lint-ansible && npm run lint-flake8-python && npm run lint-pylint && npm run lint-docs",
+ "pretest": "npm run clean && npm run lint-bot",
+ "start": "probot run ./lib/app.js",
+ "test": "jest --coverage",
+ "unit-test": "jest --coverage",
+ "pre-commit": "npm run lint-all"
+ },
+ "dependencies": {
+ "@octokit/rest": "20.0.2",
+ "express": "4.19.2",
+ "octokit-auth-probot": "2.0.0",
+ "per-env": "1.0.2",
+ "probot": "13.2.0"
+ },
+ "devDependencies": {
+ "@commitlint/cli": "18.4.3",
+ "@commitlint/config-conventional": "18.4.3",
+ "@types/jest": "29.5.11",
+ "eslint": "8.55.0",
+ "eslint-config-airbnb-base": "15.0.0",
+ "eslint-plugin-import": "2.29.0",
+ "eslint-plugin-jest": "27.6.0",
+ "husky": "8.0.3",
+ "jest": "29.7.0",
+ "nock": "13.5.4",
+ "node-fetch": "2.7.0",
+ "pino": "8.17.0"
+ },
+ "engines": {
+ "node": ">= 18.17.0"
+ },
+ "jest": {
+ "verbose": true,
+ "testEnvironment": "node",
+ "setupFiles": ["/.jest/setEnvVars.js"],
+ "collectCoverageFrom": [
+ "lib/**/*.js",
+ "!**/node_modules/**"
+ ],
+ "coverageThreshold": {
+ "global": {
+ "branches": 85,
+ "functions": 98,
+ "lines": 89
+ }
+ },
+ "coverageReporters": [
+ "html",
+ "text"
+ ]
+ }
+}