From cf0efe3849ec20119a8bcce92fda264387f61180 Mon Sep 17 00:00:00 2001 From: Anatoliy Poloz Date: Mon, 11 Dec 2023 12:24:34 +0300 Subject: [PATCH] first commit --- .eslintrc.json | 16 + .github/CODE_OF_CONDUCT.md | 76 + .github/CONTRIBUTING.md | 83 + .github/FUNDING.yml | 3 + .github/ISSUE_TEMPLATE/bug.md | 42 + .github/ISSUE_TEMPLATE/feature.md | 26 + .github/PULL_REQUEST_TEMPLATE.md | 37 + .github/SECURITY.md | 24 + .github/codeql/codeql-configuration.yml | 4 + .github/dependabot.yml | 7 + .github/workflows/codeql.yml | 32 + .github/workflows/docs.yml | 92 + .github/workflows/node.yml | 63 + .github/workflows/php.yml | 93 + .github/workflows/publish.yml | 62 + .gitignore | 93 + .prettierrc.json | 12 + LICENSE | 22 + README.md | 1074 ++ __tests__/config.test.ts | 16 + __tests__/coverage.test.ts | 44 + __tests__/extensions.test.ts | 153 + __tests__/fetch.test.ts | 39 + __tests__/install.test.ts | 82 + __tests__/packagist.test.ts | 50 + __tests__/tools.test.ts | 608 + __tests__/utils.test.ts | 315 + action.yml | 35 + dist/index.js | 5722 +++++++++ examples/bedrock.yml | 38 + examples/blackfire-player.yml | 36 + examples/blackfire.yml | 37 + examples/cakephp-mysql.yml | 138 + examples/cakephp-postgres.yml | 138 + examples/cakephp.yml | 109 + examples/codeigniter.yml | 40 + examples/laminas-mvc.yml | 39 + examples/laravel-mysql.yml | 89 + examples/laravel-postgres.yml | 91 + examples/laravel.yml | 50 + examples/lumen-mysql.yml | 89 + examples/lumen-postgres.yml | 91 + examples/lumen.yml | 45 + examples/phalcon-mysql.yml | 88 + examples/phalcon-postgres.yml | 84 + examples/sage.yml | 69 + examples/slim-framework.yml | 40 + examples/symfony-mysql.yml | 70 + examples/symfony-postgres.yml | 70 + examples/symfony.yml | 46 + examples/yii2-mysql.yml | 86 + examples/yii2-postgres.yml | 86 + jest.config.js | 12 + package-lock.json | 11566 +++++++++++++++++++ package.json | 67 + src/config.ts | 82 + src/configs/brew_extensions | 44 + src/configs/composer.env | 3 + src/configs/ini/jit.ini | 3 + src/configs/ini/php.ini | 2 + src/configs/ini/xdebug.ini | 1 + src/configs/mod_priority | 30 + src/configs/os_releases.csv | 22 + src/configs/php-versions.json | 7 + src/configs/php_debug_packages | 11 + src/configs/php_packages | 12 + src/configs/pm/php.json | 29 + src/configs/pm/phpunit.json | 24 + src/configs/tools.json | 322 + src/configs/tools_schema.json | 136 + src/configs/windows_extensions | 2 + src/coverage.ts | 149 + src/extensions.ts | 388 + src/fetch.ts | 56 + src/install.ts | 66 + src/packagist.ts | 37 + src/scripts/darwin.sh | 286 + src/scripts/extensions/add_extensions.ps1 | 260 + src/scripts/extensions/add_extensions.sh | 229 + src/scripts/extensions/blackfire.ps1 | 34 + src/scripts/extensions/blackfire.sh | 24 + src/scripts/extensions/couchbase.sh | 75 + src/scripts/extensions/cubrid.sh | 60 + src/scripts/extensions/event.sh | 50 + src/scripts/extensions/extension_map.php | 132 + src/scripts/extensions/firebird.ps1 | 20 + src/scripts/extensions/firebird.sh | 40 + src/scripts/extensions/gearman.sh | 26 + src/scripts/extensions/geos.sh | 17 + src/scripts/extensions/http.ps1 | 51 + src/scripts/extensions/http.sh | 113 + src/scripts/extensions/intl.sh | 24 + src/scripts/extensions/ioncube.ps1 | 33 + src/scripts/extensions/ioncube.sh | 21 + src/scripts/extensions/oci.ps1 | 85 + src/scripts/extensions/oci.sh | 65 + src/scripts/extensions/patches/firebird.sh | 11 + src/scripts/extensions/patches/geos.sh | 9 + src/scripts/extensions/patches/http.sh | 11 + src/scripts/extensions/patches/pdo_oci.sh | 6 + src/scripts/extensions/patches/phpize.sh | 26 + src/scripts/extensions/patches/protobuf.sh | 4 + src/scripts/extensions/phalcon.ps1 | 109 + src/scripts/extensions/phalcon.sh | 95 + src/scripts/extensions/relay.sh | 146 + src/scripts/extensions/source.sh | 159 + src/scripts/extensions/sqlsrv.ps1 | 69 + src/scripts/extensions/sqlsrv.sh | 23 + src/scripts/extensions/zephir_parser.ps1 | 80 + src/scripts/extensions/zephir_parser.sh | 38 + src/scripts/linux.sh | 298 + src/scripts/tools/add_tools.ps1 | 284 + src/scripts/tools/add_tools.sh | 217 + src/scripts/tools/blackfire.ps1 | 19 + src/scripts/tools/blackfire.sh | 40 + src/scripts/tools/brew.sh | 83 + src/scripts/tools/grpc_php_plugin.ps1 | 21 + src/scripts/tools/grpc_php_plugin.sh | 62 + src/scripts/tools/ppa.sh | 204 + src/scripts/tools/protoc.ps1 | 40 + src/scripts/tools/protoc.sh | 28 + src/scripts/tools/symfony.ps1 | 18 + src/scripts/tools/symfony.sh | 41 + src/scripts/unix.sh | 200 + src/scripts/win32.ps1 | 446 + src/tools.ts | 583 + src/utils.ts | 493 + tsconfig.json | 19 + 128 files changed, 29192 insertions(+) create mode 100644 .eslintrc.json create mode 100644 .github/CODE_OF_CONDUCT.md create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/FUNDING.yml create mode 100644 .github/ISSUE_TEMPLATE/bug.md create mode 100644 .github/ISSUE_TEMPLATE/feature.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/SECURITY.md create mode 100644 .github/codeql/codeql-configuration.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/docs.yml create mode 100644 .github/workflows/node.yml create mode 100644 .github/workflows/php.yml create mode 100644 .github/workflows/publish.yml create mode 100644 .gitignore create mode 100644 .prettierrc.json create mode 100644 LICENSE create mode 100644 README.md create mode 100644 __tests__/config.test.ts create mode 100644 __tests__/coverage.test.ts create mode 100644 __tests__/extensions.test.ts create mode 100644 __tests__/fetch.test.ts create mode 100644 __tests__/install.test.ts create mode 100644 __tests__/packagist.test.ts create mode 100644 __tests__/tools.test.ts create mode 100644 __tests__/utils.test.ts create mode 100644 action.yml create mode 100644 dist/index.js create mode 100644 examples/bedrock.yml create mode 100644 examples/blackfire-player.yml create mode 100644 examples/blackfire.yml create mode 100644 examples/cakephp-mysql.yml create mode 100644 examples/cakephp-postgres.yml create mode 100644 examples/cakephp.yml create mode 100644 examples/codeigniter.yml create mode 100644 examples/laminas-mvc.yml create mode 100644 examples/laravel-mysql.yml create mode 100644 examples/laravel-postgres.yml create mode 100644 examples/laravel.yml create mode 100644 examples/lumen-mysql.yml create mode 100644 examples/lumen-postgres.yml create mode 100644 examples/lumen.yml create mode 100644 examples/phalcon-mysql.yml create mode 100644 examples/phalcon-postgres.yml create mode 100644 examples/sage.yml create mode 100644 examples/slim-framework.yml create mode 100644 examples/symfony-mysql.yml create mode 100644 examples/symfony-postgres.yml create mode 100644 examples/symfony.yml create mode 100644 examples/yii2-mysql.yml create mode 100644 examples/yii2-postgres.yml create mode 100644 jest.config.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/config.ts create mode 100644 src/configs/brew_extensions create mode 100644 src/configs/composer.env create mode 100644 src/configs/ini/jit.ini create mode 100644 src/configs/ini/php.ini create mode 100644 src/configs/ini/xdebug.ini create mode 100644 src/configs/mod_priority create mode 100644 src/configs/os_releases.csv create mode 100644 src/configs/php-versions.json create mode 100644 src/configs/php_debug_packages create mode 100644 src/configs/php_packages create mode 100644 src/configs/pm/php.json create mode 100644 src/configs/pm/phpunit.json create mode 100644 src/configs/tools.json create mode 100644 src/configs/tools_schema.json create mode 100644 src/configs/windows_extensions create mode 100644 src/coverage.ts create mode 100644 src/extensions.ts create mode 100644 src/fetch.ts create mode 100644 src/install.ts create mode 100644 src/packagist.ts create mode 100644 src/scripts/darwin.sh create mode 100644 src/scripts/extensions/add_extensions.ps1 create mode 100644 src/scripts/extensions/add_extensions.sh create mode 100644 src/scripts/extensions/blackfire.ps1 create mode 100644 src/scripts/extensions/blackfire.sh create mode 100644 src/scripts/extensions/couchbase.sh create mode 100644 src/scripts/extensions/cubrid.sh create mode 100644 src/scripts/extensions/event.sh create mode 100644 src/scripts/extensions/extension_map.php create mode 100644 src/scripts/extensions/firebird.ps1 create mode 100644 src/scripts/extensions/firebird.sh create mode 100644 src/scripts/extensions/gearman.sh create mode 100644 src/scripts/extensions/geos.sh create mode 100644 src/scripts/extensions/http.ps1 create mode 100644 src/scripts/extensions/http.sh create mode 100644 src/scripts/extensions/intl.sh create mode 100644 src/scripts/extensions/ioncube.ps1 create mode 100644 src/scripts/extensions/ioncube.sh create mode 100644 src/scripts/extensions/oci.ps1 create mode 100644 src/scripts/extensions/oci.sh create mode 100644 src/scripts/extensions/patches/firebird.sh create mode 100644 src/scripts/extensions/patches/geos.sh create mode 100644 src/scripts/extensions/patches/http.sh create mode 100644 src/scripts/extensions/patches/pdo_oci.sh create mode 100644 src/scripts/extensions/patches/phpize.sh create mode 100644 src/scripts/extensions/patches/protobuf.sh create mode 100644 src/scripts/extensions/phalcon.ps1 create mode 100644 src/scripts/extensions/phalcon.sh create mode 100644 src/scripts/extensions/relay.sh create mode 100644 src/scripts/extensions/source.sh create mode 100644 src/scripts/extensions/sqlsrv.ps1 create mode 100644 src/scripts/extensions/sqlsrv.sh create mode 100644 src/scripts/extensions/zephir_parser.ps1 create mode 100644 src/scripts/extensions/zephir_parser.sh create mode 100644 src/scripts/linux.sh create mode 100644 src/scripts/tools/add_tools.ps1 create mode 100644 src/scripts/tools/add_tools.sh create mode 100644 src/scripts/tools/blackfire.ps1 create mode 100644 src/scripts/tools/blackfire.sh create mode 100644 src/scripts/tools/brew.sh create mode 100644 src/scripts/tools/grpc_php_plugin.ps1 create mode 100644 src/scripts/tools/grpc_php_plugin.sh create mode 100644 src/scripts/tools/ppa.sh create mode 100644 src/scripts/tools/protoc.ps1 create mode 100644 src/scripts/tools/protoc.sh create mode 100644 src/scripts/tools/symfony.ps1 create mode 100644 src/scripts/tools/symfony.sh create mode 100644 src/scripts/unix.sh create mode 100644 src/scripts/win32.ps1 create mode 100644 src/tools.ts create mode 100644 src/utils.ts create mode 100644 tsconfig.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..e70aaae --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,16 @@ +{ + "env": { "node": true, "jest": true }, + "parser": "@typescript-eslint/parser", + "parserOptions": { "ecmaVersion": 2021, "sourceType": "module" }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "plugin:import/errors", + "plugin:import/warnings", + "plugin:import/typescript", + "plugin:prettier/recommended", + "prettier" + ], + "plugins": ["@typescript-eslint", "jest"] +} \ No newline at end of file diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..d398bb4 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at contact@shivammathur.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq \ No newline at end of file diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..7dbf38e --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,83 @@ +# Contributing to setup-php + +## Welcome! + +We look forward to your contributions! Here are some examples how you can contribute: + +* [Ask any questions you may have](https://github.com/shivammathur/setup-php/discussions/new?category=Q-A-Help) +* [Report a bug](https://github.com/shivammathur/setup-php/issues/new?labels=type/bug&template=bug.md) +* [Propose a new feature](https://github.com/shivammathur/setup-php/issues/new?labels=enhancement&template=feature.md) +* [Send a pull request](https://github.com/shivammathur/setup-php/pulls) + +## Contributor Code of Conduct + +Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. + +## Getting Started + +To get started fork `setup-php` and clone it using git: + +```bash +git clone https://github.com//setup-php.git + +cd setup-php +``` + +If you are using `Windows` configure `git` to handle line endings. + +```cmd +git config --local core.autocrlf true +``` + +Install `setup-php` dependencies using [npm](https://www.npmjs.com/): + +```bash +npm install +``` + +## Workflow to create Pull Requests + +* Fork the `setup-php` project and clone it. +* Create a new branch from the develop branch. +* Make your bug fix or feature addition. +* Add tests for it, so we don't break it in a future version unintentionally. +* Ensure the test suite passes and the code complies with our coding guidelines (see below). +* Send a pull request to the develop branch with all the details. +* If possible, create a GitHub Actions workflow with an integration test for the change in a demo repository and link it in your pull request. + +Please make sure that you have [set up your user name and email address](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup) for use with Git. Strings such as `silly nick name ` look really stupid in the commit history of a project. + +Due to time constraints, you may not always get a quick response. Please do not take delays personally and feel free to remind. + +## Coding Guidelines + +This project comes with `.prettierrc.json` and `eslintrc.json` configuration files. Please run the following commands to fix and verify the code quality. + +```bash +npm run format +npm run lint +``` + +### Running the test suite + +After following the steps shown above, The `setup-php` tests in the `__tests__` directory can be run using this command: + +```bash +npm test +``` + +### Creating a release + +Creating a release means compiling all the TypeScript code to a single file which `setup-php` can run. Run this, before you push your changes. + +```bash +npm run build +npm run release +``` + +### Reporting issues and discussions + +For questions or support, we prefer GitHub Discussions. For any bugs or new features you can create an issue using the appropriate template: + +* [Discussions](https://github.com/shivammathur/setup-php/discussions) +* [Issues](https://github.com/shivammathur/setup-php/issues) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..faa04a5 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: shivammathur diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 0000000..09e78fa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,42 @@ +--- +name: Bug report +about: Nice, you found a bug! +title: '' +labels: 'bug' +assignees: 'shivammathur' + +--- + +**Describe the bug** + + +**Version** +- [ ] I have checked releases, and the bug exists in the latest patch version of `v1` or `v2`. +- [ ] `v2` +- [ ] `v1` + +**Runners** + +- [ ] GitHub Hosted +- [ ] Self Hosted + +**Operating systems** + + +**PHP versions** + + +**To Reproduce** + + +**Expected behavior** + + +**Screenshots/Logs** + + +**Additional context** + + +**Are you willing to submit a PR?** + diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md new file mode 100644 index 0000000..c88e807 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -0,0 +1,26 @@ +--- +name: Feature request +about: Suggest a new feature +title: '' +labels: 'enhancement' +assignees: 'shivammathur' + +--- + +**Describe the feature** + + +**Version** +- [ ] I have checked releases, and the feature is missing in the latest patch version of `v2`. + +**Underlying issue** + + +**Describe alternatives** + + +**Additional context** + + +**Are you willing to submit a PR?** + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..524b7de --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,37 @@ +--- +name: 🐞 Bug Fix, ⚙ Improvement or 🎉 New Feature +about: You found a bug, want to improve something or add a new feature +labels: bug or enhancement + +--- + +## A Pull Request should be associated with a Discussion. + +> If you're fixing a bug, adding a new feature or improving something please provide the details in discussions, +> so that the development can be pointed in the intended direction. + +Related discussion: + +> Further notes in [Contribution Guidelines](.github/CONTRIBUTING.md) +> Thank you for your contribution. + +### Description + +This PR [briefly explain what it does] + +> In case this PR introduced TypeScript/JavaScript code changes: + +- [ ] I have written test cases for the changes in this pull request +- [ ] I have run `npm run format` before the commit. +- [ ] I have run `npm run lint` before the commit. +- [ ] I have run `npm run release` before the commit. +- [ ] `npm test` returns with no unit test errors and all code covered. + +> In case this PR edits any scripts: + +- [ ] I have checked the edited scripts for syntax. +- [ ] I have tested the changes in an integration test (If yes, provide workflow YAML and link). + + \ No newline at end of file diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..65db6ad --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,24 @@ +# Security Policy + +## Supported Versions + +The latest patch versions of `v1` and `v2` releases of this project are supported for security updates. + +## Supported PHP Versions + +This security policy only applies to the latest patches of the following PHP versions. + +| Version | Supported | +|---------|--------------------| +| 8.1 | :white_check_mark: | +| 8.2 | :white_check_mark: | +| 8.3 | :white_check_mark: | + +## Reporting a Vulnerability + +If you have found any issues that might have security implications in the versions supported, please send a report privately to [contact@shivammathur.com](mailto:contact@shivammathur.com). +Do not report security reports publicly. + +## Tidelift + +If you use this GitHub Action through a Tidelift subscription, please refer to [https://tidelift.com/security](https://tidelift.com/security). \ No newline at end of file diff --git a/.github/codeql/codeql-configuration.yml b/.github/codeql/codeql-configuration.yml new file mode 100644 index 0000000..c70a218 --- /dev/null +++ b/.github/codeql/codeql-configuration.yml @@ -0,0 +1,4 @@ +name : CodeQL Configuration + +paths: + - './src' diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..c00c647 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: +- package-ecosystem: "github-actions" + directory: "/" + target-branch: "develop" + schedule: + interval: "weekly" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..06adcb6 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,32 @@ +name: CodeQL Workflow +on: + workflow_dispatch: + schedule: + - cron: '0 15 * * 6' +permissions: + contents: read + +jobs: + codeql: + permissions: + actions: read # for github/codeql-action/init to get workflow details + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/autobuild to send a status report + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + config-file: ./.github/codeql/codeql-configuration.yml + languages: javascript + + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..5e1a1f8 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,92 @@ +name: Docs workflow +on: + workflow_dispatch: + schedule: + - cron: '0 15 * * 6' +permissions: + contents: read + +jobs: + create: + permissions: + contents: none + name: Create + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-22.04, ubuntu-20.04, windows-2022, macos-12] + php-versions: ['5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + - name: Create for Linux and macOS + env: + file: php${{ matrix.php-versions }}-${{ matrix.operating-system }}.md + version: ${{ matrix.php-versions }} + if: matrix.operating-system != 'windows-2022' + run: | + echo "## PHP $version" >> "$file" + printf "\n" >> "$file" + echo "\`\`\`" >> "$file" + php -m >> "$file" + echo "\`\`\`" >> "$file" + printf "\n" >> "$file" + - name: Create for Windows + env: + file: php${{ matrix.php-versions }}-${{ matrix.operating-system }}.md + version: ${{ matrix.php-versions }} + if: matrix.operating-system == 'windows-2022' + run: | + Write-Output "## PHP ${{ matrix.php-versions }}`n" | Out-File -FilePath "$env:file" + Write-Output "``````" | Out-File -FilePath "$env:file" -Append + php -m | Out-File -FilePath "$env:file" -Append + Write-Output "```````n" | Out-File -FilePath "$env:file" -Append + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: lists + path: php${{ matrix.php-versions }}-${{ matrix.operating-system }}.md + update: + permissions: + contents: write # for Git to git push + name: Update + needs: create + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + repository: ${{ github.repository }}.wiki + - name: Download artifacts + uses: actions/download-artifact@v3 + with: + path: ${{ github.workspace }} + - name: Configure Git + run : | + git config --local user.email "${{ secrets.email }}" + git config --local user.name "${{ github.repository_owner }}" + - name: Combine + run: | + for os in ubuntu-22.04 ubuntu-20.04 windows-2022 windows-2019 macos-11 macos-12 macos-13; do + echo "These are extensions which are loaded by default on the following PHP versions. More extensions which are available as packages and available on pecl are supported by setup-php. Refer to [php extension support](https://github.com/shivammathur/setup-php#heavy_plus_sign-php-extension-support) for more details." > Php-extensions-loaded-on-"$os".md + for version in 5.3 5.4 5.5 5.6 7.0 7.1 7.2 7.3 7.4 8.0 8.1 8.2 8.3 8.4; do + if [[ "$os" = "macos-11" || "$os" = "macos-13" ]]; then + cat lists/php"$version"-macos-12.md >> Php-extensions-loaded-on-"$os".md + elif [ "$os" = "windows-2019" ]; then + cat lists/php"$version"-windows-2022.md >> Php-extensions-loaded-on-"$os".md + else + cat lists/php"$version"-"$os".md >> Php-extensions-loaded-on-"$os".md + fi + done + done + rm -rf ./lists + - name: Update + run: | + if [ "$(git status --porcelain=v1 2>/dev/null | wc -l)" != "0" ]; then + git add . + git commit -m "Update PHP extensions on wiki - $(date +'%d-%m-%y')" + git push -f https://${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.wiki.git master || true + fi diff --git a/.github/workflows/node.yml b/.github/workflows/node.yml new file mode 100644 index 0000000..4f75ef8 --- /dev/null +++ b/.github/workflows/node.yml @@ -0,0 +1,63 @@ +name: Node workflow +on: + pull_request: + branches: + - master + - develop + - verbose + paths-ignore: + - '**.md' + - 'examples/**' + push: + branches: + - master + - develop + - verbose + paths-ignore: + - '**.md' + - 'examples/**' +permissions: + contents: read + +jobs: + run: + name: Run + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-latest, windows-latest, macos-latest] + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Setup Node.js 16.x + uses: actions/setup-node@v4 + with: + node-version: 16.x + + - name: Install dependencies + run: npm install + + - name: Prettier Format Check + run: npm run format-check + + - name: ESLint Check + run: npm run lint + + - name: Run tests + run: npm test + + - name: Run npm audit + run: npm audit + + - name: Send Coverage + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage/lcov.info + name: github-actions-codecov-${{ matrix.operating-system }} + fail_ci_if_error: false + verbose: true diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml new file mode 100644 index 0000000..e8e3976 --- /dev/null +++ b/.github/workflows/php.yml @@ -0,0 +1,93 @@ +name: Main workflow +on: + workflow_dispatch: + pull_request: + branches: + - master + - develop + - verbose + paths-ignore: + - '**.md' + - 'examples/**' + push: + branches: + - master + - develop + - verbose + paths-ignore: + - '**.md' + - 'examples/**' +permissions: + contents: read +env: + default-php-version: '8.2' +jobs: + run: + name: Run + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-22.04, ubuntu-20.04, windows-2019, macos-latest] + php-versions: ['5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] + include: + - operating-system: ubuntu-22.04 + php-versions: '' + php-version-file: 'php-version-file' + env: + extensions: xml, opcache, xdebug, pcov, gd + key: cache-v5 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup cache environment + id: cache-env + uses: shivammathur/cache-extensions@develop + with: + php-version: ${{ matrix.php-versions || env.default-php-version }} + extensions: ${{ env.extensions }} + key: ${{ env.key }} + + - name: Cache extensions + uses: actions/cache@v3 + with: + path: ${{ steps.cache-env.outputs.dir }} + key: ${{ steps.cache-env.outputs.key }} + restore-keys: ${{ steps.cache-env.outputs.key }} + + - name: Stage php-version-file + if: ${{ matrix.php-version-file == 'php-version-file' }} + run: | + echo ${{ env.default-php-version }} > php-version-file + + - name: Setup PHP with extensions and custom config + run: node dist/index.js + env: + php-version: ${{ matrix.php-versions }} + php-version-file: ${{ matrix.php-version-file }} + extensions: ${{ env.extensions }} + ini-values: post_max_size=256M, short_open_tag=On, date.timezone=Asia/Kolkata + + - name: Testing PHP version + run: | + php -v + php -r "if(strpos(phpversion(), '${{ matrix.php-versions || env.default-php-version }}') === false) {throw new Exception('Wrong PHP version Installed');}" + + - name: Testing Composer version + run: | + composer -V + php -r "if(strpos(@exec('composer -V'), 'Composer version') === false) {throw new Exception('Composer not found');}" + - name: Testing Extensions + run: | + php -m + php -r "if(! extension_loaded('gd')) {throw new Exception('gd not found');}" + php -r "if(! extension_loaded('xml')) {throw new Exception('xml not found');}" + php -r "if(! extension_loaded('Xdebug')) {throw new Exception('Xdebug not found');}" + php -r "if(phpversion()>=7.1 && ! extension_loaded('pcov')) {throw new Exception('PCOV not found');}" + - name: Testing ini values + run: | + php -r "if(ini_get('memory_limit')!='-1') {throw new Exception('memory_limit not disabled');}" + php -r "if(ini_get('post_max_size')!='256M') {throw new Exception('post_max_size not added');}" + php -r "if(ini_get('short_open_tag')!=1) {throw new Exception('short_open_tag not added');}" + php -r "if(ini_get('date.timezone')!='Asia/Kolkata') {throw new Exception('date.timezone not added');}" \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..f90599f --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,62 @@ +name: Publish Package +on: + release: + types: [created] + workflow_dispatch: + inputs: + skip: + description: Skip release to repository + required: false + tag: + description: Tag name + required: true +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout release + if: github.event_name != 'workflow_dispatch' + uses: actions/checkout@v4 + + - name: Checkout tag + uses: actions/checkout@v4 + if: github.event_name == 'workflow_dispatch' + with: + ref: ${{ github.event.inputs.tag }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '16.x' + registry-url: https://registry.npmjs.org + + - name: Install dependencies and add lib + run: | + npm install + npm run build + sed -i -e '/lib\//d' .gitignore + + - name: Publish to NPM + if: "!contains(github.event.inputs.skip, 'skip-npm')" + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Change to GitHub Packages registry + uses: actions/setup-node@v4 + with: + registry-url: https://npm.pkg.github.com + scope: '@shivammathur' + + - name: Patch package.json + run: | + sed -i 's#"name": "#"name": "@shivammathur/#' package.json + + - name: Publish to GitHub Packages + if: "!contains(github.event.inputs.skip, 'skip-github-packages')" + run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..08528d2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,93 @@ +# Explicitly not ignoring node_modules so that they are included in package downloaded by runner +node_modules/ +__tests__/runner/* +lib/ + +# Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..966db1e --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,12 @@ +{ + "arrowParens": "avoid", + "bracketSpacing": false, + "endOfLine": "auto", + "parser": "typescript", + "printWidth": 80, + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "none", + "useTabs": false +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8b54c06 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ + +The MIT License (MIT) + +Copyright (c) shivammathur and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..914aadf --- /dev/null +++ b/README.md @@ -0,0 +1,1074 @@ +

+ + Setup PHP in GitHub Actions + +

+ +

Setup PHP in GitHub Actions

+ +

+ GitHub Actions status + Codecov Code Coverage + LICENSE + PHP Versions Supported +

+

+ setup-php reddit + setup-php twitter + setup-php status +

+ +Setup PHP with required extensions, php.ini configuration, code-coverage support and various tools like composer in [GitHub Actions](https://github.com/features/actions "GitHub Actions"). This action gives you a cross-platform interface to set up the PHP environment you need to test your application. Refer to [Usage](#memo-usage "How to use this") section and [examples](#examples "Examples of use") to see how to use this. + +## Contents + +- [OS/Platform Support](#cloud-osplatform-support) + - [GitHub-Hosted Runners](#github-hosted-runners) + - [Self-Hosted Runners](#self-hosted-runners) +- [PHP Support](#tada-php-support) +- [PHP Extension Support](#heavy_plus_sign-php-extension-support) +- [Tools Support](#wrench-tools-support) +- [Coverage Support](#signal_strength-coverage-support) + - [Xdebug](#xdebug) + - [PCOV](#pcov) + - [Disable Coverage](#disable-coverage) +- [Usage](#memo-usage) + - [Inputs](#inputs) + - [Outputs](#outputs) + - [Flags](#flags) + - [Basic Setup](#basic-setup) + - [Matrix Setup](#matrix-setup) + - [Nightly Build Setup](#nightly-build-setup) + - [Debug Build Setup](#debug-build-setup) + - [Thread Safe Setup](#thread-safe-setup) + - [Force Update Setup](#force-update-setup) + - [Verbose Setup](#verbose-setup) + - [Multi-Arch Setup](#multi-arch-setup) + - [Self Hosted Setup](#self-hosted-setup) + - [Local Testing Setup](#local-testing-setup) + - [JIT Configuration](#jit-configuration) + - [Cache Extensions](#cache-extensions) + - [Cache Composer Dependencies](#cache-composer-dependencies) + - [GitHub Composer Authentication](#github-composer-authentication) + - [Private Packagist Authentication](#private-packagist-authentication) + - [Manual Composer Authentication](#manual-composer-authentication) + - [Inline PHP Scripts](#inline-php-scripts) + - [Problem Matchers](#problem-matchers) + - [Examples](#examples) +- [Versioning](#bookmark-versioning) +- [License](#scroll-license) +- [Contributions](#1-contributions) +- [Support This Project](#sparkling_heart-support-this-project) +- [Dependencies](#package-dependencies) +- [Further Reading](#bookmark_tabs-further-reading) + +## :cloud: OS/Platform Support + +Both `GitHub-hosted` and `self-hosted` runners are supported by `setup-php` on the following OS/Platforms. + +### GitHub-Hosted Runners + +| Virtual environment | YAML workflow label | Pre-installed PHP | +|---------------------|------------------------------------|------------------------| +| Ubuntu 22.04 | `ubuntu-latest` or `ubuntu-22.04` | `PHP 8.1` | +| Ubuntu 20.04 | `ubuntu-20.04` | `PHP 7.4` to `PHP 8.2` | +| Windows Server 2022 | `windows-latest` or `windows-2022` | `PHP 8.2` | +| Windows Server 2019 | `windows-2019` | `PHP 8.2` | +| macOS Ventura 13.x | `macos-13` | `PHP 8.2` | +| macOS Monterey 12.x | `macos-latest` or `macos-12` | `PHP 8.2` | + +### Self-Hosted Runners + +| Host OS/Virtual environment | YAML workflow label | +|----------------------------------|----------------------------| +| Ubuntu 22.04 | `self-hosted` or `Linux` | +| Ubuntu 20.04 | `self-hosted` or `Linux` | +| Debian 11 | `self-hosted` or `Linux` | +| Debian 10 | `self-hosted` or `Linux` | +| Windows 7 and newer | `self-hosted` or `Windows` | +| Windows Server 2012 R2 and newer | `self-hosted` or `Windows` | +| macOS Sonoma 14.x x86_64/arm64 | `self-hosted` or `macOS` | +| macOS Ventura 13.x x86_64/arm64 | `self-hosted` or `macOS` | +| macOS Monterey 12.x x86_64/arm64 | `self-hosted` or `macOS` | + +- Refer to the [self-hosted setup](#self-hosted-setup) to use the action on self-hosted runners. +- Operating systems based on the above Ubuntu and Debian versions are also supported on best effort basis. +- If the requested PHP version is pre-installed, `setup-php` switches to it, otherwise it installs the PHP version. + +## :tada: PHP Support + +On all supported OS/Platforms the following PHP versions can be set up as per the runner. + +- PHP 5.3 to PHP 8.4 on GitHub-hosted runners. +- PHP 5.6 to PHP 8.4 on self-hosted runners. + +| PHP Version | Stability | Release Support | Runner Support | +|-------------|-----------|-----------------------|--------------------------------| +| `5.3` | `Stable` | `End of life` | `GitHub-hosted` | +| `5.4` | `Stable` | `End of life` | `GitHub-hosted` | +| `5.5` | `Stable` | `End of life` | `GitHub-hosted` | +| `5.6` | `Stable` | `End of life` | `GitHub-hosted`, `self-hosted` | +| `7.0` | `Stable` | `End of life` | `GitHub-hosted`, `self-hosted` | +| `7.1` | `Stable` | `End of life` | `GitHub-hosted`, `self-hosted` | +| `7.2` | `Stable` | `End of life` | `GitHub-hosted`, `self-hosted` | +| `7.3` | `Stable` | `End of life` | `GitHub-hosted`, `self-hosted` | +| `7.4` | `Stable` | `End of life` | `GitHub-hosted`, `self-hosted` | +| `8.0` | `Stable` | `End of life` | `GitHub-hosted`, `self-hosted` | +| `8.1` | `Stable` | `Security fixes only` | `GitHub-hosted`, `self-hosted` | +| `8.2` | `Stable` | `Active` | `GitHub-hosted`, `self-hosted` | +| `8.3` | `Nightly` | `In development` | `GitHub-hosted`, `self-hosted` | +| `8.4` | `Nightly` | `In development` | `GitHub-hosted`, `self-hosted` | + +**Notes:** +- Specifying `8.4` in `php-version` input installs a nightly build of `PHP 8.4.0-dev`. See [nightly build setup](#nightly-build-setup) for more information. +- To use JIT on `PHP 8.0` and above, refer to the [JIT configuration](#jit-configuration) section. + +## :heavy_plus_sign: PHP Extension Support + +PHP extensions can be set up using the `extensions` input. It accepts a `string` in csv-format. + +- On `Ubuntu`, extensions which are available as a package, available on `PECL` or a git repository can be set up. + +```yaml +- name: Setup PHP with PECL extension + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + extensions: imagick, swoole +``` + +- On `Windows`, extensions available on `PECL` which have the `DLL` binary can be set up. + +- On `macOS`, extensions available on `PECL` or a git repository can be set up. + +- On `Ubuntu` and `macOS` to compile and install an extension from a git repository follow this [guide](https://github.com/shivammathur/setup-php/wiki/Add-extension-from-source "Guide to compile and install PHP extensions in setup-php"). + +- Extensions installed along with PHP if specified are enabled. + +- Specific versions of extensions available on `PECL` can be set up by suffixing the extension's name with the version. This is useful for installing old versions of extensions which support end of life PHP versions. + +```yaml +- name: Setup PHP with specific version of PECL extension + uses: shivammathur/setup-php@v2 + with: + php-version: '5.4' + extensions: swoole-1.9.3 +``` + +- Extensions with pre-release versions available on `PECL` can be set up by suffixing the extension's name with its state i.e `alpha`, `beta`, `devel` or `snapshot`. + +```yaml +- name: Setup PHP with pre-release PECL extension + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + extensions: xdebug-beta +``` + +- On `Ubuntu` and `macOS` to compile and install an extension from PECL with libraries or custom configuration follow this [guide](https://github.com/shivammathur/setup-php/wiki/Add-extension-from-PECL-with-libraries-and-custom-configuration "Guide to compile and install PHP extensions using PECL with libraries and custom configuration in setup-php"). + +- Shared extensions can be disabled by prefixing them with a `:`. All extensions depending on the specified extension will also be disabled. + +```yaml +- name: Setup PHP and disable opcache + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + extensions: :opcache +``` + +- All shared extensions can be disabled by specifying `none`. When `none` is specified along with other extensions, it is hoisted to the start of the input. So, all the shared extensions will be disabled first, then rest of the extensions in the input will be processed. + +**Note:** This disables all core and third-party shared extensions and thus, can break some tools which need them. Required extensions are enabled again when the tools are set up on a best-effort basis. So it is recommended to add the extensions required for your tools after `none` in the `extensions` input to avoid any issues. + +```yaml +- name: Setup PHP without any shared extensions except mbstring + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + extensions: none, mbstring +``` + +- Extension `intl` can be set up with specific `ICU` version for `PHP 5.6` and above in `Ubuntu` workflows by suffixing `intl` with the `ICU` version. `ICU 50.2` and newer versions are supported. Refer to [`ICU builds`](https://github.com/shivammathur/icu-intl#icu4c-builds) for the specific versions supported. + +```yaml +- name: Setup PHP with intl + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + extensions: intl-70.1 +``` + +- Extensions loaded by default after `setup-php` runs can be found on the [wiki](https://github.com/shivammathur/setup-php/wiki). + +- These extensions have custom support: + - `cubrid` and `pdo_cubrid` on `Ubuntu`. + - `event`, `gearman`, `geos` and `relay` on `Ubuntu` and `macOS`. + - `blackfire`, `couchbase`, `ioncube`, `oci8`, `pdo_firebird`, `pdo_oci`, `pecl_http`, `phalcon3`, `phalcon4`, `phalcon5`, and `zephir_parser` on all supported OS. + +- By default, extensions which cannot be added or disabled gracefully leave an error message in the logs, the execution is not interrupted. To change this behaviour you can set `fail-fast` flag to `true`. + +```yaml +- name: Setup PHP with fail-fast + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + extensions: oci8 + env: + fail-fast: true +``` + +## :wrench: Tools Support + +These tools can be set up globally using the `tools` input. It accepts a string in csv-format. + +[`behat`], [`blackfire`], [`blackfire-player`], [`castor`], [`churn`], [`codeception`], [`composer`], [`composer-normalize`], [`composer-prefetcher`], [`composer-require-checker`], [`composer-unused`], [`cs2pr`], [`deployer`], [`flex`], [`grpc_php_plugin`], [`infection`], [`parallel-lint`], [`pecl`], [`phan`], [`phing`], [`phinx`], [`phive`], [`php-config`], [`php-cs-fixer`], [`phpcbf`], [`phpcpd`], [`phpcs`], [`phpdoc`] or [`phpDocumentor`], [`phpize`], [`phplint`], [`phpmd`], [`phpspec`], [`phpstan`], [`phpunit`], [`phpunit-bridge`], [`phpunit-polyfills`], [`pint`], [`prestissimo`], [`protoc`], [`psalm`], [`rector`], [`symfony`] or [`symfony-cli`], [`vapor`] or [`vapor-cli`], [`wp`] or [`wp-cli`] + +```yaml +- name: Setup PHP with tools + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + tools: php-cs-fixer, phpunit +``` + +- In addition to above tools any composer tool or package can also be set up globally by specifying it as `vendor/package` matching the listing on Packagist. This format accepts the same [version constraints](https://getcomposer.org/doc/articles/versions.md#writing-version-constraints "Composer version constraints") as `composer`. + +```yaml +- name: Setup PHP with tools + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + tools: vimeo/psalm +``` + +- To set up a particular version of a tool, specify it in the form `tool:version`. + + Version can be in the following format: + - Semver. For example `tool:1.2.3` or `tool:1.2.3-beta1`. + - Major version. For example `tool:1` or `tool:1.x`. + - Major and minor version. For example `tool:1.2` or `tool:1.2.x`. + + When you specify just the major version or the version in `major.minor` format, the latest patch version matching the input will be setup. + + With the exception of major versions of `composer`, if you specify only the `major` version or the version in `major.minor` format for a tool you can get rate limited by GitHub's API. To avoid this, it is recommended to provide a [`GitHub` OAuth token](https://github.com/shivammathur/setup-php#composer-github-oauth "Composer GitHub OAuth"). + You can do that by setting `GITHUB_TOKEN` environment variable. The `COMPOSER_TOKEN` environment variable has been deprecated in favor of `GITHUB_TOKEN` and will be removed in the next major version. + +```yaml +- name: Setup PHP with tools + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + tools: php-cs-fixer:3.39, phpunit:10.4 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +- The latest stable version of `composer` is set up by default. You can set up the required `composer` version by specifying the major version `v1` or `v2`, or the version in `major.minor` or `semver` format. Additionally, for composer `snapshot` and `preview` can also be specified to set up the respective releases. + +```yaml +- name: Setup PHP with composer v2 + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + tools: composer:v2 +``` + +- If you do not use composer in your workflow, you can specify `tools: none` to skip it. + +```yaml +- name: Setup PHP without composer + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + tools: none +``` + +- Tools `pear`, `pecl`, `phpize` and `php-config` are set up by default for all supported PHP versions on Linux and macOS. + +- The latest version of `blackfire` cli is set up when `blackfire` is specified in tools input. Please refer to the [official documentation](https://blackfire.io/docs/integrations/ci/github-actions "Blackfire.io documentation for GitHub Actions") for using `blackfire` with GitHub Actions. + +- Tools `prestissimo` and `composer-prefetcher` will be skipped unless `composer:v1` is also specified in tools input. It is recommended to drop `prestissimo` and use `composer v2`. + +- By default, except `composer` tools which cannot be set up gracefully leave an error message in the logs, the execution is not interrupted. To change this behaviour you can set `fail-fast` flag to `true`. + +```yaml +- name: Setup PHP with fail-fast + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + tools: deployer + env: + fail-fast: true +``` + +**Notes** +- Input `tools` is useful to set up tools which are only used in CI workflows, thus keeping your `composer.json` tidy. +- If you do not want to use all your dev-dependencies in workflow, you can run composer with `--no-dev` and install required tools using `tools` input to speed up your workflow. +- By default, `COMPOSER_NO_INTERACTION` is set to `1` and `COMPOSER_PROCESS_TIMEOUT` is set to `0`. In effect, this means that Composer commands in your scripts do not need to specify `--no-interaction`. +- Also, `COMPOSER_NO_AUDIT` is set to `1`. So if you want to audit your dependencies for security vulnerabilities, it is recommended to add a `composer audit` step before you install them. + +## :signal_strength: Coverage Support + +### Xdebug + +Specify `coverage: xdebug` to use `Xdebug` and disable `PCOV`. +Runs on all [PHP versions supported](#tada-php-support "List of PHP versions supported on this GitHub Action"). + +```yaml +- name: Setup PHP with Xdebug + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + coverage: xdebug +``` + +- When you specify `coverage: xdebug`, the latest version of Xdebug compatible with the PHP version is set up by default. +- If you need Xdebug 2.x on PHP 7.2, 7.3 or 7.4, you can specify `coverage: xdebug2`. + +```yaml +- name: Setup PHP with Xdebug 2.x + uses: shivammathur/setup-php@v2 + with: + php-version: '7.4' + coverage: xdebug2 +``` + +**Note**: Xdebug is enabled by default on Ubuntu GitHub Actions images, so if you are not using it in your workflow it is recommended to disable it as that will have a positive impact on your PHP performance. Please refer to the [disable coverage](#disable-coverage) section for details. + +### PCOV + +Specify `coverage: pcov` to use `PCOV` and disable `Xdebug`. +Runs on PHP 7.1 and newer PHP versions. + +- If your source code directory is other than `src`, `lib` or, `app`, specify `pcov.directory` using the `ini-values` input. + +```yaml +- name: Setup PHP with PCOV + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + ini-values: pcov.directory=api #optional, see above for usage. + coverage: pcov +``` + +- PHPUnit 8.x and above supports PCOV out of the box. +- If you are using PHPUnit 5.x, 6.x or 7.x, you need to set up `pcov/clobber` before executing your tests. + +```yaml +- name: Setup PCOV + run: | + composer require pcov/clobber + vendor/bin/pcov clobber +``` + +### Disable Coverage + +Specify `coverage: none` to disable both `Xdebug` and `PCOV`. + +Disable coverage for these reasons: + +- You are not generating coverage reports while testing. +- You are using `phpdbg` for running your tests. +- You are profiling your code using `blackfire`. +- You are using PHP in JIT mode. Please refer to [JIT configuration](#jit-configuration) section for more details. + +```yaml +- name: Setup PHP with no coverage driver + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + coverage: none +``` + +## :memo: Usage + +### Inputs + +> Specify using `with` keyword + +#### `php-version` (optional) + +- Specify the PHP version you want to set up. +- Accepts a `string`. For example `'8.0'`. +- Accepts `latest` to set up the latest stable PHP version. +- Accepts `nightly` to set up a nightly build from the master branch of PHP. +- Accepts the format `d.x`, where `d` is the major version. For example `5.x`, `7.x` and `8.x`. +- See [PHP support](#tada-php-support) for the supported PHP versions. +- If not specified, it looks for `php-version-file` input. + +#### `php-version-file` (optional) + +- Specify a file with the PHP version you want to set up. +- Accepts a `string`. For example `'.phpenv-version'`. +- See [PHP support](#tada-php-support) for the supported PHP versions. +- By default, `.php-version` file is used. +- If not specified and the default `.php-version` file is not found, the latest stable PHP version is set up. + +#### `extensions` (optional) + +- Specify the extensions you want to add or disable. +- Accepts a `string` in csv-format. For example `mbstring, :opcache`. +- Accepts `none` to disable all shared extensions. +- Shared extensions prefixed with `:` are disabled. +- See [PHP extension support](#heavy_plus_sign-php-extension-support) for more info. + +#### `ini-file` (optional) + +- Specify the base `php.ini` file. +- Accepts `production`, `development` or `none`. +- By default, production `php.ini` file is used. + +#### `ini-values` (optional) + +- Specify the values you want to add to `php.ini`. +- Accepts a `string` in csv-format. For example `post_max_size=256M, max_execution_time=180`. +- Accepts ini values with commas if wrapped in quotes. For example `xdebug.mode="develop,coverage"`. + +#### `coverage` (optional) + +- Specify the code-coverage driver you want to set up. +- Accepts `xdebug`, `pcov` or `none`. +- See [coverage support](#signal_strength-coverage-support) for more info. + +#### `tools` (optional) + +- Specify the tools you want to set up. +- Accepts a `string` in csv-format. For example: `phpunit, phpcs` +- See [tools support](#wrench-tools-support) for tools supported. + +### Outputs + +#### `php-version` + +On GitHub Actions you can assign the `setup-php` step an `id`, you can use the same to get the outputs in a later step. + +- Provides the PHP version in semver format. + +```yaml +- name: Setup PHP + id: setup-php + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + +- name: Print PHP version + run: echo ${{ steps.setup-php.outputs.php-version }} +``` + +### Flags + +> Specify using `env` keyword + +#### `fail-fast` (optional) + +- Specify to mark the workflow as failed if an extension or tool fails to set up. +- This changes the default mode from graceful warnings to fail-fast. +- By default, it is set to `false`. +- Accepts `true` and `false`. + +#### `phpts` (optional) + +- Specify to set up a thread-safe build of PHP on Linux and Windows. +- Accepts `nts` for non-thread-safe and `zts` or `ts` for thread-safe. +- By default, it is set to `nts`. +- See [thread safe setup](#thread-safe-setup) for more info. + +#### `update` (optional) + +- Specify to update PHP on the runner to the latest patch version. +- Accepts `true` and `false`. +- By default, it is set to `false`. +- See [force update setup](#force-update-setup) for more info. + +See below for more info. + +### Basic Setup + +> Set up a particular PHP version. + +```yaml +steps: +- name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + extensions: mbstring, intl + ini-values: post_max_size=256M, max_execution_time=180 + coverage: xdebug + tools: php-cs-fixer, phpunit +``` + +### Matrix Setup + +> Set up multiple PHP versions on multiple operating systems. + +```yaml +jobs: + run: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: ['ubuntu-latest', 'windows-latest', 'macos-latest'] + php-versions: ['8.1', '8.2', '8.3'] + phpunit-versions: ['latest'] + include: + - operating-system: 'ubuntu-latest' + php-versions: '8.0' + phpunit-versions: 9 + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, intl + ini-values: post_max_size=256M, max_execution_time=180 + coverage: xdebug + tools: php-cs-fixer, phpunit:${{ matrix.phpunit-versions }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +### Nightly Build Setup + +> Set up a nightly build of `PHP 8.4`. + +- These PHP versions are currently in active development and might contain bugs and breaking changes. +- Some user space extensions might not support this version currently. + +```yaml +steps: +- name: Setup nightly PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.4' + extensions: mbstring + ini-values: post_max_size=256M, max_execution_time=180 + coverage: xdebug + tools: php-cs-fixer, phpunit +``` + +### Debug Build Setup + +> Set up a PHP build with debugging symbols. + +- Production release builds of PHP without debugging symbols are set up by default. +- You can use the `debug` environment variable to set up a build with debugging symbols for PHP 5.6 and above. + +```yaml +steps: +- name: Setup PHP with debugging symbols + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + env: + debug: true # specify true or false +``` + +### Thread Safe Setup + +> Set up `TS` or `NTS` PHP on `Linux` and `Windows`. + +- `NTS` versions are set up by default. +- On `macOS` only `NTS` versions are supported currently. +- On `Linux` and `Windows` both `TS` and `NTS` versions are supported. + +```yaml +jobs: + run: + runs-on: [ubuntu-latest, windows-latest] + name: Setup PHP TS + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + env: + phpts: ts # specify ts or nts +``` + +### Force Update Setup + +> Update to the latest patch of PHP versions. + +- Pre-installed PHP versions are not updated to their latest patch release by default. +- If `ppa:ondrej/php` is missing on the Ubuntu GitHub environment, the PHP version is updated to the latest patch release. +- You can specify the `update` environment variable to `true` for updating to the latest release. + +```yaml +- name: Setup PHP with latest versions + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + env: + update: true # specify true or false +``` + +### Verbose Setup + +> Debug your workflow + +To debug any issues, you can use the `verbose` tag instead of `v2`. + +```yaml +- name: Setup PHP with logs + uses: shivammathur/setup-php@verbose + with: + php-version: '8.3' +``` + +### Multi-Arch Setup + +> Set up PHP on multiple architecture on Ubuntu GitHub Runners. + +- `PHP 5.6` to `PHP 8.3` are supported by `setup-php` on multiple architecture on `Ubuntu`. +- For this, you can use `shivammathur/node` images as containers. These have compatible `Nodejs` installed for `setup-php`. +- Currently, for `ARM` based setup, you will need [self-hosted runners](#self-hosted-setup). + +```yaml +jobs: + run: + runs-on: ubuntu-latest + container: shivammathur/node:latest-${{ matrix.arch }} + strategy: + matrix: + arch: ["amd64", "i386"] + steps: + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' +``` + +### Self Hosted Setup + +> Set up PHP on a self-hosted runner. + +- To set up a containerised self-hosted runner, refer to the following guides as per your base operating system. + - [Linux](https://github.com/shivammathur/setup-php/wiki/Dockerized-self-hosted-runner-on-Linux) + - [Windows](https://github.com/shivammathur/setup-php/wiki/Dockerized-self-hosted-runner-on-Windows) + +- To set up the runner directly on the host OS or in a virtual machine, follow this [requirements guide](https://github.com/shivammathur/setup-php/wiki/Requirements-for-self-hosted-runners "Requirements guide for self-hosted runner to run setup-php") before setting up the self-hosted runner. +- If your workflow uses [service containers](https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idservices "GitHub Actions Services"), then set up the runner on a Linux host or in a Linux virtual machine. GitHub Actions does not support nested virtualization on Linux, so services will not work in a dockerized container. + +It is recommended to specify the environment variable `runner` with the value `self-hosted` for self-hosted environments. + +```yaml +jobs: + run: + runs-on: self-hosted + strategy: + matrix: + php-versions: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] + name: PHP ${{ matrix.php-versions }} + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + env: + runner: self-hosted +``` + +**Notes** +- Do not set up multiple self-hosted runners on a single server instance as parallel workflow will conflict with each other. +- Do not set up self-hosted runners on the side on your development environment or your production server. +- Avoid using the same labels for your `self-hosted` runners which are used by `GitHub-hosted` runners. + +### Local Testing Setup + +> Test your `Ubuntu` workflow locally using [`nektos/act`](https://github.com/nektos/act "Project to test GitHub Actions locally"). + +```yaml +jobs: + run: + runs-on: ubuntu-latest + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' +``` + +Run the workflow locally with `act` using [`shivammathur/node`](https://github.com/shivammathur/node-docker "Docker image to run setup-php") docker images. + +Choose the image tag which matches the `runs-on` property in your workflow. For example, if you are using `ubuntu-20.04` in your workflow, run `act -P ubuntu-20.04=shivammathur/node:2004`. + +```bash +# For runs-on: ubuntu-latest +act -P ubuntu-latest=shivammathur/node:latest + +# For runs-on: ubuntu-22.04 +act -P ubuntu-22.04=shivammathur/node:2204 + +# For runs-on: ubuntu-20.04 +act -P ubuntu-20.04=shivammathur/node:2004 +``` + +### JIT Configuration + +> Enable Just-in-time (JIT) on PHP 8.0 and above. + +- To enable JIT, enable `opcache` in cli mode by setting `opcache.enable_cli=1`. +- JIT conflicts with `Xdebug`, `PCOV`, and other extensions which override `zend_execute_ex` function, so set `coverage: none` and disable any such extension if added. +- By default, `opcache.jit=1235` and `opcache.jit_buffer_size=256M` are set which can be changed using `ini-values` input. +- For detailed information about JIT related directives refer to the [`official PHP documentation`](https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.jit "opcache.jit documentation"). + +For example to enable JIT in `tracing` mode with buffer size of `64 MB`. + +```yaml +- name: Setup PHP with JIT in tracing mode + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + coverage: none + ini-values: opcache.enable_cli=1, opcache.jit=tracing, opcache.jit_buffer_size=64M +``` + +### Cache Extensions + +You can cache PHP extensions using `shivammathur/cache-extensions` and `action/cache` GitHub Actions. Extensions which take very long to set up when cached are available in the next workflow run and are enabled directly. This reduces the workflow execution time. +Refer to [`shivammathur/cache-extensions`](https://github.com/shivammathur/cache-extensions "GitHub Action to cache php extensions") for details. + +### Cache Composer Dependencies + +If your project uses composer, you can persist the composer's internal cache directory. Dependencies cached are loaded directly instead of downloading them while installation. The files cached are available across check-runs and will reduce the workflow execution time. + +```yaml +- name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + +- name: Cache dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + +- name: Install dependencies + run: composer install --prefer-dist +``` + +**Notes** +- Please do not cache `vendor` directory using `action/cache` as that will have side effects. +- If you do not commit `composer.lock`, you can use the hash of `composer.json` as the key for your cache. +```yaml +key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} +``` + +- If you support a range of `composer` dependencies and use `prefer-lowest` and `prefer-stable` options, you can store them in your matrix and add them to the keys. +```yaml +key: ${{ runner.os }}-composer-${{ matrix.prefer }}-${{ hashFiles('**/composer.lock') }} +restore-keys: ${{ runner.os }}-composer-${{ matrix.prefer }}- +``` + +### GitHub Composer Authentication + +If you have a number of workflows which set up multiple tools or have many composer dependencies, you might hit the GitHub's rate limit for composer. Also, if you specify only the major version or the version in `major.minor` format, you can hit the rate limit. To avoid this you can specify an `OAuth` token by setting `GITHUB_TOKEN` environment variable. You can use [`GITHUB_TOKEN`](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token "GITHUB_TOKEN documentation") secret for this purpose. + +The `COMPOSER_TOKEN` environment variable has been deprecated in favor of `GITHUB_TOKEN` and will be removed in the next major version. + +```yaml +- name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +### Private Packagist Authentication + +If you use Private Packagist for your private composer dependencies, you can set the `PACKAGIST_TOKEN` environment variable to authenticate. + +```yaml +- name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + env: + PACKAGIST_TOKEN: ${{ secrets.PACKAGIST_TOKEN }} +``` + +### Manual Composer Authentication + +In addition to GitHub or Private Packagist, if you want to authenticate private repositories hosted elsewhere, you can set the `COMPOSER_AUTH_JSON` environment variable with the authentication methods and the credentials in json format. +Please refer to the authentication section in [`composer documentation`](https://getcomposer.org/doc/articles/authentication-for-private-packages.md "composer documentation") for more details. + +```yaml +- name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + env: + COMPOSER_AUTH_JSON: | + { + "http-basic": { + "example.org": { + "username": "${{ secrets.EXAMPLE_ORG_USERNAME }}", + "password": "${{ secrets.EXAMPLE_ORG_PASSWORD }}" + } + } + } +``` + +### Inline PHP Scripts + +If you have to run multiple lines of PHP code in your workflow, you can do that easily without saving it to a file. + +Put the code in the run property of a step and specify the shell as `php {0}`. + +```yaml +- name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + +- name: Run PHP code + shell: php {0} + run: | + Here is an example with `phpcs`. + +```yaml +- name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + tools: cs2pr, phpcs + +- name: Run phpcs + run: phpcs -q --report=checkstyle src | cs2pr +``` + +### Examples + +Examples of using `setup-php` with various PHP frameworks and packages. + +| Framework/Package | Runs on | Workflow | +|----------------------------------------|---------------------------------|---------------------------------------------------------------------------------------------------------------| +| Blackfire | `macOS`, `ubuntu` and `windows` | [blackfire.yml](./examples/blackfire.yml "GitHub Action using Blackfire") | +| Blackfire Player | `macOS`, `ubuntu` and `windows` | [blackfire-player.yml](./examples/blackfire-player.yml "GitHub Action using Blackfire Player") | +| CakePHP with `MySQL` and `Redis` | `ubuntu` | [cakephp-mysql.yml](./examples/cakephp-mysql.yml "GitHub Action for CakePHP with MySQL and Redis") | +| CakePHP with `PostgreSQL` and `Redis` | `ubuntu` | [cakephp-postgres.yml](./examples/cakephp-postgres.yml "GitHub Action for CakePHP with Postgres and Redis") | +| CakePHP without services | `macOS`, `ubuntu` and `windows` | [cakephp.yml](./examples/cakephp.yml "GitHub Action for CakePHP without services") | +| CodeIgniter | `macOS`, `ubuntu` and `windows` | [codeigniter.yml](./examples/codeigniter.yml "GitHub Action for CodeIgniter") | +| Laminas MVC | `macOS`, `ubuntu` and `windows` | [laminas-mvc.yml](./examples/laminas-mvc.yml "GitHub Action for Laminas Framework MVC Projects") | +| Laravel with `MySQL` and `Redis` | `ubuntu` | [laravel-mysql.yml](./examples/laravel-mysql.yml "GitHub Action for Laravel with MySQL and Redis") | +| Laravel with `PostgreSQL` and `Redis` | `ubuntu` | [laravel-postgres.yml](./examples/laravel-postgres.yml "GitHub Action for Laravel with PostgreSQL and Redis") | +| Laravel without services | `macOS`, `ubuntu` and `windows` | [laravel.yml](./examples/laravel.yml "GitHub Action for Laravel without services") | +| Lumen with `MySQL` and `Redis` | `ubuntu` | [lumen-mysql.yml](./examples/lumen-mysql.yml "GitHub Action for Lumen with MySQL and Redis") | +| Lumen with `PostgreSQL` and `Redis` | `ubuntu` | [lumen-postgres.yml](./examples/lumen-postgres.yml "GitHub Action for Lumen with PostgreSQL and Redis") | +| Lumen without services | `macOS`, `ubuntu` and `windows` | [lumen.yml](./examples/lumen.yml "GitHub Action for Lumen without services") | +| Phalcon with `MySQL` | `ubuntu` | [phalcon-mysql.yml](./examples/phalcon-mysql.yml "GitHub Action for Phalcon with MySQL") | +| Phalcon with `PostgreSQL` | `ubuntu` | [phalcon-postgres.yml](./examples/phalcon-postgres.yml "GitHub Action for Phalcon with PostgreSQL") | +| Roots/bedrock | `ubuntu` | [bedrock.yml](./examples/bedrock.yml "GitHub Action for Wordpress Development using @roots/bedrock") | +| Roots/sage | `ubuntu` | [sage.yml](./examples/sage.yml "GitHub Action for Wordpress Development using @roots/sage") | +| Slim Framework | `macOS`, `ubuntu` and `windows` | [slim-framework.yml](./examples/slim-framework.yml "GitHub Action for Slim Framework") | +| Symfony with `MySQL` | `ubuntu` | [symfony-mysql.yml](./examples/symfony-mysql.yml "GitHub Action for Symfony with MySQL") | +| Symfony with `PostgreSQL` | `ubuntu` | [symfony-postgres.yml](./examples/symfony-postgres.yml "GitHub Action for Symfony with PostgreSQL") | +| Symfony without services | `macOS`, `ubuntu` and `windows` | [symfony.yml](./examples/symfony.yml "GitHub Action for Symfony without services") | +| Yii2 Starter Kit with `MySQL` | `ubuntu` | [yii2-mysql.yml](./examples/yii2-mysql.yml "GitHub Action for Yii2 Starter Kit with MySQL") | +| Yii2 Starter Kit with `PostgreSQL` | `ubuntu` | [yii2-postgres.yml](./examples/yii2-postgres.yml "GitHub Action for Yii2 Starter Kit with PostgreSQL") | + +## :bookmark: Versioning + +- Use the `v2` tag as `setup-php` version. It is a rolling tag and is synced with the latest minor and patch releases. With `v2` you automatically get the bug fixes, security patches, new features and support for latest PHP releases. +- Semantic release versions can also be used. It is recommended to [use dependabot](https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-github-dependabot "Setup Dependabot with GitHub Actions") with semantic versioning to keep the actions in your workflows up to date. +- Commit SHA can also be used, but are not recommended unless you set up tooling to update them with each release of the action. +- A new major version of the action will only be tagged when there are breaking changes in the setup-php API i.e. inputs, outputs, and environment flags. +- For debugging any issues `verbose` tag can be used temporarily. It outputs all the logs and is also synced with the latest releases. +- It is highly discouraged to use the `main` branch as version, it might break your workflow after major releases as they have breaking changes. +- If you are using the `v1` tag or a `1.x.y` version, you should [switch to v2](https://github.com/shivammathur/setup-php/wiki/Switch-to-v2 "Guide for switching from setup-php v1 to v2") as `v1` only gets critical bug fixes. Maintenance support for `v1` will be dropped with the last `PHP 8.0` release. + +## :scroll: License + +- The scripts and documentation in this project are under the [MIT License](LICENSE "License for shivammathur/setup-php"). +- This project has multiple [dependencies](#package-dependencies "Dependencies for this PHP Action"). Their licenses can be found in their respective repositories. +- The logo for `setup-php` is a derivative work of [php.net logo](https://www.php.net/download-logos.php) and is licensed under the [CC BY-SA 4.0 License](https://creativecommons.org/licenses/by-sa/4.0/ "Creative Commons License"). + +## :+1: Contributions + +> Contributions are welcome! + +- See [Contributor's Guide](.github/CONTRIBUTING.md "shivammathur/setup-php contribution guide") before you start. +- If you face any issues or want to suggest a feature/improvement, start a discussion [here](https://github.com/shivammathur/setup-php/discussions "Setup PHP discussions"). + +*Contributors of `setup-php` and other related projects* + +

+ + Contributors of setup-php and related projects + +

+ +## :sparkling_heart: Support This Project + +- Please star the project and share it. If you blog, please share your experience of using `setup-php`. +- Please [reach out](mailto:contact@setup-php.com) if you have any questions about sponsoring setup-php. + +Many users and organisations support setup-php via [GitHub Sponsors](https://github.com/sponsors/shivammathur). + +Sponsor shivammathur + +These companies generously provide setup-php their products and services to aid in the development of this project. + +

+ + JetBrains + +           + + Mac Stadium + + + Mac Stadium + +           + + Tidelift + +           + + Scaleway + + + Scaleway + +

+ +## :package: Dependencies + +- [Node.js dependencies](https://github.com/shivammathur/setup-php/network/dependencies "Node.js dependencies") +- [aaronparker/VcRedist](https://github.com/aaronparker/VcRedist "VcRedist PowerShell package") +- [mlocati/powershell-phpmanager](https://github.com/mlocati/powershell-phpmanager "Package to handle PHP on windows") +- [ppa:ondrej/php](https://launchpad.net/~ondrej/+archive/ubuntu/php "Packaging active PHP packages") +- [shivammathur/cache-extensions](https://github.com/shivammathur/cache-extensions "GitHub action to help with caching PHP extensions") +- [shivammathur/composer-cache](https://github.com/shivammathur/composer-cache "Cache composer releases") +- [shivammathur/homebrew-extensions](https://github.com/shivammathur/homebrew-extensions "Tap for PHP extensions on MacOS") +- [shivammathur/homebrew-php](https://github.com/shivammathur/homebrew-php "Tap for PHP builds on MacOS") +- [shivammathur/icu-intl](https://github.com/shivammathur/icu-intl "icu4c and php-intl builds") +- [shivammathur/php-builder](https://github.com/shivammathur/php-builder "Nightly PHP package for Ubuntu") +- [shivammathur/php-builder-windows](https://github.com/shivammathur/php-builder-windows "Nightly PHP package for Windows") +- [shivammathur/php-ubuntu](https://github.com/shivammathur/php-ubuntu "Cache stable PHP Packages for Ubuntu") +- [shivammathur/php5-darwin](https://github.com/shivammathur/php5-darwin "Scripts to set up PHP5 versions on darwin") +- [shivammathur/php5-ubuntu](https://github.com/shivammathur/php5-ubuntu "Scripts to set up PHP5 versions on ubuntu") + +## :bookmark_tabs: Further Reading + +- [About GitHub Actions](https://github.com/features/actions "GitHub Actions") +- [GitHub Actions Syntax](https://help.github.com/en/articles/workflow-syntax-for-github-actions "GitHub Actions Syntax") +- [Other Awesome Actions](https://github.com/sdras/awesome-actions "List of Awesome GitHub Actions") + + + +[`behat`]: https://docs.behat.org/en/latest/ +[`blackfire`]: https://blackfire.io/docs/php/index +[`blackfire-player`]: https://blackfire.io/docs/builds-cookbooks/player +[`castor`]: https://github.com/jolicode/castor +[`churn`]: https://github.com/bmitch/churn-php +[`codeception`]: https://codeception.com/ +[`composer`]: https://getcomposer.org/ +[`composer-normalize`]: https://github.com/ergebnis/composer-normalize +[`composer-prefetcher`]: https://github.com/narrowspark/automatic-composer-prefetcher +[`composer-require-checker`]: https://github.com/maglnet/ComposerRequireChecker +[`composer-unused`]: https://github.com/composer-unused/composer-unused +[`cs2pr`]: https://github.com/staabm/annotate-pull-request-from-checkstyle +[`deployer`]: https://deployer.org/ +[`flex`]: https://flex.symfony.com/ +[`grpc_php_plugin`]: https://grpc.io/ +[`infection`]: https://infection.github.io/ +[`parallel-lint`]: https://github.com/php-parallel-lint/PHP-Parallel-Lint +[`pecl`]: https://pecl.php.net/ +[`phan`]: https://github.com/phan/phan/wiki +[`phing`]: https://www.phing.info/ +[`phinx`]: https://phinx.org/ +[`phive`]: https://phar.io/ +[`php-config`]: https://www.php.net/manual/en/install.pecl.php-config.php +[`php-cs-fixer`]: https://cs.symfony.com/ +[`phpcbf`]: https://github.com/PHPCSStandards/php_codesniffer +[`phpcpd`]: https://github.com/sebastianbergmann/phpcpd +[`phpcs`]: https://github.com/PHPCSStandards/php_codesniffer +[`phpdoc`]: https://phpdoc.org/ +[`phpDocumentor`]: https://phpdoc.org/ +[`phpize`]: https://www.php.net/manual/en/install.pecl.phpize.php +[`phplint`]: https://github.com/overtrue/phplint +[`phpmd`]: https://phpmd.org/ +[`phpspec`]: https://www.phpspec.net/ +[`phpstan`]: https://phpstan.org/ +[`phpunit`]: https://phpunit.de/ +[`phpunit-bridge`]: https://symfony.com/doc/current/components/phpunit_bridge.html +[`phpunit-polyfills`]: https://github.com/Yoast/PHPUnit-Polyfills +[`pint`]: https://github.com/laravel/pint +[`prestissimo`]: https://github.com/hirak/prestissimo +[`protoc`]: https://developers.google.com/protocol-buffers/ +[`psalm`]: https://psalm.dev/ +[`rector`]: https://getrector.org/ +[`symfony`]: https://symfony.com/download +[`symfony-cli`]: https://symfony.com/download +[`vapor`]: https://docs.vapor.build/ +[`vapor-cli`]: https://docs.vapor.build/ +[`wp`]: https://wp-cli.org/ +[`wp-cli`]: https://wp-cli.org/ diff --git a/__tests__/config.test.ts b/__tests__/config.test.ts new file mode 100644 index 0000000..6c9dc56 --- /dev/null +++ b/__tests__/config.test.ts @@ -0,0 +1,16 @@ +import * as config from '../src/config'; + +describe('Config tests', () => { + it.each` + ini_values | os | output + ${'a=b, c=d'} | ${'win32'} | ${'Add-Content "$php_dir\\php.ini" "a=b\nc=d"'} + ${'a=b, c=d'} | ${'linux'} | ${'echo "a=b\nc=d" | sudo tee -a "${pecl_file:-${ini_file[@]}}"'} + ${'a=b, c=d'} | ${'darwin'} | ${'echo "a=b\nc=d" | sudo tee -a "${pecl_file:-${ini_file[@]}}"'} + ${'a=b & ~c'} | ${'win32'} | ${'Add-Content "$php_dir\\php.ini" "a=\'b & ~c\'"'} + ${'a="~(b)"'} | ${'win32'} | ${'Add-Content "$php_dir\\php.ini" "a=\'~(b)\'"'} + ${'a="b, c"'} | ${'win32'} | ${'Add-Content "$php_dir\\php.ini" "a=b, c"'} + ${'a=b, c=d'} | ${'openbsd'} | ${'Platform openbsd is not supported'} + `('checking addINIValues on $os', async ({ini_values, os, output}) => { + expect(await config.addINIValues(ini_values, os)).toContain(output); + }); +}); diff --git a/__tests__/coverage.test.ts b/__tests__/coverage.test.ts new file mode 100644 index 0000000..f8e460e --- /dev/null +++ b/__tests__/coverage.test.ts @@ -0,0 +1,44 @@ +import * as coverage from '../src/coverage'; + +describe('Config tests', () => { + it.each` + driver | php | os | output + ${'PCOV'} | ${'7.4'} | ${'win32'} | ${'Add-Extension pcov,Disable-Extension xdebug false'} + ${'pcov'} | ${'7.4'} | ${'win32'} | ${'$pcov_version = php -r "echo phpversion(\'pcov\');"'} + ${'pcov'} | ${'7.4'} | ${'win32'} | ${'PCOV $pcov_version enabled as coverage driver'} + ${'pcov'} | ${'7.0'} | ${'win32'} | ${'PHP 7.1 or newer is required'} + ${'pcov'} | ${'5.6'} | ${'win32'} | ${'PHP 7.1 or newer is required'} + ${'pcov'} | ${'7.4'} | ${'win32'} | ${'Add-Extension pcov,Disable-Extension xdebug false'} + ${'pcov'} | ${'7.4'} | ${'linux'} | ${'add_extension pcov,disable_extension xdebug false'} + ${'pcov'} | ${'7.4'} | ${'darwin'} | ${'add_brew_extension pcov,disable_extension xdebug false'} + ${'xdebug'} | ${'7.4'} | ${'win32'} | ${'Add-Extension xdebug'} + ${'xdebug3'} | ${'7.1'} | ${'win32'} | ${'xdebug3 is not supported on PHP 7.1'} + ${'xdebug2'} | ${'7.4'} | ${'win32'} | ${'Add-Extension xdebug stable 2.9.8'} + ${'xdebug'} | ${'8.0'} | ${'linux'} | ${'add_extension xdebug'} + ${'xdebug3'} | ${'8.0'} | ${'linux'} | ${'add_extension xdebug'} + ${'xdebug2'} | ${'7.4'} | ${'linux'} | ${'add_pecl_extension xdebug 2.9.8 zend_extension'} + ${'xdebug'} | ${'7.4'} | ${'linux'} | ${'xdebug_version="$(php -r "echo phpversion(\'xdebug\');")"'} + ${'xdebug'} | ${'7.4'} | ${'linux'} | ${'Xdebug $xdebug_version enabled as coverage driver'} + ${'xdebug'} | ${'7.4'} | ${'darwin'} | ${'add_brew_extension xdebug'} + ${'xdebug3'} | ${'7.1'} | ${'darwin'} | ${'xdebug3 is not supported on PHP 7.1'} + ${'xdebug2'} | ${'7.4'} | ${'darwin'} | ${'add_brew_extension xdebug2'} + ${'xdebug2'} | ${'8.0'} | ${'darwin'} | ${'xdebug2 is not supported on PHP 8.0'} + ${'none'} | ${'7.4'} | ${'win32'} | ${'Disable-Extension xdebug false,Disable-Extension pcov false'} + ${'none'} | ${'7.4'} | ${'linux'} | ${'disable_extension xdebug false,disable_extension pcov false'} + ${'none'} | ${'7.4'} | ${'darwin'} | ${'disable_extension xdebug false,disable_extension pcov false'} + ${'nocov'} | ${'7.x'} | ${'any'} | ${''} + ${''} | ${'7.x'} | ${'any'} | ${''} + `( + 'checking addCoverage with $driver on $os', + async ({driver, php, os, output}) => { + const script: string = await coverage.addCoverage(driver, php, os); + if (output) { + output.split(',').forEach((command: string) => { + expect(script).toContain(command); + }); + } else { + expect(script).toEqual(output); + } + } + ); +}); diff --git a/__tests__/extensions.test.ts b/__tests__/extensions.test.ts new file mode 100644 index 0000000..17cbfa6 --- /dev/null +++ b/__tests__/extensions.test.ts @@ -0,0 +1,153 @@ +import * as fs from 'fs'; +import * as extensions from '../src/extensions'; + +describe('Extension tests', () => { + it.each` + extension | version | output + ${'none'} | ${'7.4'} | ${'Disable-AllShared'} + ${':intl'} | ${'7.4'} | ${'Disable-Extension intl'} + ${'ast-beta'} | ${'7.4'} | ${'Add-Extension ast beta'} + ${'blackfire'} | ${'7.3'} | ${'Add-Blackfire blackfire'} + ${'blackfire-1.31.0'} | ${'7.3'} | ${'Add-Blackfire blackfire-1.31.0'} + ${'grpc-1.2.3'} | ${'7.4'} | ${'Add-Extension grpc stable 1.2.3'} + ${'inotify-1.2.3alpha2'} | ${'7.4'} | ${'Add-Extension inotify alpha 1.2.3'} + ${'ioncube'} | ${'7.4'} | ${'Add-Ioncube'} + ${'mongodb-mongodb/mongo-php-driver@master'} | ${'7.3'} | ${'Add-Log "$cross" "mongodb-mongodb/mongo-php-driver@master" "mongodb-mongodb/mongo-php-driver@master is not supported on PHP 7.3"'} + ${'mysql'} | ${'7.4'} | ${'Add-Extension mysqli\nAdd-Extension mysqlnd'} + ${'mysql'} | ${'5.5'} | ${'Add-Extension mysql\nAdd-Extension mysqli\nAdd-Extension mysqlnd'} + ${'oci8'} | ${'7.4'} | ${'Add-Oci oci8'} + ${'pcov'} | ${'5.6'} | ${'Add-Log "$cross" "pcov" "pcov is not supported on PHP 5.6"'} + ${'pdo_oci'} | ${'7.4'} | ${'Add-Oci pdo_oci'} + ${'pecl_http'} | ${'7.4'} | ${'Add-Http'} + ${'pdo_sqlsrv'} | ${'7.4'} | ${'Add-Sqlsrv pdo_sqlsrv'} + ${'phalcon3'} | ${'7.2'} | ${'Add-Phalcon phalcon3'} + ${'phalcon4'} | ${'7.4'} | ${'Add-Phalcon phalcon4'} + ${'sqlite'} | ${'7.4'} | ${'Add-Extension sqlite3'} + ${'sqlsrv'} | ${'5.6'} | ${'Add-Extension sqlsrv'} + ${'sqlsrv'} | ${'7.4'} | ${'Add-Sqlsrv sqlsrv'} + ${'sqlsrv-1.2.3preview1'} | ${'7.4'} | ${'Add-Extension sqlsrv devel 1.2.3'} + ${'Xdebug'} | ${'7.4'} | ${'Add-Extension xdebug'} + ${'xdebug2'} | ${'7.2'} | ${'Add-Extension xdebug stable 2.9.8'} + ${'zephir_parser'} | ${'7.2'} | ${'Add-ZephirParser zephir_parser'} + `( + 'checking addExtensionOnWindows for extension $extension on version $version', + async ({extension, version, output}) => { + expect( + await extensions.addExtension(extension, version, 'win32') + ).toContain(output); + } + ); + + it.each` + extension | version | output + ${'none'} | ${'7.4'} | ${'disable_all_shared'} + ${':intl'} | ${'7.4'} | ${'disable_extension intl'} + ${'ast-beta'} | ${'7.4'} | ${'add_unstable_extension ast beta extension'} + ${'blackfire'} | ${'7.3'} | ${'add_blackfire blackfire'} + ${'blackfire-1.31.0'} | ${'7.3'} | ${'add_blackfire blackfire-1.31.0'} + ${'couchbase'} | ${'7.4'} | ${'add_couchbase'} + ${'gearman'} | ${'5.6'} | ${'add_gearman'} + ${'geos'} | ${'7.3'} | ${'add_geos'} + ${'grpc-1.2.3'} | ${'7.4'} | ${'add_pecl_extension grpc 1.2.3 extension'} + ${'http-1.2.3'} | ${'7.3'} | ${'add_http http-1.2.3'} + ${'intl-65.1'} | ${'5.6'} | ${'add_intl intl-65.1'} + ${'ioncube'} | ${'7.3'} | ${'add_ioncube'} + ${'memcache-8.2'} | ${'8.2'} | ${'add_pecl_extension memcache 8.2 extension'} + ${'mongodb-mongodb/mongo-php-driver@master'} | ${'7.3'} | ${'add_extension_from_source mongodb https://github.com mongodb mongo-php-driver master extension'} + ${'oci8'} | ${'7.3'} | ${'add_oci oci8'} + ${'pcov'} | ${'5.6'} | ${'add_log "$cross" "pcov" "pcov is not supported on PHP 5.6'} + ${'pdo-odbc'} | ${'7.4'} | ${'add_pdo_extension odbc'} + ${'pdo_cubrid'} | ${'7.0'} | ${'add_cubrid pdo_cubrid'} + ${'pdo_cubrid'} | ${'7.4'} | ${'add_pdo_extension cubrid'} + ${'pdo_mysql'} | ${'7.4'} | ${'add_pdo_extension mysql'} + ${'pdo_oci'} | ${'7.3'} | ${'add_oci pdo_oci'} + ${'pdo_sqlsrv'} | ${'7.4'} | ${'add_sqlsrv pdo_sqlsrv'} + ${'pecl_http'} | ${'7.3'} | ${'add_http'} + ${'phalcon3'} | ${'7.3'} | ${'add_phalcon phalcon3'} + ${'relay'} | ${'7.4'} | ${'add_relay relay'} + ${'relay-v1.2.3'} | ${'7.4'} | ${'add_relay relay-v1.2.3'} + ${'sqlite'} | ${'7.4'} | ${'add_extension sqlite3'} + ${'sqlsrv-1.2.3-beta1'} | ${'7.4'} | ${'add_pecl_extension sqlsrv 1.2.3beta1 extension'} + ${'Xdebug'} | ${'7.4'} | ${'add_extension xdebug'} + ${'xdebug-alpha'} | ${'7.4'} | ${'add_unstable_extension xdebug alpha zend_extension'} + ${'xdebug2'} | ${'7.2'} | ${'add_pecl_extension xdebug 2.9.8 zend_extension'} + ${'zephir_parser-1.2.3'} | ${'7.2'} | ${'add_zephir_parser zephir_parser-1.2.3'} + `( + 'checking addExtensionOnLinux for extension $extension on version $version', + async ({extension, version, output}) => { + expect( + await extensions.addExtension(extension, version, 'linux') + ).toContain(output); + } + ); + + it.each` + extension | version | output + ${'none'} | ${'7.2'} | ${'disable_all_shared'} + ${':intl'} | ${'7.2'} | ${'disable_extension intl'} + ${'ast-beta'} | ${'7.2'} | ${'add_unstable_extension ast beta extension'} + ${'blackfire'} | ${'7.3'} | ${'add_blackfire blackfire'} + ${'blackfire-1.31.0'} | ${'7.3'} | ${'add_blackfire blackfire-1.31.0'} + ${'couchbase'} | ${'5.6'} | ${'add_couchbase'} + ${'does_not_exist'} | ${'7.2'} | ${'add_extension does_not_exist'} + ${'geos'} | ${'7.3'} | ${'add_geos'} + ${'grpc-1.2.3'} | ${'7.2'} | ${'add_pecl_extension grpc 1.2.3 extension'} + ${'http-1.2.3'} | ${'7.3'} | ${'add_http http-1.2.3'} + ${'imagick'} | ${'5.5'} | ${'add_extension imagick'} + ${'ioncube'} | ${'7.3'} | ${'add_ioncube'} + ${'mongodb-mongodb/mongo-php-driver@master'} | ${'7.2'} | ${'add_extension_from_source mongodb https://github.com mongodb mongo-php-driver master extension'} + ${'oci8'} | ${'7.3'} | ${'add_oci oci8'} + ${'pcov'} | ${'5.6'} | ${'add_log "$cross" "pcov" "pcov is not supported on PHP 5.6"'} + ${'pdo_oci'} | ${'7.3'} | ${'add_oci pdo_oci'} + ${'pecl_http'} | ${'7.3'} | ${'add_http'} + ${'relay-1.2.3'} | ${'7.4'} | ${'add_relay relay-1.2.3'} + ${'sqlite'} | ${'7.2'} | ${'add_extension sqlite3'} + ${'zephir_parser-v1.2.3'} | ${'7.2'} | ${'add_zephir_parser zephir_parser-v1.2.3'} + `( + 'checking addExtensionOnDarwin for extension $extension on version $version', + async ({extension, version, output}) => { + expect( + await extensions.addExtension(extension, version, 'darwin') + ).toContain(output); + } + ); + + const data: string[][] = fs + .readFileSync('src/configs/brew_extensions') + .toString() + .split(/\r?\n/) + .filter(Boolean) + .map(line => { + const [formula, extension]: string[] = line.split('='); + const prefix: string = + extension == 'xdebug' ? 'zend_extension' : 'extension'; + const ext_name = extension.replace(/\d+|(pdo|pecl)[_-]/, ''); + const output: string = fs.existsSync( + `src/scripts/extensions/${ext_name}.sh` + ) + ? `add_${ext_name}` + : `add_brew_extension ${formula} ${prefix}`; + return [formula, formula === 'phalcon3' ? '7.3' : '7.4', output]; + }); + + it.each(data)( + 'checking addExtensionOnDarwin for brew extension %s', + async (extension, version, output) => { + expect( + await extensions.addExtension(extension, version, 'darwin') + ).toContain(output); + } + ); + + it.each` + extension | version | output + ${'xdebug'} | ${'7.2'} | ${'Platform openbsd is not supported'} + `( + 'checking addExtension on openbsd for extension $extension on version $version', + async ({extension, version, output}) => { + expect( + await extensions.addExtension(extension, version, 'openbsd') + ).toContain(output); + } + ); +}); diff --git a/__tests__/fetch.test.ts b/__tests__/fetch.test.ts new file mode 100644 index 0000000..0e1881f --- /dev/null +++ b/__tests__/fetch.test.ts @@ -0,0 +1,39 @@ +import * as fetch from '../src/fetch'; +import nock = require('nock'); + +it('checking fetch', async () => { + const host_url = 'https://example.com'; + const manifest_url = host_url + '/manifest'; + const ping_url = host_url + '/ping'; + + nock(host_url) + .get('/manifest') + .reply(200, {latest: 'latest'}) + .get('/manifest', '', { + reqheaders: {authorization: 'Bearer invalid_token'} + }) + .reply(401, {error: '401: Unauthorized'}) + .get('/ping') + .twice() + .reply(301, undefined, { + Location: host_url + '/pong' + }) + .get('/pong') + .reply(200, 'pong'); + + let response: Record = await fetch.fetch(manifest_url); + expect(response.error).toBe(undefined); + expect(response.data).toContain('latest'); + + response = await fetch.fetch(ping_url, '', 1); + expect(response.error).toBe(undefined); + expect(response.data).toContain('pong'); + + response = await fetch.fetch(ping_url, '', 0); + expect(response.error).toBe('301: Redirect error'); + expect(response.data).toBe(undefined); + + response = await fetch.fetch(manifest_url, 'invalid_token'); + expect(response.error).not.toBe(undefined); + expect(response.data).toBe(undefined); +}); diff --git a/__tests__/install.test.ts b/__tests__/install.test.ts new file mode 100644 index 0000000..ed0bcd3 --- /dev/null +++ b/__tests__/install.test.ts @@ -0,0 +1,82 @@ +import * as install from '../src/install'; +import * as utils from '../src/utils'; + +/** + * Mock install.ts + */ +jest.mock('../src/install', () => ({ + getScript: jest + .fn() + .mockImplementation(async (os: string): Promise => { + const filename = os + (await utils.scriptExtension(os)); + const version: string = await utils.parseVersion( + await utils.readPHPVersion() + ); + const ini_file: string = await utils.parseIniFile( + await utils.getInput('ini-file', false) + ); + const extension_csv: string = process.env['extensions'] || ''; + const ini_values_csv: string = process.env['ini-values'] || ''; + const coverage_driver: string = process.env['coverage'] || ''; + const tools_csv: string = process.env['tools'] || ''; + let script = await utils.joins(filename, version, ini_file); + script += extension_csv ? ' install extensions' : ''; + script += tools_csv ? ' add_tool' : ''; + script += coverage_driver ? ' set coverage driver' : ''; + script += ini_values_csv ? ' edit php.ini' : ''; + return script; + }), + run: jest.fn().mockImplementation(async (): Promise => { + const os: string = process.env['RUNNER_OS'] || ''; + const tool = await utils.scriptTool(os); + return tool + (await install.getScript(os)); + }) +})); + +/** + * Mock fetch.ts + */ +jest.mock('../src/fetch', () => ({ + fetch: jest.fn().mockImplementation(() => { + return {data: '{ "latest": "8.1", "5.x": "5.6" }'}; + }) +})); + +describe('Install', () => { + it.each` + version | os | extension_csv | ini_file | ini_values_csv | coverage_driver | tools | output + ${'7.3'} | ${'darwin'} | ${''} | ${'production'} | ${''} | ${''} | ${''} | ${'bash darwin.sh 7.3 production'} + ${'7.3'} | ${'darwin'} | ${'a, b'} | ${'development'} | ${'a=b'} | ${'x'} | ${''} | ${'bash darwin.sh 7.3 development install extensions set coverage driver edit php.ini'} + ${'7.4.1'} | ${'darwin'} | ${''} | ${'none'} | ${''} | ${''} | ${''} | ${'bash darwin.sh 7.4 none'} + ${'8'} | ${'darwin'} | ${''} | ${''} | ${''} | ${''} | ${''} | ${'bash darwin.sh 8.0 production'} + ${'8.0'} | ${'darwin'} | ${''} | ${'development'} | ${''} | ${''} | ${''} | ${'bash darwin.sh 8.0 development'} + ${'8.1'} | ${'darwin'} | ${''} | ${'none'} | ${''} | ${''} | ${''} | ${'bash darwin.sh 8.1 none'} + ${'7.3'} | ${'linux'} | ${''} | ${'invalid'} | ${''} | ${''} | ${''} | ${'bash linux.sh 7.3 production'} + ${'7.3'} | ${'linux'} | ${'a, b'} | ${'development'} | ${'a=b'} | ${'x'} | ${'phpunit'} | ${'bash linux.sh 7.3 development install extensions add_tool set coverage driver edit php.ini'} + ${'latest'} | ${'linux'} | ${''} | ${'none'} | ${''} | ${''} | ${''} | ${'bash linux.sh 8.1 none'} + ${'7.0'} | ${'win32'} | ${''} | ${'production'} | ${''} | ${''} | ${''} | ${'pwsh win32.ps1 7.0 production'} + ${'7.3'} | ${'win32'} | ${''} | ${'development'} | ${''} | ${''} | ${''} | ${'pwsh win32.ps1 7.3 development'} + ${'7.3'} | ${'win32'} | ${'a, b'} | ${'none'} | ${'a=b'} | ${'x'} | ${''} | ${'pwsh win32.ps1 7.3 none install extensions set coverage driver edit php.ini'} + `( + 'Test install on $os for $version with extensions=$extension_csv, ini_values=$ini_values_csv, coverage_driver=$coverage_driver, tools=$tools', + async ({ + version, + os, + extension_csv, + ini_file, + ini_values_csv, + coverage_driver, + tools, + output + }) => { + process.env['php-version'] = version.toString(); + process.env['RUNNER_OS'] = os; + process.env['extensions'] = extension_csv; + process.env['ini-file'] = ini_file; + process.env['ini-values'] = ini_values_csv; + process.env['coverage'] = coverage_driver; + process.env['tools'] = tools; + expect(await install.run()).toBe(output); + } + ); +}); diff --git a/__tests__/packagist.test.ts b/__tests__/packagist.test.ts new file mode 100644 index 0000000..f3af7da --- /dev/null +++ b/__tests__/packagist.test.ts @@ -0,0 +1,50 @@ +import * as packagist from '../src/packagist'; +import nock = require('nock'); + +describe('search function', () => { + const mockResponse = { + packages: { + 'test-package': [ + { + require: { + php: '8.0.0' + }, + version: '1.0.0' + }, + { + version: '2.0.0' + } + ] + } + }; + + test('should return the version if matching php version is found', async () => { + nock('https://repo.packagist.org') + .get('/p2/test-package.json') + .reply(200, mockResponse); + const result = await packagist.search('test-package', '8.0'); + expect(result).toBe('1.0.0'); + }); + + test('should return null if no matching php version is found', async () => { + nock('https://repo.packagist.org') + .get('/p2/test-package.json') + .reply(200, mockResponse); + const result = await packagist.search('test-package', '5.6'); + expect(result).toBeNull(); + }); + + test('should return null if fetch fails', async () => { + nock('https://repo.packagist.org').get('/p2/test-package.json').reply(404); + const result = await packagist.search('test-package', '8.0'); + expect(result).toBeNull(); + }); + + test('should return null if the response is empty', async () => { + nock('https://repo.packagist.org') + .get('/p2/test-package.json') + .reply(200, {error: true, data: '[]'}); + const result = await packagist.search('test-package', '8.0'); + expect(result).toBeNull(); + }); +}); diff --git a/__tests__/tools.test.ts b/__tests__/tools.test.ts new file mode 100644 index 0000000..0af7fc4 --- /dev/null +++ b/__tests__/tools.test.ts @@ -0,0 +1,608 @@ +import fs = require('fs'); +import * as tools from '../src/tools'; + +interface IData { + tool: string; + version?: string; + domain?: string; + extension?: string; + os?: string; + php_version?: string; + release?: string; + repository?: string; + scope?: string; + type?: string; + fetch_latest?: string; + version_parameter?: string; + version_prefix?: string; +} + +function getData(data: IData): Record { + return { + tool: data.tool, + version: data.version || '', + domain: data.domain || 'https://example.com', + extension: data.extension || '.phar', + os: data.os || 'linux', + php_version: data.php_version || '7.4', + release: data.release || [data.tool, data.version].join(':'), + repository: data.repository || '', + scope: data.scope || 'global', + type: data.type || 'phar', + fetch_latest: data.fetch_latest || 'false', + version_parameter: data.version_parameter || '-V', + version_prefix: data.version_prefix || '', + github: 'https://github.com', + prefix: 'releases', + verb: 'download' + }; +} + +/** + * Mock fetch.ts + */ +jest.mock('../src/fetch', () => ({ + fetch: jest + .fn() + .mockImplementation( + async (url: string, token?: string): Promise> => { + if (url.includes('deployer')) { + return { + data: '[{"version": "1.2.3", "url": "https://deployer.org/releases/v1.2.3/deployer.phar"}]' + }; + } else if (url.includes('atom') && !url.includes('no-')) { + return { + data: '"releases/tag/1.2.3", "releases/tag/3.2.1", "releases/tag/2.3.1"' + }; + } else if (url.includes('no-data')) { + return {}; + } else if (url.includes('no-release')) { + return {data: 'no-release'}; + } else if (!token || token === 'valid_token') { + return {data: `[{"ref": "refs/tags/1.2.3", "url": "${url}"}]`}; + } else if (token === 'beta_token') { + return {data: `[{"ref": "refs/tags/1.2.3-beta1", "url": "${url}"}]`}; + } else if (token === 'no_data') { + return {data: '[]'}; + } else { + return {error: 'Invalid token'}; + } + } + ) +})); + +jest.mock('../src/packagist', () => ({ + search: jest + .fn() + .mockImplementation( + async ( + package_name: string, + php_version: string + ): Promise => { + if (package_name === 'phpunit/phpunit') { + return php_version + '.0'; + } + return null; + } + ) +})); + +describe('Tools tests', () => { + it.each` + token | version + ${'invalid_token'} | ${'1.2'} + ${'valid_token'} | ${'1.2.3'} + ${'beta_token'} | ${'1.2.3-beta1'} + ${''} | ${'1.2.3'} + `('checking getSemverVersion: $token', async ({token, version}) => { + process.env['COMPOSER_TOKEN'] = token; + expect( + await tools.getSemverVersion(getData({tool: 'tool', version: '1.2'})) + ).toBe(version); + }); + + it.each` + tool | fetch_latest | version + ${'tool'} | ${'true'} | ${'3.2.1'} + ${'tool-no-data'} | ${'true'} | ${'latest'} + ${'tool-no-release'} | ${'true'} | ${'latest'} + ${'tool'} | ${'false'} | ${'latest'} + `( + 'checking getLatestVersion: $tool, $fetch_latest, $version', + async ({tool, fetch_latest, version}) => { + expect( + await tools.getLatestVersion( + getData({ + tool: tool, + repository: 'user/' + tool, + fetch_latest: fetch_latest + }) + ) + ).toBe(version); + } + ); + + it.each` + version | tool | type | expected + ${'latest'} | ${'tool'} | ${'phar'} | ${'latest'} + ${'1'} | ${'composer'} | ${'phar'} | ${'1'} + ${'1.2'} | ${'tool'} | ${'composer'} | ${'1.2.*'} + ${'^1.2.3'} | ${'tool'} | ${'phar'} | ${'1.2.3'} + ${'>=1.2.3'} | ${'tool'} | ${'phar'} | ${'1.2.3'} + ${'>1.2.3'} | ${'tool'} | ${'phar'} | ${'1.2.3'} + ${'1.2.3-ALPHA'} | ${'tool'} | ${'phar'} | ${'1.2.3-ALPHA'} + ${'1.2.3-alpha'} | ${'tool'} | ${'phar'} | ${'1.2.3-alpha'} + ${'1.2.3-beta'} | ${'tool'} | ${'phar'} | ${'1.2.3-beta'} + ${'1.2.3-rc'} | ${'tool'} | ${'phar'} | ${'1.2.3-rc'} + ${'1.2.3-dev'} | ${'tool'} | ${'phar'} | ${'1.2.3-dev'} + ${'1.2.3-alpha1'} | ${'tool'} | ${'phar'} | ${'1.2.3-alpha1'} + ${'1.2.3-alpha.1'} | ${'tool'} | ${'phar'} | ${'1.2.3-alpha.1'} + `( + 'checking getVersion: $version, $tool, $type', + async ({version, tool, type, expected}) => { + expect( + await tools.getVersion( + version, + getData({tool: tool, version: version, type: type}) + ) + ).toBe(expected); + } + ); + + it.each` + input | expected + ${'tool'} | ${'tool'} + ${'alias:1.2.3'} | ${'tool:1.2.3'} + ${'tool:1.2.3'} | ${'tool:1.2.3'} + ${'tool:^1.2.3'} | ${'tool:^1.2.3'} + ${'tool:>=1.2.3'} | ${'tool:>=1.2.3'} + ${'tool:>1.2.3'} | ${'tool:>1.2.3'} + ${'tool:1.2.3-ALPHA'} | ${'tool:1.2.3-ALPHA'} + ${'tool:1.2.3-beta'} | ${'tool:1.2.3-beta'} + ${'tool:1.2.3-rc'} | ${'tool:1.2.3-rc'} + ${'tool:1.2.3-dev'} | ${'tool:1.2.3-dev'} + ${'tool:1.2.3-alpha1'} | ${'tool:1.2.3-alpha1'} + ${'tool:1.2.3-alpha.1'} | ${'tool:1.2.3-alpha.1'} + ${'user/tool:^1.2.3'} | ${'tool:^1.2.3'} + `('checking getRelease: $input', async ({input, expected}) => { + expect( + await tools.getRelease(input, getData({tool: 'tool', version: 'latest'})) + ).toBe(expected); + }); + + it.each` + input_list | filtered_list + ${'a, b'} | ${'composer, a, b'} + ${'a, b, composer'} | ${'composer, a, b'} + ${'a, b, composer:1.2.3'} | ${'composer:1.2.3, a, b'} + ${'a, b, composer:v1.2.3'} | ${'composer:1.2.3, a, b'} + ${'a, b, composer:snapshot'} | ${'composer:snapshot, a, b'} + ${'a, b, composer:preview'} | ${'composer:preview, a, b'} + ${'a, b, composer:1'} | ${'composer:1, a, b'} + ${'a, b, composer:2'} | ${'composer:2, a, b'} + ${'a, b, composer:v1'} | ${'composer:1, a, b'} + ${'a, b, composer:v2'} | ${'composer:2, a, b'} + `('checking filterList $input_list', async ({input_list, filtered_list}) => { + expect(await tools.filterList(input_list.split(', '))).toStrictEqual( + filtered_list.split(', ') + ); + }); + + it.each` + version | version_prefix | url_suffix + ${'latest'} | ${'v'} | ${'latest/download/tool.phar'} + ${'1.2.3'} | ${'v'} | ${'download/v1.2.3/tool.phar'} + ${'1.2.3'} | ${''} | ${'download/1.2.3/tool.phar'} + `( + 'checking getUrl: $version_prefix$version', + async ({version, version_prefix, url_suffix}) => { + const data = getData({ + tool: 'tool', + version: version, + version_prefix: version_prefix + }); + expect(await tools.getUrl(data)).toContain(url_suffix); + } + ); + + it.each` + version | version_prefix | url + ${'latest'} | ${''} | ${'https://example.com/tool.phar'} + ${'1.2.3'} | ${'v'} | ${'https://example.com/tool-v1.2.3.phar'} + `( + 'checking getPharUrl: $version_prefix$version', + async ({version, version_prefix, url}) => { + const data = getData({ + tool: 'tool', + version: version, + version_prefix: version_prefix + }); + expect(await tools.getPharUrl(data)).toBe(url); + } + ); + + it.each` + os | script + ${'linux'} | ${'add_tool https://example.com/tool.phar tool "-v"'} + ${'darwin'} | ${'add_tool https://example.com/tool.phar tool "-v"'} + ${'win32'} | ${'Add-Tool https://example.com/tool.phar tool "-v"'} + ${'openbsd'} | ${'Platform openbsd is not supported'} + `('checking addArchive: $os', async ({os, script}) => { + const data = getData({ + tool: 'tool', + version: 'latest', + version_parameter: JSON.stringify('-v'), + os: os + }); + data['url'] = 'https://example.com/tool.phar'; + expect(await tools.addArchive(data)).toContain(script); + }); + + it.each` + os | script | scope + ${'linux'} | ${'add_composer_tool tool tool:1.2.3 user/ global'} | ${'global'} + ${'darwin'} | ${'add_composer_tool tool tool:1.2.3 user/ scoped'} | ${'scoped'} + ${'win32'} | ${'Add-ComposerTool tool tool:1.2.3 user/ scoped'} | ${'scoped'} + ${'openbsd'} | ${'Platform openbsd is not supported'} | ${'global'} + `('checking addPackage: $os, $scope', async ({os, script, scope}) => { + const data = getData({ + tool: 'tool', + version: '1.2.3', + repository: 'user/tool', + os: os, + scope: scope + }); + data['release'] = [data['tool'], data['version']].join(':'); + expect(await tools.addPackage(data)).toContain(script); + }); + + it.each` + version | php_version | os | script + ${'latest'} | ${'7.4'} | ${'linux'} | ${'add_tool https://github.com/phar-io/phive/releases/download/3.2.1/phive-3.2.1.phar phive'} + ${'1.2.3'} | ${'7.4'} | ${'darwin'} | ${'add_tool https://github.com/phar-io/phive/releases/download/1.2.3/phive-1.2.3.phar phive'} + ${'1.2.3'} | ${'7.2'} | ${'win32'} | ${'Add-Tool https://github.com/phar-io/phive/releases/download/0.14.5/phive-0.14.5.phar phive'} + ${'1.2.3'} | ${'7.1'} | ${'win32'} | ${'Add-Tool https://github.com/phar-io/phive/releases/download/0.13.5/phive-0.13.5.phar phive'} + ${'latest'} | ${'5.6'} | ${'win32'} | ${'Add-Tool https://github.com/phar-io/phive/releases/download/0.12.1/phive-0.12.1.phar phive'} + ${'latest'} | ${'5.5'} | ${'win32'} | ${'Phive is not supported on PHP 5.5'} + `( + 'checking addPhive: $version, $php_version, $os', + async ({version, php_version, os, script}) => { + const data = getData({ + tool: 'phive', + repository: 'phar-io/phive', + version_parameter: 'status', + version: version, + php_version: php_version, + os: os + }); + script = await tools.addPhive(data); + expect(script).toContain(script); + } + ); + + it.each` + os | version | php_version | url + ${'linux'} | ${'latest'} | ${'8.1'} | ${'https://get.blackfire.io/blackfire-player.phar'} + ${'linux'} | ${'1.2.3'} | ${'7.4'} | ${'https://get.blackfire.io/blackfire-player-v1.2.3.phar'} + ${'linux'} | ${'latest'} | ${'7.4'} | ${'https://get.blackfire.io/blackfire-player-v1.22.0.phar'} + ${'linux'} | ${'latest'} | ${'5.5'} | ${'https://get.blackfire.io/blackfire-player-v1.9.3.phar'} + ${'linux'} | ${'latest'} | ${'7.0'} | ${'https://get.blackfire.io/blackfire-player-v1.9.3.phar'} + ${'win32'} | ${'latest'} | ${'7.0'} | ${'blackfire-player is not a windows tool'} + `( + 'checking addBlackfirePlayer: $os, $version, $php_version', + async ({os, version, php_version, url}) => { + const data = getData({ + os: os, + tool: 'blackfire-player', + domain: 'https://get.blackfire.io', + version_prefix: 'v', + version: version, + php_version: php_version + }); + expect(await tools.addBlackfirePlayer(data)).toContain(url); + } + ); + + it.each` + version | url + ${'latest'} | ${'https://deployer.org/deployer.phar'} + ${'1.2.3'} | ${'https://deployer.org/releases/v1.2.3/deployer.phar'} + ${'3.2.1'} | ${'Version missing in deployer manifest'} + `('checking addDeployer: $version', async ({version, url}) => { + const data = getData({ + tool: 'deployer', + domain: 'https://deployer.org', + version: version + }); + expect(await tools.addDeployer(data)).toContain(url); + }); + + it.each` + version | php_version | no_tool_cache | cache_url | source_url + ${'latest'} | ${'7.4'} | ${'true'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-stable.phar'} | ${'https://getcomposer.org/composer-stable.phar'} + ${'stable'} | ${'7.4'} | ${'true'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-stable.phar'} | ${'https://getcomposer.org/composer-stable.phar'} + ${'snapshot'} | ${'7.4'} | ${'true'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-snapshot.phar'} | ${'https://getcomposer.org/composer.phar'} + ${'preview'} | ${'7.4'} | ${'true'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-preview.phar'} | ${'https://getcomposer.org/composer-preview.phar'} + ${'1'} | ${'7.4'} | ${'false'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-1.phar'} | ${'https://getcomposer.org/composer-1.phar'} + ${'2'} | ${'7.4'} | ${'false'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-2.phar'} | ${'https://getcomposer.org/composer-2.phar'} + ${'latest'} | ${'7.4'} | ${'true'} | ${'https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-stable.phar'} | ${'https://getcomposer.org/composer-stable.phar'} + ${'stable'} | ${'7.4'} | ${'true'} | ${'https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-stable.phar'} | ${'https://getcomposer.org/composer-stable.phar'} + ${'snapshot'} | ${'7.4'} | ${'true'} | ${'https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-snapshot.phar'} | ${'https://getcomposer.org/composer.phar'} + ${'preview'} | ${'7.4'} | ${'true'} | ${'https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-preview.phar'} | ${'https://getcomposer.org/composer-preview.phar'} + ${'1'} | ${'7.4'} | ${'false'} | ${'https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-1.phar'} | ${'https://getcomposer.org/composer-1.phar'} + ${'2'} | ${'7.4'} | ${'false'} | ${'https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-2.phar'} | ${'https://getcomposer.org/composer-2.phar'} + ${'latest'} | ${'7.1'} | ${'true'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.1-stable.phar'} | ${'https://getcomposer.org/download/latest-2.2.x/composer.phar'} + ${'stable'} | ${'7.1'} | ${'true'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.1-stable.phar'} | ${'https://getcomposer.org/download/latest-2.2.x/composer.phar'} + ${'snapshot'} | ${'7.1'} | ${'true'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.1-snapshot.phar'} | ${'https://getcomposer.org/download/latest-2.2.x/composer.phar'} + ${'preview'} | ${'7.1'} | ${'true'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.1-preview.phar'} | ${'https://getcomposer.org/download/latest-2.2.x/composer.phar'} + ${'1'} | ${'7.1'} | ${'false'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.1-1.phar'} | ${'https://getcomposer.org/composer-1.phar'} + ${'2'} | ${'7.1'} | ${'false'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.1-2.phar'} | ${'https://getcomposer.org/download/latest-2.2.x/composer.phar'} + ${'1.2.3'} | ${'7.4'} | ${'false'} | ${'https://github.com/composer/composer/releases/download/1.2.3/composer.phar'} | ${'https://getcomposer.org/composer-1.2.3.phar'} + ${'1.2.3-RC1'} | ${'7.4'} | ${'false'} | ${'https://github.com/composer/composer/releases/download/1.2.3-RC1/composer.phar'} | ${'https://getcomposer.org/composer-1.2.3-RC1.phar'} + `( + 'checking addComposer: $version, $php_version, $no_tool_cache', + async ({version, php_version, no_tool_cache, cache_url, source_url}) => { + const data = getData({ + tool: 'composer', + php_version: php_version, + domain: 'https://getcomposer.org', + repository: 'composer/composer', + version: version + }); + process.env['no_tools_cache'] = no_tool_cache; + expect(await tools.addComposer(data)).toContain(source_url); + if (no_tool_cache !== 'true') { + expect(await tools.addComposer(data)).toContain(cache_url); + } + } + ); + + it.each` + version | uri + ${'latest'} | ${'wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true'} + ${'1.2.3'} | ${'wp-cli/wp-cli/releases/download/v1.2.3/wp-cli-1.2.3.phar'} + `('checking addWPCLI: $version', async ({version, uri}) => { + const data = getData({ + tool: 'wp-cli', + repository: 'wp-cli/wp-cli', + php_version: '7.4', + version_prefix: 'v', + version: version + }); + expect(await tools.addWPCLI(data)).toContain(uri); + }); + + it.each` + tool | os | script + ${'phpize'} | ${'linux'} | ${'add_devtools phpize'} + ${'php-config'} | ${'linux'} | ${'add_devtools php-config'} + ${'phpize'} | ${'darwin'} | ${'add_devtools phpize'} + ${'php-config'} | ${'darwin'} | ${'add_devtools php-config'} + ${'phpize'} | ${'win32'} | ${'Add-Log "$tick" "phpize" "phpize is not a windows tool"'} + ${'php-config'} | ${'win32'} | ${'Add-Log "$tick" "php-config" "php-config is not a windows tool"'} + ${'phpize'} | ${'openbsd'} | ${'Platform openbsd is not supported'} + `('checking addDevTools: $tool, $os', async ({tool, os, script}) => { + const data = getData({ + version: '7.4', + tool: tool, + os: os + }); + expect(await tools.addDevTools(data)).toContain(script); + }); + + it.each([ + [ + 'blackfire, blackfire-player, box, churn, cs2pr, flex, grpc_php_plugin, parallel-lint, php-cs-fixer, php-scoper, phpDocumentor, phplint, phpstan, phpunit, pecl, phing, phinx, phinx:1.2.3, phive, phpunit-bridge, phpunit-polyfills, pint, php-config, phpize, protoc, symfony, vapor, wp', + [ + 'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-stable.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-stable.phar,https://getcomposer.org/composer-stable.phar composer', + 'add_blackfire', + 'add_tool https://get.blackfire.io/blackfire-player-v1.22.0.phar blackfire-player "-V"', + 'add_tool https://github.com/box-project/box/releases/latest/download/box.phar box "--version"', + 'add_tool https://github.com/bmitch/churn-php/releases/latest/download/churn.phar churn "-V"', + 'add_tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/latest/download/cs2pr cs2pr "-V"', + 'add_composer_tool flex flex symfony/ global', + 'add_grpc_php_plugin latest', + 'add_tool https://github.com/php-parallel-lint/PHP-Parallel-Lint/releases/latest/download/parallel-lint.phar parallel-lint "--version"', + 'add_tool https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v3.2.1/php-cs-fixer.phar php-cs-fixer "-V"', + 'add_tool https://github.com/humbug/php-scoper/releases/latest/download/php-scoper.phar php-scoper "--version"', + 'add_tool https://github.com/phpDocumentor/phpDocumentor/releases/latest/download/phpDocumentor.phar phpDocumentor "--version"', + 'add_composer_tool phplint phplint overtrue/', + 'add_tool https://github.com/phpstan/phpstan/releases/latest/download/phpstan.phar phpstan "-V"', + 'add_tool https://phar.phpunit.de/phpunit-7.4.0.phar phpunit "--version"', + 'add_pecl', + 'add_tool https://www.phing.info/get/phing-latest.phar phing "-v"', + 'add_composer_tool phinx phinx robmorgan/ scoped', + 'add_composer_tool phinx phinx:1.2.3 robmorgan/ scoped', + 'add_tool https://github.com/phar-io/phive/releases/download/3.2.1/phive-3.2.1.phar phive "status"', + 'add_composer_tool phpunit-bridge phpunit-bridge symfony/ global', + 'add_composer_tool phpunit-polyfills phpunit-polyfills yoast/ global', + 'add_tool https://github.com/laravel/pint/releases/latest/download/pint.phar pint "-V"', + 'add_devtools php-config', + 'add_devtools phpize', + 'add_protoc latest', + 'add_symfony latest', + 'add_composer_tool vapor-cli vapor-cli laravel/ scoped', + 'add_tool https://github.com/wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true wp-cli "--version"' + ] + ] + ])('checking addTools on linux', async (tools_csv, scripts) => { + const expected = await tools.addTools(tools_csv, '7.4', 'linux'); + scripts.forEach(script => { + expect(expected).toContain(script); + }); + }); + + it.each([ + [ + 'behat, blackfire, blackfire-player, churn, composer-normalize, composer-require-checker, composer-unused, cs2pr:1.2.3, flex, grpc_php_plugin:1.2.3, infection, phan, phan:1.2.3, phing:1.2.3, phinx, phive:1.2.3, php-config, phpcbf, phpcpd, phpcs, phpdoc, phpize, phpmd, phpspec, phpunit-bridge:5.6, phpunit-polyfills:1.0.1, protoc:v1.2.3, psalm, rector, symfony-cli, vapor-cli, wp-cli', + [ + 'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-stable.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-stable.phar,https://getcomposer.org/composer-stable.phar composer', + 'add_composer_tool behat behat behat/ scoped', + 'add_blackfire', + 'add_tool https://get.blackfire.io/blackfire-player-v1.22.0.phar blackfire-player "-V"', + 'add_tool https://github.com/bmitch/churn-php/releases/latest/download/churn.phar churn "-V"', + 'add_tool https://github.com/ergebnis/composer-normalize/releases/latest/download/composer-normalize.phar composer-normalize "-V"', + 'add_composer_tool composer-require-checker composer-require-checker maglnet/ scoped', + 'add_tool https://github.com/composer-unused/composer-unused/releases/latest/download/composer-unused.phar composer-unused "-V"', + 'add_tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/download/1.2.3/cs2pr cs2pr "-V"', + 'add_composer_tool flex flex symfony/ global', + 'add_grpc_php_plugin 1.2.3', + 'add_tool https://github.com/infection/infection/releases/latest/download/infection.phar infection "-V"', + 'add_tool https://github.com/phan/phan/releases/latest/download/phan.phar phan "-v"', + 'add_tool https://github.com/phan/phan/releases/download/1.2.3/phan.phar phan "-v"', + 'add_tool https://www.phing.info/get/phing-1.2.3.phar,https://github.com/phingofficial/phing/releases/download/1.2.3/phing-1.2.3.phar phing "-v"', + 'add_composer_tool phinx phinx robmorgan/ scoped', + 'add_tool https://github.com/phar-io/phive/releases/download/1.2.3/phive-1.2.3.phar phive', + 'add_devtools php-config', + 'add_tool https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/latest/download/phpcbf.phar phpcbf "--version"', + 'add_tool https://phar.phpunit.de/phpcpd.phar phpcpd "--version"', + 'add_tool https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/latest/download/phpcs.phar phpcs "--version"', + 'add_tool https://github.com/phpDocumentor/phpDocumentor/releases/latest/download/phpDocumentor.phar phpDocumentor "--version"', + 'add_devtools phpize', + 'add_tool https://github.com/phpmd/phpmd/releases/latest/download/phpmd.phar phpmd "--version"', + 'add_tool https://github.com/phpspec/phpspec/releases/latest/download/phpspec.phar phpspec "-V"', + 'add_composer_tool phpunit-bridge phpunit-bridge:5.6.* symfony/ global', + 'add_composer_tool phpunit-polyfills phpunit-polyfills:1.0.1 yoast/ global', + 'add_protoc 1.2.3', + 'add_tool https://github.com/vimeo/psalm/releases/latest/download/psalm.phar psalm "-v"', + 'add_composer_tool rector rector rector/ scoped', + 'add_symfony latest', + 'add_composer_tool vapor-cli vapor-cli laravel/ scoped', + 'add_tool https://github.com/wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true wp-cli "--version"' + ] + ] + ])('checking addTools on darwin', async (tools_csv, scripts) => { + const expected = await tools.addTools(tools_csv, '7.4', 'darwin'); + scripts.forEach(script => { + expect(expected).toContain(script); + }); + }); + + it.each([ + [ + 'blackfire, blackfire-player:1.2.3, cs2pr, churn, deployer, does_not_exist, flex, phinx, phive:0.13.2, php-config, phpize, phpmd, simple-phpunit, symfony, wp', + [ + 'Add-Tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-stable.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-stable.phar,https://getcomposer.org/composer-stable.phar composer', + 'Add-Blackfire', + 'blackfire-player is not a windows tool', + 'Add-Tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/latest/download/cs2pr cs2pr "-V"', + 'Add-Tool https://github.com/bmitch/churn-php/releases/latest/download/churn.phar churn "-V"', + 'Add-Tool https://deployer.org/deployer.phar deployer "-V"', + 'Tool does_not_exist is not supported', + 'Add-ComposerTool flex flex symfony/ global', + 'Add-ComposerTool phinx phinx robmorgan/ scoped', + 'Add-Tool https://github.com/phar-io/phive/releases/download/0.13.2/phive-0.13.2.phar phive "status"', + 'php-config is not a windows tool', + 'phpize is not a windows tool', + 'Add-Tool https://github.com/phpmd/phpmd/releases/latest/download/phpmd.phar phpmd "--version"', + 'Add-ComposerTool phpunit-bridge phpunit-bridge symfony/ global', + 'Add-Symfony', + 'Add-Tool https://github.com/wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true wp-cli "--version"' + ] + ] + ])('checking addTools on Windows', async (tools_csv, scripts) => { + const expected = await tools.addTools(tools_csv, '7.4', 'win32'); + scripts.forEach(script => { + expect(expected).toContain(script); + }); + }); + + it.each([ + [ + 'composer:v1, codeception/codeception, prestissimo, hirak/prestissimo, composer-prefetcher, narrowspark/automatic-composer-prefetcher, phinx: 1.2, robmorgan/phinx: ^1.2, user/tool:1.2.3, user/tool:~1.2', + [ + 'Add-Tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-1.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-1.phar,https://getcomposer.org/composer-1.phar composer', + 'Add-ComposerTool codeception codeception codeception/ global', + 'Add-ComposerTool prestissimo prestissimo hirak/ global', + 'Add-ComposerTool automatic-composer-prefetcher automatic-composer-prefetcher narrowspark/ global', + 'Add-ComposerTool phinx phinx:1.2.* robmorgan/ scoped', + 'Add-ComposerTool phinx phinx:^1.2 robmorgan/ global', + 'Add-ComposerTool tool tool:1.2.3 user/ global', + 'Add-ComposerTool tool tool:~1.2 user/ global' + ] + ] + ])( + 'checking addTools with composer tool using user/tool as input', + async (tools_csv, scripts) => { + const expected = await tools.addTools(tools_csv, '7.4', 'win32'); + scripts.forEach(script => { + expect(expected).toContain(script); + }); + } + ); + + it.each` + version | os | uri + ${'latest'} | ${'linux'} | ${'releases/latest/download/castor.linux-amd64.phar'} + ${'0.5.1'} | ${'linux'} | ${'releases/download/v0.5.1/castor.linux-amd64.phar'} + ${'latest'} | ${'darwin'} | ${'releases/latest/download/castor.darwin-amd64.phar'} + ${'0.5.1'} | ${'darwin'} | ${'releases/download/v0.5.1/castor.darwin-amd64.phar'} + ${'latest'} | ${'win32'} | ${'releases/latest/download/castor.windows-amd64.phar'} + ${'0.5.1'} | ${'win32'} | ${'releases/download/v0.5.1/castor.windows-amd64.phar castor -V'} + ${'latest'} | ${'openbsd'} | ${'Platform openbsd is not supported'} + `('checking addCastor: $version, $os', async ({version, os, uri}) => { + const data = getData({ + tool: 'castor', + php_version: '8.1', + version_prefix: 'v', + version: version, + os: os + }); + if (os === 'win32' && version === '0.5.1') { + fs.writeFileSync('castor.php', ''); + expect(await tools.addCastor(data)).toContain(uri); + fs.unlinkSync('castor.php'); + } else { + expect(await tools.addCastor(data)).toContain(uri); + } + }); + + it.each` + tools_csv | script + ${'none'} | ${''} + ${'none, phpunit'} | ${'\nstep_log "Setup Tools"\nadd_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-stable.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-stable.phar,https://getcomposer.org/composer-stable.phar composer latest\n\nadd_tool https://phar.phpunit.de/phpunit-7.4.0.phar phpunit "--version"'} + ${'composer:preview'} | ${'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-preview.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-preview.phar,https://getcomposer.org/composer-preview.phar composer preview'} + ${'composer, composer:v1'} | ${'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-1.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-1.phar,https://getcomposer.org/composer-1.phar composer'} + ${'composer:v1, composer:preview, composer:snapshot'} | ${'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-snapshot.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-snapshot.phar,https://getcomposer.org/composer.phar composer snapshot'} + `('checking composer setup: $tools_csv', async ({tools_csv, script}) => { + expect(await tools.addTools(tools_csv, '7.4', 'linux')).toContain(script); + }); + + it.each` + tools_csv | token | script + ${'cs2pr:1.2'} | ${'invalid_token'} | ${'add_log "$cross" "cs2pr" "Invalid token"'} + ${'phpunit:1.2'} | ${'invalid_token'} | ${'add_log "$cross" "phpunit" "Invalid token"'} + ${'phpunit:0.1'} | ${'no_data'} | ${'add_log "$cross" "phpunit" "No version found with prefix 0.1."'} + `('checking error: $tools_csv', async ({tools_csv, token, script}) => { + process.env['COMPOSER_TOKEN'] = token; + expect(await tools.addTools(tools_csv, '7.4', 'linux')).toContain(script); + }); + + it.each` + tools_csv | token | script + ${'cs2pr:1.2'} | ${'invalid_token'} | ${'add_log "$cross" "cs2pr" "Invalid token"'} + ${'phpunit:1.2'} | ${'invalid_token'} | ${'add_log "$cross" "phpunit" "Invalid token"'} + ${'phpunit:0.1'} | ${'no_data'} | ${'add_log "$cross" "phpunit" "No version found with prefix 0.1."'} + `('checking error: $tools_csv', async ({tools_csv, token, script}) => { + process.env['GITHUB_TOKEN'] = token; + expect(await tools.addTools(tools_csv, '7.4', 'linux')).toContain(script); + }); + + it.each` + tools_csv | php_version | resolved + ${'phpunit'} | ${'8.2'} | ${'/phpunit-8.2.0.phar'} + ${'phpunit'} | ${'8.1'} | ${'/phpunit-8.1.0.phar'} + ${'phpunit'} | ${'8.0'} | ${'/phpunit-8.0.0.phar'} + ${'phpunit'} | ${'7.3'} | ${'/phpunit-7.3.0.phar'} + ${'phpunit'} | ${'7.2'} | ${'/phpunit-7.2.0.phar'} + ${'phpunit'} | ${'7.1'} | ${'/phpunit-7.1.0.phar'} + ${'phpunit'} | ${'7.0'} | ${'/phpunit-7.0.0.phar'} + `( + 'checking error: $tools_csv', + async ({tools_csv, php_version, resolved}) => { + expect(await tools.addTools(tools_csv, php_version, 'linux')).toContain( + resolved + ); + } + ); +}); diff --git a/__tests__/utils.test.ts b/__tests__/utils.test.ts new file mode 100644 index 0000000..f64be9b --- /dev/null +++ b/__tests__/utils.test.ts @@ -0,0 +1,315 @@ +import fs = require('fs'); +import * as path from 'path'; +import * as utils from '../src/utils'; + +/** + * Mock @actions/core + */ +jest.mock('@actions/core', () => ({ + getInput: jest.fn().mockImplementation(key => { + return ['setup-php'].indexOf(key) !== -1 ? key : ''; + }), + info: jest.fn() +})); + +/** + * Mock fetch.ts + */ +jest.mock('../src/fetch', () => ({ + fetch: jest.fn().mockImplementation(() => { + return {data: '{ "latest": "8.1", "5.x": "5.6" }'}; + }) +})); + +describe('Utils tests', () => { + it('checking readEnv', async () => { + process.env['test'] = 'setup-php'; + process.env['test-hyphen'] = 'setup-php'; + expect(await utils.readEnv('test')).toBe('setup-php'); + expect(await utils.readEnv('TEST')).toBe('setup-php'); + expect(await utils.readEnv('test_hyphen')).toBe('setup-php'); + expect(await utils.readEnv('TEST_HYPHEN')).toBe('setup-php'); + expect(await utils.readEnv('undefined')).toBe(''); + }); + + it('checking getInput', async () => { + process.env['test'] = 'setup-php'; + expect(await utils.getInput('test', false)).toBe('setup-php'); + expect(await utils.getInput('setup-php', false)).toBe('setup-php'); + expect(await utils.getInput('DoesNotExist', false)).toBe(''); + await expect(async () => { + await utils.getInput('DoesNotExist', true); + }).rejects.toThrow('Input required and not supplied: DoesNotExist'); + }); + + it('checking getManifestURL', async () => { + expect(await utils.getManifestURL()).toContain('php-versions.json'); + }); + + it('checking parseVersion', async () => { + expect(await utils.parseVersion('latest')).toBe('8.1'); + expect(await utils.parseVersion('7')).toBe('7.0'); + expect(await utils.parseVersion('7.4')).toBe('7.4'); + expect(await utils.parseVersion('5.x')).toBe('5.6'); + expect(await utils.parseVersion('4.x')).toBe(undefined); + }); + + it('checking parseIniFile', async () => { + expect(await utils.parseIniFile('production')).toBe('production'); + expect(await utils.parseIniFile('development')).toBe('development'); + expect(await utils.parseIniFile('none')).toBe('none'); + expect(await utils.parseIniFile('php.ini-production')).toBe('production'); + expect(await utils.parseIniFile('php.ini-development')).toBe('development'); + expect(await utils.parseIniFile('invalid')).toBe('production'); + }); + + it('checking asyncForEach', async () => { + const array: Array = ['a', 'b', 'c']; + let concat = ''; + await utils.asyncForEach( + array, + async function (str: string): Promise { + concat += str; + } + ); + expect(concat).toBe('abc'); + }); + + it('checking asyncForEach', async () => { + expect(await utils.color('error')).toBe('31'); + expect(await utils.color('success')).toBe('32'); + expect(await utils.color('any')).toBe('32'); + expect(await utils.color('warning')).toBe('33'); + }); + + it('checking extensionArray', async () => { + expect( + await utils.extensionArray('a, :b, php_c, none, php-d, Zend e, :Zend f') + ).toEqual(['none', 'a', ':b', 'c', 'd', 'e', ':f']); + + expect(await utils.extensionArray('')).toEqual([]); + expect(await utils.extensionArray(' ')).toEqual([]); + }); + + it('checking INIArray', async () => { + expect(await utils.CSVArray('a=1, b=2, c=3')).toEqual([ + 'a=1', + 'b=2', + 'c=3' + ]); + expect(await utils.CSVArray('\'a=1,2\', "b=3, 4", c=5, d=~e~')).toEqual([ + 'a=1,2', + 'b=3, 4', + 'c=5', + "d='~e~'" + ]); + expect(await utils.CSVArray('a=\'1,2\', b="3, 4", c=5')).toEqual([ + 'a=1,2', + 'b=3, 4', + 'c=5' + ]); + expect( + await utils.CSVArray('a=E_ALL, b=E_ALL & ~ E_ALL, c="E_ALL", d=\'E_ALL\'') + ).toEqual(['a=E_ALL', 'b=E_ALL & ~ E_ALL', 'c=E_ALL', 'd=E_ALL']); + expect( + await utils.CSVArray('a="b=c;d=e", b=\'c=d,e\', c="g=h,i=j", d=g=h, a===') + ).toEqual(["a='b=c;d=e'", "b='c=d,e'", "c='g=h,i=j'", "d='g=h'", "a='=='"]); + expect(await utils.CSVArray('')).toEqual([]); + expect(await utils.CSVArray(' ')).toEqual([]); + }); + + it('checking log', async () => { + const message = 'Test message'; + + let warning_log: string = await utils.log(message, 'win32', 'warning'); + expect(warning_log).toEqual('printf "\\033[33;1m' + message + ' \\033[0m"'); + warning_log = await utils.log(message, 'linux', 'warning'); + expect(warning_log).toEqual('echo "\\033[33;1m' + message + '\\033[0m"'); + warning_log = await utils.log(message, 'darwin', 'warning'); + expect(warning_log).toEqual('echo "\\033[33;1m' + message + '\\033[0m"'); + + let error_log: string = await utils.log(message, 'win32', 'error'); + expect(error_log).toEqual('printf "\\033[31;1m' + message + ' \\033[0m"'); + error_log = await utils.log(message, 'linux', 'error'); + expect(error_log).toEqual('echo "\\033[31;1m' + message + '\\033[0m"'); + error_log = await utils.log(message, 'darwin', 'error'); + expect(error_log).toEqual('echo "\\033[31;1m' + message + '\\033[0m"'); + + let success_log: string = await utils.log(message, 'win32', 'success'); + expect(success_log).toEqual('printf "\\033[32;1m' + message + ' \\033[0m"'); + success_log = await utils.log(message, 'linux', 'success'); + expect(success_log).toEqual('echo "\\033[32;1m' + message + '\\033[0m"'); + success_log = await utils.log(message, 'darwin', 'success'); + expect(success_log).toEqual('echo "\\033[32;1m' + message + '\\033[0m"'); + + let step_log: string = await utils.stepLog(message, 'win32'); + expect(step_log).toEqual('Step-Log "Test message"'); + step_log = await utils.stepLog(message, 'linux'); + expect(step_log).toEqual('step_log "Test message"'); + step_log = await utils.stepLog(message, 'darwin'); + expect(step_log).toEqual('step_log "Test message"'); + step_log = await utils.stepLog(message, 'openbsd'); + expect(step_log).toContain('Platform openbsd is not supported'); + + let add_log: string = await utils.addLog( + 'tick', + 'xdebug', + 'enabled', + 'win32' + ); + expect(add_log).toEqual('Add-Log "tick" "xdebug" "enabled"'); + add_log = await utils.addLog('tick', 'xdebug', 'enabled', 'linux'); + expect(add_log).toEqual('add_log "tick" "xdebug" "enabled"'); + add_log = await utils.addLog('tick', 'xdebug', 'enabled', 'darwin'); + expect(add_log).toEqual('add_log "tick" "xdebug" "enabled"'); + add_log = await utils.addLog('tick', 'xdebug', 'enabled', 'openbsd'); + expect(add_log).toContain('Platform openbsd is not supported'); + }); + + it('checking getExtensionPrefix', async () => { + expect(await utils.getExtensionPrefix('extensionDoesNotExist')).toEqual( + 'extension' + ); + expect(await utils.getExtensionPrefix('xsl')).toEqual('extension'); + expect(await utils.getExtensionPrefix('xdebug')).toEqual('zend_extension'); + expect(await utils.getExtensionPrefix('xdebug3')).toEqual('zend_extension'); + expect(await utils.getExtensionPrefix('opcache')).toEqual('zend_extension'); + }); + + it('checking suppressOutput', async () => { + expect(await utils.suppressOutput('win32')).toEqual(' >$null 2>&1'); + expect(await utils.suppressOutput('linux')).toEqual(' >/dev/null 2>&1'); + expect(await utils.suppressOutput('darwin')).toEqual(' >/dev/null 2>&1'); + expect(await utils.suppressOutput('openbsd')).toContain( + 'Platform openbsd is not supported' + ); + }); + + it('checking getUnsupportedLog', async () => { + expect(await utils.getUnsupportedLog('ext', '5.6', 'linux')).toContain( + 'add_log "$cross" "ext" "ext is not supported on PHP 5.6"' + ); + }); + + it('checking getCommand', async () => { + expect(await utils.getCommand('linux', 'tool')).toBe('add_tool '); + expect(await utils.getCommand('darwin', 'tool')).toBe('add_tool '); + expect(await utils.getCommand('win32', 'tool')).toBe('Add-Tool '); + expect(await utils.getCommand('win32', 'tool_name')).toBe('Add-ToolName '); + expect(await utils.getCommand('openbsd', 'tool')).toContain( + 'Platform openbsd is not supported' + ); + }); + + it('checking joins', async () => { + expect(await utils.joins('a', 'b', 'c')).toBe('a b c'); + }); + + it('checking scriptExtension', async () => { + expect(await utils.scriptExtension('linux')).toBe('.sh'); + expect(await utils.scriptExtension('darwin')).toBe('.sh'); + expect(await utils.scriptExtension('win32')).toBe('.ps1'); + expect(await utils.scriptExtension('openbsd')).toContain( + 'Platform openbsd is not supported' + ); + }); + + it('checking scriptTool', async () => { + expect(await utils.scriptTool('linux')).toBe('bash '); + expect(await utils.scriptTool('darwin')).toBe('bash '); + expect(await utils.scriptTool('win32')).toBe('pwsh '); + expect(await utils.scriptTool('openbsd')).toContain( + 'Platform openbsd is not supported' + ); + }); + + it('checking customPackage', async () => { + const script_path: string = path.join('ext', 'pkg.sh'); + expect(await utils.customPackage('pkg', 'ext', '1.2.3', 'linux')).toContain( + script_path + '\nadd_pkg 1.2.3' + ); + expect( + await utils.customPackage('pdo_pkg', 'ext', '1.2.3', 'linux') + ).toContain(script_path + '\nadd_pkg 1.2.3'); + expect( + await utils.customPackage('pkg8', 'ext', '1.2.3', 'linux') + ).toContain(script_path + '\nadd_pkg 1.2.3'); + }); + + it('checking parseExtensionSource', async () => { + expect( + await utils.parseExtensionSource( + 'ext-org-name/repo-name@release', + 'extension' + ) + ).toContain( + '\nadd_extension_from_source ext https://github.com org-name repo-name release extension' + ); + expect( + await utils.parseExtensionSource( + 'ext-https://sub.domain.tld/org/repo@release', + 'extension' + ) + ).toContain( + '\nadd_extension_from_source ext https://sub.domain.tld org repo release extension' + ); + expect( + await utils.parseExtensionSource( + 'ext-https://sub.domain.XN--tld/org/repo@release', + 'extension' + ) + ).toContain( + '\nadd_extension_from_source ext https://sub.domain.XN--tld org repo release extension' + ); + }); + + it('checking readPHPVersion', async () => { + expect(await utils.readPHPVersion()).toBe('latest'); + + process.env['php-version-file'] = '.phpenv-version'; + await expect(utils.readPHPVersion()).rejects.toThrow( + "Could not find '.phpenv-version' file." + ); + + const existsSync = jest.spyOn(fs, 'existsSync').mockImplementation(); + const readFileSync = jest.spyOn(fs, 'readFileSync').mockImplementation(); + + existsSync.mockReturnValue(true); + readFileSync.mockReturnValue('8.1'); + + expect(await utils.readPHPVersion()).toBe('8.1'); + + process.env['php-version'] = '8.2'; + expect(await utils.readPHPVersion()).toBe('8.2'); + + delete process.env['php-version-file']; + delete process.env['php-version']; + + existsSync.mockReturnValueOnce(false).mockReturnValueOnce(true); + readFileSync.mockReturnValue( + '{ "platform-overrides": { "php": "7.3.25" } }' + ); + expect(await utils.readPHPVersion()).toBe('7.3.25'); + + existsSync + .mockReturnValueOnce(false) + .mockReturnValueOnce(false) + .mockReturnValueOnce(true); + readFileSync.mockReturnValue( + '{ "config": { "platform": { "php": "7.4.33" } } }' + ); + expect(await utils.readPHPVersion()).toBe('7.4.33'); + + existsSync.mockClear(); + readFileSync.mockClear(); + }); + + it('checking setVariable', async () => { + let script: string = await utils.setVariable('var', 'command', 'linux'); + expect(script).toEqual('\nvar="$(command)"\n'); + script = await utils.setVariable('var', 'command', 'darwin'); + expect(script).toEqual('\nvar="$(command)"\n'); + script = await utils.setVariable('var', 'command', 'win32'); + expect(script).toEqual('\n$var = command\n'); + }); +}); diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..357b9c1 --- /dev/null +++ b/action.yml @@ -0,0 +1,35 @@ +name: 'Setup PHP Action' +author: shivammathur +description: 'GitHub Action for PHP' +branding: + color: 'purple' + icon: 'play-circle' +inputs: + php-version: + description: 'Setup PHP version.' + required: false + php-version-file: + description: 'Setup PHP version from a file.' + required: false + extensions: + description: 'Setup PHP extensions.' + required: false + ini-file: + description: 'Set base ini file.' + required: false + default: 'production' + ini-values: + description: 'Add values to php.ini.' + required: false + coverage: + description: 'Setup code coverage driver.' + required: false + tools: + description: 'Setup popular tools globally.' + required: false +outputs: + php-version: + description: 'PHP version in semver format' +runs: + using: 'node20' + main: 'dist/index.js' diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..2d3b809 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,5722 @@ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ 88: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.addINIValues = exports.addINIValuesWindows = exports.addINIValuesUnix = void 0; +const utils = __importStar(__nccwpck_require__(918)); +async function addINIValuesUnix(ini_values_csv) { + const ini_values = await utils.CSVArray(ini_values_csv); + let script = ''; + await utils.asyncForEach(ini_values, async function (line) { + script += + '\n' + (await utils.addLog('$tick', line, 'Added to php.ini', 'linux')); + }); + return ('echo "' + + ini_values.join('\n') + + '" | sudo tee -a "${pecl_file:-${ini_file[@]}}" >/dev/null 2>&1' + + script); +} +exports.addINIValuesUnix = addINIValuesUnix; +async function addINIValuesWindows(ini_values_csv) { + const ini_values = await utils.CSVArray(ini_values_csv); + let script = '\n'; + await utils.asyncForEach(ini_values, async function (line) { + script += + (await utils.addLog('$tick', line, 'Added to php.ini', 'win32')) + '\n'; + }); + return ('Add-Content "$php_dir\\php.ini" "' + ini_values.join('\n') + '"' + script); +} +exports.addINIValuesWindows = addINIValuesWindows; +async function addINIValues(ini_values_csv, os, no_step = false) { + let script = '\n'; + switch (no_step) { + case true: + script += + (await utils.stepLog('Add php.ini values', os)) + + (await utils.suppressOutput(os)) + + '\n'; + break; + case false: + default: + script += (await utils.stepLog('Add php.ini values', os)) + '\n'; + break; + } + switch (os) { + case 'win32': + return script + (await addINIValuesWindows(ini_values_csv)); + case 'darwin': + case 'linux': + return script + (await addINIValuesUnix(ini_values_csv)); + default: + return await utils.log('Platform ' + os + ' is not supported', os, 'error'); + } +} +exports.addINIValues = addINIValues; +//# sourceMappingURL=config.js.map + +/***/ }), + +/***/ 5730: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.addCoverage = exports.disableCoverage = exports.addCoveragePCOV = exports.addCoverageXdebug = exports.checkXdebugError = void 0; +const utils = __importStar(__nccwpck_require__(918)); +const extensions = __importStar(__nccwpck_require__(3390)); +const config = __importStar(__nccwpck_require__(88)); +async function checkXdebugError(extension, version) { + if ((/^5\.[3-6]$|^7\.[0-1]$/.test(version) && extension == 'xdebug3') || + (/^8\.[0-9]$/.test(version) && extension == 'xdebug2')) { + return extension + ' is not supported on PHP ' + version; + } + return ''; +} +exports.checkXdebugError = checkXdebugError; +async function addCoverageXdebug(extension, version, os, pipe) { + let script = '\n'; + const error = await checkXdebugError(extension, version); + if (!error) { + script += + (await extensions.addExtension(':pcov:false', version, os, true)) + pipe; + extension = extension == 'xdebug3' ? 'xdebug' : extension; + script += + (await extensions.addExtension(extension, version, os, true)) + pipe; + script += await utils.setVariable('xdebug_version', 'php -r "echo phpversion(\'xdebug\');"', os); + script += + (await utils.getCommand(os, 'extension_log')) + + 'xdebug "Xdebug $xdebug_version enabled as coverage driver"'; + } + else { + script += await utils.addLog('$cross', extension, error, os); + } + return script; +} +exports.addCoverageXdebug = addCoverageXdebug; +async function addCoveragePCOV(version, os, pipe) { + let script = '\n'; + switch (true) { + default: + script += + (await extensions.addExtension(':xdebug:false', version, os, true)) + + pipe; + script += + (await extensions.addExtension('pcov', version, os, true)) + pipe; + script += (await config.addINIValues('pcov.enabled=1', os, true)) + '\n'; + script += await utils.setVariable('pcov_version', 'php -r "echo phpversion(\'pcov\');"', os); + script += + (await utils.getCommand(os, 'extension_log')) + + 'pcov "PCOV $pcov_version enabled as coverage driver"'; + break; + case /5\.[3-6]|7\.0/.test(version): + script += await utils.addLog('$cross', 'pcov', 'PHP 7.1 or newer is required', os); + break; + } + return script; +} +exports.addCoveragePCOV = addCoveragePCOV; +async function disableCoverage(version, os, pipe) { + let script = '\n'; + script += + (await extensions.addExtension(':pcov:false', version, os, true)) + pipe; + script += + (await extensions.addExtension(':xdebug:false', version, os, true)) + pipe; + script += await utils.addLog('$tick', 'none', 'Disabled Xdebug and PCOV', os); + return script; +} +exports.disableCoverage = disableCoverage; +async function addCoverage(coverage_driver, version, os) { + coverage_driver = coverage_driver.toLowerCase(); + const script = '\n' + (await utils.stepLog('Setup Coverage', os)); + const pipe = (await utils.suppressOutput(os)) + '\n'; + switch (coverage_driver) { + case 'pcov': + return script + (await addCoveragePCOV(version, os, pipe)); + case 'xdebug': + case 'xdebug2': + case 'xdebug3': + return (script + (await addCoverageXdebug(coverage_driver, version, os, pipe))); + case 'none': + return script + (await disableCoverage(version, os, pipe)); + default: + return ''; + } +} +exports.addCoverage = addCoverage; +//# sourceMappingURL=coverage.js.map + +/***/ }), + +/***/ 3390: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.addExtension = exports.addExtensionLinux = exports.addExtensionWindows = exports.addExtensionDarwin = void 0; +const utils = __importStar(__nccwpck_require__(918)); +async function addExtensionDarwin(extension_csv, version) { + const extensions = await utils.extensionArray(extension_csv); + let add_script = '\n'; + let remove_script = ''; + await utils.asyncForEach(extensions, async function (extension) { + const version_extension = version + extension; + const [ext_name, ext_version] = extension.split('-'); + const ext_prefix = await utils.getExtensionPrefix(ext_name); + switch (true) { + case /^:/.test(ext_name): + remove_script += '\ndisable_extension' + ext_name.replace(/:/g, ' '); + return; + case /^none$/.test(ext_name): + add_script += '\ndisable_all_shared'; + return; + case /.+-.+\/.+@.+/.test(extension): + add_script += await utils.parseExtensionSource(extension, ext_prefix); + return; + case /^(7\.4|8\.[0-3])relay(-v?\d+\.\d+\.\d+)?$/.test(version_extension): + case /^(5\.[3-6]|7\.[0-4]|8\.[0-3])blackfire(-\d+\.\d+\.\d+)?$/.test(version_extension): + case /^couchbase|^event|^gearman$|^geos$|^pdo_oci$|^oci8$|^(pecl_)?http|^pdo_firebird$/.test(extension): + case /^(5\.[3-6]|7\.[0-4])ioncube$/.test(version_extension): + case /(5\.6|7\.[0-3])phalcon3|7\.[2-4]phalcon4|(7\.4|8\.[0-2])phalcon5/.test(version_extension): + case /(? { + const url_object = new url.URL(input_url); + const headers = { + 'User-Agent': `Mozilla/5.0 (${process.platform} ${process.arch}) setup-php` + }; + if (auth_token) { + headers.authorization = 'Bearer ' + auth_token; + } + const options = { + hostname: url_object.hostname, + path: url_object.pathname, + headers: headers, + agent: new https.Agent({ keepAlive: false }) + }; + const req = https.get(options, (res) => { + if (res.statusCode === 200) { + let body = ''; + res.setEncoding('utf8'); + res.on('data', chunk => (body += chunk)); + res.on('end', () => resolve({ data: `${body}` })); + } + else if ([301, 302, 303, 307, 308].includes(res.statusCode)) { + if (redirect_count > 0 && res.headers.location) { + fetch(res.headers.location, auth_token, redirect_count--).then(resolve); + } + else { + resolve({ error: `${res.statusCode}: Redirect error` }); + } + } + else { + resolve({ error: `${res.statusCode}: ${res.statusMessage}` }); + } + }); + req.end(); + }); + return await fetch_promise; +} +exports.fetch = fetch; +//# sourceMappingURL=fetch.js.map + +/***/ }), + +/***/ 9039: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.run = exports.getScript = void 0; +const path_1 = __importDefault(__nccwpck_require__(1017)); +const fs_1 = __importDefault(__nccwpck_require__(7147)); +const exec_1 = __nccwpck_require__(1514); +const core = __importStar(__nccwpck_require__(2186)); +const config = __importStar(__nccwpck_require__(88)); +const coverage = __importStar(__nccwpck_require__(5730)); +const extensions = __importStar(__nccwpck_require__(3390)); +const tools = __importStar(__nccwpck_require__(7740)); +const utils = __importStar(__nccwpck_require__(918)); +async function getScript(os) { + const url = 'https://setup-php.com/sponsor'; + const filename = os + (await utils.scriptExtension(os)); + const script_path = path_1.default.join(__dirname, '../src/scripts', filename); + const run_path = script_path.replace(os, 'run'); + process.env['fail_fast'] = await utils.getInput('fail-fast', false); + const extension_csv = await utils.getInput('extensions', false); + const ini_values_csv = await utils.getInput('ini-values', false); + const coverage_driver = await utils.getInput('coverage', false); + const tools_csv = await utils.getInput('tools', false); + const version = await utils.parseVersion(await utils.readPHPVersion()); + const ini_file = await utils.parseIniFile(await utils.getInput('ini-file', false)); + let script = await utils.joins('.', script_path, version, ini_file); + if (extension_csv) { + script += await extensions.addExtension(extension_csv, version, os); + } + script += await tools.addTools(tools_csv, version, os); + if (coverage_driver) { + script += await coverage.addCoverage(coverage_driver, version, os); + } + if (ini_values_csv) { + script += await config.addINIValues(ini_values_csv, os); + } + script += '\n' + (await utils.stepLog(`Sponsor setup-php`, os)); + script += '\n' + (await utils.addLog('$tick', 'setup-php', url, os)); + fs_1.default.writeFileSync(run_path, script, { mode: 0o755 }); + return run_path; +} +exports.getScript = getScript; +async function run() { + const os = process.platform; + const tool = await utils.scriptTool(os); + const run_path = await getScript(os); + await (0, exec_1.exec)(tool + run_path); +} +exports.run = run; +(async () => { + await run(); +})().catch(error => { + core.setFailed(error.message); +}); +//# sourceMappingURL=install.js.map + +/***/ }), + +/***/ 5151: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.search = void 0; +const cv = __importStar(__nccwpck_require__(4773)); +const fetch = __importStar(__nccwpck_require__(2387)); +async function search(package_name, php_version) { + const response = await fetch.fetch(`https://repo.packagist.org/p2/${package_name}.json`); + if (response.error || response.data === '[]') { + return null; + } + const data = JSON.parse(response['data']); + if (data && data.packages) { + const versions = data.packages[package_name]; + versions.sort((a, b) => cv.compareVersions(b.version, a.version)); + const result = versions.find((versionData) => { + if (versionData?.require?.php) { + return versionData?.require?.php + .split('|') + .some(require => require && cv.satisfies(php_version + '.0', require)); + } + return false; + }); + return result ? result.version : null; + } + return null; +} +exports.search = search; +//# sourceMappingURL=packagist.js.map + +/***/ }), + +/***/ 7740: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.addTools = exports.functionRecord = exports.getData = exports.addWPCLI = exports.addPHPUnitTools = exports.addPhive = exports.addPhing = exports.addPECL = exports.addDevTools = exports.addDeployer = exports.addComposer = exports.addCastor = exports.addBlackfirePlayer = exports.addPackage = exports.addArchive = exports.getPharUrl = exports.getUrl = exports.filterList = exports.getRelease = exports.getVersion = exports.getLatestVersion = exports.getSemverVersion = void 0; +const path_1 = __importDefault(__nccwpck_require__(1017)); +const fs_1 = __importDefault(__nccwpck_require__(7147)); +const fetch = __importStar(__nccwpck_require__(2387)); +const packagist = __importStar(__nccwpck_require__(5151)); +const utils = __importStar(__nccwpck_require__(918)); +async function getSemverVersion(data) { + const search = data['version_prefix'] + data['version']; + const url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${search}.`; + let github_token = await utils.readEnv('GITHUB_TOKEN'); + const composer_token = await utils.readEnv('COMPOSER_TOKEN'); + if (composer_token && !github_token) { + github_token = composer_token; + } + const response = await fetch.fetch(url, github_token); + if (response.error || response.data === '[]') { + data['error'] = response.error ?? `No version found with prefix ${search}.`; + return data['version']; + } + else { + const refs = JSON.parse(response['data']).reverse(); + const ref = refs.find((i) => /.*\d+.\d+.\d+$/.test(i['ref'])); + const tag = (ref || refs[0])['ref'].split('/').pop(); + return tag.replace(/^v(\d)/, '$1'); + } +} +exports.getSemverVersion = getSemverVersion; +async function getLatestVersion(data) { + if (!data['version'] && data['fetch_latest'] === 'false') { + return 'latest'; + } + const resp = await fetch.fetch(`${data['github']}/${data['repository']}/releases.atom`); + if (resp['data']) { + const releases = [ + ...resp['data'].matchAll(/releases\/tag\/([a-zA-Z]*)?(\d+.\d+.\d+)"/g) + ].map(match => match[2]); + return (releases + .sort((a, b) => a.localeCompare(b, undefined, { numeric: true })) + .pop() || 'latest'); + } + return 'latest'; +} +exports.getLatestVersion = getLatestVersion; +async function getVersion(version, data) { + const semver_regex = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/; + const composer_regex = /^composer:(stable|preview|snapshot|[1|2])$/; + const constraint_regex = /[><=^~]+.*/; + const major_minor_regex = /^\d+(\.\d+)?$/; + data['version'] = version.replace(/v?(\d)/, '$1').replace(/\.x/, ''); + switch (true) { + case composer_regex.test(data['release']): + case semver_regex.test(data['version']): + case constraint_regex.test(data['version']) && data['type'] === 'composer': + return data['version']; + case major_minor_regex.test(data['version']) && data['type'] === 'composer': + data['release'] = `${data['tool']}:${data['version']}.*`; + return `${data['version']}.*`; + case data['repository'] && major_minor_regex.test(data['version']): + return await getSemverVersion(data); + default: + return data['version'].replace(/[><=^~]*/, ''); + } +} +exports.getVersion = getVersion; +async function getRelease(release, data) { + release = release.includes('/') ? release.split('/')[1] : release; + return release.includes(':') + ? [data['tool'], release.split(':')[1]].join(':') + : data['tool']; +} +exports.getRelease = getRelease; +async function filterList(tools_list) { + const regex_any = /^composer($|:.*)/; + const regex_valid = /^composer:?($|preview$|snapshot$|v?\d+(\.\d+)?$|v?\d+\.\d+\.\d+[\w-]*$)/; + const matches = tools_list.filter(tool => regex_valid.test(tool)); + let composer = 'composer'; + tools_list = tools_list.filter(tool => !regex_any.test(tool)); + switch (true) { + case matches[0] == undefined: + break; + default: + composer = matches[matches.length - 1].replace(/v(\d\S*)/, '$1'); + break; + } + tools_list.unshift(composer); + return tools_list; +} +exports.filterList = filterList; +async function getUrl(data) { + if (data['version'] === 'latest') { + return [ + data['domain'], + data['repository'], + data['prefix'], + data['version'], + data['verb'], + data['tool'] + data['extension'] + ] + .filter(Boolean) + .join('/'); + } + else { + return [ + data['domain'], + data['repository'], + data['prefix'], + data['verb'], + data['version_prefix'] + data['version'], + data['tool'] + data['extension'] + ] + .filter(Boolean) + .join('/'); + } +} +exports.getUrl = getUrl; +async function getPharUrl(data) { + if (data['version'] === 'latest') { + return data['domain'] + '/' + data['tool'] + '.phar'; + } + else { + return (data['domain'] + + '/' + + data['tool'] + + '-' + + data['version_prefix'] + + data['version'] + + '.phar'); + } +} +exports.getPharUrl = getPharUrl; +async function addArchive(data) { + return ((await utils.getCommand(data['os'], 'tool')) + + (await utils.joins(data['url'], data['tool'], data['version_parameter']))); +} +exports.addArchive = addArchive; +async function addPackage(data) { + const command = await utils.getCommand(data['os'], 'composer_tool'); + const parts = data['repository'].split('/'); + const args = await utils.joins(parts[1], data['release'], parts[0] + '/', data['scope']); + return command + args; +} +exports.addPackage = addPackage; +async function addBlackfirePlayer(data) { + switch (data['os']) { + case 'win32': + return await utils.addLog('$cross', data['tool'], data['tool'] + ' is not a windows tool', 'win32'); + default: + if (data['version'] == 'latest') { + if (/5\.[5-6]|7\.0/.test(data['php_version'])) { + data['version'] = '1.9.3'; + } + else if (/7\.[1-4]|8\.0/.test(data['php_version'])) { + data['version'] = '1.22.0'; + } + } + data['url'] = await getPharUrl(data); + return addArchive(data); + } +} +exports.addBlackfirePlayer = addBlackfirePlayer; +async function addCastor(data) { + data['tool'] = 'castor.' + data['os'].replace('win32', 'windows') + '-amd64'; + data['url'] = await getUrl(data); + data['tool'] = 'castor'; + data['version_parameter'] = fs_1.default.existsSync('castor.php') + ? data['version_parameter'] + : ''; + return await addArchive(data); +} +exports.addCastor = addCastor; +async function addComposer(data) { + const channel = data['version'].replace('latest', 'stable'); + const github = data['github']; + const getcomposer = data['domain']; + const cds = 'https://dl.cloudsmith.io'; + const filename = `composer-${data['php_version']}-${channel}.phar`; + const releases_url = `${github}/shivammathur/composer-cache/releases/latest/download/${filename}`; + const cds_url = `${cds}/public/shivammathur/composer-cache/raw/files/${filename}`; + const lts_url = `${getcomposer}/download/latest-2.2.x/composer.phar`; + const is_lts = /^5\.[3-6]$|^7\.[0-1]$/.test(data['php_version']); + const version_source_url = `${getcomposer}/composer-${channel}.phar`; + let cache_url = `${releases_url},${cds_url}`; + let source_url = `${getcomposer}/composer.phar`; + switch (true) { + case /^snapshot$/.test(channel): + source_url = is_lts ? lts_url : source_url; + break; + case /^preview$|^2$/.test(channel): + source_url = is_lts ? lts_url : version_source_url; + break; + case /^1$/.test(channel): + source_url = version_source_url; + break; + case /^\d+\.\d+\.\d+[\w-]*$/.test(data['version']): + cache_url = `${github}/${data['repository']}/releases/download/${data['version']}/composer.phar`; + source_url = version_source_url; + break; + default: + source_url = is_lts ? lts_url : version_source_url; + } + const use_cache = (await utils.readEnv('NO_TOOLS_CACHE')) !== 'true'; + data['url'] = use_cache ? `${cache_url},${source_url}` : source_url; + data['version_parameter'] = data['version']; + return await addArchive(data); +} +exports.addComposer = addComposer; +async function addDeployer(data) { + if (data['version'] === 'latest') { + data['url'] = data['domain'] + '/deployer.phar'; + } + else { + const manifest = await fetch.fetch('https://deployer.org/manifest.json'); + const version_data = JSON.parse(manifest.data); + const version_key = Object.keys(version_data).find((key) => { + return version_data[key]['version'] === data['version']; + }); + if (version_key) { + data['url'] = version_data[version_key]['url']; + } + else { + return await utils.addLog('$cross', 'deployer', 'Version missing in deployer manifest', data['os']); + } + } + return await addArchive(data); +} +exports.addDeployer = addDeployer; +async function addDevTools(data) { + switch (data['os']) { + case 'linux': + case 'darwin': + return 'add_devtools ' + data['tool']; + case 'win32': + return await utils.addLog('$tick', data['tool'], data['tool'] + ' is not a windows tool', 'win32'); + default: + return await utils.log('Platform ' + data['os'] + ' is not supported', data['os'], 'error'); + } +} +exports.addDevTools = addDevTools; +async function addPECL(data) { + return await utils.getCommand(data['os'], 'pecl'); +} +exports.addPECL = addPECL; +async function addPhing(data) { + data['url'] = + data['domain'] + '/get/phing-' + data['version'] + data['extension']; + if (data['version'] != 'latest') { + [data['prefix'], data['verb']] = ['releases', 'download']; + data['domain'] = data['github']; + data['extension'] = '-' + data['version'] + data['extension']; + data['url'] += ',' + (await getUrl(data)); + } + return await addArchive(data); +} +exports.addPhing = addPhing; +async function addPhive(data) { + switch (true) { + case /5\.[3-5]/.test(data['php_version']): + return await utils.addLog('$cross', 'phive', 'Phive is not supported on PHP ' + data['php_version'], data['os']); + case /5\.6|7\.0/.test(data['php_version']): + data['version'] = '0.12.1'; + break; + case /7\.1/.test(data['php_version']): + data['version'] = '0.13.5'; + break; + case /7\.2/.test(data['php_version']): + data['version'] = '0.14.5'; + break; + case /^latest$/.test(data['version']): + data['version'] = await getLatestVersion(data); + break; + } + data['extension'] = '-' + data['version'] + data['extension']; + data['url'] = await getUrl(data); + return await addArchive(data); +} +exports.addPhive = addPhive; +async function addPHPUnitTools(data) { + if (data['version'] === 'latest') { + data['version'] = + (await packagist.search(data['packagist'], data['php_version'])) ?? + 'latest'; + } + data['url'] = await getPharUrl(data); + return await addArchive(data); +} +exports.addPHPUnitTools = addPHPUnitTools; +async function addWPCLI(data) { + if (data['version'] === 'latest') { + data['uri'] = 'wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true'; + data['url'] = [data['domain'], data['uri']].join('/'); + } + else { + data['extension'] = '-' + data['version'] + data['extension']; + data['url'] = await getUrl(data); + } + return await addArchive(data); +} +exports.addWPCLI = addWPCLI; +async function getData(release, php_version, os) { + const json_file_path = path_1.default.join(__dirname, '../src/configs/tools.json'); + const json_file = fs_1.default.readFileSync(json_file_path, 'utf8'); + const json_objects = JSON.parse(json_file); + release = release.replace(/\s+/g, ''); + const parts = release.split(':'); + const tool = parts[0]; + const version = parts[1]; + let data; + if (Object.keys(json_objects).includes(tool)) { + data = json_objects[tool]; + data['tool'] = tool; + } + else { + const key = Object.keys(json_objects).find((key) => { + return json_objects[key]['alias'] == tool; + }); + if (key) { + data = json_objects[key]; + data['tool'] = key; + } + else { + data = { + tool: tool.split('/')[1], + repository: tool, + type: 'composer' + }; + data = !tool.includes('/') ? { tool: tool } : data; + } + } + data['github'] = 'https://github.com'; + data['domain'] ??= data['github']; + data['extension'] ??= '.phar'; + data['os'] = os; + data['php_version'] = php_version; + data['packagist'] ??= data['repository']; + data['prefix'] = data['github'] === data['domain'] ? 'releases' : ''; + data['verb'] = data['github'] === data['domain'] ? 'download' : ''; + data['fetch_latest'] ??= 'false'; + data['scope'] ??= 'global'; + data['version_parameter'] = JSON.stringify(data['version_parameter']) || ''; + data['version_prefix'] ??= ''; + data['release'] = await getRelease(release, data); + data['version'] = version + ? await getVersion(version, data) + : await getLatestVersion(data); + return data; +} +exports.getData = getData; +exports.functionRecord = { + castor: addCastor, + composer: addComposer, + deployer: addDeployer, + dev_tools: addDevTools, + phive: addPhive, + blackfire_player: addBlackfirePlayer, + pecl: addPECL, + phing: addPhing, + phpunit: addPHPUnitTools, + phpcpd: addPHPUnitTools, + wp_cli: addWPCLI +}; +async function addTools(tools_csv, php_version, os) { + let script = '\n'; + if (tools_csv === 'none') { + return ''; + } + else { + script += await utils.stepLog('Setup Tools', os); + } + const tools_list = await filterList(await utils.CSVArray(tools_csv)); + await utils.asyncForEach(tools_list, async function (release) { + const data = await getData(release, php_version, os); + script += '\n'; + switch (true) { + case data['error'] !== undefined: + script += await utils.addLog('$cross', data['tool'], data['error'], data['os']); + break; + case 'phar' === data['type']: + data['url'] = await getUrl(data); + script += await addArchive(data); + break; + case 'composer' === data['type']: + script += await addPackage(data); + break; + case 'custom-package' === data['type']: + script += await utils.customPackage(data['tool'].split('-')[0], 'tools', data['version'], data['os']); + break; + case 'custom-function' === data['type']: + script += await exports.functionRecord[data['function']](data); + break; + case /^none$/.test(data['tool']): + break; + default: + script += await utils.addLog('$cross', data['tool'], 'Tool ' + data['tool'] + ' is not supported', data['os']); + break; + } + }); + return script; +} +exports.addTools = addTools; +//# sourceMappingURL=tools.js.map + +/***/ }), + +/***/ 918: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.setVariable = exports.readPHPVersion = exports.parseExtensionSource = exports.customPackage = exports.scriptTool = exports.scriptExtension = exports.joins = exports.getCommand = exports.getUnsupportedLog = exports.suppressOutput = exports.getExtensionPrefix = exports.CSVArray = exports.extensionArray = exports.addLog = exports.stepLog = exports.log = exports.color = exports.asyncForEach = exports.parseIniFile = exports.parseVersion = exports.getManifestURL = exports.getInput = exports.readEnv = void 0; +const fs_1 = __importDefault(__nccwpck_require__(7147)); +const path = __importStar(__nccwpck_require__(1017)); +const core = __importStar(__nccwpck_require__(2186)); +const fetch = __importStar(__nccwpck_require__(2387)); +async function readEnv(property) { + const property_lc = property.toLowerCase(); + const property_uc = property.toUpperCase(); + return (process.env[property] || + process.env[property_lc] || + process.env[property_uc] || + process.env[property_lc.replace('_', '-')] || + process.env[property_uc.replace('_', '-')] || + ''); +} +exports.readEnv = readEnv; +async function getInput(name, mandatory) { + const input = core.getInput(name); + const env_input = await readEnv(name); + switch (true) { + case input != '': + return input; + case input == '' && env_input != '': + return env_input; + case input == '' && env_input == '' && mandatory: + throw new Error(`Input required and not supplied: ${name}`); + default: + return ''; + } +} +exports.getInput = getInput; +async function getManifestURL() { + return 'https://raw.githubusercontent.com/shivammathur/setup-php/develop/src/configs/php-versions.json'; +} +exports.getManifestURL = getManifestURL; +async function parseVersion(version) { + switch (true) { + case /^(latest|nightly|\d+\.x)$/.test(version): + return JSON.parse((await fetch.fetch(await getManifestURL()))['data'])[version]; + default: + switch (true) { + case version.length > 1: + return version.slice(0, 3); + default: + return version + '.0'; + } + } +} +exports.parseVersion = parseVersion; +async function parseIniFile(ini_file) { + switch (true) { + case /^(production|development|none)$/.test(ini_file): + return ini_file; + case /php\.ini-(production|development)$/.test(ini_file): + return ini_file.split('-')[1]; + default: + return 'production'; + } +} +exports.parseIniFile = parseIniFile; +async function asyncForEach(array, callback) { + for (let index = 0; index < array.length; index++) { + await callback(array[index], index, array); + } +} +exports.asyncForEach = asyncForEach; +async function color(type) { + switch (type) { + case 'error': + return '31'; + default: + case 'success': + return '32'; + case 'warning': + return '33'; + } +} +exports.color = color; +async function log(message, os, log_type) { + switch (os) { + case 'win32': + return ('printf "\\033[' + + (await color(log_type)) + + ';1m' + + message + + ' \\033[0m"'); + case 'linux': + case 'darwin': + default: + return ('echo "\\033[' + (await color(log_type)) + ';1m' + message + '\\033[0m"'); + } +} +exports.log = log; +async function stepLog(message, os) { + switch (os) { + case 'win32': + return 'Step-Log "' + message + '"'; + case 'linux': + case 'darwin': + return 'step_log "' + message + '"'; + default: + return await log('Platform ' + os + ' is not supported', os, 'error'); + } +} +exports.stepLog = stepLog; +async function addLog(mark, subject, message, os) { + switch (os) { + case 'win32': + return 'Add-Log "' + mark + '" "' + subject + '" "' + message + '"'; + case 'linux': + case 'darwin': + return 'add_log "' + mark + '" "' + subject + '" "' + message + '"'; + default: + return await log('Platform ' + os + ' is not supported', os, 'error'); + } +} +exports.addLog = addLog; +async function extensionArray(extension_csv) { + switch (extension_csv) { + case '': + case ' ': + return []; + default: + return [ + extension_csv.match(/(^|,\s?)none(\s?,|$)/) ? 'none' : '', + ...extension_csv + .split(',') + .map(function (extension) { + if (/.+-.+\/.+@.+/.test(extension)) { + return extension; + } + return extension + .trim() + .toLowerCase() + .replace(/^(:)?(php[-_]|none|zend )|(-[^-]*)-/, '$1$3'); + }) + ].filter(Boolean); + } +} +exports.extensionArray = extensionArray; +async function CSVArray(values_csv) { + switch (values_csv) { + case '': + case ' ': + return []; + default: + return values_csv + .split(/,(?=(?:(?:[^"']*["']){2})*[^"']*$)/) + .map(function (value) { + return value + .trim() + .replace(/^["']|["']$|(?<==)["']/g, '') + .replace(/=(((?!E_).)*[?{}|&~![()^]+((?!E_).)+)/, "='$1'") + .replace(/=(.*?)(=.*)/, "='$1$2'") + .replace(/:\s*["'](.*?)/g, ':$1'); + }) + .filter(Boolean); + } +} +exports.CSVArray = CSVArray; +async function getExtensionPrefix(extension) { + switch (true) { + default: + return 'extension'; + case /xdebug([2-3])?$|opcache|ioncube|eaccelerator/.test(extension): + return 'zend_extension'; + } +} +exports.getExtensionPrefix = getExtensionPrefix; +async function suppressOutput(os) { + switch (os) { + case 'win32': + return ' >$null 2>&1'; + case 'linux': + case 'darwin': + return ' >/dev/null 2>&1'; + default: + return await log('Platform ' + os + ' is not supported', os, 'error'); + } +} +exports.suppressOutput = suppressOutput; +async function getUnsupportedLog(extension, version, os) { + return ('\n' + + (await addLog('$cross', extension, [extension, 'is not supported on PHP', version].join(' '), os)) + + '\n'); +} +exports.getUnsupportedLog = getUnsupportedLog; +async function getCommand(os, suffix) { + switch (os) { + case 'linux': + case 'darwin': + return 'add_' + suffix + ' '; + case 'win32': + return ('Add-' + + suffix + .split('_') + .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) + .join('') + + ' '); + default: + return await log('Platform ' + os + ' is not supported', os, 'error'); + } +} +exports.getCommand = getCommand; +async function joins(...str) { + return [...str].join(' '); +} +exports.joins = joins; +async function scriptExtension(os) { + switch (os) { + case 'win32': + return '.ps1'; + case 'linux': + case 'darwin': + return '.sh'; + default: + return await log('Platform ' + os + ' is not supported', os, 'error'); + } +} +exports.scriptExtension = scriptExtension; +async function scriptTool(os) { + switch (os) { + case 'win32': + return 'pwsh '; + case 'linux': + case 'darwin': + return 'bash '; + default: + return await log('Platform ' + os + ' is not supported', os, 'error'); + } +} +exports.scriptTool = scriptTool; +async function customPackage(pkg, type, version, os) { + const pkg_name = pkg.replace(/\d+|(pdo|pecl)[_-]/, ''); + const script_extension = await scriptExtension(os); + const script = path.join(__dirname, '../src/scripts/' + type + '/' + pkg_name + script_extension); + const command = await getCommand(os, pkg_name); + return '\n. ' + script + '\n' + command + version; +} +exports.customPackage = customPackage; +async function parseExtensionSource(extension, prefix) { + const regex = /(\w+)-(\w+:\/\/.{1,253}(?:[.:][^:/\s]{2,63})+\/)?([\w.-]+)\/([\w.-]+)@(.+)/; + const matches = regex.exec(extension); + matches[2] = matches[2] ? matches[2].slice(0, -1) : 'https://github.com'; + return await joins('\nadd_extension_from_source', ...matches.splice(1, matches.length), prefix); +} +exports.parseExtensionSource = parseExtensionSource; +async function readPHPVersion() { + const version = await getInput('php-version', false); + if (version) { + return version; + } + const versionFile = (await getInput('php-version-file', false)) || '.php-version'; + if (fs_1.default.existsSync(versionFile)) { + return fs_1.default.readFileSync(versionFile, 'utf8').replace(/[\r\n]/g, ''); + } + else if (versionFile !== '.php-version') { + throw new Error(`Could not find '${versionFile}' file.`); + } + const composerLock = 'composer.lock'; + if (fs_1.default.existsSync(composerLock)) { + const lockFileContents = JSON.parse(fs_1.default.readFileSync(composerLock, 'utf8')); + if (lockFileContents['platform-overrides'] && + lockFileContents['platform-overrides']['php']) { + return lockFileContents['platform-overrides']['php']; + } + } + const composerJson = 'composer.json'; + if (fs_1.default.existsSync(composerJson)) { + const composerFileContents = JSON.parse(fs_1.default.readFileSync(composerJson, 'utf8')); + if (composerFileContents['config'] && + composerFileContents['config']['platform'] && + composerFileContents['config']['platform']['php']) { + return composerFileContents['config']['platform']['php']; + } + } + return 'latest'; +} +exports.readPHPVersion = readPHPVersion; +async function setVariable(variable, command, os) { + switch (os) { + case 'win32': + return '\n$' + variable + ' = ' + command + '\n'; + case 'linux': + case 'darwin': + default: + return '\n' + variable + '="$(' + command + ')"\n'; + } +} +exports.setVariable = setVariable; +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ 5241: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.issue = exports.issueCommand = void 0; +const os = __importStar(__nccwpck_require__(2037)); +const utils_1 = __nccwpck_require__(5278); +/** + * Commands + * + * Command Format: + * ::name key=value,key=value::message + * + * Examples: + * ::warning::This is the message + * ::set-env name=MY_VAR::some value + */ +function issueCommand(command, properties, message) { + const cmd = new Command(command, properties, message); + process.stdout.write(cmd.toString() + os.EOL); +} +exports.issueCommand = issueCommand; +function issue(name, message = '') { + issueCommand(name, {}, message); +} +exports.issue = issue; +const CMD_STRING = '::'; +class Command { + constructor(command, properties, message) { + if (!command) { + command = 'missing.command'; + } + this.command = command; + this.properties = properties; + this.message = message; + } + toString() { + let cmdStr = CMD_STRING + this.command; + if (this.properties && Object.keys(this.properties).length > 0) { + cmdStr += ' '; + let first = true; + for (const key in this.properties) { + if (this.properties.hasOwnProperty(key)) { + const val = this.properties[key]; + if (val) { + if (first) { + first = false; + } + else { + cmdStr += ','; + } + cmdStr += `${key}=${escapeProperty(val)}`; + } + } + } + } + cmdStr += `${CMD_STRING}${escapeData(this.message)}`; + return cmdStr; + } +} +function escapeData(s) { + return utils_1.toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A'); +} +function escapeProperty(s) { + return utils_1.toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A') + .replace(/:/g, '%3A') + .replace(/,/g, '%2C'); +} +//# sourceMappingURL=command.js.map + +/***/ }), + +/***/ 2186: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; +const command_1 = __nccwpck_require__(5241); +const file_command_1 = __nccwpck_require__(717); +const utils_1 = __nccwpck_require__(5278); +const os = __importStar(__nccwpck_require__(2037)); +const path = __importStar(__nccwpck_require__(1017)); +const oidc_utils_1 = __nccwpck_require__(8041); +/** + * The code to exit an action + */ +var ExitCode; +(function (ExitCode) { + /** + * A code indicating that the action was successful + */ + ExitCode[ExitCode["Success"] = 0] = "Success"; + /** + * A code indicating that the action was a failure + */ + ExitCode[ExitCode["Failure"] = 1] = "Failure"; +})(ExitCode = exports.ExitCode || (exports.ExitCode = {})); +//----------------------------------------------------------------------- +// Variables +//----------------------------------------------------------------------- +/** + * Sets env variable for this action and future actions in the job + * @param name the name of the variable to set + * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function exportVariable(name, val) { + const convertedVal = utils_1.toCommandValue(val); + process.env[name] = convertedVal; + const filePath = process.env['GITHUB_ENV'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); + } + command_1.issueCommand('set-env', { name }, convertedVal); +} +exports.exportVariable = exportVariable; +/** + * Registers a secret which will get masked from logs + * @param secret value of the secret + */ +function setSecret(secret) { + command_1.issueCommand('add-mask', {}, secret); +} +exports.setSecret = setSecret; +/** + * Prepends inputPath to the PATH (for this action and future actions) + * @param inputPath + */ +function addPath(inputPath) { + const filePath = process.env['GITHUB_PATH'] || ''; + if (filePath) { + file_command_1.issueFileCommand('PATH', inputPath); + } + else { + command_1.issueCommand('add-path', {}, inputPath); + } + process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; +} +exports.addPath = addPath; +/** + * Gets the value of an input. + * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed. + * Returns an empty string if the value is not defined. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string + */ +function getInput(name, options) { + const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; + if (options && options.required && !val) { + throw new Error(`Input required and not supplied: ${name}`); + } + if (options && options.trimWhitespace === false) { + return val; + } + return val.trim(); +} +exports.getInput = getInput; +/** + * Gets the values of an multiline input. Each value is also trimmed. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string[] + * + */ +function getMultilineInput(name, options) { + const inputs = getInput(name, options) + .split('\n') + .filter(x => x !== ''); + if (options && options.trimWhitespace === false) { + return inputs; + } + return inputs.map(input => input.trim()); +} +exports.getMultilineInput = getMultilineInput; +/** + * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. + * Support boolean input list: `true | True | TRUE | false | False | FALSE` . + * The return value is also in boolean type. + * ref: https://yaml.org/spec/1.2/spec.html#id2804923 + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns boolean + */ +function getBooleanInput(name, options) { + const trueValue = ['true', 'True', 'TRUE']; + const falseValue = ['false', 'False', 'FALSE']; + const val = getInput(name, options); + if (trueValue.includes(val)) + return true; + if (falseValue.includes(val)) + return false; + throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` + + `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); +} +exports.getBooleanInput = getBooleanInput; +/** + * Sets the value of an output. + * + * @param name name of the output to set + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function setOutput(name, value) { + const filePath = process.env['GITHUB_OUTPUT'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value)); + } + process.stdout.write(os.EOL); + command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value)); +} +exports.setOutput = setOutput; +/** + * Enables or disables the echoing of commands into stdout for the rest of the step. + * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. + * + */ +function setCommandEcho(enabled) { + command_1.issue('echo', enabled ? 'on' : 'off'); +} +exports.setCommandEcho = setCommandEcho; +//----------------------------------------------------------------------- +// Results +//----------------------------------------------------------------------- +/** + * Sets the action status to failed. + * When the action exits it will be with an exit code of 1 + * @param message add error issue message + */ +function setFailed(message) { + process.exitCode = ExitCode.Failure; + error(message); +} +exports.setFailed = setFailed; +//----------------------------------------------------------------------- +// Logging Commands +//----------------------------------------------------------------------- +/** + * Gets whether Actions Step Debug is on or not + */ +function isDebug() { + return process.env['RUNNER_DEBUG'] === '1'; +} +exports.isDebug = isDebug; +/** + * Writes debug message to user log + * @param message debug message + */ +function debug(message) { + command_1.issueCommand('debug', {}, message); +} +exports.debug = debug; +/** + * Adds an error issue + * @param message error issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function error(message, properties = {}) { + command_1.issueCommand('error', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.error = error; +/** + * Adds a warning issue + * @param message warning issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function warning(message, properties = {}) { + command_1.issueCommand('warning', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.warning = warning; +/** + * Adds a notice issue + * @param message notice issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function notice(message, properties = {}) { + command_1.issueCommand('notice', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.notice = notice; +/** + * Writes info to log with console.log. + * @param message info message + */ +function info(message) { + process.stdout.write(message + os.EOL); +} +exports.info = info; +/** + * Begin an output group. + * + * Output until the next `groupEnd` will be foldable in this group + * + * @param name The name of the output group + */ +function startGroup(name) { + command_1.issue('group', name); +} +exports.startGroup = startGroup; +/** + * End an output group. + */ +function endGroup() { + command_1.issue('endgroup'); +} +exports.endGroup = endGroup; +/** + * Wrap an asynchronous function call in a group. + * + * Returns the same type as the function itself. + * + * @param name The name of the group + * @param fn The function to wrap in the group + */ +function group(name, fn) { + return __awaiter(this, void 0, void 0, function* () { + startGroup(name); + let result; + try { + result = yield fn(); + } + finally { + endGroup(); + } + return result; + }); +} +exports.group = group; +//----------------------------------------------------------------------- +// Wrapper action state +//----------------------------------------------------------------------- +/** + * Saves state for current action, the state can only be retrieved by this action's post job execution. + * + * @param name name of the state to store + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function saveState(name, value) { + const filePath = process.env['GITHUB_STATE'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value)); + } + command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value)); +} +exports.saveState = saveState; +/** + * Gets the value of an state set by this action's main execution. + * + * @param name name of the state to get + * @returns string + */ +function getState(name) { + return process.env[`STATE_${name}`] || ''; +} +exports.getState = getState; +function getIDToken(aud) { + return __awaiter(this, void 0, void 0, function* () { + return yield oidc_utils_1.OidcClient.getIDToken(aud); + }); +} +exports.getIDToken = getIDToken; +/** + * Summary exports + */ +var summary_1 = __nccwpck_require__(1327); +Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); +/** + * @deprecated use core.summary + */ +var summary_2 = __nccwpck_require__(1327); +Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); +/** + * Path exports + */ +var path_utils_1 = __nccwpck_require__(2981); +Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); +Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); +Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); +//# sourceMappingURL=core.js.map + +/***/ }), + +/***/ 717: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// For internal use, subject to change. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +const fs = __importStar(__nccwpck_require__(7147)); +const os = __importStar(__nccwpck_require__(2037)); +const uuid_1 = __nccwpck_require__(5840); +const utils_1 = __nccwpck_require__(5278); +function issueFileCommand(command, message) { + const filePath = process.env[`GITHUB_${command}`]; + if (!filePath) { + throw new Error(`Unable to find environment variable for file command ${command}`); + } + if (!fs.existsSync(filePath)) { + throw new Error(`Missing file at path: ${filePath}`); + } + fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, { + encoding: 'utf8' + }); +} +exports.issueFileCommand = issueFileCommand; +function prepareKeyValueMessage(key, value) { + const delimiter = `ghadelimiter_${uuid_1.v4()}`; + const convertedValue = utils_1.toCommandValue(value); + // These should realistically never happen, but just in case someone finds a + // way to exploit uuid generation let's not allow keys or values that contain + // the delimiter. + if (key.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedValue.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; +} +exports.prepareKeyValueMessage = prepareKeyValueMessage; +//# sourceMappingURL=file-command.js.map + +/***/ }), + +/***/ 8041: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.OidcClient = void 0; +const http_client_1 = __nccwpck_require__(6255); +const auth_1 = __nccwpck_require__(5526); +const core_1 = __nccwpck_require__(2186); +class OidcClient { + static createHttpClient(allowRetry = true, maxRetry = 10) { + const requestOptions = { + allowRetries: allowRetry, + maxRetries: maxRetry + }; + return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions); + } + static getRequestToken() { + const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN']; + if (!token) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable'); + } + return token; + } + static getIDTokenUrl() { + const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL']; + if (!runtimeUrl) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'); + } + return runtimeUrl; + } + static getCall(id_token_url) { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const httpclient = OidcClient.createHttpClient(); + const res = yield httpclient + .getJson(id_token_url) + .catch(error => { + throw new Error(`Failed to get ID Token. \n + Error Code : ${error.statusCode}\n + Error Message: ${error.message}`); + }); + const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; + if (!id_token) { + throw new Error('Response json body do not have ID Token field'); + } + return id_token; + }); + } + static getIDToken(audience) { + return __awaiter(this, void 0, void 0, function* () { + try { + // New ID Token is requested from action service + let id_token_url = OidcClient.getIDTokenUrl(); + if (audience) { + const encodedAudience = encodeURIComponent(audience); + id_token_url = `${id_token_url}&audience=${encodedAudience}`; + } + core_1.debug(`ID token url is ${id_token_url}`); + const id_token = yield OidcClient.getCall(id_token_url); + core_1.setSecret(id_token); + return id_token; + } + catch (error) { + throw new Error(`Error message: ${error.message}`); + } + }); + } +} +exports.OidcClient = OidcClient; +//# sourceMappingURL=oidc-utils.js.map + +/***/ }), + +/***/ 2981: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; +const path = __importStar(__nccwpck_require__(1017)); +/** + * toPosixPath converts the given path to the posix form. On Windows, \\ will be + * replaced with /. + * + * @param pth. Path to transform. + * @return string Posix path. + */ +function toPosixPath(pth) { + return pth.replace(/[\\]/g, '/'); +} +exports.toPosixPath = toPosixPath; +/** + * toWin32Path converts the given path to the win32 form. On Linux, / will be + * replaced with \\. + * + * @param pth. Path to transform. + * @return string Win32 path. + */ +function toWin32Path(pth) { + return pth.replace(/[/]/g, '\\'); +} +exports.toWin32Path = toWin32Path; +/** + * toPlatformPath converts the given path to a platform-specific path. It does + * this by replacing instances of / and \ with the platform-specific path + * separator. + * + * @param pth The path to platformize. + * @return string The platform-specific path. + */ +function toPlatformPath(pth) { + return pth.replace(/[/\\]/g, path.sep); +} +exports.toPlatformPath = toPlatformPath; +//# sourceMappingURL=path-utils.js.map + +/***/ }), + +/***/ 1327: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; +const os_1 = __nccwpck_require__(2037); +const fs_1 = __nccwpck_require__(7147); +const { access, appendFile, writeFile } = fs_1.promises; +exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; +exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; +class Summary { + constructor() { + this._buffer = ''; + } + /** + * Finds the summary file path from the environment, rejects if env var is not found or file does not exist + * Also checks r/w permissions. + * + * @returns step summary file path + */ + filePath() { + return __awaiter(this, void 0, void 0, function* () { + if (this._filePath) { + return this._filePath; + } + const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR]; + if (!pathFromEnv) { + throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); + } + try { + yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK); + } + catch (_a) { + throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); + } + this._filePath = pathFromEnv; + return this._filePath; + }); + } + /** + * Wraps content in an HTML tag, adding any HTML attributes + * + * @param {string} tag HTML tag to wrap + * @param {string | null} content content within the tag + * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add + * + * @returns {string} content wrapped in HTML element + */ + wrap(tag, content, attrs = {}) { + const htmlAttrs = Object.entries(attrs) + .map(([key, value]) => ` ${key}="${value}"`) + .join(''); + if (!content) { + return `<${tag}${htmlAttrs}>`; + } + return `<${tag}${htmlAttrs}>${content}`; + } + /** + * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. + * + * @param {SummaryWriteOptions} [options] (optional) options for write operation + * + * @returns {Promise} summary instance + */ + write(options) { + return __awaiter(this, void 0, void 0, function* () { + const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); + const filePath = yield this.filePath(); + const writeFunc = overwrite ? writeFile : appendFile; + yield writeFunc(filePath, this._buffer, { encoding: 'utf8' }); + return this.emptyBuffer(); + }); + } + /** + * Clears the summary buffer and wipes the summary file + * + * @returns {Summary} summary instance + */ + clear() { + return __awaiter(this, void 0, void 0, function* () { + return this.emptyBuffer().write({ overwrite: true }); + }); + } + /** + * Returns the current summary buffer as a string + * + * @returns {string} string of summary buffer + */ + stringify() { + return this._buffer; + } + /** + * If the summary buffer is empty + * + * @returns {boolen} true if the buffer is empty + */ + isEmptyBuffer() { + return this._buffer.length === 0; + } + /** + * Resets the summary buffer without writing to summary file + * + * @returns {Summary} summary instance + */ + emptyBuffer() { + this._buffer = ''; + return this; + } + /** + * Adds raw text to the summary buffer + * + * @param {string} text content to add + * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) + * + * @returns {Summary} summary instance + */ + addRaw(text, addEOL = false) { + this._buffer += text; + return addEOL ? this.addEOL() : this; + } + /** + * Adds the operating system-specific end-of-line marker to the buffer + * + * @returns {Summary} summary instance + */ + addEOL() { + return this.addRaw(os_1.EOL); + } + /** + * Adds an HTML codeblock to the summary buffer + * + * @param {string} code content to render within fenced code block + * @param {string} lang (optional) language to syntax highlight code + * + * @returns {Summary} summary instance + */ + addCodeBlock(code, lang) { + const attrs = Object.assign({}, (lang && { lang })); + const element = this.wrap('pre', this.wrap('code', code), attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML list to the summary buffer + * + * @param {string[]} items list of items to render + * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) + * + * @returns {Summary} summary instance + */ + addList(items, ordered = false) { + const tag = ordered ? 'ol' : 'ul'; + const listItems = items.map(item => this.wrap('li', item)).join(''); + const element = this.wrap(tag, listItems); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML table to the summary buffer + * + * @param {SummaryTableCell[]} rows table rows + * + * @returns {Summary} summary instance + */ + addTable(rows) { + const tableBody = rows + .map(row => { + const cells = row + .map(cell => { + if (typeof cell === 'string') { + return this.wrap('td', cell); + } + const { header, data, colspan, rowspan } = cell; + const tag = header ? 'th' : 'td'; + const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan })); + return this.wrap(tag, data, attrs); + }) + .join(''); + return this.wrap('tr', cells); + }) + .join(''); + const element = this.wrap('table', tableBody); + return this.addRaw(element).addEOL(); + } + /** + * Adds a collapsable HTML details element to the summary buffer + * + * @param {string} label text for the closed state + * @param {string} content collapsable content + * + * @returns {Summary} summary instance + */ + addDetails(label, content) { + const element = this.wrap('details', this.wrap('summary', label) + content); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML image tag to the summary buffer + * + * @param {string} src path to the image you to embed + * @param {string} alt text description of the image + * @param {SummaryImageOptions} options (optional) addition image attributes + * + * @returns {Summary} summary instance + */ + addImage(src, alt, options) { + const { width, height } = options || {}; + const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height })); + const element = this.wrap('img', null, Object.assign({ src, alt }, attrs)); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML section heading element + * + * @param {string} text heading text + * @param {number | string} [level=1] (optional) the heading level, default: 1 + * + * @returns {Summary} summary instance + */ + addHeading(text, level) { + const tag = `h${level}`; + const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag) + ? tag + : 'h1'; + const element = this.wrap(allowedTag, text); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML thematic break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addSeparator() { + const element = this.wrap('hr', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML line break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addBreak() { + const element = this.wrap('br', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML blockquote to the summary buffer + * + * @param {string} text quote text + * @param {string} cite (optional) citation url + * + * @returns {Summary} summary instance + */ + addQuote(text, cite) { + const attrs = Object.assign({}, (cite && { cite })); + const element = this.wrap('blockquote', text, attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML anchor tag to the summary buffer + * + * @param {string} text link text/content + * @param {string} href hyperlink + * + * @returns {Summary} summary instance + */ + addLink(text, href) { + const element = this.wrap('a', text, { href }); + return this.addRaw(element).addEOL(); + } +} +const _summary = new Summary(); +/** + * @deprecated use `core.summary` + */ +exports.markdownSummary = _summary; +exports.summary = _summary; +//# sourceMappingURL=summary.js.map + +/***/ }), + +/***/ 5278: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toCommandProperties = exports.toCommandValue = void 0; +/** + * Sanitizes an input into a string so it can be passed into issueCommand safely + * @param input input to sanitize into a string + */ +function toCommandValue(input) { + if (input === null || input === undefined) { + return ''; + } + else if (typeof input === 'string' || input instanceof String) { + return input; + } + return JSON.stringify(input); +} +exports.toCommandValue = toCommandValue; +/** + * + * @param annotationProperties + * @returns The command properties to send with the actual annotation command + * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 + */ +function toCommandProperties(annotationProperties) { + if (!Object.keys(annotationProperties).length) { + return {}; + } + return { + title: annotationProperties.title, + file: annotationProperties.file, + line: annotationProperties.startLine, + endLine: annotationProperties.endLine, + col: annotationProperties.startColumn, + endColumn: annotationProperties.endColumn + }; +} +exports.toCommandProperties = toCommandProperties; +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ 1514: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getExecOutput = exports.exec = void 0; +const string_decoder_1 = __nccwpck_require__(1576); +const tr = __importStar(__nccwpck_require__(8159)); +/** + * Exec a command. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param commandLine command to execute (can include additional args). Must be correctly escaped. + * @param args optional arguments for tool. Escaping is handled by the lib. + * @param options optional exec options. See ExecOptions + * @returns Promise exit code + */ +function exec(commandLine, args, options) { + return __awaiter(this, void 0, void 0, function* () { + const commandArgs = tr.argStringToArray(commandLine); + if (commandArgs.length === 0) { + throw new Error(`Parameter 'commandLine' cannot be null or empty.`); + } + // Path to tool to execute should be first arg + const toolPath = commandArgs[0]; + args = commandArgs.slice(1).concat(args || []); + const runner = new tr.ToolRunner(toolPath, args, options); + return runner.exec(); + }); +} +exports.exec = exec; +/** + * Exec a command and get the output. + * Output will be streamed to the live console. + * Returns promise with the exit code and collected stdout and stderr + * + * @param commandLine command to execute (can include additional args). Must be correctly escaped. + * @param args optional arguments for tool. Escaping is handled by the lib. + * @param options optional exec options. See ExecOptions + * @returns Promise exit code, stdout, and stderr + */ +function getExecOutput(commandLine, args, options) { + var _a, _b; + return __awaiter(this, void 0, void 0, function* () { + let stdout = ''; + let stderr = ''; + //Using string decoder covers the case where a mult-byte character is split + const stdoutDecoder = new string_decoder_1.StringDecoder('utf8'); + const stderrDecoder = new string_decoder_1.StringDecoder('utf8'); + const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout; + const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr; + const stdErrListener = (data) => { + stderr += stderrDecoder.write(data); + if (originalStdErrListener) { + originalStdErrListener(data); + } + }; + const stdOutListener = (data) => { + stdout += stdoutDecoder.write(data); + if (originalStdoutListener) { + originalStdoutListener(data); + } + }; + const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener }); + const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners })); + //flush any remaining characters + stdout += stdoutDecoder.end(); + stderr += stderrDecoder.end(); + return { + exitCode, + stdout, + stderr + }; + }); +} +exports.getExecOutput = getExecOutput; +//# sourceMappingURL=exec.js.map + +/***/ }), + +/***/ 8159: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.argStringToArray = exports.ToolRunner = void 0; +const os = __importStar(__nccwpck_require__(2037)); +const events = __importStar(__nccwpck_require__(2361)); +const child = __importStar(__nccwpck_require__(2081)); +const path = __importStar(__nccwpck_require__(1017)); +const io = __importStar(__nccwpck_require__(7351)); +const ioUtil = __importStar(__nccwpck_require__(1962)); +const timers_1 = __nccwpck_require__(9512); +/* eslint-disable @typescript-eslint/unbound-method */ +const IS_WINDOWS = process.platform === 'win32'; +/* + * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. + */ +class ToolRunner extends events.EventEmitter { + constructor(toolPath, args, options) { + super(); + if (!toolPath) { + throw new Error("Parameter 'toolPath' cannot be null or empty."); + } + this.toolPath = toolPath; + this.args = args || []; + this.options = options || {}; + } + _debug(message) { + if (this.options.listeners && this.options.listeners.debug) { + this.options.listeners.debug(message); + } + } + _getCommandString(options, noPrefix) { + const toolPath = this._getSpawnFileName(); + const args = this._getSpawnArgs(options); + let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool + if (IS_WINDOWS) { + // Windows + cmd file + if (this._isCmdFile()) { + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } + // Windows + verbatim + else if (options.windowsVerbatimArguments) { + cmd += `"${toolPath}"`; + for (const a of args) { + cmd += ` ${a}`; + } + } + // Windows (regular) + else { + cmd += this._windowsQuoteCmdArg(toolPath); + for (const a of args) { + cmd += ` ${this._windowsQuoteCmdArg(a)}`; + } + } + } + else { + // OSX/Linux - this can likely be improved with some form of quoting. + // creating processes on Unix is fundamentally different than Windows. + // on Unix, execvp() takes an arg array. + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } + return cmd; + } + _processLineBuffer(data, strBuffer, onLine) { + try { + let s = strBuffer + data.toString(); + let n = s.indexOf(os.EOL); + while (n > -1) { + const line = s.substring(0, n); + onLine(line); + // the rest of the string ... + s = s.substring(n + os.EOL.length); + n = s.indexOf(os.EOL); + } + return s; + } + catch (err) { + // streaming lines to console is best effort. Don't fail a build. + this._debug(`error processing line. Failed with error ${err}`); + return ''; + } + } + _getSpawnFileName() { + if (IS_WINDOWS) { + if (this._isCmdFile()) { + return process.env['COMSPEC'] || 'cmd.exe'; + } + } + return this.toolPath; + } + _getSpawnArgs(options) { + if (IS_WINDOWS) { + if (this._isCmdFile()) { + let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; + for (const a of this.args) { + argline += ' '; + argline += options.windowsVerbatimArguments + ? a + : this._windowsQuoteCmdArg(a); + } + argline += '"'; + return [argline]; + } + } + return this.args; + } + _endsWith(str, end) { + return str.endsWith(end); + } + _isCmdFile() { + const upperToolPath = this.toolPath.toUpperCase(); + return (this._endsWith(upperToolPath, '.CMD') || + this._endsWith(upperToolPath, '.BAT')); + } + _windowsQuoteCmdArg(arg) { + // for .exe, apply the normal quoting rules that libuv applies + if (!this._isCmdFile()) { + return this._uvQuoteCmdArg(arg); + } + // otherwise apply quoting rules specific to the cmd.exe command line parser. + // the libuv rules are generic and are not designed specifically for cmd.exe + // command line parser. + // + // for a detailed description of the cmd.exe command line parser, refer to + // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 + // need quotes for empty arg + if (!arg) { + return '""'; + } + // determine whether the arg needs to be quoted + const cmdSpecialChars = [ + ' ', + '\t', + '&', + '(', + ')', + '[', + ']', + '{', + '}', + '^', + '=', + ';', + '!', + "'", + '+', + ',', + '`', + '~', + '|', + '<', + '>', + '"' + ]; + let needsQuotes = false; + for (const char of arg) { + if (cmdSpecialChars.some(x => x === char)) { + needsQuotes = true; + break; + } + } + // short-circuit if quotes not needed + if (!needsQuotes) { + return arg; + } + // the following quoting rules are very similar to the rules that by libuv applies. + // + // 1) wrap the string in quotes + // + // 2) double-up quotes - i.e. " => "" + // + // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately + // doesn't work well with a cmd.exe command line. + // + // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. + // for example, the command line: + // foo.exe "myarg:""my val""" + // is parsed by a .NET console app into an arg array: + // [ "myarg:\"my val\"" ] + // which is the same end result when applying libuv quoting rules. although the actual + // command line from libuv quoting rules would look like: + // foo.exe "myarg:\"my val\"" + // + // 3) double-up slashes that precede a quote, + // e.g. hello \world => "hello \world" + // hello\"world => "hello\\""world" + // hello\\"world => "hello\\\\""world" + // hello world\ => "hello world\\" + // + // technically this is not required for a cmd.exe command line, or the batch argument parser. + // the reasons for including this as a .cmd quoting rule are: + // + // a) this is optimized for the scenario where the argument is passed from the .cmd file to an + // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. + // + // b) it's what we've been doing previously (by deferring to node default behavior) and we + // haven't heard any complaints about that aspect. + // + // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be + // escaped when used on the command line directly - even though within a .cmd file % can be escaped + // by using %%. + // + // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts + // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. + // + // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would + // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the + // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args + // to an external program. + // + // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. + // % can be escaped within a .cmd file. + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + // walk the string in reverse + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === '\\') { + reverse += '\\'; // double the slash + } + else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '"'; // double the quote + } + else { + quoteHit = false; + } + } + reverse += '"'; + return reverse + .split('') + .reverse() + .join(''); + } + _uvQuoteCmdArg(arg) { + // Tool runner wraps child_process.spawn() and needs to apply the same quoting as + // Node in certain cases where the undocumented spawn option windowsVerbatimArguments + // is used. + // + // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, + // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), + // pasting copyright notice from Node within this function: + // + // Copyright Joyent, Inc. and other Node contributors. All rights reserved. + // + // Permission is hereby granted, free of charge, to any person obtaining a copy + // of this software and associated documentation files (the "Software"), to + // deal in the Software without restriction, including without limitation the + // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + // sell copies of the Software, and to permit persons to whom the Software is + // furnished to do so, subject to the following conditions: + // + // The above copyright notice and this permission notice shall be included in + // all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + // IN THE SOFTWARE. + if (!arg) { + // Need double quotation for empty argument + return '""'; + } + if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { + // No quotation needed + return arg; + } + if (!arg.includes('"') && !arg.includes('\\')) { + // No embedded double quotes or backslashes, so I can just wrap + // quote marks around the whole thing. + return `"${arg}"`; + } + // Expected input/output: + // input : hello"world + // output: "hello\"world" + // input : hello""world + // output: "hello\"\"world" + // input : hello\world + // output: hello\world + // input : hello\\world + // output: hello\\world + // input : hello\"world + // output: "hello\\\"world" + // input : hello\\"world + // output: "hello\\\\\"world" + // input : hello world\ + // output: "hello world\\" - note the comment in libuv actually reads "hello world\" + // but it appears the comment is wrong, it should be "hello world\\" + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + // walk the string in reverse + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === '\\') { + reverse += '\\'; + } + else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '\\'; + } + else { + quoteHit = false; + } + } + reverse += '"'; + return reverse + .split('') + .reverse() + .join(''); + } + _cloneExecOptions(options) { + options = options || {}; + const result = { + cwd: options.cwd || process.cwd(), + env: options.env || process.env, + silent: options.silent || false, + windowsVerbatimArguments: options.windowsVerbatimArguments || false, + failOnStdErr: options.failOnStdErr || false, + ignoreReturnCode: options.ignoreReturnCode || false, + delay: options.delay || 10000 + }; + result.outStream = options.outStream || process.stdout; + result.errStream = options.errStream || process.stderr; + return result; + } + _getSpawnOptions(options, toolPath) { + options = options || {}; + const result = {}; + result.cwd = options.cwd; + result.env = options.env; + result['windowsVerbatimArguments'] = + options.windowsVerbatimArguments || this._isCmdFile(); + if (options.windowsVerbatimArguments) { + result.argv0 = `"${toolPath}"`; + } + return result; + } + /** + * Exec a tool. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param tool path to tool to exec + * @param options optional exec options. See ExecOptions + * @returns number + */ + exec() { + return __awaiter(this, void 0, void 0, function* () { + // root the tool path if it is unrooted and contains relative pathing + if (!ioUtil.isRooted(this.toolPath) && + (this.toolPath.includes('/') || + (IS_WINDOWS && this.toolPath.includes('\\')))) { + // prefer options.cwd if it is specified, however options.cwd may also need to be rooted + this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); + } + // if the tool is only a file name, then resolve it from the PATH + // otherwise verify it exists (add extension on Windows if necessary) + this.toolPath = yield io.which(this.toolPath, true); + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + this._debug(`exec tool: ${this.toolPath}`); + this._debug('arguments:'); + for (const arg of this.args) { + this._debug(` ${arg}`); + } + const optionsNonNull = this._cloneExecOptions(this.options); + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); + } + const state = new ExecState(optionsNonNull, this.toolPath); + state.on('debug', (message) => { + this._debug(message); + }); + if (this.options.cwd && !(yield ioUtil.exists(this.options.cwd))) { + return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`)); + } + const fileName = this._getSpawnFileName(); + const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); + let stdbuffer = ''; + if (cp.stdout) { + cp.stdout.on('data', (data) => { + if (this.options.listeners && this.options.listeners.stdout) { + this.options.listeners.stdout(data); + } + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(data); + } + stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => { + if (this.options.listeners && this.options.listeners.stdline) { + this.options.listeners.stdline(line); + } + }); + }); + } + let errbuffer = ''; + if (cp.stderr) { + cp.stderr.on('data', (data) => { + state.processStderr = true; + if (this.options.listeners && this.options.listeners.stderr) { + this.options.listeners.stderr(data); + } + if (!optionsNonNull.silent && + optionsNonNull.errStream && + optionsNonNull.outStream) { + const s = optionsNonNull.failOnStdErr + ? optionsNonNull.errStream + : optionsNonNull.outStream; + s.write(data); + } + errbuffer = this._processLineBuffer(data, errbuffer, (line) => { + if (this.options.listeners && this.options.listeners.errline) { + this.options.listeners.errline(line); + } + }); + }); + } + cp.on('error', (err) => { + state.processError = err.message; + state.processExited = true; + state.processClosed = true; + state.CheckComplete(); + }); + cp.on('exit', (code) => { + state.processExitCode = code; + state.processExited = true; + this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); + state.CheckComplete(); + }); + cp.on('close', (code) => { + state.processExitCode = code; + state.processExited = true; + state.processClosed = true; + this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); + state.CheckComplete(); + }); + state.on('done', (error, exitCode) => { + if (stdbuffer.length > 0) { + this.emit('stdline', stdbuffer); + } + if (errbuffer.length > 0) { + this.emit('errline', errbuffer); + } + cp.removeAllListeners(); + if (error) { + reject(error); + } + else { + resolve(exitCode); + } + }); + if (this.options.input) { + if (!cp.stdin) { + throw new Error('child process missing stdin'); + } + cp.stdin.end(this.options.input); + } + })); + }); + } +} +exports.ToolRunner = ToolRunner; +/** + * Convert an arg string to an array of args. Handles escaping + * + * @param argString string of arguments + * @returns string[] array of arguments + */ +function argStringToArray(argString) { + const args = []; + let inQuotes = false; + let escaped = false; + let arg = ''; + function append(c) { + // we only escape double quotes. + if (escaped && c !== '"') { + arg += '\\'; + } + arg += c; + escaped = false; + } + for (let i = 0; i < argString.length; i++) { + const c = argString.charAt(i); + if (c === '"') { + if (!escaped) { + inQuotes = !inQuotes; + } + else { + append(c); + } + continue; + } + if (c === '\\' && escaped) { + append(c); + continue; + } + if (c === '\\' && inQuotes) { + escaped = true; + continue; + } + if (c === ' ' && !inQuotes) { + if (arg.length > 0) { + args.push(arg); + arg = ''; + } + continue; + } + append(c); + } + if (arg.length > 0) { + args.push(arg.trim()); + } + return args; +} +exports.argStringToArray = argStringToArray; +class ExecState extends events.EventEmitter { + constructor(options, toolPath) { + super(); + this.processClosed = false; // tracks whether the process has exited and stdio is closed + this.processError = ''; + this.processExitCode = 0; + this.processExited = false; // tracks whether the process has exited + this.processStderr = false; // tracks whether stderr was written to + this.delay = 10000; // 10 seconds + this.done = false; + this.timeout = null; + if (!toolPath) { + throw new Error('toolPath must not be empty'); + } + this.options = options; + this.toolPath = toolPath; + if (options.delay) { + this.delay = options.delay; + } + } + CheckComplete() { + if (this.done) { + return; + } + if (this.processClosed) { + this._setResult(); + } + else if (this.processExited) { + this.timeout = timers_1.setTimeout(ExecState.HandleTimeout, this.delay, this); + } + } + _debug(message) { + this.emit('debug', message); + } + _setResult() { + // determine whether there is an error + let error; + if (this.processExited) { + if (this.processError) { + error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); + } + else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { + error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); + } + else if (this.processStderr && this.options.failOnStdErr) { + error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); + } + } + // clear the timeout + if (this.timeout) { + clearTimeout(this.timeout); + this.timeout = null; + } + this.done = true; + this.emit('done', error, this.processExitCode); + } + static HandleTimeout(state) { + if (state.done) { + return; + } + if (!state.processClosed && state.processExited) { + const message = `The STDIO streams did not close within ${state.delay / + 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; + state._debug(message); + } + state._setResult(); + } +} +//# sourceMappingURL=toolrunner.js.map + +/***/ }), + +/***/ 5526: +/***/ (function(__unused_webpack_module, exports) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0; +class BasicCredentialHandler { + constructor(username, password) { + this.username = username; + this.password = password; + } + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BasicCredentialHandler = BasicCredentialHandler; +class BearerCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Bearer ${this.token}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BearerCredentialHandler = BearerCredentialHandler; +class PersonalAccessTokenCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler; +//# sourceMappingURL=auth.js.map + +/***/ }), + +/***/ 6255: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/* eslint-disable @typescript-eslint/no-explicit-any */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; +const http = __importStar(__nccwpck_require__(3685)); +const https = __importStar(__nccwpck_require__(5687)); +const pm = __importStar(__nccwpck_require__(9835)); +const tunnel = __importStar(__nccwpck_require__(4294)); +var HttpCodes; +(function (HttpCodes) { + HttpCodes[HttpCodes["OK"] = 200] = "OK"; + HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; + HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; + HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; + HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; + HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; + HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; + HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; + HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; + HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; + HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; + HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; + HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; + HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; + HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; + HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; + HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; + HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; + HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; + HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; + HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; + HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests"; + HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; + HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; + HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; + HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; + HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; +})(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {})); +var Headers; +(function (Headers) { + Headers["Accept"] = "accept"; + Headers["ContentType"] = "content-type"; +})(Headers = exports.Headers || (exports.Headers = {})); +var MediaTypes; +(function (MediaTypes) { + MediaTypes["ApplicationJson"] = "application/json"; +})(MediaTypes = exports.MediaTypes || (exports.MediaTypes = {})); +/** + * Returns the proxy URL, depending upon the supplied url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ +function getProxyUrl(serverUrl) { + const proxyUrl = pm.getProxyUrl(new URL(serverUrl)); + return proxyUrl ? proxyUrl.href : ''; +} +exports.getProxyUrl = getProxyUrl; +const HttpRedirectCodes = [ + HttpCodes.MovedPermanently, + HttpCodes.ResourceMoved, + HttpCodes.SeeOther, + HttpCodes.TemporaryRedirect, + HttpCodes.PermanentRedirect +]; +const HttpResponseRetryCodes = [ + HttpCodes.BadGateway, + HttpCodes.ServiceUnavailable, + HttpCodes.GatewayTimeout +]; +const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; +const ExponentialBackoffCeiling = 10; +const ExponentialBackoffTimeSlice = 5; +class HttpClientError extends Error { + constructor(message, statusCode) { + super(message); + this.name = 'HttpClientError'; + this.statusCode = statusCode; + Object.setPrototypeOf(this, HttpClientError.prototype); + } +} +exports.HttpClientError = HttpClientError; +class HttpClientResponse { + constructor(message) { + this.message = message; + } + readBody() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + let output = Buffer.alloc(0); + this.message.on('data', (chunk) => { + output = Buffer.concat([output, chunk]); + }); + this.message.on('end', () => { + resolve(output.toString()); + }); + })); + }); + } +} +exports.HttpClientResponse = HttpClientResponse; +function isHttps(requestUrl) { + const parsedUrl = new URL(requestUrl); + return parsedUrl.protocol === 'https:'; +} +exports.isHttps = isHttps; +class HttpClient { + constructor(userAgent, handlers, requestOptions) { + this._ignoreSslError = false; + this._allowRedirects = true; + this._allowRedirectDowngrade = false; + this._maxRedirects = 50; + this._allowRetries = false; + this._maxRetries = 1; + this._keepAlive = false; + this._disposed = false; + this.userAgent = userAgent; + this.handlers = handlers || []; + this.requestOptions = requestOptions; + if (requestOptions) { + if (requestOptions.ignoreSslError != null) { + this._ignoreSslError = requestOptions.ignoreSslError; + } + this._socketTimeout = requestOptions.socketTimeout; + if (requestOptions.allowRedirects != null) { + this._allowRedirects = requestOptions.allowRedirects; + } + if (requestOptions.allowRedirectDowngrade != null) { + this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; + } + if (requestOptions.maxRedirects != null) { + this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); + } + if (requestOptions.keepAlive != null) { + this._keepAlive = requestOptions.keepAlive; + } + if (requestOptions.allowRetries != null) { + this._allowRetries = requestOptions.allowRetries; + } + if (requestOptions.maxRetries != null) { + this._maxRetries = requestOptions.maxRetries; + } + } + } + options(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); + }); + } + get(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('GET', requestUrl, null, additionalHeaders || {}); + }); + } + del(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('DELETE', requestUrl, null, additionalHeaders || {}); + }); + } + post(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('POST', requestUrl, data, additionalHeaders || {}); + }); + } + patch(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PATCH', requestUrl, data, additionalHeaders || {}); + }); + } + put(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PUT', requestUrl, data, additionalHeaders || {}); + }); + } + head(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('HEAD', requestUrl, null, additionalHeaders || {}); + }); + } + sendStream(verb, requestUrl, stream, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request(verb, requestUrl, stream, additionalHeaders); + }); + } + /** + * Gets a typed object from an endpoint + * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise + */ + getJson(requestUrl, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + const res = yield this.get(requestUrl, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + postJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.post(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + putJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.put(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + patchJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.patch(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + /** + * Makes a raw http request. + * All other methods such as get, post, patch, and request ultimately call this. + * Prefer get, del, post and patch + */ + request(verb, requestUrl, data, headers) { + return __awaiter(this, void 0, void 0, function* () { + if (this._disposed) { + throw new Error('Client has already been disposed.'); + } + const parsedUrl = new URL(requestUrl); + let info = this._prepareRequest(verb, parsedUrl, headers); + // Only perform retries on reads since writes may not be idempotent. + const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) + ? this._maxRetries + 1 + : 1; + let numTries = 0; + let response; + do { + response = yield this.requestRaw(info, data); + // Check if it's an authentication challenge + if (response && + response.message && + response.message.statusCode === HttpCodes.Unauthorized) { + let authenticationHandler; + for (const handler of this.handlers) { + if (handler.canHandleAuthentication(response)) { + authenticationHandler = handler; + break; + } + } + if (authenticationHandler) { + return authenticationHandler.handleAuthentication(this, info, data); + } + else { + // We have received an unauthorized response but have no handlers to handle it. + // Let the response return to the caller. + return response; + } + } + let redirectsRemaining = this._maxRedirects; + while (response.message.statusCode && + HttpRedirectCodes.includes(response.message.statusCode) && + this._allowRedirects && + redirectsRemaining > 0) { + const redirectUrl = response.message.headers['location']; + if (!redirectUrl) { + // if there's no location to redirect to, we won't + break; + } + const parsedRedirectUrl = new URL(redirectUrl); + if (parsedUrl.protocol === 'https:' && + parsedUrl.protocol !== parsedRedirectUrl.protocol && + !this._allowRedirectDowngrade) { + throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.'); + } + // we need to finish reading the response before reassigning response + // which will leak the open socket. + yield response.readBody(); + // strip authorization header if redirected to a different hostname + if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { + for (const header in headers) { + // header names are case insensitive + if (header.toLowerCase() === 'authorization') { + delete headers[header]; + } + } + } + // let's make the request with the new redirectUrl + info = this._prepareRequest(verb, parsedRedirectUrl, headers); + response = yield this.requestRaw(info, data); + redirectsRemaining--; + } + if (!response.message.statusCode || + !HttpResponseRetryCodes.includes(response.message.statusCode)) { + // If not a retry code, return immediately instead of retrying + return response; + } + numTries += 1; + if (numTries < maxTries) { + yield response.readBody(); + yield this._performExponentialBackoff(numTries); + } + } while (numTries < maxTries); + return response; + }); + } + /** + * Needs to be called if keepAlive is set to true in request options. + */ + dispose() { + if (this._agent) { + this._agent.destroy(); + } + this._disposed = true; + } + /** + * Raw request. + * @param info + * @param data + */ + requestRaw(info, data) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + function callbackForResult(err, res) { + if (err) { + reject(err); + } + else if (!res) { + // If `err` is not passed, then `res` must be passed. + reject(new Error('Unknown error')); + } + else { + resolve(res); + } + } + this.requestRawWithCallback(info, data, callbackForResult); + }); + }); + } + /** + * Raw request with callback. + * @param info + * @param data + * @param onResult + */ + requestRawWithCallback(info, data, onResult) { + if (typeof data === 'string') { + if (!info.options.headers) { + info.options.headers = {}; + } + info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8'); + } + let callbackCalled = false; + function handleResult(err, res) { + if (!callbackCalled) { + callbackCalled = true; + onResult(err, res); + } + } + const req = info.httpModule.request(info.options, (msg) => { + const res = new HttpClientResponse(msg); + handleResult(undefined, res); + }); + let socket; + req.on('socket', sock => { + socket = sock; + }); + // If we ever get disconnected, we want the socket to timeout eventually + req.setTimeout(this._socketTimeout || 3 * 60000, () => { + if (socket) { + socket.end(); + } + handleResult(new Error(`Request timeout: ${info.options.path}`)); + }); + req.on('error', function (err) { + // err has statusCode property + // res should have headers + handleResult(err); + }); + if (data && typeof data === 'string') { + req.write(data, 'utf8'); + } + if (data && typeof data !== 'string') { + data.on('close', function () { + req.end(); + }); + data.pipe(req); + } + else { + req.end(); + } + } + /** + * Gets an http agent. This function is useful when you need an http agent that handles + * routing through a proxy server - depending upon the url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ + getAgent(serverUrl) { + const parsedUrl = new URL(serverUrl); + return this._getAgent(parsedUrl); + } + _prepareRequest(method, requestUrl, headers) { + const info = {}; + info.parsedUrl = requestUrl; + const usingSsl = info.parsedUrl.protocol === 'https:'; + info.httpModule = usingSsl ? https : http; + const defaultPort = usingSsl ? 443 : 80; + info.options = {}; + info.options.host = info.parsedUrl.hostname; + info.options.port = info.parsedUrl.port + ? parseInt(info.parsedUrl.port) + : defaultPort; + info.options.path = + (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); + info.options.method = method; + info.options.headers = this._mergeHeaders(headers); + if (this.userAgent != null) { + info.options.headers['user-agent'] = this.userAgent; + } + info.options.agent = this._getAgent(info.parsedUrl); + // gives handlers an opportunity to participate + if (this.handlers) { + for (const handler of this.handlers) { + handler.prepareRequest(info.options); + } + } + return info; + } + _mergeHeaders(headers) { + if (this.requestOptions && this.requestOptions.headers) { + return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {})); + } + return lowercaseKeys(headers || {}); + } + _getExistingOrDefaultHeader(additionalHeaders, header, _default) { + let clientHeader; + if (this.requestOptions && this.requestOptions.headers) { + clientHeader = lowercaseKeys(this.requestOptions.headers)[header]; + } + return additionalHeaders[header] || clientHeader || _default; + } + _getAgent(parsedUrl) { + let agent; + const proxyUrl = pm.getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (this._keepAlive && useProxy) { + agent = this._proxyAgent; + } + if (this._keepAlive && !useProxy) { + agent = this._agent; + } + // if agent is already assigned use that agent. + if (agent) { + return agent; + } + const usingSsl = parsedUrl.protocol === 'https:'; + let maxSockets = 100; + if (this.requestOptions) { + maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; + } + // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis. + if (proxyUrl && proxyUrl.hostname) { + const agentOptions = { + maxSockets, + keepAlive: this._keepAlive, + proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && { + proxyAuth: `${proxyUrl.username}:${proxyUrl.password}` + })), { host: proxyUrl.hostname, port: proxyUrl.port }) + }; + let tunnelAgent; + const overHttps = proxyUrl.protocol === 'https:'; + if (usingSsl) { + tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; + } + else { + tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; + } + agent = tunnelAgent(agentOptions); + this._proxyAgent = agent; + } + // if reusing agent across request and tunneling agent isn't assigned create a new agent + if (this._keepAlive && !agent) { + const options = { keepAlive: this._keepAlive, maxSockets }; + agent = usingSsl ? new https.Agent(options) : new http.Agent(options); + this._agent = agent; + } + // if not using private agent and tunnel agent isn't setup then use global agent + if (!agent) { + agent = usingSsl ? https.globalAgent : http.globalAgent; + } + if (usingSsl && this._ignoreSslError) { + // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process + // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options + // we have to cast it to any and change it directly + agent.options = Object.assign(agent.options || {}, { + rejectUnauthorized: false + }); + } + return agent; + } + _performExponentialBackoff(retryNumber) { + return __awaiter(this, void 0, void 0, function* () { + retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); + const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); + return new Promise(resolve => setTimeout(() => resolve(), ms)); + }); + } + _processResponse(res, options) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + const statusCode = res.message.statusCode || 0; + const response = { + statusCode, + result: null, + headers: {} + }; + // not found leads to null obj returned + if (statusCode === HttpCodes.NotFound) { + resolve(response); + } + // get the result from the body + function dateTimeDeserializer(key, value) { + if (typeof value === 'string') { + const a = new Date(value); + if (!isNaN(a.valueOf())) { + return a; + } + } + return value; + } + let obj; + let contents; + try { + contents = yield res.readBody(); + if (contents && contents.length > 0) { + if (options && options.deserializeDates) { + obj = JSON.parse(contents, dateTimeDeserializer); + } + else { + obj = JSON.parse(contents); + } + response.result = obj; + } + response.headers = res.message.headers; + } + catch (err) { + // Invalid resource (contents not json); leaving result obj null + } + // note that 3xx redirects are handled by the http layer. + if (statusCode > 299) { + let msg; + // if exception/error in body, attempt to get better error + if (obj && obj.message) { + msg = obj.message; + } + else if (contents && contents.length > 0) { + // it may be the case that the exception is in the body message as string + msg = contents; + } + else { + msg = `Failed request: (${statusCode})`; + } + const err = new HttpClientError(msg, statusCode); + err.result = response.result; + reject(err); + } + else { + resolve(response); + } + })); + }); + } +} +exports.HttpClient = HttpClient; +const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 9835: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.checkBypass = exports.getProxyUrl = void 0; +function getProxyUrl(reqUrl) { + const usingSsl = reqUrl.protocol === 'https:'; + if (checkBypass(reqUrl)) { + return undefined; + } + const proxyVar = (() => { + if (usingSsl) { + return process.env['https_proxy'] || process.env['HTTPS_PROXY']; + } + else { + return process.env['http_proxy'] || process.env['HTTP_PROXY']; + } + })(); + if (proxyVar) { + return new URL(proxyVar); + } + else { + return undefined; + } +} +exports.getProxyUrl = getProxyUrl; +function checkBypass(reqUrl) { + if (!reqUrl.hostname) { + return false; + } + const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; + if (!noProxy) { + return false; + } + // Determine the request port + let reqPort; + if (reqUrl.port) { + reqPort = Number(reqUrl.port); + } + else if (reqUrl.protocol === 'http:') { + reqPort = 80; + } + else if (reqUrl.protocol === 'https:') { + reqPort = 443; + } + // Format the request hostname and hostname with port + const upperReqHosts = [reqUrl.hostname.toUpperCase()]; + if (typeof reqPort === 'number') { + upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); + } + // Compare request host against noproxy + for (const upperNoProxyItem of noProxy + .split(',') + .map(x => x.trim().toUpperCase()) + .filter(x => x)) { + if (upperReqHosts.some(x => x === upperNoProxyItem)) { + return true; + } + } + return false; +} +exports.checkBypass = checkBypass; +//# sourceMappingURL=proxy.js.map + +/***/ }), + +/***/ 1962: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.READONLY = exports.UV_FS_O_EXLOCK = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rm = exports.rename = exports.readlink = exports.readdir = exports.open = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0; +const fs = __importStar(__nccwpck_require__(7147)); +const path = __importStar(__nccwpck_require__(1017)); +_a = fs.promises +// export const {open} = 'fs' +, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.open = _a.open, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rm = _a.rm, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; +// export const {open} = 'fs' +exports.IS_WINDOWS = process.platform === 'win32'; +// See https://github.com/nodejs/node/blob/d0153aee367422d0858105abec186da4dff0a0c5/deps/uv/include/uv/win.h#L691 +exports.UV_FS_O_EXLOCK = 0x10000000; +exports.READONLY = fs.constants.O_RDONLY; +function exists(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + try { + yield exports.stat(fsPath); + } + catch (err) { + if (err.code === 'ENOENT') { + return false; + } + throw err; + } + return true; + }); +} +exports.exists = exists; +function isDirectory(fsPath, useStat = false) { + return __awaiter(this, void 0, void 0, function* () { + const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); + return stats.isDirectory(); + }); +} +exports.isDirectory = isDirectory; +/** + * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: + * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). + */ +function isRooted(p) { + p = normalizeSeparators(p); + if (!p) { + throw new Error('isRooted() parameter "p" cannot be empty'); + } + if (exports.IS_WINDOWS) { + return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello + ); // e.g. C: or C:\hello + } + return p.startsWith('/'); +} +exports.isRooted = isRooted; +/** + * Best effort attempt to determine whether a file exists and is executable. + * @param filePath file path to check + * @param extensions additional file extensions to try + * @return if file exists and is executable, returns the file path. otherwise empty string. + */ +function tryGetExecutablePath(filePath, extensions) { + return __awaiter(this, void 0, void 0, function* () { + let stats = undefined; + try { + // test file exists + stats = yield exports.stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports.IS_WINDOWS) { + // on Windows, test for valid extension + const upperExt = path.extname(filePath).toUpperCase(); + if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { + return filePath; + } + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + // try each extension + const originalFilePath = filePath; + for (const extension of extensions) { + filePath = originalFilePath + extension; + stats = undefined; + try { + stats = yield exports.stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports.IS_WINDOWS) { + // preserve the case of the actual file (since an extension was appended) + try { + const directory = path.dirname(filePath); + const upperName = path.basename(filePath).toUpperCase(); + for (const actualName of yield exports.readdir(directory)) { + if (upperName === actualName.toUpperCase()) { + filePath = path.join(directory, actualName); + break; + } + } + } + catch (err) { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); + } + return filePath; + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + } + return ''; + }); +} +exports.tryGetExecutablePath = tryGetExecutablePath; +function normalizeSeparators(p) { + p = p || ''; + if (exports.IS_WINDOWS) { + // convert slashes on Windows + p = p.replace(/\//g, '\\'); + // remove redundant slashes + return p.replace(/\\\\+/g, '\\'); + } + // remove redundant slashes + return p.replace(/\/\/+/g, '/'); +} +// on Mac/Linux, test the execute bit +// R W X R W X R W X +// 256 128 64 32 16 8 4 2 1 +function isUnixExecutable(stats) { + return ((stats.mode & 1) > 0 || + ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || + ((stats.mode & 64) > 0 && stats.uid === process.getuid())); +} +// Get the path of cmd.exe in windows +function getCmdPath() { + var _a; + return (_a = process.env['COMSPEC']) !== null && _a !== void 0 ? _a : `cmd.exe`; +} +exports.getCmdPath = getCmdPath; +//# sourceMappingURL=io-util.js.map + +/***/ }), + +/***/ 7351: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0; +const assert_1 = __nccwpck_require__(9491); +const path = __importStar(__nccwpck_require__(1017)); +const ioUtil = __importStar(__nccwpck_require__(1962)); +/** + * Copies a file or folder. + * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js + * + * @param source source path + * @param dest destination path + * @param options optional. See CopyOptions. + */ +function cp(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + const { force, recursive, copySourceDirectory } = readCopyOptions(options); + const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; + // Dest is an existing file, but not forcing + if (destStat && destStat.isFile() && !force) { + return; + } + // If dest is an existing directory, should copy inside. + const newDest = destStat && destStat.isDirectory() && copySourceDirectory + ? path.join(dest, path.basename(source)) + : dest; + if (!(yield ioUtil.exists(source))) { + throw new Error(`no such file or directory: ${source}`); + } + const sourceStat = yield ioUtil.stat(source); + if (sourceStat.isDirectory()) { + if (!recursive) { + throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); + } + else { + yield cpDirRecursive(source, newDest, 0, force); + } + } + else { + if (path.relative(source, newDest) === '') { + // a file cannot be copied to itself + throw new Error(`'${newDest}' and '${source}' are the same file`); + } + yield copyFile(source, newDest, force); + } + }); +} +exports.cp = cp; +/** + * Moves a path. + * + * @param source source path + * @param dest destination path + * @param options optional. See MoveOptions. + */ +function mv(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + if (yield ioUtil.exists(dest)) { + let destExists = true; + if (yield ioUtil.isDirectory(dest)) { + // If dest is directory copy src into dest + dest = path.join(dest, path.basename(source)); + destExists = yield ioUtil.exists(dest); + } + if (destExists) { + if (options.force == null || options.force) { + yield rmRF(dest); + } + else { + throw new Error('Destination already exists'); + } + } + } + yield mkdirP(path.dirname(dest)); + yield ioUtil.rename(source, dest); + }); +} +exports.mv = mv; +/** + * Remove a path recursively with force + * + * @param inputPath path to remove + */ +function rmRF(inputPath) { + return __awaiter(this, void 0, void 0, function* () { + if (ioUtil.IS_WINDOWS) { + // Check for invalid characters + // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file + if (/[*"<>|]/.test(inputPath)) { + throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'); + } + } + try { + // note if path does not exist, error is silent + yield ioUtil.rm(inputPath, { + force: true, + maxRetries: 3, + recursive: true, + retryDelay: 300 + }); + } + catch (err) { + throw new Error(`File was unable to be removed ${err}`); + } + }); +} +exports.rmRF = rmRF; +/** + * Make a directory. Creates the full path with folders in between + * Will throw if it fails + * + * @param fsPath path to create + * @returns Promise + */ +function mkdirP(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + assert_1.ok(fsPath, 'a path argument must be provided'); + yield ioUtil.mkdir(fsPath, { recursive: true }); + }); +} +exports.mkdirP = mkdirP; +/** + * Returns path of a tool had the tool actually been invoked. Resolves via paths. + * If you check and the tool does not exist, it will throw. + * + * @param tool name of the tool + * @param check whether to check if tool exists + * @returns Promise path to tool + */ +function which(tool, check) { + return __awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + // recursive when check=true + if (check) { + const result = yield which(tool, false); + if (!result) { + if (ioUtil.IS_WINDOWS) { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); + } + else { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); + } + } + return result; + } + const matches = yield findInPath(tool); + if (matches && matches.length > 0) { + return matches[0]; + } + return ''; + }); +} +exports.which = which; +/** + * Returns a list of all occurrences of the given tool on the system path. + * + * @returns Promise the paths of the tool + */ +function findInPath(tool) { + return __awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + // build the list of extensions to try + const extensions = []; + if (ioUtil.IS_WINDOWS && process.env['PATHEXT']) { + for (const extension of process.env['PATHEXT'].split(path.delimiter)) { + if (extension) { + extensions.push(extension); + } + } + } + // if it's rooted, return it if exists. otherwise return empty. + if (ioUtil.isRooted(tool)) { + const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); + if (filePath) { + return [filePath]; + } + return []; + } + // if any path separators, return empty + if (tool.includes(path.sep)) { + return []; + } + // build the list of directories + // + // Note, technically "where" checks the current directory on Windows. From a toolkit perspective, + // it feels like we should not do this. Checking the current directory seems like more of a use + // case of a shell, and the which() function exposed by the toolkit should strive for consistency + // across platforms. + const directories = []; + if (process.env.PATH) { + for (const p of process.env.PATH.split(path.delimiter)) { + if (p) { + directories.push(p); + } + } + } + // find all matches + const matches = []; + for (const directory of directories) { + const filePath = yield ioUtil.tryGetExecutablePath(path.join(directory, tool), extensions); + if (filePath) { + matches.push(filePath); + } + } + return matches; + }); +} +exports.findInPath = findInPath; +function readCopyOptions(options) { + const force = options.force == null ? true : options.force; + const recursive = Boolean(options.recursive); + const copySourceDirectory = options.copySourceDirectory == null + ? true + : Boolean(options.copySourceDirectory); + return { force, recursive, copySourceDirectory }; +} +function cpDirRecursive(sourceDir, destDir, currentDepth, force) { + return __awaiter(this, void 0, void 0, function* () { + // Ensure there is not a run away recursive copy + if (currentDepth >= 255) + return; + currentDepth++; + yield mkdirP(destDir); + const files = yield ioUtil.readdir(sourceDir); + for (const fileName of files) { + const srcFile = `${sourceDir}/${fileName}`; + const destFile = `${destDir}/${fileName}`; + const srcFileStat = yield ioUtil.lstat(srcFile); + if (srcFileStat.isDirectory()) { + // Recurse + yield cpDirRecursive(srcFile, destFile, currentDepth, force); + } + else { + yield copyFile(srcFile, destFile, force); + } + } + // Change the mode for the newly created directory + yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); + }); +} +// Buffered file copy +function copyFile(srcFile, destFile, force) { + return __awaiter(this, void 0, void 0, function* () { + if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { + // unlink/re-link it + try { + yield ioUtil.lstat(destFile); + yield ioUtil.unlink(destFile); + } + catch (e) { + // Try to override file permission + if (e.code === 'EPERM') { + yield ioUtil.chmod(destFile, '0666'); + yield ioUtil.unlink(destFile); + } + // other errors = it doesn't exist, no work to do + } + // Copy over symlink + const symlinkFull = yield ioUtil.readlink(srcFile); + yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null); + } + else if (!(yield ioUtil.exists(destFile)) || force) { + yield ioUtil.copyFile(srcFile, destFile); + } + }); +} +//# sourceMappingURL=io.js.map + +/***/ }), + +/***/ 4773: +/***/ (function(__unused_webpack_module, exports) { + +(function (global, factory) { + true ? factory(exports) : + 0; +})(this, (function (exports) { 'use strict'; + + const semver = /^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i; + const validateAndParse = (version) => { + if (typeof version !== 'string') { + throw new TypeError('Invalid argument expected string'); + } + const match = version.match(semver); + if (!match) { + throw new Error(`Invalid argument not valid semver ('${version}' received)`); + } + match.shift(); + return match; + }; + const isWildcard = (s) => s === '*' || s === 'x' || s === 'X'; + const tryParse = (v) => { + const n = parseInt(v, 10); + return isNaN(n) ? v : n; + }; + const forceType = (a, b) => typeof a !== typeof b ? [String(a), String(b)] : [a, b]; + const compareStrings = (a, b) => { + if (isWildcard(a) || isWildcard(b)) + return 0; + const [ap, bp] = forceType(tryParse(a), tryParse(b)); + if (ap > bp) + return 1; + if (ap < bp) + return -1; + return 0; + }; + const compareSegments = (a, b) => { + for (let i = 0; i < Math.max(a.length, b.length); i++) { + const r = compareStrings(a[i] || '0', b[i] || '0'); + if (r !== 0) + return r; + } + return 0; + }; + + /** + * Compare [semver](https://semver.org/) version strings to find greater, equal or lesser. + * This library supports the full semver specification, including comparing versions with different number of digits like `1.0.0`, `1.0`, `1`, and pre-release versions like `1.0.0-alpha`. + * @param v1 - First version to compare + * @param v2 - Second version to compare + * @returns Numeric value compatible with the [Array.sort(fn) interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters). + */ + const compareVersions = (v1, v2) => { + // validate input and split into segments + const n1 = validateAndParse(v1); + const n2 = validateAndParse(v2); + // pop off the patch + const p1 = n1.pop(); + const p2 = n2.pop(); + // validate numbers + const r = compareSegments(n1, n2); + if (r !== 0) + return r; + // validate pre-release + if (p1 && p2) { + return compareSegments(p1.split('.'), p2.split('.')); + } + else if (p1 || p2) { + return p1 ? -1 : 1; + } + return 0; + }; + + /** + * Compare [semver](https://semver.org/) version strings using the specified operator. + * + * @param v1 First version to compare + * @param v2 Second version to compare + * @param operator Allowed arithmetic operator to use + * @returns `true` if the comparison between the firstVersion and the secondVersion satisfies the operator, `false` otherwise. + * + * @example + * ``` + * compare('10.1.8', '10.0.4', '>'); // return true + * compare('10.0.1', '10.0.1', '='); // return true + * compare('10.1.1', '10.2.2', '<'); // return true + * compare('10.1.1', '10.2.2', '<='); // return true + * compare('10.1.1', '10.2.2', '>='); // return false + * ``` + */ + const compare = (v1, v2, operator) => { + // validate input operator + assertValidOperator(operator); + // since result of compareVersions can only be -1 or 0 or 1 + // a simple map can be used to replace switch + const res = compareVersions(v1, v2); + return operatorResMap[operator].includes(res); + }; + const operatorResMap = { + '>': [1], + '>=': [0, 1], + '=': [0], + '<=': [-1, 0], + '<': [-1], + '!=': [-1, 1], + }; + const allowedOperators = Object.keys(operatorResMap); + const assertValidOperator = (op) => { + if (typeof op !== 'string') { + throw new TypeError(`Invalid operator type, expected string but got ${typeof op}`); + } + if (allowedOperators.indexOf(op) === -1) { + throw new Error(`Invalid operator, expected one of ${allowedOperators.join('|')}`); + } + }; + + /** + * Match [npm semver](https://docs.npmjs.com/cli/v6/using-npm/semver) version range. + * + * @param version Version number to match + * @param range Range pattern for version + * @returns `true` if the version number is within the range, `false` otherwise. + * + * @example + * ``` + * satisfies('1.1.0', '^1.0.0'); // return true + * satisfies('1.1.0', '~1.0.0'); // return false + * ``` + */ + const satisfies = (version, range) => { + // clean input + range = range.replace(/([><=]+)\s+/g, '$1'); + // handle multiple comparators + if (range.includes('||')) { + return range.split('||').some((r) => satisfies(version, r)); + } + else if (range.includes(' - ')) { + const [a, b] = range.split(' - ', 2); + return satisfies(version, `>=${a} <=${b}`); + } + else if (range.includes(' ')) { + return range + .trim() + .replace(/\s{2,}/g, ' ') + .split(' ') + .every((r) => satisfies(version, r)); + } + // if no range operator then "=" + const m = range.match(/^([<>=~^]+)/); + const op = m ? m[1] : '='; + // if gt/lt/eq then operator compare + if (op !== '^' && op !== '~') + return compare(version, range, op); + // else range of either "~" or "^" is assumed + const [v1, v2, v3, , vp] = validateAndParse(version); + const [r1, r2, r3, , rp] = validateAndParse(range); + const v = [v1, v2, v3]; + const r = [r1, r2 !== null && r2 !== void 0 ? r2 : 'x', r3 !== null && r3 !== void 0 ? r3 : 'x']; + // validate pre-release + if (rp) { + if (!vp) + return false; + if (compareSegments(v, r) !== 0) + return false; + if (compareSegments(vp.split('.'), rp.split('.')) === -1) + return false; + } + // first non-zero number + const nonZero = r.findIndex((v) => v !== '0') + 1; + // pointer to where segments can be >= + const i = op === '~' ? 2 : nonZero > 1 ? nonZero : 1; + // before pointer must be equal + if (compareSegments(v.slice(0, i), r.slice(0, i)) !== 0) + return false; + // after pointer must be >= + if (compareSegments(v.slice(i), r.slice(i)) === -1) + return false; + return true; + }; + + /** + * Validate [semver](https://semver.org/) version strings. + * + * @param version Version number to validate + * @returns `true` if the version number is a valid semver version number, `false` otherwise. + * + * @example + * ``` + * validate('1.0.0-rc.1'); // return true + * validate('1.0-rc.1'); // return false + * validate('foo'); // return false + * ``` + */ + const validate = (version) => typeof version === 'string' && /^[v\d]/.test(version) && semver.test(version); + /** + * Validate [semver](https://semver.org/) version strings strictly. Will not accept wildcards and version ranges. + * + * @param version Version number to validate + * @returns `true` if the version number is a valid semver version number `false` otherwise + * + * @example + * ``` + * validate('1.0.0-rc.1'); // return true + * validate('1.0-rc.1'); // return false + * validate('foo'); // return false + * ``` + */ + const validateStrict = (version) => typeof version === 'string' && + /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/.test(version); + + exports.compare = compare; + exports.compareVersions = compareVersions; + exports.satisfies = satisfies; + exports.validate = validate; + exports.validateStrict = validateStrict; + +})); +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 4294: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +module.exports = __nccwpck_require__(4219); + + +/***/ }), + +/***/ 4219: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +var net = __nccwpck_require__(1808); +var tls = __nccwpck_require__(4404); +var http = __nccwpck_require__(3685); +var https = __nccwpck_require__(5687); +var events = __nccwpck_require__(2361); +var assert = __nccwpck_require__(9491); +var util = __nccwpck_require__(3837); + + +exports.httpOverHttp = httpOverHttp; +exports.httpsOverHttp = httpsOverHttp; +exports.httpOverHttps = httpOverHttps; +exports.httpsOverHttps = httpsOverHttps; + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + return agent; +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + return agent; +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + + +function TunnelingAgent(options) { + var self = this; + self.options = options || {}; + self.proxyOptions = self.options.proxy || {}; + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; + self.requests = []; + self.sockets = []; + + self.on('free', function onFree(socket, host, port, localAddress) { + var options = toOptions(host, port, localAddress); + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i]; + if (pending.host === options.host && pending.port === options.port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1); + pending.request.onSocket(socket); + return; + } + } + socket.destroy(); + self.removeSocket(socket); + }); +} +util.inherits(TunnelingAgent, events.EventEmitter); + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { + var self = this; + var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push(options); + return; + } + + // If we are under maxSockets create a new one. + self.createSocket(options, function(socket) { + socket.on('free', onFree); + socket.on('close', onCloseOrRemove); + socket.on('agentRemove', onCloseOrRemove); + req.onSocket(socket); + + function onFree() { + self.emit('free', socket, options); + } + + function onCloseOrRemove(err) { + self.removeSocket(socket); + socket.removeListener('free', onFree); + socket.removeListener('close', onCloseOrRemove); + socket.removeListener('agentRemove', onCloseOrRemove); + } + }); +}; + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this; + var placeholder = {}; + self.sockets.push(placeholder); + + var connectOptions = mergeOptions({}, self.proxyOptions, { + method: 'CONNECT', + path: options.host + ':' + options.port, + agent: false, + headers: { + host: options.host + ':' + options.port + } + }); + if (options.localAddress) { + connectOptions.localAddress = options.localAddress; + } + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {}; + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64'); + } + + debug('making CONNECT request'); + var connectReq = self.request(connectOptions); + connectReq.useChunkedEncodingByDefault = false; // for v0.6 + connectReq.once('response', onResponse); // for v0.6 + connectReq.once('upgrade', onUpgrade); // for v0.6 + connectReq.once('connect', onConnect); // for v0.7 or later + connectReq.once('error', onError); + connectReq.end(); + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true; + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head); + }); + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners(); + socket.removeAllListeners(); + + if (res.statusCode !== 200) { + debug('tunneling socket could not be established, statusCode=%d', + res.statusCode); + socket.destroy(); + var error = new Error('tunneling socket could not be established, ' + + 'statusCode=' + res.statusCode); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + if (head.length > 0) { + debug('got illegal response body from proxy'); + socket.destroy(); + var error = new Error('got illegal response body from proxy'); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + debug('tunneling connection has established'); + self.sockets[self.sockets.indexOf(placeholder)] = socket; + return cb(socket); + } + + function onError(cause) { + connectReq.removeAllListeners(); + + debug('tunneling socket could not be established, cause=%s\n', + cause.message, cause.stack); + var error = new Error('tunneling socket could not be established, ' + + 'cause=' + cause.message); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + } +}; + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) { + return; + } + this.sockets.splice(pos, 1); + + var pending = this.requests.shift(); + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket); + }); + } +}; + +function createSecureSocket(options, cb) { + var self = this; + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + var hostHeader = options.request.getHeader('host'); + var tlsOptions = mergeOptions({}, self.options, { + socket: socket, + servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host + }); + + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, tlsOptions); + self.sockets[self.sockets.indexOf(socket)] = secureSocket; + cb(secureSocket); + }); +} + + +function toOptions(host, port, localAddress) { + if (typeof host === 'string') { // since v0.10 + return { + host: host, + port: port, + localAddress: localAddress + }; + } + return host; // for v0.11 or later +} + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i]; + if (typeof overrides === 'object') { + var keys = Object.keys(overrides); + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j]; + if (overrides[k] !== undefined) { + target[k] = overrides[k]; + } + } + } + } + return target; +} + + +var debug; +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0]; + } else { + args.unshift('TUNNEL:'); + } + console.error.apply(console, args); + } +} else { + debug = function() {}; +} +exports.debug = debug; // for test + + +/***/ }), + +/***/ 5840: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +Object.defineProperty(exports, "v1", ({ + enumerable: true, + get: function () { + return _v.default; + } +})); +Object.defineProperty(exports, "v3", ({ + enumerable: true, + get: function () { + return _v2.default; + } +})); +Object.defineProperty(exports, "v4", ({ + enumerable: true, + get: function () { + return _v3.default; + } +})); +Object.defineProperty(exports, "v5", ({ + enumerable: true, + get: function () { + return _v4.default; + } +})); +Object.defineProperty(exports, "NIL", ({ + enumerable: true, + get: function () { + return _nil.default; + } +})); +Object.defineProperty(exports, "version", ({ + enumerable: true, + get: function () { + return _version.default; + } +})); +Object.defineProperty(exports, "validate", ({ + enumerable: true, + get: function () { + return _validate.default; + } +})); +Object.defineProperty(exports, "stringify", ({ + enumerable: true, + get: function () { + return _stringify.default; + } +})); +Object.defineProperty(exports, "parse", ({ + enumerable: true, + get: function () { + return _parse.default; + } +})); + +var _v = _interopRequireDefault(__nccwpck_require__(8628)); + +var _v2 = _interopRequireDefault(__nccwpck_require__(6409)); + +var _v3 = _interopRequireDefault(__nccwpck_require__(5122)); + +var _v4 = _interopRequireDefault(__nccwpck_require__(9120)); + +var _nil = _interopRequireDefault(__nccwpck_require__(5332)); + +var _version = _interopRequireDefault(__nccwpck_require__(1595)); + +var _validate = _interopRequireDefault(__nccwpck_require__(6900)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(8950)); + +var _parse = _interopRequireDefault(__nccwpck_require__(2746)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/***/ }), + +/***/ 4569: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function md5(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('md5').update(bytes).digest(); +} + +var _default = md5; +exports["default"] = _default; + +/***/ }), + +/***/ 5332: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = '00000000-0000-0000-0000-000000000000'; +exports["default"] = _default; + +/***/ }), + +/***/ 2746: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(6900)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function parse(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + let v; + const arr = new Uint8Array(16); // Parse ########-....-....-....-............ + + arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; + arr[1] = v >>> 16 & 0xff; + arr[2] = v >>> 8 & 0xff; + arr[3] = v & 0xff; // Parse ........-####-....-....-............ + + arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; + arr[5] = v & 0xff; // Parse ........-....-####-....-............ + + arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; + arr[7] = v & 0xff; // Parse ........-....-....-####-............ + + arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; + arr[9] = v & 0xff; // Parse ........-....-....-....-############ + // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) + + arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; + arr[11] = v / 0x100000000 & 0xff; + arr[12] = v >>> 24 & 0xff; + arr[13] = v >>> 16 & 0xff; + arr[14] = v >>> 8 & 0xff; + arr[15] = v & 0xff; + return arr; +} + +var _default = parse; +exports["default"] = _default; + +/***/ }), + +/***/ 814: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; +exports["default"] = _default; + +/***/ }), + +/***/ 807: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = rng; + +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate + +let poolPtr = rnds8Pool.length; + +function rng() { + if (poolPtr > rnds8Pool.length - 16) { + _crypto.default.randomFillSync(rnds8Pool); + + poolPtr = 0; + } + + return rnds8Pool.slice(poolPtr, poolPtr += 16); +} + +/***/ }), + +/***/ 5274: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function sha1(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('sha1').update(bytes).digest(); +} + +var _default = sha1; +exports["default"] = _default; + +/***/ }), + +/***/ 8950: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(6900)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +const byteToHex = []; + +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 0x100).toString(16).substr(1)); +} + +function stringify(arr, offset = 0) { + // Note: Be careful editing this code! It's been tuned for performance + // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 + const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one + // of the following: + // - One or more input array values don't map to a hex octet (leading to + // "undefined" in the uuid) + // - Invalid input values for the RFC `version` or `variant` fields + + if (!(0, _validate.default)(uuid)) { + throw TypeError('Stringified UUID is invalid'); + } + + return uuid; +} + +var _default = stringify; +exports["default"] = _default; + +/***/ }), + +/***/ 8628: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(807)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(8950)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html +let _nodeId; + +let _clockseq; // Previous uuid creation time + + +let _lastMSecs = 0; +let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details + +function v1(options, buf, offset) { + let i = buf && offset || 0; + const b = buf || new Array(16); + options = options || {}; + let node = options.node || _nodeId; + let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + + if (node == null || clockseq == null) { + const seedBytes = options.random || (options.rng || _rng.default)(); + + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; + } + + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + + + let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + + let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) + + const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression + + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + + + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } // Per 4.2.1.2 Throw error if too many uuids are requested + + + if (nsecs >= 10000) { + throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + + msecs += 12219292800000; // `time_low` + + const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; // `time_mid` + + const tmh = msecs / 0x100000000 * 10000 & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; // `time_high_and_version` + + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + + b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + + b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` + + b[i++] = clockseq & 0xff; // `node` + + for (let n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf || (0, _stringify.default)(b); +} + +var _default = v1; +exports["default"] = _default; + +/***/ }), + +/***/ 6409: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(5998)); + +var _md = _interopRequireDefault(__nccwpck_require__(4569)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v3 = (0, _v.default)('v3', 0x30, _md.default); +var _default = v3; +exports["default"] = _default; + +/***/ }), + +/***/ 5998: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = _default; +exports.URL = exports.DNS = void 0; + +var _stringify = _interopRequireDefault(__nccwpck_require__(8950)); + +var _parse = _interopRequireDefault(__nccwpck_require__(2746)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function stringToBytes(str) { + str = unescape(encodeURIComponent(str)); // UTF8 escape + + const bytes = []; + + for (let i = 0; i < str.length; ++i) { + bytes.push(str.charCodeAt(i)); + } + + return bytes; +} + +const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; +exports.DNS = DNS; +const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; +exports.URL = URL; + +function _default(name, version, hashfunc) { + function generateUUID(value, namespace, buf, offset) { + if (typeof value === 'string') { + value = stringToBytes(value); + } + + if (typeof namespace === 'string') { + namespace = (0, _parse.default)(namespace); + } + + if (namespace.length !== 16) { + throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); + } // Compute hash of namespace and value, Per 4.3 + // Future: Use spread syntax when supported on all platforms, e.g. `bytes = + // hashfunc([...namespace, ... value])` + + + let bytes = new Uint8Array(16 + value.length); + bytes.set(namespace); + bytes.set(value, namespace.length); + bytes = hashfunc(bytes); + bytes[6] = bytes[6] & 0x0f | version; + bytes[8] = bytes[8] & 0x3f | 0x80; + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = bytes[i]; + } + + return buf; + } + + return (0, _stringify.default)(bytes); + } // Function#name is not settable on some platforms (#270) + + + try { + generateUUID.name = name; // eslint-disable-next-line no-empty + } catch (err) {} // For CommonJS default export support + + + generateUUID.DNS = DNS; + generateUUID.URL = URL; + return generateUUID; +} + +/***/ }), + +/***/ 5122: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(807)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(8950)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function v4(options, buf, offset) { + options = options || {}; + + const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + + + rnds[6] = rnds[6] & 0x0f | 0x40; + rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + + return buf; + } + + return (0, _stringify.default)(rnds); +} + +var _default = v4; +exports["default"] = _default; + +/***/ }), + +/***/ 9120: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(5998)); + +var _sha = _interopRequireDefault(__nccwpck_require__(5274)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v5 = (0, _v.default)('v5', 0x50, _sha.default); +var _default = v5; +exports["default"] = _default; + +/***/ }), + +/***/ 6900: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _regex = _interopRequireDefault(__nccwpck_require__(814)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function validate(uuid) { + return typeof uuid === 'string' && _regex.default.test(uuid); +} + +var _default = validate; +exports["default"] = _default; + +/***/ }), + +/***/ 1595: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(6900)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function version(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + return parseInt(uuid.substr(14, 1), 16); +} + +var _default = version; +exports["default"] = _default; + +/***/ }), + +/***/ 9491: +/***/ ((module) => { + +"use strict"; +module.exports = require("assert"); + +/***/ }), + +/***/ 2081: +/***/ ((module) => { + +"use strict"; +module.exports = require("child_process"); + +/***/ }), + +/***/ 6113: +/***/ ((module) => { + +"use strict"; +module.exports = require("crypto"); + +/***/ }), + +/***/ 2361: +/***/ ((module) => { + +"use strict"; +module.exports = require("events"); + +/***/ }), + +/***/ 7147: +/***/ ((module) => { + +"use strict"; +module.exports = require("fs"); + +/***/ }), + +/***/ 3685: +/***/ ((module) => { + +"use strict"; +module.exports = require("http"); + +/***/ }), + +/***/ 5687: +/***/ ((module) => { + +"use strict"; +module.exports = require("https"); + +/***/ }), + +/***/ 1808: +/***/ ((module) => { + +"use strict"; +module.exports = require("net"); + +/***/ }), + +/***/ 2037: +/***/ ((module) => { + +"use strict"; +module.exports = require("os"); + +/***/ }), + +/***/ 1017: +/***/ ((module) => { + +"use strict"; +module.exports = require("path"); + +/***/ }), + +/***/ 1576: +/***/ ((module) => { + +"use strict"; +module.exports = require("string_decoder"); + +/***/ }), + +/***/ 9512: +/***/ ((module) => { + +"use strict"; +module.exports = require("timers"); + +/***/ }), + +/***/ 4404: +/***/ ((module) => { + +"use strict"; +module.exports = require("tls"); + +/***/ }), + +/***/ 7310: +/***/ ((module) => { + +"use strict"; +module.exports = require("url"); + +/***/ }), + +/***/ 3837: +/***/ ((module) => { + +"use strict"; +module.exports = require("util"); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __nccwpck_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ var threw = true; +/******/ try { +/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__); +/******/ threw = false; +/******/ } finally { +/******/ if(threw) delete __webpack_module_cache__[moduleId]; +/******/ } +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat */ +/******/ +/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; +/******/ +/************************************************************************/ +/******/ +/******/ // startup +/******/ // Load entry module and return exports +/******/ // This entry module is referenced by other modules so it can't be inlined +/******/ var __webpack_exports__ = __nccwpck_require__(9039); +/******/ module.exports = __webpack_exports__; +/******/ +/******/ })() +; \ No newline at end of file diff --git a/examples/bedrock.yml b/examples/bedrock.yml new file mode 100644 index 0000000..665e1dd --- /dev/null +++ b/examples/bedrock.yml @@ -0,0 +1,38 @@ +# GitHub Action for roots/bedrock +name: Testing Bedrock +on: [push, pull_request] +jobs: + bedrock: + name: Bedrock (PHP ${{ matrix.php-versions }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: PHP test + run: composer test diff --git a/examples/blackfire-player.yml b/examples/blackfire-player.yml new file mode 100644 index 0000000..9047391 --- /dev/null +++ b/examples/blackfire-player.yml @@ -0,0 +1,36 @@ +# GitHub Action for Blackfire Player +name: Play a Blackfire Scenario +on: [push, pull_request] +jobs: + blackfire-player: + name: Blackfire (PHP ${{ matrix.php-versions }}) + # Add your Blackfire credentials securely using GitHub Secrets + env: + BLACKFIRE_SERVER_ID: ${{ secrets.BLACKFIRE_SERVER_ID }} + BLACKFIRE_SERVER_TOKEN: ${{ secrets.BLACKFIRE_SERVER_TOKEN }} + BLACKFIRE_CLIENT_ID: ${{ secrets.BLACKFIRE_CLIENT_ID }} + BLACKFIRE_CLIENT_TOKEN: ${{ secrets.BLACKFIRE_CLIENT_TOKEN }} + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-latest, windows-latest, macos-latest] + php-versions: ['7.4', '8.0', '8.1'] + # blackfire-player supports PHP >= 5.5 + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: blackfire + # Setup Blackfire CLI and player + tools: blackfire, blackfire-player + coverage: none + + # Refer to https://blackfire.io/docs/player/index#usage + - name: Play the scenario + run: blackfire-player run scenario.bkf diff --git a/examples/blackfire.yml b/examples/blackfire.yml new file mode 100644 index 0000000..5dc2684 --- /dev/null +++ b/examples/blackfire.yml @@ -0,0 +1,37 @@ +# GitHub Action for Blackfire +name: Profiling with blackfire +on: [push, pull_request] +jobs: + blackfire: + name: Blackfire (PHP ${{ matrix.php-versions }}) + # Add your Blackfire credentials securely using GitHub Secrets + env: + BLACKFIRE_SERVER_ID: ${{ secrets.BLACKFIRE_SERVER_ID }} + BLACKFIRE_SERVER_TOKEN: ${{ secrets.BLACKFIRE_SERVER_TOKEN }} + BLACKFIRE_CLIENT_ID: ${{ secrets.BLACKFIRE_CLIENT_ID }} + BLACKFIRE_CLIENT_TOKEN: ${{ secrets.BLACKFIRE_CLIENT_TOKEN }} + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-latest, windows-latest, macos-latest] + php-versions: ['7.4', '8.0', '8.1'] + # Blackfire supports PHP >= 5.3 on Ubuntu and macOS, and PHP >= 5.4 on Windows + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + # Setup Blackfire extension and CLI + extensions: blackfire + tools: blackfire + # Disable Xdebug and PCOV coverage drivers + coverage: none + + # Refer to https://blackfire.io/docs/cookbooks/profiling-cli + - name: Profile + run: blackfire run php my-script.php diff --git a/examples/cakephp-mysql.yml b/examples/cakephp-mysql.yml new file mode 100644 index 0000000..afb8f9e --- /dev/null +++ b/examples/cakephp-mysql.yml @@ -0,0 +1,138 @@ +# GitHub Action for CakePHP with MySQL and Redis +# Tested with https://github.com/cakephp/app +name: Testing CakePHP with MySQL +on: [push, pull_request] +jobs: + tests: + strategy: + matrix: + php-versions: ['7.4', '8.0', '8.1'] + runs-on: ubuntu-latest + + # Docs: https://docs.github.com/en/actions/using-containerized-services + services: + mysql: + image: mysql:latest + env: + MYSQL_ALLOW_EMPTY_PASSWORD: false + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: cakephp + ports: + - 3306/tcp + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + + redis: + image: redis + ports: + - 6379/tcp + options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3 + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + # You can also use ext-apcu or ext-memcached instead of ext-redis + # Install memcached if using ext-memcached + extensions: mbstring, intl, redis, pdo_mysql + coverage: pcov + + # Local MySQL service in GitHub hosted environments is disabled by default. + # If you are using it instead of service containers, make sure you start it. + # - name: Start mysql service + # run: sudo systemctl start mysql.service + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + composer install --no-progress --prefer-dist --optimize-autoloader + composer run-script post-install-cmd + + # Add a step to run migrations if required + - name: Test with phpunit + run: vendor/bin/phpunit --coverage-text + env: + REDIS_PORT: ${{ job.services.redis.ports['6379'] }} + DB_DSN: "mysql://root:password@127.0.0.1:${{ job.services.mysql.ports['3306'] }}/cakephp?init[]=SET sql_mode = \"STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION\"" + + coding-standard: + name: Coding Standard + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + extensions: mbstring, intl + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: PHP CodeSniffer + run: composer cs-check + + static-analysis: + name: Static Analysis + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + extensions: mbstring, intl + tools: phpstan + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Static Analysis using PHPStan + run: phpstan analyse --no-progress src/ diff --git a/examples/cakephp-postgres.yml b/examples/cakephp-postgres.yml new file mode 100644 index 0000000..302bae2 --- /dev/null +++ b/examples/cakephp-postgres.yml @@ -0,0 +1,138 @@ +# GitHub Action for CakePHP with PostgreSQL and Redis +# Tested with https://github.com/cakephp/app +name: Testing CakePHP with PostgreSQL +on: [push, pull_request] +jobs: + tests: + strategy: + matrix: + php-versions: ['7.4', '8.0', '8.1'] + runs-on: ubuntu-latest + + # Docs: https://docs.github.com/en/actions/using-containerized-services + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432/tcp + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 + + redis: + image: redis + ports: + - 6379/tcp + options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3 + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + # You can also use ext-apcu or ext-memcached instead of ext-redis + # Install memcached if using ext-memcached + extensions: mbstring, intl, redis, pdo_pgsql + coverage: pcov + + # Local PostgreSQL service in GitHub hosted environments is disabled by default. + # If you are using it instead of service containers, make sure you start it. + # - name: Start postgresql service + # run: sudo systemctl start postgresql.service + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + composer install --no-progress --prefer-dist --optimize-autoloader + composer run-script post-install-cmd + + # Add a step to run migrations if required + - name: Test with phpunit + run: vendor/bin/phpunit --coverage-text + env: + REDIS_PORT: ${{ job.services.redis.ports['6379'] }} + DB_DSN: postgres://postgres@127.0.0.1:${{ job.services.postgres.ports['5432'] }}/postgres + + coding-standard: + name: Coding Standard + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + extensions: mbstring, intl + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: PHP CodeSniffer + run: composer cs-check + + static-analysis: + name: Static Analysis + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + extensions: mbstring, intl + tools: phpstan + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Static Analysis using PHPStan + run: phpstan analyse --no-progress src/ diff --git a/examples/cakephp.yml b/examples/cakephp.yml new file mode 100644 index 0000000..71a3bc6 --- /dev/null +++ b/examples/cakephp.yml @@ -0,0 +1,109 @@ +# GitHub Action for CakePHP +# Tested with https://github.com/cakephp/app +name: Testing CakePHP +on: [push, pull_request] +jobs: + tests: + strategy: + matrix: + operating-system: [ubuntu-latest, windows-latest, macos-latest] + php-versions: ['7.4', '8.0', '8.1'] + runs-on: ${{ matrix.operating-system }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, intl, pdo_sqlite, pdo_mysql + coverage: pcov + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + composer install --no-progress --prefer-dist --optimize-autoloader + composer run-script post-install-cmd + + - name: Test with phpunit + run: vendor/bin/phpunit --coverage-text + + coding-standard: + name: Coding Standard + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + extensions: mbstring, intl + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: PHP CodeSniffer + run: composer cs-check + + static-analysis: + name: Static Analysis + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + extensions: mbstring, intl + tools: phpstan + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Static Analysis using PHPStan + run: phpstan analyse --no-progress src/ diff --git a/examples/codeigniter.yml b/examples/codeigniter.yml new file mode 100644 index 0000000..5416749 --- /dev/null +++ b/examples/codeigniter.yml @@ -0,0 +1,40 @@ +# GitHub Action for CodeIgniter +name: Testing CodeIgniter +on: [push, pull_request] +jobs: + build: + strategy: + matrix: + operating-system: [ubuntu-latest, windows-latest, macos-latest] + php-versions: ['7.4', '8.0', '8.1'] + runs-on: ${{ matrix.operating-system }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, intl, curl, dom + coverage: xdebug + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Test with phpunit + run: vendor/bin/phpunit --coverage-text diff --git a/examples/laminas-mvc.yml b/examples/laminas-mvc.yml new file mode 100644 index 0000000..0cc820e --- /dev/null +++ b/examples/laminas-mvc.yml @@ -0,0 +1,39 @@ +# GitHub Action for Laminas framework MVC projects +name: Testing Zend Framework +on: [push, pull_request] +jobs: + build: + strategy: + matrix: + operating-system: [ubuntu-latest, windows-latest, macos-latest] + php-versions: ['7.4', '8.0', '8.1'] + runs-on: ${{ matrix.operating-system }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + coverage: xdebug + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Test with phpunit + run: vendor/bin/phpunit --coverage-text diff --git a/examples/laravel-mysql.yml b/examples/laravel-mysql.yml new file mode 100644 index 0000000..9f9e18e --- /dev/null +++ b/examples/laravel-mysql.yml @@ -0,0 +1,89 @@ +# GitHub Action for Laravel with MySQL and Redis +name: Testing Laravel with MySQL +on: [push, pull_request] +jobs: + laravel: + name: Laravel (PHP ${{ matrix.php-versions }}) + runs-on: ubuntu-latest + env: + DB_DATABASE: laravel + DB_USERNAME: root + DB_PASSWORD: password + BROADCAST_DRIVER: log + CACHE_DRIVER: redis + QUEUE_CONNECTION: redis + SESSION_DRIVER: redis + + # Docs: https://docs.github.com/en/actions/using-containerized-services + services: + mysql: + image: mysql:latest + env: + MYSQL_ALLOW_EMPTY_PASSWORD: false + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: laravel + ports: + - 3306/tcp + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + + redis: + image: redis + ports: + - 6379/tcp + options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3 + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, dom, fileinfo, mysql + coverage: xdebug + + # Local MySQL service in GitHub hosted environments is disabled by default. + # If you are using it instead of service containers, make sure you start it. + # - name: Start mysql service + # run: sudo systemctl start mysql.service + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Prepare the application + run: | + php -r "file_exists('.env') || copy('.env.example', '.env');" + php artisan key:generate + + - name: Clear Config + run: php artisan config:clear + + - name: Run Migration + run: php artisan migrate -v + env: + DB_PORT: ${{ job.services.mysql.ports['3306'] }} + REDIS_PORT: ${{ job.services.redis.ports['6379'] }} + + - name: Test with phpunit + run: vendor/bin/phpunit --coverage-text + env: + DB_PORT: ${{ job.services.mysql.ports['3306'] }} + REDIS_PORT: ${{ job.services.redis.ports['6379'] }} diff --git a/examples/laravel-postgres.yml b/examples/laravel-postgres.yml new file mode 100644 index 0000000..61e83d0 --- /dev/null +++ b/examples/laravel-postgres.yml @@ -0,0 +1,91 @@ +# GitHub Action for Laravel with PostgreSQL and Redis +name: Testing Laravel with PostgreSQL +on: [push, pull_request] +jobs: + laravel: + name: Laravel (PHP ${{ matrix.php-versions }}) + runs-on: ubuntu-latest + env: + BROADCAST_DRIVER: log + CACHE_DRIVER: redis + QUEUE_CONNECTION: redis + SESSION_DRIVER: redis + DB_CONNECTION: pgsql + DB_HOST: localhost + DB_PASSWORD: postgres + DB_USERNAME: postgres + DB_DATABASE: postgres + + # Docs: https://docs.github.com/en/actions/using-containerized-services + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432/tcp + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 + + redis: + image: redis + ports: + - 6379/tcp + options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3 + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, dom, fileinfo, pgsql + coverage: xdebug + + # Local PostgreSQL service in GitHub hosted environments is disabled by default. + # If you are using it instead of service containers, make sure you start it. + # - name: Start postgresql service + # run: sudo systemctl start postgresql.service + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Prepare the application + run: | + php -r "file_exists('.env') || copy('.env.example', '.env');" + php artisan key:generate + + - name: Clear Config + run: php artisan config:clear + + - name: Run Migration + run: php artisan migrate -v + env: + DB_PORT: ${{ job.services.postgres.ports[5432] }} + REDIS_PORT: ${{ job.services.redis.ports['6379'] }} + + - name: Test with phpunit + run: vendor/bin/phpunit --coverage-text + env: + DB_PORT: ${{ job.services.postgres.ports[5432] }} + REDIS_PORT: ${{ job.services.redis.ports['6379'] }} diff --git a/examples/laravel.yml b/examples/laravel.yml new file mode 100644 index 0000000..8c44c88 --- /dev/null +++ b/examples/laravel.yml @@ -0,0 +1,50 @@ +# GitHub Action for Laravel +name: Testing Laravel +on: [push, pull_request] +jobs: + laravel: + name: Laravel (PHP ${{ matrix.php-versions }} on ${{ matrix.operating-system }}) + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-latest, windows-latest, macos-latest] + php-versions: ['7.4', '8.0', '8.1'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, dom, fileinfo + coverage: xdebug + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Prepare the application + run: | + php -r "file_exists('.env') || copy('.env.example', '.env');" + php artisan key:generate + + - name: Clear Config + run: php artisan config:clear + + - name: Test with phpunit + run: vendor/bin/phpunit --coverage-text diff --git a/examples/lumen-mysql.yml b/examples/lumen-mysql.yml new file mode 100644 index 0000000..1167f60 --- /dev/null +++ b/examples/lumen-mysql.yml @@ -0,0 +1,89 @@ +# GitHub Action for Lumen with MySQL and Redis +name: Testing Lumen with MySQL +on: [push, pull_request] +jobs: + lumen: + name: Lumen (PHP ${{ matrix.php-versions }}) + runs-on: ubuntu-latest + env: + DB_DATABASE: lumen + DB_USERNAME: root + DB_PASSWORD: password + BROADCAST_DRIVER: log + CACHE_DRIVER: redis + QUEUE_CONNECTION: redis + SESSION_DRIVER: redis + + # Docs: https://docs.github.com/en/actions/using-containerized-services + services: + mysql: + image: mysql:latest + env: + MYSQL_ALLOW_EMPTY_PASSWORD: false + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: lumen + ports: + - 3306/tcp + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + + redis: + image: redis + ports: + - 6379/tcp + options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3 + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, dom, fileinfo, mysql + coverage: xdebug + + # Local MySQL service in GitHub hosted environments is disabled by default. + # If you are using it instead of service containers, make sure you start it. + # - name: Start mysql service + # run: sudo systemctl start mysql.service + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: | + composer install --no-progress --prefer-dist --optimize-autoloader + composer require predis/predis illuminate/redis + + - name: Prepare the application + run: php -r "file_exists('.env') || copy('.env.example', '.env');" + + - name: Register Redis as service provider + run: sed -i '$i\$app->register(Illuminate\\Redis\\RedisServiceProvider::class);' bootstrap/app.php + + - name: Run Migration + run: php artisan migrate -v + env: + DB_PORT: ${{ job.services.mysql.ports['3306'] }} + REDIS_PORT: ${{ job.services.redis.ports['6379'] }} + + - name: Test with phpunit + run: vendor/bin/phpunit --coverage-text + env: + DB_PORT: ${{ job.services.mysql.ports['3306'] }} + REDIS_PORT: ${{ job.services.redis.ports['6379'] }} diff --git a/examples/lumen-postgres.yml b/examples/lumen-postgres.yml new file mode 100644 index 0000000..727420a --- /dev/null +++ b/examples/lumen-postgres.yml @@ -0,0 +1,91 @@ +# GitHub Action for Lumen with PostgreSQL and Redis +name: Testing Lumen with PostgreSQL +on: [push, pull_request] +jobs: + laravel: + name: Lumen (PHP ${{ matrix.php-versions }}) + runs-on: ubuntu-latest + env: + BROADCAST_DRIVER: log + CACHE_DRIVER: redis + QUEUE_CONNECTION: redis + SESSION_DRIVER: redis + DB_CONNECTION: pgsql + DB_HOST: localhost + DB_PASSWORD: postgres + DB_USERNAME: postgres + DB_DATABASE: postgres + + # Docs: https://docs.github.com/en/actions/using-containerized-services + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432/tcp + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 + + redis: + image: redis + ports: + - 6379/tcp + options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3 + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, dom, fileinfo, pgsql + coverage: xdebug + + # Local PostgreSQL service in GitHub hosted environments is disabled by default. + # If you are using it instead of service containers, make sure you start it. + # - name: Start postgresql service + # run: sudo systemctl start postgresql.service + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: | + composer install --no-progress --prefer-dist --optimize-autoloader + composer require predis/predis illuminate/redis + + - name: Prepare the application + run: php -r "file_exists('.env') || copy('.env.example', '.env');" + + - name: Register Redis as service provider + run: sed -i '$i\$app->register(Illuminate\\Redis\\RedisServiceProvider::class);' bootstrap/app.php + + - name: Run Migration + run: php artisan migrate -v + env: + DB_PORT: ${{ job.services.postgres.ports[5432] }} + REDIS_PORT: ${{ job.services.redis.ports['6379'] }} + + - name: Test with phpunit + run: vendor/bin/phpunit --coverage-text + env: + DB_PORT: ${{ job.services.postgres.ports[5432] }} + REDIS_PORT: ${{ job.services.redis.ports['6379'] }} diff --git a/examples/lumen.yml b/examples/lumen.yml new file mode 100644 index 0000000..808e12a --- /dev/null +++ b/examples/lumen.yml @@ -0,0 +1,45 @@ +# GitHub Action for Lumen +name: Unit Testing Lumen +on: [push, pull_request] +jobs: + lumen: + name: Lumen (PHP ${{ matrix.php-versions }} on ${{ matrix.operating-system }}) + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-latest, windows-latest, macos-latest] + php-versions: ['7.4', '8.0', '8.1'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, dom, fileinfo, mysql + coverage: xdebug + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Prepare the application + run: php -r "file_exists('.env') || copy('.env.example', '.env');" + + - name: Test with phpunit + run: vendor/bin/phpunit --coverage-text diff --git a/examples/phalcon-mysql.yml b/examples/phalcon-mysql.yml new file mode 100644 index 0000000..6793db8 --- /dev/null +++ b/examples/phalcon-mysql.yml @@ -0,0 +1,88 @@ +# GitHub Action for Phalcon with MySQL +## Notes +## Make sure you have .env.example or .env file in your project +## and you have loaded Dotenv (https://github.com/vlucas/phpdotenv) +name: Testing Phalcon with MySQL +on: [push, pull_request] +jobs: + phalcon: + name: Phalcon (PHP ${{ matrix.php-versions }}) + runs-on: ubuntu-latest + env: + DB_ADAPTER: mysql + DB_HOST: 127.0.0.1 + DB_NAME: phalcon + DB_USERNAME: root + DB_PASSWORD: password + CODECEPTION_URL: 127.0.0.1 + CODECEPTION_PORT: 8888 + + # Docs: https://docs.github.com/en/actions/using-containerized-services + services: + mysql: + image: mysql:latest + env: + MYSQL_ALLOW_EMPTY_PASSWORD: false + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: phalcon + ports: + - 3306/tcp + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + strategy: + fail-fast: false + matrix: + php-versions: ['7.2', '7.3', '7.4'] + # For phalcon 3.x, use + # php-versions: ['7.0', '7.1', '7.2', '7.3'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + # Use phalcon3 for the phalcon 3.x. + extensions: mbstring, dom, zip, phalcon4, mysql + coverage: xdebug + + # Local MySQL service in GitHub hosted environments is disabled by default. + # If you are using it instead of service containers, make sure you start it. + # - name: Start mysql service + # run: sudo systemctl start mysql.service + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Prepare the application + run: php -r "file_exists('.env') || copy('.env.example', '.env');" + + - name: Run Migration + run: | + if [ ! -e phinx.yml ]; then vendor/bin/phinx init; fi + vendor/bin/phinx migrate + vendor/bin/phinx seed:run + env: + DB_PORT: ${{ job.services.mysql.ports['3306'] }} + + - name: Run Tests + run: | + (cd public && nohup php -S $CODECEPTION_URL:$CODECEPTION_PORT > phalcon.log 2>&1 &) + vendor/bin/codecept build + vendor/bin/codecept run + env: + DB_PORT: ${{ job.services.mysql.ports['3306'] }} diff --git a/examples/phalcon-postgres.yml b/examples/phalcon-postgres.yml new file mode 100644 index 0000000..78daee6 --- /dev/null +++ b/examples/phalcon-postgres.yml @@ -0,0 +1,84 @@ +# GitHub Action for Phalcon with PostgreSQL +## Notes +## Make sure you have .env.example or .env file in your project +## and you have loaded Dotenv (https://github.com/vlucas/phpdotenv) +name: Testing Phalcon with PostgreSQL +on: [push, pull_request] +jobs: + phalcon: + name: Phalcon (PHP ${{ matrix.php-versions }}) + runs-on: ubuntu-latest + env: + DB_ADAPTER: pgsql + DB_HOST: 127.0.0.1 + DB_NAME: postgres + DB_USERNAME: postgres + DB_PASSWORD: postgres + CODECEPTION_URL: 127.0.0.1 + CODECEPTION_PORT: 8888 + DB_CONNECTION: pgsql + + # Docs: https://docs.github.com/en/actions/using-containerized-services + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432/tcp + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 + strategy: + fail-fast: false + matrix: + php-versions: ['7.2', '7.3', '7.4'] + # For phalcon 3.x, use + # php-versions: ['7.0', '7.1', '7.2', '7.3'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + # Use phalcon3 for the phalcon 3.x + extensions: mbstring, dom, zip, phalcon4, pgsql + coverage: xdebug + + # Local PostgreSQL service in GitHub hosted environments is disabled by default. + # If you are using it instead of service containers, make sure you start it. + # - name: Start postgresql service + # run: sudo systemctl start postgresql.service + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + - name: Prepare the application + run: php -r "file_exists('.env') || copy('.env.example', '.env');" + - name: Run Migration + run: | + if [ ! -e phinx.yml ]; then vendor/bin/phinx init; fi + vendor/bin/phinx migrate + vendor/bin/phinx seed:run + env: + DB_PORT: ${{ job.services.postgres.ports['5432'] }} + - name: Run Tests + run: | + (cd public && nohup php -S $CODECEPTION_URL:$CODECEPTION_PORT > phalcon.log 2>&1 &) + vendor/bin/codecept build + vendor/bin/codecept run + env: + DB_PORT: ${{ job.services.postgres.ports['5432'] }} \ No newline at end of file diff --git a/examples/sage.yml b/examples/sage.yml new file mode 100644 index 0000000..0cae17e --- /dev/null +++ b/examples/sage.yml @@ -0,0 +1,69 @@ +# GitHub Action for roots/sage +name: Testing Sage +on: [push, pull_request] +jobs: + sage: + name: Sage (PHP ${{ matrix.php-versions }} & Node ${{ matrix.node-versions }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + node-versions: ['16'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-versions }} + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring + + - name: Check node versions + run: node -v + + - name: Get yarn cache + id: yarn-cache + run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT + + - uses: actions/cache@v3 + with: + path: ${{ steps.yarn-cache.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: ${{ runner.os }}-yarn- + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install yarn dependencies + run: yarn -V + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Yarn test and build + run: | + yarn run test + yarn run build + yarn run rmdist + yarn run "build:production" + + - name: PHP test + run: composer test diff --git a/examples/slim-framework.yml b/examples/slim-framework.yml new file mode 100644 index 0000000..2dec4b6 --- /dev/null +++ b/examples/slim-framework.yml @@ -0,0 +1,40 @@ +# GitHub Action for Slim Framework +name: Testing Slim Framework +on: [push, pull_request] +jobs: + build: + strategy: + matrix: + operating-system: [ubuntu-latest, windows-latest, macos-latest] + php-versions: ['7.4', '8.0', '8.1'] + runs-on: ${{ matrix.operating-system }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, simplexml, dom + coverage: xdebug + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Test with phpunit + run: vendor/bin/phpunit --coverage-text diff --git a/examples/symfony-mysql.yml b/examples/symfony-mysql.yml new file mode 100644 index 0000000..b5c009f --- /dev/null +++ b/examples/symfony-mysql.yml @@ -0,0 +1,70 @@ +# GitHub Action for Symfony with MySQL +name: Testing Symfony with MySQL +on: [push, pull_request] +jobs: + symfony: + name: Symfony (PHP ${{ matrix.php-versions }}) + runs-on: ubuntu-latest + + # Docs: https://docs.github.com/en/actions/using-containerized-services + services: + mysql: + image: mysql:latest + env: + MYSQL_ALLOW_EMPTY_PASSWORD: false + MYSQL_ROOT_PASSWORD: symfony + MYSQL_DATABASE: symfony + ports: + - 3306/tcp + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpunit-bridge + extensions: mbstring, xml, ctype, iconv, intl, pdo_sqlite, mysql + coverage: xdebug + + # Local MySQL service in GitHub hosted environments is disabled by default. + # If you are using it instead of service containers, make sure you start it. + # - name: Start mysql service + # run: sudo systemctl start mysql.service + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Run Migration + run: | + composer require --dev symfony/orm-pack + php bin/console doctrine:schema:update --force || echo "No migrations found or schema update failed" + php bin/console doctrine:migrations:migrate || echo "No migrations found or migration failed" + env: + DATABASE_URL: mysql://root:symfony@127.0.0.1:${{ job.services.mysql.ports['3306'] }}/symfony + + - name: Install PHPUnit + run: simple-phpunit install + + - name: Run tests + run: simple-phpunit --coverage-text diff --git a/examples/symfony-postgres.yml b/examples/symfony-postgres.yml new file mode 100644 index 0000000..9672e0a --- /dev/null +++ b/examples/symfony-postgres.yml @@ -0,0 +1,70 @@ +# GitHub Action for Symfony with PostgreSQL +name: Testing Symfony with PostgreSQL +on: [push, pull_request] +jobs: + symfony: + name: Symfony (PHP ${{ matrix.php-versions }}) + runs-on: ubuntu-latest + + # Docs: https://docs.github.com/en/actions/using-containerized-services + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432/tcp + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpunit-bridge + extensions: mbstring, xml, ctype, iconv, intl, pdo_sqlite, pgsql + coverage: xdebug + + # Local PostgreSQL service in GitHub hosted environments is disabled by default. + # If you are using it instead of service containers, make sure you start it. + # - name: Start postgresql service + # run: sudo systemctl start postgresql.service + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Run Migration + run: | + composer require --dev symfony/orm-pack + php bin/console doctrine:schema:update --force || echo "No migrations found or schema update failed" + php bin/console doctrine:migrations:migrate || echo "No migrations found or migration failed" + env: + DATABASE_URL: postgres://postgres:postgres@127.0.0.1:${{ job.services.postgres.ports[5432] }}/postgres?charset=UTF-8 + + - name: Install PHPUnit + run: simple-phpunit install + + - name: Run tests + run: simple-phpunit --coverage-text diff --git a/examples/symfony.yml b/examples/symfony.yml new file mode 100644 index 0000000..38edaac --- /dev/null +++ b/examples/symfony.yml @@ -0,0 +1,46 @@ +# GitHub Action for Symfony +name: Testing Symfony +on: [push, pull_request] +jobs: + symfony: + name: Symfony (PHP ${{ matrix.php-versions }} on ${{ matrix.operating-system }}) + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-latest, windows-latest, macos-latest] + php-versions: ['7.4', '8.0', '8.1'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpunit-bridge + extensions: mbstring, xml, ctype, iconv, intl, pdo_sqlite + coverage: xdebug + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Install PHPUnit + run: simple-phpunit install + + - name: Run tests + run: simple-phpunit --coverage-text diff --git a/examples/yii2-mysql.yml b/examples/yii2-mysql.yml new file mode 100644 index 0000000..b813720 --- /dev/null +++ b/examples/yii2-mysql.yml @@ -0,0 +1,86 @@ +# GitHub Action for Yii Framework with MySQL +name: Testing Yii2 with MySQL +on: [push, pull_request] +jobs: + yii: + name: Yii2 (PHP ${{ matrix.php-versions }}) + runs-on: ubuntu-latest + env: + DB_USERNAME: root + DB_PASSWORD: yii + TEST_DB_USERNAME: root + TEST_DB_PASSWORD: yii + DB_CHARSET: utf8 + + # Docs: https://docs.github.com/en/actions/using-containerized-services + services: + mysql: + image: mysql:latest + env: + MYSQL_ALLOW_EMPTY_PASSWORD: false + MYSQL_ROOT_PASSWORD: yii + MYSQL_DATABASE: yii + ports: + - 3306/tcp + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set Node.js 10.x + uses: actions/setup-node@v1 + with: + node-version: 10.x + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, intl, gd, imagick, zip, dom, mysql + coverage: xdebug + + # Local MySQL service in GitHub hosted environments is disabled by default. + # If you are using it instead of service containers, make sure you start it. + # - name: Start mysql service + # run: sudo systemctl start mysql.service + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Prepare the application + run: | + php -r "file_exists('.env') || copy('.env.dist', '.env');" + php console/yii app/setup + npm install --development + npm run build + env: + DB_DSN: mysql:host=127.0.0.1;port=${{ job.services.mysql.ports['3306'] }};dbname=yii + TEST_DB_DSN: mysql:host=127.0.0.1;port=${{ job.services.mysql.ports['3306'] }};dbname=yii + + - name: Run Tests + run: | + vendor/bin/codecept build + php tests/bin/yii app/setup --interactive=0 + nohup php -S localhost:8080 > yii.log 2>&1 & + vendor/bin/codecept run + env: + DB_DSN: mysql:host=127.0.0.1;port=${{ job.services.mysql.ports['3306'] }};dbname=yii + TEST_DB_DSN: mysql:host=127.0.0.1;port=${{ job.services.mysql.ports['3306'] }};dbname=yii diff --git a/examples/yii2-postgres.yml b/examples/yii2-postgres.yml new file mode 100644 index 0000000..c69c573 --- /dev/null +++ b/examples/yii2-postgres.yml @@ -0,0 +1,86 @@ +# GitHub Action for Yii Framework with PostgreSQL +name: Testing Yii2 with PostgreSQL +on: [push, pull_request] +jobs: + yii: + name: Yii2 (PHP ${{ matrix.php-versions }}) + runs-on: ubuntu-latest + env: + DB_USERNAME: postgres + DB_PASSWORD: postgres + TEST_DB_USERNAME: postgres + TEST_DB_PASSWORD: postgres + DB_CHARSET: utf8 + + # Docs: https://docs.github.com/en/actions/using-containerized-services + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432/tcp + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0'] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set Node.js 10.x + uses: actions/setup-node@v1 + with: + node-version: 10.x + + # Docs: https://github.com/shivammathur/setup-php + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, intl, gd, imagick, zip, dom, pgsql + coverage: xdebug + + # Local PostgreSQL service in GitHub hosted environments is disabled by default. + # If you are using it instead of service containers, make sure you start it. + # - name: Start postgresql service + # run: sudo systemctl start postgresql.service + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Prepare the application + run: | + php -r "file_exists('.env') || copy('.env.dist', '.env');" + php console/yii app/setup + npm install --development + npm run build + env: + DB_DSN: pgsql:host=127.0.0.1;port=${{ job.services.postgres.ports['5432'] }};dbname=postgres + TEST_DB_DSN: pgsql:host=127.0.0.1;port=${{ job.services.postgres.ports['5432'] }};dbname=postgres + + - name: Run Tests + run: | + vendor/bin/codecept build + php tests/bin/yii app/setup --interactive=0 + nohup php -S localhost:8080 > yii.log 2>&1 & + vendor/bin/codecept run + env: + DB_DSN: pgsql:host=127.0.0.1;port=${{ job.services.postgres.ports['5432'] }};dbname=postgres + TEST_DB_DSN: pgsql:host=127.0.0.1;port=${{ job.services.postgres.ports['5432'] }};dbname=postgres diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..f670531 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,12 @@ +module.exports = { + clearMocks: true, + moduleFileExtensions: ['js', 'ts'], + testEnvironment: 'node', + testMatch: ['**/*.test.ts'], + testRunner: 'jest-circus/runner', + transform: { + '^.+\\.ts$': 'ts-jest' + }, + verbose: true, + collectCoverage: true +}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..863e018 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,11566 @@ +{ + "name": "setup-php", + "version": "2.28.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "setup-php", + "version": "2.28.0", + "license": "MIT", + "dependencies": { + "@actions/core": "^1.10.1", + "@actions/exec": "^1.1.1", + "@actions/io": "^1.1.3", + "compare-versions": "^6.1.0" + }, + "devDependencies": { + "@types/jest": "^29.5.10", + "@types/node": "^20.10.0", + "@typescript-eslint/eslint-plugin": "^6.12.0", + "@typescript-eslint/parser": "^6.12.0", + "@vercel/ncc": "^0.38.1", + "eslint": "^8.54.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-import": "^2.29.0", + "eslint-plugin-jest": "^27.6.0", + "eslint-plugin-prettier": "^5.0.1", + "jest": "^29.7.0", + "jest-circus": "^29.7.0", + "nock": "^13.3.8", + "prettier": "^3.1.0", + "simple-git-hooks": "^2.9.0", + "ts-jest": "^29.1.1", + "typescript": "^5.3.2" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@actions/core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", + "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", + "dependencies": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "dependencies": { + "@actions/io": "^1.0.1" + } + }, + "node_modules/@actions/http-client": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", + "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", + "dependencies": { + "tunnel": "^0.0.6" + } + }, + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==" + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/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/code-frame/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/code-frame/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/code-frame/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/code-frame/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/code-frame/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/code-frame/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/compat-data": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz", + "integrity": "sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz", + "integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helpers": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "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.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz", + "integrity": "sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/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/@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-compilation-targets/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/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz", + "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz", + "integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/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.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "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.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "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.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "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.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "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/@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.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "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.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.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.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "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/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/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/@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/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", + "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": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "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.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "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.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "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/@pkgr/utils": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", + "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "fast-glob": "^3.3.0", + "is-glob": "^4.0.3", + "open": "^9.1.0", + "picocolors": "^1.0.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@pkgr/utils/node_modules/tslib": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", + "dev": true + }, + "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.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "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.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "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.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz", + "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.10", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.10.tgz", + "integrity": "sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "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/node": { + "version": "20.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", + "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", + "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/type-utils": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "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" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.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/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.12.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/@typescript-eslint/parser": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", + "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.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/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.12.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/@typescript-eslint/scope-manager": { + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.1.tgz", + "integrity": "sha512-Dn/LnN7fEoRD+KspEOV0xDMynEmR3iSHdgNsarlXNLGGtcUok8L4N71dxUgt3YvlO8si7E+BJ5Fe3wb5yUw7DQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/visitor-keys": "5.60.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", + "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.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/type-utils/node_modules/@typescript-eslint/utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.12.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/@typescript-eslint/types": { + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.1.tgz", + "integrity": "sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==", + "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.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.1.tgz", + "integrity": "sha512-hkX70J9+2M2ZT6fhti5Q2FoU9zb+GeZK2SLP1WZlvUDqdMbEKhexZODD1WodNRyO8eS+4nScvT0dts8IdaBzfw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/visitor-keys": "5.60.1", + "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.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.1.tgz", + "integrity": "sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ==", + "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.60.1", + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/typescript-estree": "5.60.1", + "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/visitor-keys": { + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.1.tgz", + "integrity": "sha512-xEYIxKcultP6E/RMKqube11pGjXH1DCo60mQoWhVYyKfLkwbIVVjYxmOenNMxILx0TjCujPTjjnTIVzm09TXIw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.60.1", + "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/@vercel/ncc": { + "version": "0.38.1", + "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.1.tgz", + "integrity": "sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==", + "dev": true, + "bin": { + "ncc": "dist/ncc/cli.js" + } + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "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-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==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "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.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + }, + "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.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "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-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/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.44" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "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.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.21.9", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", + "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", + "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.30001503", + "electron-to-chromium": "^1.4.431", + "node-releases": "^2.0.12", + "update-browserslist-db": "^1.0.11" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "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/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/bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "dependencies": { + "run-applescript": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "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/caniuse-lite": { + "version": "1.0.30001509", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001509.tgz", + "integrity": "sha512-2uDDk+TRiTX5hMcUYT/7CSyzMZxjfGu0vAUjS2g0LSD8UoXOv0LtpH4LxGMemsiPq6LCVIUjNwVM0erkOkGCDA==", + "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.5.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", + "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", + "dev": true + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "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/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/compare-versions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz", + "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==" + }, + "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/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/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/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "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==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "dev": true, + "dependencies": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "dependencies": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/default-browser/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/default-browser/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/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/electron-to-chromium": { + "version": "1.4.447", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.447.tgz", + "integrity": "sha512-sxX0LXh+uL41hSJsujAN86PjhrV/6c79XmpY0TvjZStV6VxIgarf8SRkUoUTuYmFcZQTemsoqo8qXOGw5npWfw==", + "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/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + }, + "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.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "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.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.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-prettier": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", + "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "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.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "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-plugin-prettier": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz", + "integrity": "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.5" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "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/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/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/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/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/eslint/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/eslint/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/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/esquery/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/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/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "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/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/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/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-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "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.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "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.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "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/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==", + "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/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "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/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "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.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "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.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "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.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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/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/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "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-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/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "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.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "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==", + "dev": true + }, + "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.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "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-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "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-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-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "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-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "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-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-wsl/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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/istanbul-lib-instrument/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/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.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "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/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==", + "dev": true, + "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-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": "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/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/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/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "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/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-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/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "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/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/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.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/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/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/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/nock": { + "version": "13.3.8", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.8.tgz", + "integrity": "sha512-96yVFal0c/W1lG7mmfRe7eO+hovrhJYd2obzzOZ90f6fjpeU/XNvd9cYHZKZAQJumDfhXgoTpkpJ9pvMj+hqHw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "propagate": "^2.0.0" + }, + "engines": { + "node": ">= 10.13" + } + }, + "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.12", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", + "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", + "dev": 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==", + "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.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, + "node_modules/object.values": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "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/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/open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dev": true, + "dependencies": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "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": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/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/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==", + "dev": true, + "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/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-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.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.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/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-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/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/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/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/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.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "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-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "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/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-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-cwd/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-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.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/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "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.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "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.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "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/simple-git-hooks": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/simple-git-hooks/-/simple-git-hooks-2.9.0.tgz", + "integrity": "sha512-waSQ5paUQtyGC0ZxlHmcMmD9I1rRXauikBwX31bX58l5vTOhCEcBC5Bi+ZDkPXTjDnZAF8TbCqKBY+9+sVPScw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "simple-git-hooks": "cli.js" + } + }, + "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/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/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.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "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/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.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "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-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "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/synckit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dev": true, + "dependencies": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/synckit/node_modules/tslib": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", + "dev": true + }, + "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-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/ts-api-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", + "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "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==", + "dev": true + }, + "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/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "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/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "dev": 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==", + "dev": true + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "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.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "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/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", + "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", + "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/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/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.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "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": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "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" + } + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@actions/core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", + "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", + "requires": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "requires": { + "@actions/io": "^1.0.1" + } + }, + "@actions/http-client": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", + "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", + "requires": { + "tunnel": "^0.0.6" + } + }, + "@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==" + }, + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "requires": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "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 + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/compat-data": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz", + "integrity": "sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==", + "dev": true + }, + "@babel/core": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz", + "integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helpers": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.0" + }, + "dependencies": { + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "requires": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz", + "integrity": "sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", + "semver": "^6.3.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-transforms": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz", + "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz", + "integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==", + "dev": true, + "requires": { + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5" + } + }, + "@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "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 + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-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, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-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, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + } + }, + "@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@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 + }, + "@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, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "dev": true, + "requires": { + "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" + } + }, + "@eslint/js": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@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 + }, + "@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "@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, + "requires": { + "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" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "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, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "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 + } + } + }, + "@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 + }, + "@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "requires": { + "@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" + } + }, + "@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, + "requires": { + "@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" + } + }, + "@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, + "requires": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + } + }, + "@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, + "requires": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + } + }, + "@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, + "requires": { + "jest-get-type": "^29.6.3" + } + }, + "@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, + "requires": { + "@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" + } + }, + "@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + } + }, + "@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "requires": { + "@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" + }, + "dependencies": { + "istanbul-lib-instrument": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + } + } + } + }, + "@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, + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@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, + "requires": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + } + }, + "@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, + "requires": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@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, + "requires": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "requires": { + "@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" + } + }, + "@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, + "requires": { + "@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" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@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 + }, + "@jridgewell/trace-mapping": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + }, + "dependencies": { + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@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, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@pkgr/utils": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", + "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "fast-glob": "^3.3.0", + "is-glob": "^4.0.3", + "open": "^9.1.0", + "picocolors": "^1.0.0", + "tslib": "^2.6.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", + "dev": true + } + } + }, + "@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 + }, + "@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@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, + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, + "@types/babel__core": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/graceful-fs": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz", + "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "29.5.10", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.10.tgz", + "integrity": "sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==", + "dev": true, + "requires": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true + }, + "@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 + }, + "@types/node": { + "version": "20.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", + "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + }, + "@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "@types/yargs": { + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", + "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/type-utils": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" + } + }, + "@typescript-eslint/types": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "semver": "^7.5.4" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.12.0", + "eslint-visitor-keys": "^3.4.1" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", + "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" + } + }, + "@typescript-eslint/types": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.12.0", + "eslint-visitor-keys": "^3.4.1" + } + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.1.tgz", + "integrity": "sha512-Dn/LnN7fEoRD+KspEOV0xDMynEmR3iSHdgNsarlXNLGGtcUok8L4N71dxUgt3YvlO8si7E+BJ5Fe3wb5yUw7DQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/visitor-keys": "5.60.1" + } + }, + "@typescript-eslint/type-utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", + "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" + } + }, + "@typescript-eslint/types": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "semver": "^7.5.4" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.12.0", + "eslint-visitor-keys": "^3.4.1" + } + } + } + }, + "@typescript-eslint/types": { + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.1.tgz", + "integrity": "sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.1.tgz", + "integrity": "sha512-hkX70J9+2M2ZT6fhti5Q2FoU9zb+GeZK2SLP1WZlvUDqdMbEKhexZODD1WodNRyO8eS+4nScvT0dts8IdaBzfw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/visitor-keys": "5.60.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.1.tgz", + "integrity": "sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.60.1", + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/typescript-estree": "5.60.1", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.1.tgz", + "integrity": "sha512-xEYIxKcultP6E/RMKqube11pGjXH1DCo60mQoWhVYyKfLkwbIVVjYxmOenNMxILx0TjCujPTjjnTIVzm09TXIw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.60.1", + "eslint-visitor-keys": "^3.3.0" + } + }, + "@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 + }, + "@vercel/ncc": { + "version": "0.38.1", + "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.1.tgz", + "integrity": "sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==", + "dev": true + }, + "acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "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 + }, + "array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + } + }, + "array-includes": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-string": "^1.0.7" + } + }, + "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 + }, + "array.prototype.findlastindex": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + } + }, + "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, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "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, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + } + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, + "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, + "requires": { + "@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" + } + }, + "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, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-jest-hoist": { + "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, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + } + }, + "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, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "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, + "requires": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "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 + }, + "big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true + }, + "bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "requires": { + "big-integer": "^1.6.44" + } + }, + "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, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.21.9", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", + "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001503", + "electron-to-chromium": "^1.4.431", + "node-releases": "^2.0.12", + "update-browserslist-db": "^1.0.11" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "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, + "requires": { + "node-int64": "^0.4.0" + } + }, + "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 + }, + "bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "requires": { + "run-applescript": "^5.0.0" + } + }, + "call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001509", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001509.tgz", + "integrity": "sha512-2uDDk+TRiTX5hMcUYT/7CSyzMZxjfGu0vAUjS2g0LSD8UoXOv0LtpH4LxGMemsiPq6LCVIUjNwVM0erkOkGCDA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "ci-info": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", + "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", + "dev": true + }, + "cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "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, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true + }, + "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 + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "compare-versions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz", + "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "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 + }, + "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, + "requires": { + "@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" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "requires": {} + }, + "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 + }, + "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==", + "dev": true + }, + "default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "dev": true, + "requires": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" + }, + "dependencies": { + "execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, + "npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + } + } + }, + "default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "requires": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + } + }, + "define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, + "define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true + }, + "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, + "requires": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "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 + }, + "diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "electron-to-chromium": { + "version": "1.4.447", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.447.tgz", + "integrity": "sha512-sxX0LXh+uL41hSJsujAN86PjhrV/6c79XmpY0TvjZStV6VxIgarf8SRkUoUTuYmFcZQTemsoqo8qXOGw5npWfw==", + "dev": true + }, + "emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true + }, + "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 + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" + } + }, + "es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + } + }, + "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, + "requires": { + "hasown": "^2.0.0" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.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" + }, + "dependencies": { + "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, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "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, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "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, + "requires": { + "p-locate": "^5.0.0" + } + }, + "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, + "requires": { + "p-limit": "^3.0.2" + } + } + } + }, + "eslint-config-prettier": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", + "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "dev": true, + "requires": {} + }, + "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, + "requires": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, + "requires": { + "debug": "^3.2.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "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, + "requires": { + "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" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "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, + "requires": { + "@typescript-eslint/utils": "^5.10.0" + } + }, + "eslint-plugin-prettier": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz", + "integrity": "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.5" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-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 + }, + "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, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true + }, + "expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "requires": { + "@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" + } + }, + "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 + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-glob": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "dev": true, + "requires": { + "@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" + }, + "dependencies": { + "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, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "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 + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "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, + "requires": { + "bser": "2.1.1" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "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, + "requires": { + "is-callable": "^1.1.3" + } + }, + "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 + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "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 + }, + "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, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + } + }, + "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 + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dev": true, + "requires": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "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 + }, + "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 + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "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" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "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" + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "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 + }, + "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 + }, + "has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.2" + } + }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true + }, + "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 + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, + "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 + }, + "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 + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "internal-slot": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + } + }, + "is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "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, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "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 + }, + "is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "requires": { + "hasown": "^2.0.0" + } + }, + "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, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "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 + }, + "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, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "requires": { + "is-docker": "^3.0.0" + } + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "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, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "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 + }, + "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, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "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 + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "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, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "requires": { + "which-typed-array": "^1.1.11" + } + }, + "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, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + }, + "dependencies": { + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + } + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "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, + "requires": { + "@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" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "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, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + } + }, + "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, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + } + }, + "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, + "requires": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + } + }, + "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, + "requires": { + "@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" + } + }, + "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, + "requires": { + "@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" + } + }, + "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, + "requires": { + "@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" + } + }, + "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, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "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, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "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, + "requires": { + "@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" + } + }, + "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, + "requires": { + "@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" + } + }, + "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 + }, + "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, + "requires": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "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" + } + }, + "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, + "requires": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "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, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "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, + "requires": { + "@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" + } + }, + "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, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + } + }, + "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, + "requires": {} + }, + "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 + }, + "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, + "requires": { + "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" + } + }, + "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, + "requires": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + } + }, + "jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "requires": { + "@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" + } + }, + "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, + "requires": { + "@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" + } + }, + "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, + "requires": { + "@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" + } + }, + "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, + "requires": { + "@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" + } + }, + "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, + "requires": { + "@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" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + } + } + }, + "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, + "requires": { + "@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" + } + }, + "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, + "requires": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "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 + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema-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 + }, + "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 + }, + "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 + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "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 + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "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, + "requires": { + "semver": "^7.5.3" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "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 + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "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 + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "nock": { + "version": "13.3.8", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.8.tgz", + "integrity": "sha512-96yVFal0c/W1lG7mmfRe7eO+hovrhJYd2obzzOZ90f6fjpeU/XNvd9cYHZKZAQJumDfhXgoTpkpJ9pvMj+hqHw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "propagate": "^2.0.0" + } + }, + "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-releases": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", + "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "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, + "requires": { + "path-key": "^3.0.0" + } + }, + "object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "object.fromentries": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, + "object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, + "object.values": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, + "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, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dev": true, + "requires": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "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 + }, + "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 + }, + "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 + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-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 + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "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 + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "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 + }, + "prettier": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "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, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "dependencies": { + "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 + } + } + }, + "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, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true + }, + "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 + }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + } + }, + "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 + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "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, + "requires": { + "resolve-from": "^5.0.0" + }, + "dependencies": { + "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 + } + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve.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 + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "requires": { + "execa": "^5.0.0" + } + }, + "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, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + } + }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "requires": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, + "set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "requires": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "simple-git-hooks": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/simple-git-hooks/-/simple-git-hooks-2.9.0.tgz", + "integrity": "sha512-waSQ5paUQtyGC0ZxlHmcMmD9I1rRXauikBwX31bX58l5vTOhCEcBC5Bi+ZDkPXTjDnZAF8TbCqKBY+9+sVPScw==", + "dev": true + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "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, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "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 + } + } + }, + "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, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, + "string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, + "string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "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 + }, + "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 + }, + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "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 + }, + "synckit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dev": true, + "requires": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", + "dev": true + } + } + }, + "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, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "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 + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "ts-api-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", + "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "dev": true, + "requires": {} + }, + "ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + } + }, + "tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "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, + "requires": { + "minimist": "^1.2.0" + } + }, + "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 + } + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-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 + }, + "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 + }, + "typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, + "typescript": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "dev": true + }, + "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, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "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==", + "dev": true + }, + "untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "v8-to-istanbul": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", + "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "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, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "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" + } + }, + "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 + }, + "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 + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..82396ec --- /dev/null +++ b/package.json @@ -0,0 +1,67 @@ +{ + "name": "setup-php", + "version": "2.28.0", + "private": false, + "description": "Setup PHP for use with GitHub Actions", + "main": "lib/install.js", + "types": "lib/install.d.ts", + "directories": { + "lib": "lib", + "test": "__tests__", + "src": "src" + }, + "files": [ + "lib", + "src" + ], + "scripts": { + "build": "tsc", + "lint": "eslint **/src/*.ts **/__tests__/*.ts --cache --fix", + "format": "prettier --write **/src/*.ts **/__tests__/*.ts && git add -f __tests__/ ", + "format-check": "prettier --check **/src/*.ts **/__tests__/*.ts", + "release": "ncc build -o dist && git add -f dist/", + "test": "jest" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/shivammathur/setup-php.git" + }, + "keywords": [ + "actions", + "php", + "setup" + ], + "author": "shivammathur", + "license": "MIT", + "dependencies": { + "@actions/core": "^1.10.1", + "@actions/exec": "^1.1.1", + "@actions/io": "^1.1.3", + "compare-versions": "^6.1.0" + }, + "devDependencies": { + "@types/jest": "^29.5.10", + "@types/node": "^20.10.0", + "@typescript-eslint/eslint-plugin": "^6.12.0", + "@typescript-eslint/parser": "^6.12.0", + "@vercel/ncc": "^0.38.1", + "eslint": "^8.54.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-import": "^2.29.0", + "eslint-plugin-jest": "^27.6.0", + "eslint-plugin-prettier": "^5.0.1", + "jest": "^29.7.0", + "jest-circus": "^29.7.0", + "nock": "^13.3.8", + "prettier": "^3.1.0", + "simple-git-hooks": "^2.9.0", + "ts-jest": "^29.1.1", + "typescript": "^5.3.2" + }, + "bugs": { + "url": "https://github.com/shivammathur/setup-php/issues" + }, + "simple-git-hooks": { + "pre-commit": "npm run format && npm run lint && npm run test && npm run build && npm run release" + } +} diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..07f8976 --- /dev/null +++ b/src/config.ts @@ -0,0 +1,82 @@ +import * as utils from './utils'; + +/** + * Add script to set custom ini values for unix + * + * @param ini_values_csv + */ +export async function addINIValuesUnix( + ini_values_csv: string +): Promise { + const ini_values: Array = await utils.CSVArray(ini_values_csv); + let script = ''; + await utils.asyncForEach(ini_values, async function (line: string) { + script += + '\n' + (await utils.addLog('$tick', line, 'Added to php.ini', 'linux')); + }); + return ( + 'echo "' + + ini_values.join('\n') + + '" | sudo tee -a "${pecl_file:-${ini_file[@]}}" >/dev/null 2>&1' + + script + ); +} + +/** + * Add script to set custom ini values for windows + * + * @param ini_values_csv + */ +export async function addINIValuesWindows( + ini_values_csv: string +): Promise { + const ini_values: Array = await utils.CSVArray(ini_values_csv); + let script = '\n'; + await utils.asyncForEach(ini_values, async function (line: string) { + script += + (await utils.addLog('$tick', line, 'Added to php.ini', 'win32')) + '\n'; + }); + return ( + 'Add-Content "$php_dir\\php.ini" "' + ini_values.join('\n') + '"' + script + ); +} + +/** + * Function to add custom ini values + * + * @param ini_values_csv + * @param os + * @param no_step + */ +export async function addINIValues( + ini_values_csv: string, + os: string, + no_step = false +): Promise { + let script = '\n'; + switch (no_step) { + case true: + script += + (await utils.stepLog('Add php.ini values', os)) + + (await utils.suppressOutput(os)) + + '\n'; + break; + case false: + default: + script += (await utils.stepLog('Add php.ini values', os)) + '\n'; + break; + } + switch (os) { + case 'win32': + return script + (await addINIValuesWindows(ini_values_csv)); + case 'darwin': + case 'linux': + return script + (await addINIValuesUnix(ini_values_csv)); + default: + return await utils.log( + 'Platform ' + os + ' is not supported', + os, + 'error' + ); + } +} diff --git a/src/configs/brew_extensions b/src/configs/brew_extensions new file mode 100644 index 0000000..729023b --- /dev/null +++ b/src/configs/brew_extensions @@ -0,0 +1,44 @@ +amqp=amqp +apcu=apcu +ast=ast +couchbase=couchbase +ds=ds +event=event +expect=expect +gearman=gearman +gnupg=gnupg +grpc=grpc +igbinary=igbinary +imagick=imagick +imap=imap +lua=lua +mailparse=mailparse +mcrypt=mcrypt +memcache=memcache +memcached=memcached +mongodb=mongodb +msgpack=msgpack +pcov=pcov +pdo_sqlsrv=pdo_sqlsrv +pecl_http=http +phalcon3=phalcon +phalcon4=phalcon +phalcon5=phalcon +propro=propro +protobuf=protobuf +psr=psr +raphf=raphf +rdkafka=rdkafka +redis=redis +snmp=snmp +sqlsrv=sqlsrv +ssh2=ssh2 +swoole=swoole +uuid=uuid +v8js=v8js +vips=vips +xdebug=xdebug +xdebug2=xdebug +xlswriter=xlswriter +yaml=yaml +zmq=zmq diff --git a/src/configs/composer.env b/src/configs/composer.env new file mode 100644 index 0000000..6335d61 --- /dev/null +++ b/src/configs/composer.env @@ -0,0 +1,3 @@ +COMPOSER_PROCESS_TIMEOUT=0 +COMPOSER_NO_INTERACTION=1 +COMPOSER_NO_AUDIT=1 diff --git a/src/configs/ini/jit.ini b/src/configs/ini/jit.ini new file mode 100644 index 0000000..0fe0350 --- /dev/null +++ b/src/configs/ini/jit.ini @@ -0,0 +1,3 @@ +opcache.enable=1 +opcache.jit_buffer_size=256M +opcache.jit=1235 diff --git a/src/configs/ini/php.ini b/src/configs/ini/php.ini new file mode 100644 index 0000000..494cfc8 --- /dev/null +++ b/src/configs/ini/php.ini @@ -0,0 +1,2 @@ +date.timezone=UTC +memory_limit=-1 diff --git a/src/configs/ini/xdebug.ini b/src/configs/ini/xdebug.ini new file mode 100644 index 0000000..cea362e --- /dev/null +++ b/src/configs/ini/xdebug.ini @@ -0,0 +1 @@ +xdebug.mode=coverage diff --git a/src/configs/mod_priority b/src/configs/mod_priority new file mode 100644 index 0000000..4eda30d --- /dev/null +++ b/src/configs/mod_priority @@ -0,0 +1,30 @@ +apc=25 +apcu_bc=25 +apcu-bc=25 +blackfire=30 +couchbase=30 +decimal=30 +ds=30 +event=30 +grpc=30 +http=25 +pecl_http=25 +pecl-http=25 +psr=15 +inotify=30 +libvirt-php=40 +mailparse=25 +maxminddb=30 +memcached=25 +mysqlnd=10 +mysqlnd_ms=30 +opcache=10 +pdo=10 +phalcon=35 +protobuf=30 +psr=15 +rdkafka=30 +swoole=25 +vips=30 +xml=15 +zstd=30 diff --git a/src/configs/os_releases.csv b/src/configs/os_releases.csv new file mode 100644 index 0000000..a0041d4 --- /dev/null +++ b/src/configs/os_releases.csv @@ -0,0 +1,22 @@ +8,jessie +9,stretch +10,buster +11,bullseye +12,bookworm +13,trixie +16.04 LTS,xenial +16.10,yakkety +17.04,zesty +17.10,artful +18.04 LTS,bionic +18.10,cosmic +19.04,disco +19.10,eoan +20.04 LTS,focal +20.10,groovy +21.04,hirsute +21.10,impish +22.04,jammy +23.04,lunar +23.10,mantic +24.04,noble diff --git a/src/configs/php-versions.json b/src/configs/php-versions.json new file mode 100644 index 0000000..aa48bae --- /dev/null +++ b/src/configs/php-versions.json @@ -0,0 +1,7 @@ +{ + "latest": "8.3", + "nightly": "8.4", + "5.x": "5.6", + "7.x": "7.4", + "8.x": "8.3" +} \ No newline at end of file diff --git a/src/configs/php_debug_packages b/src/configs/php_debug_packages new file mode 100644 index 0000000..5475016 --- /dev/null +++ b/src/configs/php_debug_packages @@ -0,0 +1,11 @@ +cgi +cli +curl +fpm +intl +mbstring +mysql +opcache +pgsql +xml +zip diff --git a/src/configs/php_packages b/src/configs/php_packages new file mode 100644 index 0000000..cf581a0 --- /dev/null +++ b/src/configs/php_packages @@ -0,0 +1,12 @@ +cgi +cli +curl +dev +fpm +intl +mbstring +mysql +opcache +pgsql +xml +zip diff --git a/src/configs/pm/php.json b/src/configs/pm/php.json new file mode 100644 index 0000000..1f0ee8b --- /dev/null +++ b/src/configs/pm/php.json @@ -0,0 +1,29 @@ +{ + "problemMatcher": [ + { + "owner": "php_native_error", + "severity": "error", + "pattern": [ + { + "regexp": "^(.*error):\\s+\\s+(.+) in (.+) on line (\\d+)$", + "code": 1, + "message": 2, + "file": 3, + "line": 4 + } + ] + }, { + "owner": "php_native_warning", + "severity": "warning", + "pattern": [ + { + "regexp": "^(.*Warning|.*Deprecated|.*Notice):\\s+\\s+(.+) in (.+) on line (\\d+)$", + "code": 1, + "message": 2, + "file": 3, + "line": 4 + } + ] + } + ] +} diff --git a/src/configs/pm/phpunit.json b/src/configs/pm/phpunit.json new file mode 100644 index 0000000..2cc9dab --- /dev/null +++ b/src/configs/pm/phpunit.json @@ -0,0 +1,24 @@ +{ + "problemMatcher": [ + { + "owner": "phpunit", + "pattern": [ + { + "regexp": "^\\d+\\)\\s.*$" + }, + { + "regexp": "^(.*Failed\\sasserting\\sthat.*)$", + "message": 1 + }, + { + "regexp": "^\\s*$" + }, + { + "regexp": "^(.*):(\\d+)$", + "file": 1, + "line": 2 + } + ] + } + ] +} diff --git a/src/configs/tools.json b/src/configs/tools.json new file mode 100644 index 0000000..437ff38 --- /dev/null +++ b/src/configs/tools.json @@ -0,0 +1,322 @@ +{ + "box": { + "type": "phar", + "repository": "box-project/box", + "packagist": "humbug/box", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "--version" + }, + "churn": { + "type": "phar", + "repository": "bmitch/churn-php", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "-V" + }, + "composer-unused": { + "type": "phar", + "repository": "composer-unused/composer-unused", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "-V" + }, + "composer-normalize": { + "type": "phar", + "repository": "ergebnis/composer-normalize", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "-V" + }, + "cs2pr": { + "type": "phar", + "repository": "staabm/annotate-pull-request-from-checkstyle", + "extension": "", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "-V" + }, + "infection": { + "type": "phar", + "repository": "infection/infection", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "-V" + }, + "phan": { + "type": "phar", + "repository": "phan/phan", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "-v" + }, + "parallel-lint": { + "type": "phar", + "repository": "php-parallel-lint/PHP-Parallel-Lint", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "v", + "version_parameter": "--version" + }, + "php-cs-fixer": { + "type": "phar", + "repository": "FriendsOfPHP/PHP-CS-Fixer", + "extension": ".phar", + "domain": "https://github.com", + "fetch_latest": "true", + "version_prefix": "v", + "version_parameter": "-V" + }, + "php-scoper": { + "type": "phar", + "repository": "humbug/php-scoper", + "packagist": "humbug/php-scoper", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "--version" + }, + "phpcbf": { + "type": "phar", + "repository": "PHPCSStandards/PHP_CodeSniffer", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "--version" + }, + "phpcs": { + "type": "phar", + "repository": "PHPCSStandards/PHP_CodeSniffer", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "--version" + }, + "phpDocumentor": { + "type": "phar", + "repository": "phpDocumentor/phpDocumentor", + "extension": ".phar", + "domain": "https://github.com", + "alias": "phpdoc", + "version_prefix": "v", + "version_parameter": "--version" + }, + "phpmd": { + "type": "phar", + "repository": "phpmd/phpmd", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "--version" + }, + "phpspec": { + "type": "phar", + "repository": "phpspec/phpspec", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "-V" + }, + "phpstan": { + "type": "phar", + "repository": "phpstan/phpstan", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "-V" + }, + "pint": { + "type": "phar", + "repository": "laravel/pint", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "v", + "version_parameter": "-V" + }, + "psalm": { + "type": "phar", + "repository": "vimeo/psalm", + "extension": ".phar", + "domain": "https://github.com", + "version_prefix": "", + "version_parameter": "-v" + }, + "behat": { + "type": "composer", + "repository": "behat/behat", + "scope": "scoped" + }, + "codeception": { + "type": "composer", + "repository": "codeception/codeception", + "scope": "scoped" + }, + "automatic-composer-prefetcher": { + "type": "composer", + "alias": "composer-prefetcher", + "repository": "narrowspark/automatic-composer-prefetcher", + "scope": "global" + }, + "composer-require-checker": { + "type": "composer", + "repository": "maglnet/composer-require-checker", + "scope": "scoped" + }, + "flex": { + "type": "composer", + "repository": "symfony/flex", + "scope": "global" + }, + "phinx": { + "type": "composer", + "repository": "robmorgan/phinx", + "scope": "scoped" + }, + "phplint": { + "type": "composer", + "repository": "overtrue/phplint", + "scope": "scoped" + }, + "phpunit-bridge": { + "alias": "simple-phpunit", + "type": "composer", + "repository": "symfony/phpunit-bridge", + "scope": "global" + }, + "phpunit-polyfills": { + "type": "composer", + "repository": "yoast/phpunit-polyfills", + "scope": "global" + }, + "prestissimo": { + "type": "composer", + "repository": "hirak/prestissimo", + "scope": "global" + }, + "vapor-cli": { + "type": "composer", + "alias": "vapor", + "repository": "laravel/vapor-cli", + "scope": "scoped" + }, + "rector": { + "type": "composer", + "repository": "rector/rector", + "scope": "scoped" + }, + "blackfire": { + "type": "custom-package", + "alias": "blackfire-agent" + }, + "grpc_php_plugin": { + "type": "custom-package", + "repository": "grpc/grpc", + "domain": "https://github.com", + "version_prefix": "v" + }, + "protoc": { + "type": "custom-package", + "repository": "protocolbuffers/protobuf", + "domain": "https://github.com", + "version_prefix": "v" + }, + "symfony-cli": { + "alias": "symfony", + "type": "custom-package", + "repository": "symfony-cli/symfony-cli", + "domain": "https://github.com", + "version_prefix": "-V" + }, + "blackfire-player": { + "type": "custom-function", + "domain": "https://get.blackfire.io", + "function": "blackfire_player", + "version_prefix": "v", + "version_parameter": "-V" + }, + "castor": { + "type": "custom-function", + "domain": "https://github.com", + "repository": "jolicode/castor", + "function": "castor", + "version_prefix": "v", + "version_parameter": "-V" + }, + "composer": { + "type": "custom-function", + "domain": "https://getcomposer.org", + "repository": "composer/composer", + "function": "composer" + }, + "deployer": { + "type": "custom-function", + "domain": "https://deployer.org", + "repository": "deployphp/deployer", + "function": "deployer", + "version_prefix": "v", + "version_parameter": "-V" + }, + "pecl": { + "type": "custom-function", + "function": "pecl" + }, + "phing": { + "type": "custom-function", + "domain": "https://www.phing.info", + "repository": "phingofficial/phing", + "function": "phing", + "extension": ".phar", + "version_prefix": "", + "version_parameter": "-v" + }, + "phive": { + "type": "custom-function", + "repository": "phar-io/phive", + "domain": "https://github.com", + "function": "phive", + "version_prefix": "", + "version_parameter": "status" + }, + "phpcpd": { + "type": "custom-function", + "repository": "sebastianbergmann/phpcpd", + "domain": "https://phar.phpunit.de", + "function": "phpcpd", + "version_prefix": "", + "version_parameter": "--version" + }, + "phpunit": { + "type": "custom-function", + "repository": "sebastianbergmann/phpunit", + "packagist": "phpunit/phpunit", + "domain": "https://phar.phpunit.de", + "function": "phpunit", + "version_prefix": "", + "version_parameter": "--version" + }, + "phpize": { + "type": "custom-function", + "function": "dev_tools", + "alias": "php-config" + }, + "php-config": { + "type": "custom-function", + "function": "dev_tools" + }, + "wp-cli": { + "type": "custom-function", + "function": "wp_cli", + "repository": "wp-cli/wp-cli", + "domain": "https://github.com", + "alias": "wp", + "extension": ".phar", + "version_parameter": "--version", + "version_prefix": "v" + } +} \ No newline at end of file diff --git a/src/configs/tools_schema.json b/src/configs/tools_schema.json new file mode 100644 index 0000000..a85d308 --- /dev/null +++ b/src/configs/tools_schema.json @@ -0,0 +1,136 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://raw.githubusercontent.com/shivammathur/setup-php/develop/src/configs/tools_schema.json", + "type": "object", + "title": "Tools", + "default": {}, + "examples": [ + { + "tool": { + "alias": "tool_alias", + "domain": "https://example.com", + "extension": ".ext", + "fetch_latest": "true", + "function": "function_name", + "repository": "user/tool", + "packagist": "user/tool", + "scope": "global, scoped", + "type": "phar, composer, custom-package or custom-function", + "version_parameter": "--version", + "version_prefix": "v" + } + } + ], + "items": { + "properties": { + "alias": { + "$id": "#/items/properties/alias", + "type": "string", + "title": "The alias schema", + "description": "Alias for a tool.", + "examples": [ + "tool_alias" + ] + }, + "domain": { + "$id": "#/items/properties/domain", + "type": "string", + "title": "The domain schema", + "description": "Domain URL of the tool.", + "examples": [ + "https://example.com" + ] + }, + "extension": { + "$id": "#/items/properties/extension", + "type": "string", + "title": "The extension schema", + "description": "File extension of the tool.", + "examples": [ + ".ext" + ] + }, + "fetch_latest": { + "$id": "#/items/properties/fetch_latest", + "type": "string", + "title": "The fetch_latest schema", + "description": "Fetch the latest version from GitHub releases.", + "enum": [ + "true", + "false" + ] + }, + "function": { + "$id": "#/items/properties/function", + "type": "string", + "title": "The function schema", + "description": "Function name in tools.ts which returns the script to setup the tool.", + "examples": [ + "function_name" + ] + }, + "repository": { + "$id": "#/items/properties/repository", + "type": "string", + "title": "The repository schema", + "description": "GitHub repository of the tool.", + "examples": [ + "user/tool" + ] + }, + "packagist": { + "$id": "#/items/properties/packagist", + "type": "string", + "title": "The repository schema", + "description": "Packagist repository of the tool in case different from repository.", + "examples": [ + "user/tool" + ] + }, + "scope": { + "$id": "#/items/properties/scope", + "type": "string", + "title": "The scope schema", + "description": "Scope of tool installation: global or scoped", + "enum": [ + "global", + "scoped" + ] + }, + "type": { + "$id": "#/items/properties/type", + "type": "string", + "title": "The type schema", + "description": "Type of tool: phar, composer, custom-package or custom-function.", + "enum": [ + "phar", + "composer", + "custom-package", + "custom-function" + ] + }, + "version_parameter": { + "$id": "#/items/properties/version_parameter", + "type": "string", + "title": "The version_parameter schema", + "description": "Parameter to get the tool version.", + "examples": [ + "--version" + ] + }, + "version_prefix": { + "$id": "#/items/properties/version_prefix", + "type": "string", + "title": "The version_prefix schema", + "description": "Prefix of the version in the download URL.", + "examples": [ + "v" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": true + } +} \ No newline at end of file diff --git a/src/configs/windows_extensions b/src/configs/windows_extensions new file mode 100644 index 0000000..1a8c801 --- /dev/null +++ b/src/configs/windows_extensions @@ -0,0 +1,2 @@ +xdebug +pcov \ No newline at end of file diff --git a/src/coverage.ts b/src/coverage.ts new file mode 100644 index 0000000..0b92b86 --- /dev/null +++ b/src/coverage.ts @@ -0,0 +1,149 @@ +import * as utils from './utils'; +import * as extensions from './extensions'; +import * as config from './config'; + +export async function checkXdebugError( + extension: string, + version: string +): Promise { + if ( + (/^5\.[3-6]$|^7\.[0-1]$/.test(version) && extension == 'xdebug3') || + (/^8\.[0-9]$/.test(version) && extension == 'xdebug2') + ) { + return extension + ' is not supported on PHP ' + version; + } + return ''; +} + +/** + * Function to set up Xdebug + * + * @param extension + * @param version + * @param os + * @param pipe + */ +export async function addCoverageXdebug( + extension: string, + version: string, + os: string, + pipe: string +): Promise { + let script = '\n'; + const error: string = await checkXdebugError(extension, version); + if (!error) { + script += + (await extensions.addExtension(':pcov:false', version, os, true)) + pipe; + extension = extension == 'xdebug3' ? 'xdebug' : extension; + script += + (await extensions.addExtension(extension, version, os, true)) + pipe; + script += await utils.setVariable( + 'xdebug_version', + 'php -r "echo phpversion(\'xdebug\');"', + os + ); + script += + (await utils.getCommand(os, 'extension_log')) + + 'xdebug "Xdebug $xdebug_version enabled as coverage driver"'; + } else { + script += await utils.addLog('$cross', extension, error, os); + } + return script; +} + +/** + * Function to set up PCOV + * + * @param version + * @param os + * @param pipe + */ +export async function addCoveragePCOV( + version: string, + os: string, + pipe: string +): Promise { + let script = '\n'; + switch (true) { + default: + script += + (await extensions.addExtension(':xdebug:false', version, os, true)) + + pipe; + script += + (await extensions.addExtension('pcov', version, os, true)) + pipe; + script += (await config.addINIValues('pcov.enabled=1', os, true)) + '\n'; + script += await utils.setVariable( + 'pcov_version', + 'php -r "echo phpversion(\'pcov\');"', + os + ); + script += + (await utils.getCommand(os, 'extension_log')) + + 'pcov "PCOV $pcov_version enabled as coverage driver"'; + break; + + case /5\.[3-6]|7\.0/.test(version): + script += await utils.addLog( + '$cross', + 'pcov', + 'PHP 7.1 or newer is required', + os + ); + break; + } + + return script; +} + +/** + * Function to disable Xdebug and PCOV + * + * @param version + * @param os + * @param pipe + */ +export async function disableCoverage( + version: string, + os: string, + pipe: string +): Promise { + let script = '\n'; + script += + (await extensions.addExtension(':pcov:false', version, os, true)) + pipe; + script += + (await extensions.addExtension(':xdebug:false', version, os, true)) + pipe; + script += await utils.addLog('$tick', 'none', 'Disabled Xdebug and PCOV', os); + + return script; +} + +/** + * Function to set coverage driver + * + * @param coverage_driver + * @param version + * @param os + */ +export async function addCoverage( + coverage_driver: string, + version: string, + os: string +): Promise { + coverage_driver = coverage_driver.toLowerCase(); + const script: string = '\n' + (await utils.stepLog('Setup Coverage', os)); + const pipe: string = (await utils.suppressOutput(os)) + '\n'; + switch (coverage_driver) { + case 'pcov': + return script + (await addCoveragePCOV(version, os, pipe)); + case 'xdebug': + case 'xdebug2': + case 'xdebug3': + return ( + script + (await addCoverageXdebug(coverage_driver, version, os, pipe)) + ); + case 'none': + return script + (await disableCoverage(version, os, pipe)); + default: + return ''; + } +} diff --git a/src/extensions.ts b/src/extensions.ts new file mode 100644 index 0000000..743db27 --- /dev/null +++ b/src/extensions.ts @@ -0,0 +1,388 @@ +import * as utils from './utils'; + +/** + * Install and enable extensions for darwin + * + * @param extension_csv + * @param version + */ +export async function addExtensionDarwin( + extension_csv: string, + version: string +): Promise { + const extensions: Array = await utils.extensionArray(extension_csv); + let add_script = '\n'; + let remove_script = ''; + await utils.asyncForEach(extensions, async function (extension: string) { + const version_extension: string = version + extension; + const [ext_name, ext_version]: string[] = extension.split('-'); + const ext_prefix = await utils.getExtensionPrefix(ext_name); + + switch (true) { + // match :extension + case /^:/.test(ext_name): + remove_script += '\ndisable_extension' + ext_name.replace(/:/g, ' '); + return; + // Match none + case /^none$/.test(ext_name): + add_script += '\ndisable_all_shared'; + return; + // match extensions for compiling from source + case /.+-.+\/.+@.+/.test(extension): + add_script += await utils.parseExtensionSource(extension, ext_prefix); + return; + // match 7.4relay...8.3relay + // match 5.3blackfire...8.3blackfire + // match 5.3blackfire-(semver)...8.3blackfire-(semver) + // match couchbase, event, geos, pdo_oci, oci8, http, pecl_http + // match 5.3ioncube...7.4ioncube + // match 7.0phalcon3...7.3phalcon3, 7.2phalcon4...7.4phalcon4, and 7.4phalcon5...8.2phalcon5 + // match 7.0zephir_parser...8.2zephir_parser + case /^(7\.4|8\.[0-3])relay(-v?\d+\.\d+\.\d+)?$/.test(version_extension): + case /^(5\.[3-6]|7\.[0-4]|8\.[0-3])blackfire(-\d+\.\d+\.\d+)?$/.test( + version_extension + ): + case /^couchbase|^event|^gearman$|^geos$|^pdo_oci$|^oci8$|^(pecl_)?http|^pdo_firebird$/.test( + extension + ): + case /^(5\.[3-6]|7\.[0-4])ioncube$/.test(version_extension): + case /(5\.6|7\.[0-3])phalcon3|7\.[2-4]phalcon4|(7\.4|8\.[0-2])phalcon5/.test( + version_extension + ): + case /(? { + const extensions: Array = await utils.extensionArray(extension_csv); + let add_script = '\n'; + let remove_script = ''; + await utils.asyncForEach(extensions, async function (extension: string) { + const [ext_name, ext_version]: string[] = extension.split('-'); + const version_extension: string = version + extension; + let matches: RegExpExecArray; + switch (true) { + // Match :extension + case /^:/.test(ext_name): + remove_script += '\nDisable-Extension' + ext_name.replace(/:/g, ' '); + break; + // Match none + case /^none$/.test(ext_name): + add_script += '\nDisable-AllShared'; + break; + // match 5.3blackfire...8.3blackfire + // match 5.3blackfire-(semver)...8.3blackfire-(semver) + // match pdo_oci and oci8 + // match 5.3ioncube...7.4ioncube + // match 7.0phalcon3...7.3phalcon3, 7.2phalcon4...7.4phalcon4, and 7.4phalcon5...8.2phalcon5 + // match 7.1pecl_http...8.1pecl_http and 7.1http...8.1http + // match 7.0zephir_parser...8.2zephir_parser + case /^(5\.[3-6]|7\.[0-4]|8\.[0-3])blackfire(-\d+\.\d+\.\d+)?$/.test( + version_extension + ): + case /^pdo_oci$|^oci8$|^pdo_firebird$/.test(extension): + case /^(5\.[3-6]|7\.[0-4])ioncube$/.test(version_extension): + case /^7\.[0-3]phalcon3$|^7\.[2-4]phalcon4$|^(7\.4|8\.[0-2])phalcon5$/.test( + version_extension + ): + case /^(7\.[1-4]|8\.1)(pecl_)?http/.test(version_extension): + case /(? { + const extensions: Array = await utils.extensionArray(extension_csv); + let add_script = '\n'; + let remove_script = ''; + await utils.asyncForEach(extensions, async function (extension: string) { + const version_extension: string = version + extension; + const [ext_name, ext_version]: string[] = extension + .split(/-(.+)/) + .filter(Boolean); + const ext_prefix = await utils.getExtensionPrefix(ext_name); + + switch (true) { + // Match :extension + case /^:/.test(ext_name): + remove_script += '\ndisable_extension' + ext_name.replace(/:/g, ' '); + return; + // Match none + case /^none$/.test(ext_name): + add_script += '\ndisable_all_shared'; + return; + // match extensions for compiling from source + case /.+-.+\/.+@.+/.test(extension): + add_script += await utils.parseExtensionSource(extension, ext_prefix); + return; + // match 7.4relay...8.3relay + // match 5.3blackfire...8.3blackfire + // match 5.3blackfire-(semver)...8.3blackfire-(semver) + // match 5.3pdo_cubrid...7.2php_cubrid, 5.3cubrid...7.4cubrid + // match couchbase, geos, pdo_oci, oci8, http, pecl_http + // match 5.3ioncube...7.4ioncube + // match 7.0phalcon3...7.3phalcon3, 7.2phalcon4...7.4phalcon4, 7.4phalcon5...8.2phalcon5 + // match 7.0zephir_parser...8.2zephir_parser + case /^(7\.4|8\.[0-3])relay(-v?\d+\.\d+\.\d+)?$/.test(version_extension): + case /^(5\.[3-6]|7\.[0-4]|8\.[0-3])blackfire(-\d+\.\d+\.\d+)?$/.test( + version_extension + ): + case /^((5\.[3-6])|(7\.[0-2]))pdo_cubrid$|^((5\.[3-6])|(7\.[0-4]))cubrid$/.test( + version_extension + ): + case /^couchbase|^event|^gearman$|^geos$|^pdo_oci$|^oci8$|^(pecl_)?http|^pdo_firebird$/.test( + extension + ): + case /(? { + const log: string = await utils.stepLog('Setup Extensions', os); + let script = '\n'; + switch (no_step) { + case true: + script += log + (await utils.suppressOutput(os)); + break; + case false: + default: + script += log; + break; + } + + switch (os) { + case 'win32': + return script + (await addExtensionWindows(extension_csv, version)); + case 'darwin': + return script + (await addExtensionDarwin(extension_csv, version)); + case 'linux': + return script + (await addExtensionLinux(extension_csv, version)); + default: + return await utils.log( + 'Platform ' + os + ' is not supported', + os, + 'error' + ); + } +} diff --git a/src/fetch.ts b/src/fetch.ts new file mode 100644 index 0000000..b3f3c51 --- /dev/null +++ b/src/fetch.ts @@ -0,0 +1,56 @@ +import {IncomingMessage, OutgoingHttpHeaders} from 'http'; +import * as https from 'https'; +import * as url from 'url'; + +/** + * Function to fetch a URL + * + * @param input_url + * @param auth_token + * @param redirect_count + */ +export async function fetch( + input_url: string, + auth_token?: string, + redirect_count = 5 +): Promise> { + const fetch_promise: Promise> = new Promise( + resolve => { + const url_object: url.UrlObject = new url.URL(input_url); + const headers: OutgoingHttpHeaders = { + 'User-Agent': `Mozilla/5.0 (${process.platform} ${process.arch}) setup-php` + }; + if (auth_token) { + headers.authorization = 'Bearer ' + auth_token; + } + const options: https.RequestOptions = { + hostname: url_object.hostname, + path: url_object.pathname, + headers: headers, + agent: new https.Agent({keepAlive: false}) + }; + const req = https.get(options, (res: IncomingMessage) => { + if (res.statusCode === 200) { + let body = ''; + res.setEncoding('utf8'); + res.on('data', chunk => (body += chunk)); + res.on('end', () => resolve({data: `${body}`})); + } else if ( + [301, 302, 303, 307, 308].includes(res.statusCode as number) + ) { + if (redirect_count > 0 && res.headers.location) { + fetch(res.headers.location, auth_token, redirect_count--).then( + resolve + ); + } else { + resolve({error: `${res.statusCode}: Redirect error`}); + } + } else { + resolve({error: `${res.statusCode}: ${res.statusMessage}`}); + } + }); + req.end(); + } + ); + return await fetch_promise; +} diff --git a/src/install.ts b/src/install.ts new file mode 100644 index 0000000..003a4d5 --- /dev/null +++ b/src/install.ts @@ -0,0 +1,66 @@ +import path from 'path'; +import fs from 'fs'; +import {exec} from '@actions/exec'; +import * as core from '@actions/core'; +import * as config from './config'; +import * as coverage from './coverage'; +import * as extensions from './extensions'; +import * as tools from './tools'; +import * as utils from './utils'; + +/** + * Build the script + * + * @param os + */ +export async function getScript(os: string): Promise { + const url = 'https://setup-php.com/sponsor'; + const filename = os + (await utils.scriptExtension(os)); + const script_path = path.join(__dirname, '../src/scripts', filename); + const run_path = script_path.replace(os, 'run'); + process.env['fail_fast'] = await utils.getInput('fail-fast', false); + const extension_csv: string = await utils.getInput('extensions', false); + const ini_values_csv: string = await utils.getInput('ini-values', false); + const coverage_driver: string = await utils.getInput('coverage', false); + const tools_csv: string = await utils.getInput('tools', false); + const version: string = await utils.parseVersion( + await utils.readPHPVersion() + ); + const ini_file: string = await utils.parseIniFile( + await utils.getInput('ini-file', false) + ); + let script = await utils.joins('.', script_path, version, ini_file); + if (extension_csv) { + script += await extensions.addExtension(extension_csv, version, os); + } + script += await tools.addTools(tools_csv, version, os); + if (coverage_driver) { + script += await coverage.addCoverage(coverage_driver, version, os); + } + if (ini_values_csv) { + script += await config.addINIValues(ini_values_csv, os); + } + script += '\n' + (await utils.stepLog(`Sponsor setup-php`, os)); + script += '\n' + (await utils.addLog('$tick', 'setup-php', url, os)); + + fs.writeFileSync(run_path, script, {mode: 0o755}); + + return run_path; +} + +/** + * Run the script + */ +export async function run(): Promise { + const os: string = process.platform; + const tool = await utils.scriptTool(os); + const run_path = await getScript(os); + await exec(tool + run_path); +} + +// call the run function +(async () => { + await run(); +})().catch(error => { + core.setFailed(error.message); +}); diff --git a/src/packagist.ts b/src/packagist.ts new file mode 100644 index 0000000..46d6a3d --- /dev/null +++ b/src/packagist.ts @@ -0,0 +1,37 @@ +import * as cv from 'compare-versions'; +import * as fetch from './fetch'; + +type RS = Record; +type RSRS = Record; + +export async function search( + package_name: string, + php_version: string +): Promise { + const response = await fetch.fetch( + `https://repo.packagist.org/p2/${package_name}.json` + ); + if (response.error || response.data === '[]') { + return null; + } + + const data = JSON.parse(response['data']); + if (data && data.packages) { + const versions = data.packages[package_name]; + versions.sort((a: RS, b: RS) => cv.compareVersions(b.version, a.version)); + + const result = versions.find((versionData: RSRS) => { + if (versionData?.require?.php) { + return versionData?.require?.php + .split('|') + .some( + require => require && cv.satisfies(php_version + '.0', require) + ); + } + return false; + }); + + return result ? result.version : null; + } + return null; +} diff --git a/src/scripts/darwin.sh b/src/scripts/darwin.sh new file mode 100644 index 0000000..c744140 --- /dev/null +++ b/src/scripts/darwin.sh @@ -0,0 +1,286 @@ +# Disable dependency extensions +disable_dependency_extensions() { + local extension=$1 + formula_file="${tap_dir:?}/$ext_tap/Formula/$extension@${version:?}.rb" + if [ -e "$formula_file" ]; then + IFS=" " read -r -a dependency_extensions <<< "$(grep -Eo "shivammathur.*@" "$formula_file" | xargs -I {} -n 1 basename '{}' | cut -d '@' -f 1 | tr '\n' ' ')" + for dependency_extension in "${dependency_extensions[@]}"; do + sudo sed -Ei '' "/=(.*\/)?\"?$dependency_extension(.so)?$/d" "${ini_file:?}" + done + fi +} + +# Helper function to disable an extension. +disable_extension_helper() { + local extension=$1 + local disable_dependents=${2:-false} + get_extension_map + if [ "$disable_dependents" = "true" ]; then + disable_extension_dependents "$extension" + fi + sudo sed -Ei '' "/=(.*\/)?\"?$extension(.so)?$/d" "${ini_file:?}" + sudo rm -rf "$scan_dir"/*"$extension"* /tmp/php"$version"_extensions + mkdir -p /tmp/extdisabled/"$version" + echo '' | sudo tee /tmp/extdisabled/"$version"/"$extension" >/dev/null 2>&1 +} + +# Function to get extension name from brew formula. +get_extension_from_formula() { + local formula=$1 + local extension + extension=$(grep -E "^$formula=" "$src"/configs/brew_extensions | cut -d '=' -f 2) + [[ -z "$extension" ]] && extension="$(echo "$formula" | sed -E "s/pecl_|[0-9]//g")" + echo "$extension" +} + +# Function to copy extension binaries to the extension directory. +copy_brew_extensions() { + local formula=$1 + formula_file="$tap_dir/$ext_tap/Formula/$formula@$version.rb" + deps="$(grep -Eo 'depends_on "shivammathur[^"]+' "$formula_file" | cut -d '/' -f 3 | tr '\n' ' ')" + IFS=' ' read -r -a deps <<< "$formula@$version $deps" + for dependency in "${deps[@]}"; do + extension_file="${brew_prefix:?}/opt/$dependency/$(get_extension_from_formula "${dependency%@*}").so" + [ -e "$extension_file" ] && sudo cp "$extension_file" "$ext_dir" + done + if [ -d "$brew_prefix"/Cellar/"$formula"@"$version" ]; then + sudo find -- "$brew_prefix"/Cellar/"$formula"@"$version" -name "*.dylib" -exec cp {} "$ext_dir" \; + fi +} + +# Function to install a php extension from shivammathur/extensions tap. +add_brew_extension() { + formula=$1 + prefix=$2 + extension="$(get_extension_from_formula "$formula")" + enable_extension "$extension" "$prefix" + if check_extension "$extension"; then + add_log "${tick:?}" "$extension" "Enabled" + else + add_brew_tap "$php_tap" + add_brew_tap "$ext_tap" + sudo mv "$tap_dir"/"$ext_tap"/.github/deps/"$formula"/* "${core_repo:?}/Formula/" 2>/dev/null || true + update_dependencies >/dev/null 2>&1 + disable_dependency_extensions "$extension" >/dev/null 2>&1 + (brew install -f "$ext_tap/$formula@$version" >/dev/null 2>&1 && copy_brew_extensions "$formula") || pecl_install "$extension" >/dev/null 2>&1 + add_extension_log "$extension" "Installed and enabled" + fi +} + +# Helper function to add an extension. +add_extension_helper() { + local extension=$1 + prefix=$2 + if [[ "$version" =~ ${old_versions:?} ]] && [ "$extension" = "imagick" ]; then + run_script "php5-darwin" "${version/./}" "$extension" >/dev/null 2>&1 + else + pecl_install "$extension" >/dev/null 2>&1 && + if [[ "$version" =~ ${old_versions:?} ]]; then echo "$prefix=$ext_dir/$extension.so" >>"$ini_file"; fi + fi + add_extension_log "$extension" "Installed and enabled" +} + +# Function to handle request to add phpize and php-config. +add_devtools() { + tool=$1 + add_log "${tick:?}" "$tool" "Added $tool $semver" +} + +# Function to handle request to add PECL. +add_pecl() { + enable_extension xml extension >/dev/null 2>&1 + configure_pecl >/dev/null 2>&1 + pear_version=$(get_tool_version "pecl" "version") + add_log "${tick:?}" "PECL" "Found PECL $pear_version" +} + +# Function to link all libraries of a formula. +link_libraries() { + formula=$1 + formula_prefix="$(brew --prefix "$formula")" + sudo mkdir -p "$formula_prefix"/lib + for lib in "$formula_prefix"/lib/*.dylib; do + lib_name=$(basename "$lib") + sudo cp -a "$lib" "$brew_prefix/lib/$lib_name" 2>/dev/null || true + done +} + +# Link opcache extension to extensions directory. +link_opcache() { + opcache_ini="$brew_prefix"/etc/php/"$version"/conf.d/ext-opcache.ini + if [ -e "$opcache_ini" ]; then + opcache_ext=$(grep -Eo "zend_extension.*opcache.*\.so" "$opcache_ini" | cut -d '"' -f 2) + sudo ln -sf "$opcache_ext" "$ext_dir" + fi +} + +# Patch brew to overwrite packages. +patch_brew() { + formula_installer="${brew_repo:?}"/Library/Homebrew/formula_installer.rb + code=" keg.link\(verbose: verbose\?" + sudo sed -Ei '' "s/$code.*/$code, overwrite: true\)/" "$formula_installer" + # shellcheck disable=SC2064 + trap "sudo sed -Ei '' 's/$code.*/$code, overwrite: overwrite?\)/' $formula_installer" exit +} + +# Helper function to update the dependencies. +update_dependencies_helper() { + dependency=$1 + [[ "${dependency:0:3}" = "lib" ]] && prefix=lib || prefix="${dependency:0:1}" + get -q -n "$core_repo/Formula/$prefix/$dependency.rb" "https://raw.githubusercontent.com/Homebrew/homebrew-core/master/Formula/$prefix/$dependency.rb" + link_libraries "$dependency" +} + +# Function to update dependencies. +update_dependencies() { + patch_brew + if ! [ -e /tmp/update_dependencies ]; then + if [ "${runner:?}" != "self-hosted" ] && [ "${ImageOS:-}" != "" ] && [ "${ImageVersion:-}" != "" ]; then + deps_file="$tap_dir/$php_tap/.github/deps/${ImageOS:?}_${ImageVersion:?}" + if [ -e "$deps_file" ]; then + while read -r dependency; do + update_dependencies_helper "$dependency" & + to_wait+=($!) + done <"$deps_file" + fi + wait "${to_wait[@]}" + else + git -C "$core_repo" fetch origin master && git -C "$core_repo" reset --hard origin/master + fi + echo '' | sudo tee /tmp/update_dependencies >/dev/null 2>&1 + fi +} + +# Function to fix dependencies on install PHP version. +fix_dependencies() { + broken_deps_paths=$(php -v 2>&1 | grep -Eo '/opt/[a-zA-Z0-9@\.]+') + if [ "x$broken_deps_paths" != "x" ]; then + update_dependencies + IFS=" " read -r -a formulae <<< "$(echo "$broken_deps_paths" | tr '\n' ' ' | sed 's|/opt/||g' 2>&1)$php_formula" + brew reinstall "${formulae[@]}" + brew link --force --overwrite "$php_formula" || true + fi +} + +# Function to get PHP version if it is already installed using Homebrew. +get_brewed_php() { + cellar="$brew_prefix"/Cellar + php_cellar="$cellar"/php + if [ -d "$cellar" ] && ! [[ "$(find "$cellar" -maxdepth 1 -name "php@$version*" | wc -l 2>/dev/null)" -eq 0 ]]; then + php_semver | cut -c 1-3 + elif [ -d "$php_cellar" ] && ! [[ "$(find "$php_cellar" -maxdepth 1 -name "$version*" | wc -l 2>/dev/null)" -eq 0 ]]; then + php_semver | cut -c 1-3 + else + echo 'false'; + fi +} + +# Function to setup PHP 5.6 and newer using Homebrew. +add_php() { + action=$1 + existing_version=$2 + add_brew_tap "$php_tap" + update_dependencies + [ "${debug:?}" = "debug" ] && php_formula="$php_formula-debug" + if [ "$existing_version" != "false" ]; then + ([ "$action" = "upgrade" ] && brew upgrade -f "$php_formula") || brew unlink "$php_formula" + else + brew install -f "$php_formula" + fi + brew link --force --overwrite "$php_formula" +} + +# Function to get extra version. +php_extra_version() { + php_formula_file="$tap_dir"/"$php_tap"/Formula/php@"$version".rb + if [ -e "$php_formula_file" ] && ! grep -q "deprecate!" "$php_formula_file" && grep -Eq "archive/[0-9a-zA-Z]+" "$php_formula_file"; then + echo " ($(grep -Eo "archive/[0-9a-zA-Z]+" "$php_formula_file" | cut -d'/' -f 2))" + fi +} + +# Function to set php.ini +add_php_config() { + if ! [ -e "$ini_dir"/php.ini-development ]; then + sudo cp "$ini_dir"/php.ini "$ini_dir"/php.ini-development + fi + if [[ "$ini" = "production" || "$ini" = "development" ]]; then + sudo cp "$ini_dir"/php.ini-"$ini" "$ini_dir"/php.ini + elif [ "$ini" = "none" ]; then + echo '' | sudo tee "${ini_file[@]}" >/dev/null 2>&1 + fi +} + +# Function to get scan directory. +get_scan_dir() { + if [[ "$version" =~ ${old_versions:?} ]]; then + php --ini | grep additional | sed -e "s|.*: s*||" + else + echo "$ini_dir"/conf.d + fi +} + +# Function to Setup PHP. +setup_php() { + step_log "Setup PHP" + php_config="$(command -v php-config 2>/dev/null)" + existing_version=$(get_brewed_php) + if [[ "$version" =~ ${old_versions:?} ]]; then + run_script "php5-darwin" "${version/./}" >/dev/null 2>&1 + status="Installed" + elif [ "$existing_version" != "$version" ]; then + add_php "install" "$existing_version" >/dev/null 2>&1 + status="Installed" + elif [ "$existing_version" = "$version" ] && [ "${update:?}" = "true" ]; then + add_php "upgrade" "$existing_version" >/dev/null 2>&1 + status="Updated to" + else + status="Found" + fix_dependencies >/dev/null 2>&1 + fi + php_config="$(command -v php-config)" + ext_dir="$(grep 'extension_dir=' "$php_config" | cut -d "'" -f 2)" + ini_dir="$(php_ini_path)" + scan_dir="$(get_scan_dir)" + ini_file="$ini_dir"/php.ini + sudo mkdir -m 777 -p "$ext_dir" "$HOME/.composer" + sudo chmod 777 "$ini_file" "${tool_path_dir:?}" + semver="$(php_semver)" + extra_version="$(php_extra_version)" + configure_php + link_opcache + set_output "php-version" "$semver" + if [ "${semver%.*}" != "$version" ]; then + add_log "${cross:?}" "PHP" "Could not setup PHP $version" + exit 1 + fi + + sudo cp "$src"/configs/pm/*.json "$RUNNER_TOOL_CACHE/" + add_log "$tick" "PHP" "$status PHP $semver$extra_version" +} + +# Variables +version=${1:-'8.3'} +ini=${2:-'production'} +src=${0%/*}/.. +php_formula=shivammathur/php/php@"$version" +scripts="$src"/scripts +ext_tap=shivammathur/homebrew-extensions +php_tap=shivammathur/homebrew-php +export HOMEBREW_CHANGE_ARCH_TO_ARM=1 +export HOMEBREW_DEVELOPER=1 +export HOMEBREW_NO_AUTO_UPDATE=1 +export HOMEBREW_NO_ENV_HINTS=1 +export HOMEBREW_NO_INSTALL_CLEANUP=1 +export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 +export HOMEBREW_NO_INSTALL_FROM_API=1 + +# shellcheck source=. +. "${scripts:?}"/unix.sh +. "${scripts:?}"/tools/brew.sh +. "${scripts:?}"/tools/add_tools.sh +. "${scripts:?}"/extensions/source.sh +. "${scripts:?}"/extensions/add_extensions.sh +configure_brew +read_env +self_hosted_setup +setup_php diff --git a/src/scripts/extensions/add_extensions.ps1 b/src/scripts/extensions/add_extensions.ps1 new file mode 100644 index 0000000..b6debf9 --- /dev/null +++ b/src/scripts/extensions/add_extensions.ps1 @@ -0,0 +1,260 @@ +# Function to check if extension is enabled. +Function Test-Extension() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [string] + $extension + ) + $extension_info = Get-PhpExtension -Path $php_dir | Where-Object { $_.Name -eq $extension -or $_.Handle -eq $extension } + return $null -ne $extension_info +} + +# Function to add extension log. +Function Add-ExtensionLog() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + $extension, + [Parameter(Position = 1, Mandatory = $true)] + [ValidateNotNull()] + $message + ) + if (Test-Extension $extension) { + Add-Log $tick $extension $message + } else { + Add-Log $cross $extension "Could not install $extension on PHP $( $installed.FullVersion )" + } +} + +# Function to link dependencies to PHP directory. +Function Set-ExtensionPrerequisites +{ + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $extension + ) + $deps_dir = "$ext_dir\$extension-vc$($installed.VCVersion)-$arch" + $deps = Get-ChildItem -Recurse -Path $deps_dir + if ($deps.Count -ne 0) { + # Symlink dependencies instead of adding the directory to PATH ... + # as other actions change the PATH thus breaking extensions. + $deps | ForEach-Object { + New-Item -Itemtype SymbolicLink -Path $php_dir -Name $_.Name -Target $_.FullName -Force > $null 2>&1 + } + } else { + Remove-Item $deps_dir -Recurse -Force + } +} + +# Function to enable extension. +Function Enable-Extension() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $extension + ) + Enable-ExtensionDependencies $extension + Enable-PhpExtension -Extension $extension -Path $php_dir + Set-ExtensionPrerequisites $extension + Add-Log $tick $extension "Enabled" +} + +# Function to add custom built PHP extension for nightly builds. +Function Add-NightlyExtension { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $extension + ) + if($ts) { $ts_part = 'ts' } else { $ts_part = 'nts' } + $repo = "$github/shivammathur/php-extensions-windows" + $url = "$repo/releases/download/builds/php$version`_$ts_part`_$arch`_$extension.dll" + Get-File -Url $url -OutFile "$ext_dir\php_$extension.dll" + if(Test-Path "$ext_dir\php_$extension.dll") { + Enable-Extension $extension > $null + } else { + throw "Failed to download the $extension" + } +} + +# Function to add PHP extensions. +Function Add-Extension { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $extension, + [Parameter(Position = 1, Mandatory = $false)] + [ValidateNotNull()] + [ValidateSet('stable', 'beta', 'alpha', 'devel', 'snapshot')] + [string] + $stability = 'stable', + [Parameter(Position = 2, Mandatory = $false)] + [ValidateNotNull()] + [ValidatePattern('^\d+(\.\d+){0,2}$')] + [string] + $extension_version = '' + ) + try { + $extension_info = Get-PhpExtension -Path $php_dir | Where-Object { $_.Name -eq $extension -or $_.Handle -eq $extension } + $deps_dir = "$ext_dir\$extension-vc$($installed.VCVersion)-$arch" + New-Item $deps_dir -Type Directory -Force > $null 2>&1 + if ($null -ne $extension_info) { + switch ($extension_info.State) { + 'Builtin' { + Add-Log $tick $extension "Enabled" + } + 'Enabled' { + Add-Log $tick $extension "Enabled" + } + default { + Enable-Extension $extension_info.Handle + } + } + } + else { + if(($version -match $nightly_versions) -and (Select-String -Path $src\configs\windows_extensions -Pattern $extension -SimpleMatch -Quiet)) { + Add-NightlyExtension $extension + } else { + # Patch till DLLs for PHP 8.2 and above are released as stable. + $minimumStability = $stability + if ($version -match '8.[2-4]' -and $stability -eq 'stable') { + $minimumStability = 'snapshot' + } + + $params = @{ Extension = $extension; MinimumStability = $minimumStability; MaximumStability = $stability; Path = $php_dir; AdditionalFilesPath = $deps_dir; NoDependencies = $true } + if ($extension_version -ne '') + { + $params["Version"] = $extension_version + } + Install-PhpExtension @params + Set-ExtensionPrerequisites $extension + } + Add-Log $tick $extension "Installed and enabled" + } + } catch { + Add-Log $cross $extension "Could not install $extension on PHP $( $installed.FullVersion )" + } +} + +# Function to get a map of extensions and their dependent shared extensions. +Function Get-ExtensionMap { + php -d'error_reporting=0' $src\scripts\extensions\extension_map.php $env:TEMP\map$version.orig +} + +# Function to enable extension dependencies which are also extensions. +Function Enable-ExtensionDependencies { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $extension + ) + if (-not(Test-Path $env:TEMP\extdisabled\$extension)) { + return + } + Get-ExtensionMap + $entry = findstr /r "$extension`:.*" $env:TEMP\map$version.orig + if($entry) { + $entry.split(':')[1].trim().split(' ') | ForEach-Object { + if (-not(php -m | findstr -i $_)) { + Enable-PhpExtension -Extension $_ -Path $php_dir + } + } + } + Remove-Item $env:TEMP\extdisabled\$extension -Force +} + +# Function to disable dependent extensions. +Function Disable-DependentExtensions() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $extension + ) + Select-String -Pattern ".*:.*\s$extension(\s|$)" $env:TEMP\map$version.orig | ForEach-Object { + $dependent = $_.Matches[0].Value.split(':')[0]; + Disable-ExtensionHelper -Extension $dependent -DisableDependents + Add-Log $tick ":$extension" "Disabled $dependent as it depends on $extension" + } +} + +# Helper function to disable an extension. +Function Disable-ExtensionHelper() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $extension, + [switch] $DisableDependents + ) + Get-ExtensionMap + if($DisableDependents) { + Disable-DependentExtensions $extension + } + Disable-PhpExtension -Extension $extension -Path $php_dir + New-Item $env:TEMP\extdisabled -Type Directory -Force > $null 2>&1 + New-Item $env:TEMP\extdisabled\$extension -Type File -Force > $null 2>&1 +} + +# Function to disable an extension. +Function Disable-Extension() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $extension, + [Parameter(Position = 1, Mandatory = $false)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $DisableDependents + ) + if(php -m | findstr -i $extension) { + if(Test-Path $ext_dir\php_$extension.dll) { + try { + $params = @{ Extension = $extension; DisableDependents = ($DisableDependents -ne 'false') } + Disable-ExtensionHelper @params + Add-Log $tick ":$extension" "Disabled" + } catch { + Add-Log $cross ":$extension" "Could not disable $extension on PHP $($installed.FullVersion)" + } + } else { + Add-Log $cross ":$extension" "Could not disable $extension on PHP $($installed.FullVersion) as it not a shared extension" + } + } elseif(Test-Path $ext_dir\php_$extension.dll) { + Add-Log $tick ":$extension" "Disabled" + } else { + Add-Log $tick ":$extension" "Could not find $extension on PHP $($installed.FullVersion)" + } +} + +# Function to disable shared extensions. +Function Disable-AllShared() { + Get-ExtensionMap + (Get-Content $php_dir\php.ini) | Where-Object {$_ -notmatch '^(zend_)?extension\s*='} | Set-Content $php_dir\php.ini + New-Item $env:TEMP\extdisabled\$version -Type Directory -Force > $null 2>&1 + Get-Childitem $ext_dir\*.dll | ForEach-Object { + New-Item ("$env:TEMP\extdisabled\$version\" + ($_.Name.split('.')[0].split('_')[1])) -Type File -Force > $null 2>&1 + } + Add-Log $tick "none" "Disabled all shared extensions" +} + +# Function to handle request to add PECL. +Function Add-Pecl() { + Add-Log $tick "PECL" "Use extensions input to setup PECL extensions on windows" +} \ No newline at end of file diff --git a/src/scripts/extensions/add_extensions.sh b/src/scripts/extensions/add_extensions.sh new file mode 100644 index 0000000..6ad9870 --- /dev/null +++ b/src/scripts/extensions/add_extensions.sh @@ -0,0 +1,229 @@ +# Function to log result of installing extension. +add_extension_log() { + ( + check_extension "$(echo "$1" | cut -d '-' -f 1)" && add_log "${tick:?}" "$1" "$2" + ) || add_log "${cross:?}" "$1" "Could not install $1 on PHP ${semver:?}" +} + +# Function to test if extension is loaded. +check_extension() { + local extension=$1 + local extension_list=/tmp/php${version:?}_extensions + if [ ! -e "$extension_list" ]; then + php -m > "$extension_list" + fi + if [ "$extension" != "mysql" ]; then + grep -i -q -w "$extension" "$extension_list" || php -m | grep -i -q -w "$extension" + else + grep -i -q "$extension" "$extension_list" || php -m | grep -i -q "$extension" + fi +} + +# Function to check if extension is shared +shared_extension() { + [ -e "${ext_dir:?}/$1.so" ] +} + +# Function to enable cached extension's dependencies. +enable_cache_extension_dependencies() { + if [ -d /tmp/extcache ] && shared_extension "$1"; then + cache_dir=$(find /tmp/extcache -maxdepth 1 -type d -regex ".*$1[0-9]*") + if [[ -n "$cache_dir" ]]; then + IFS=" " read -r -a deps <<<"$(find "$cache_dir" -maxdepth 1 -type f -name "*" -exec basename {} \; | tr '\n' ' ')" + IFS="#" read -r -a deps_enable <<<"$(printf -- "-d ${2}=%s.so#" "${deps[@]}")" + if [[ -n "${deps[*]}" ]] && php "${deps_enable[@]}" -d "${2}=$1.so" -m 2>/dev/null | grep -i -q "$1"; then + for ext in "${deps[@]}"; do + sudo rm -rf /tmp/extcache/"$ext" + enable_extension "$ext" "$2" + done + fi + fi + fi +} + +# Function to enable existing extensions. +enable_extension() { + if ! check_extension "$1" && shared_extension "$1"; then + modules_dir="/var/lib/php/modules/${version:?}" + [ -d "$modules_dir" ] && sudo find "$modules_dir" -path "*disabled*$1" -delete + enable_extension_dependencies "$1" "$2" + enable_cache_extension_dependencies "$1" "$2" + if ! [[ "${version:?}" =~ ${old_versions:?} ]] && command -v phpenmod >/dev/null 2>&1; then + sudo sed -Ei "/=(.*\/)?\"?$extension(.so)?\"?$/d" "$pecl_file" + mod="${ini_dir:?}"/../mods-available/"$1".ini + if ! [ -e "$mod" ]; then + priority="${3:-20}"; + mod_priority_line="$(grep -E "^$1=" "${src:?}/configs/mod_priority")"; + [ -n "$mod_priority_line" ] && priority=$(echo "$mod_priority_line" | cut -d'=' -f 2) + (echo "; priority=$priority"; echo "$2=${ext_dir:?}/$1.so") | sudo tee "$mod" >/dev/null + fi + sudo phpenmod -v "$version" "$1" >/dev/null 2>&1 + else + echo "$2=${ext_dir:?}/$1.so" | sudo tee -a "${pecl_file:-${ini_file[@]}}" >/dev/null + fi + fi +} + +# Function to enable array of extensions +enable_extensions() { + local extensions=("$@") + to_wait=() + for ext in "${extensions[@]}"; do + enable_extension "$ext" extension >/dev/null 2>&1 & + to_wait+=($!) + done + wait "${to_wait[@]}" +} + +# Function to get a map of extensions and their dependent shared extensions. +get_extension_map() { + php -d'error_reporting=0' "${src:?}"/scripts/extensions/extension_map.php /tmp/map"$version".orig >/dev/null 2>&1 +} + +# Function to enable extension dependencies which are also extensions. +enable_extension_dependencies() { + local extension=$1 + local prefix=$2 + [ -e /tmp/extdisabled/"$version"/"$extension" ] || return; + get_extension_map + for dependency in $(grep "$extension:" /tmp/map"$version".orig | cut -d ':' -f 2 | tr '\n' ' '); do + enable_extension "$dependency" "$prefix" + done + rm /tmp/extdisabled/"$version"/"$extension" +} + +# Function to disable dependent extensions. +disable_extension_dependents() { + local extension=$1 + for dependent in $(grep -E ".*:.*\s$extension(\s|$)" /tmp/map"$version".orig | cut -d ':' -f 1 | tr '\n' ' '); do + disable_extension_helper "$dependent" true + add_log "${tick:?}" ":$extension" "Disabled $dependent as it depends on $extension" + done +} + +# Function to disable an extension. +disable_extension() { + local extension=$1 + if check_extension "$extension"; then + if shared_extension "$extension"; then + disable_extension_helper "$extension" true + (! check_extension "$extension" && add_log "${tick:?}" ":$extension" "Disabled") || + add_log "${cross:?}" ":$extension" "Could not disable $extension on PHP ${semver:?}" + else + add_log "${cross:?}" ":$extension" "Could not disable $extension on PHP $semver as it not a shared extension" + fi + elif shared_extension "$extension"; then + add_log "${tick:?}" ":$extension" "Disabled" + else + add_log "${tick:?}" ":$extension" "Could not find $extension on PHP $semver" + fi +} + +# Function to disable shared extensions. +disable_all_shared() { + get_extension_map + sudo sed -i.orig -E -e "/^(zend_)?extension\s*=/d" "${ini_file[@]}" "$pecl_file" 2>/dev/null || true + sudo find "${ini_dir:-$scan_dir}"/.. -name "*.ini" -not -path "*php.ini" -not -path "*phar.ini" -not -path "*pecl.ini" -not -path "*mods-available*" -delete >/dev/null 2>&1 || true + mkdir -p /tmp/extdisabled/"$version" + sudo rm -f /tmp/php"$version"_extensions + sudo find "$ext_dir" -name '*.so' -print0 | xargs -0 -n 1 basename -s .so | xargs -I{} touch /tmp/extdisabled/"$version"/{} + add_log "${tick:?}" "none" "Disabled all shared extensions" +} + +# Function to configure PECL. +configure_pecl() { + [ -z "${pecl_file:-${ini_file[@]}}" ] && return + if ! [ -e /tmp/pecl_config ]; then + for script in pear pecl; do + sudo "$script" channel-update "$script".php.net + done + echo '' | sudo tee /tmp/pecl_config >/dev/null 2>&1 + fi +} + +# Function to add an extension. +add_extension() { + local extension=$1 + local prefix=$2 + enable_extension "$extension" "$prefix" + if check_extension "$extension"; then + add_log "${tick:?}" "$extension" "Enabled" + else + add_extension_helper "$extension" "$prefix" + fi +} + +# Function to get the PECL version of an extension. +get_pecl_version() { + local extension=$1 + states=("stable" "rc" "preview" "beta" "alpha" "snapshot") + stability="$(echo "$2" | grep -m 1 -Eio "($(IFS='|' ; echo "${states[*]}"))")" + IFS=' ' read -r -a states <<< "$(echo "${states[@]}" | grep -Eo "$stability.*")" + major_version=${3:-'[0-9]+'} + pecl_rest='https://pecl.php.net/rest/r/' + response=$(get -s -n "" "$pecl_rest$extension"/allreleases.xml) + for state in "${states[@]}"; do + pecl_version=$(echo "$response" | grep -m 1 -Eio "($major_version\.[0-9]+\.[0-9]+${state}[0-9]+<)" | cut -d '<' -f 1) + [ -z "$pecl_version" ] && pecl_version=$(echo "$response" | grep -m 1 -Eio "v>(.*)<\/v>.*$state<" | grep -m 1 -Eo "($major_version\.[0-9]+\.[0-9]+.*)<" | cut -d '<' -f 1) + [ -n "$pecl_version" ] && break; + done + [ -z "$pecl_version" ] && pecl_version=$(echo "$response" | grep -m 1 -Eo "($major_version\.[0-9]+\.[0-9]+)<" | cut -d '<' -f 1) + echo "$pecl_version" +} + +# Function to install PECL extensions and accept default options +pecl_install() { + local extension=$1 + local prefix=${2:-extension} + add_pecl >/dev/null 2>&1 + cpu_count="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo '1')" + prefix_opts="$(parse_args "$extension" CONFIGURE_PREFIX_OPTS) MAKEFLAGS='-j $cpu_count'" + suffix_opts="$(parse_args "$extension" CONFIGURE_OPTS) $(parse_args "$extension" CONFIGURE_SUFFIX_OPTS)" + IFS=' ' read -r -a libraries <<<"$(parse_args "$extension" LIBS) $(parse_args "$extension" "$(uname -s)"_LIBS)" + (( ${#libraries[@]} )) && add_libs "${libraries[@]}" >/dev/null 2>&1 + disable_extension_helper "${extension%-*}" >/dev/null 2>&1 + if [ "$version" = "5.3" ]; then + yes '' 2>/dev/null | sudo "$prefix_opts" pecl install -f "$extension" >/dev/null 2>&1 + else + yes '' 2>/dev/null | sudo "$prefix_opts" pecl install -f -D "$(parse_pecl_configure_options "$suffix_opts")" "$extension" >/dev/null 2>&1 + fi + local exit_code=$? + sudo pecl info "$extension" | grep -iq 'zend extension' && prefix=zend_extension + enable_extension "${extension%-*}" "$prefix" + return "$exit_code" +} + +# Function to install a specific version of PECL extension. +add_pecl_extension() { + local extension=$1 + local pecl_version=$2 + local prefix=$3 + enable_extension "$extension" "$prefix" + if [[ $pecl_version =~ .*(alpha|beta|rc|snapshot|preview).* ]]; then + pecl_version=$(get_pecl_version "$extension" "$pecl_version") + fi + ext_version=$(php -r "echo phpversion('$extension');") + if check_extension "$extension" && [[ -z "$pecl_version" || (-n "$pecl_version" && "${ext_version/-/}" == "$pecl_version") ]]; then + add_log "${tick:?}" "$extension" "Enabled" + else + [ -n "$pecl_version" ] && pecl_version="-$pecl_version" + pecl_install "$extension$pecl_version" || add_extension "$extension" "$(get_extension_prefix "$extension")" >/dev/null 2>&1 + extension_version="$(php -r "echo phpversion('$extension');")" + [ -n "$extension_version" ] && extension_version="-$extension_version" + add_extension_log "$extension$extension_version" "Installed and enabled" + fi +} + +# Function to setup pre-release extensions using PECL. +add_unstable_extension() { + local extension=$1 + local stability=$2 + local prefix=$3 + pecl_version=$(get_pecl_version "$extension" "$stability") + add_pecl_extension "$extension" "$pecl_version" "$prefix" +} + +# Function to get extension prefix +get_extension_prefix() { + echo "$1" | grep -Eq "xdebug([2-3])?$|opcache|ioncube|eaccelerator" && echo zend_extension || echo extension +} diff --git a/src/scripts/extensions/blackfire.ps1 b/src/scripts/extensions/blackfire.ps1 new file mode 100644 index 0000000..4afe8ed --- /dev/null +++ b/src/scripts/extensions/blackfire.ps1 @@ -0,0 +1,34 @@ +# Function to install blackfire extension. +Function Add-Blackfire() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [string] + $extension + ) + try { + $no_dot_version = $version.replace('.', '') + $extension_version = $extension.split('-')[1] + if ($extension_version -notmatch "\S") { + if($version -lt '7.0') { + $extension_version = '1.50.0' + } else { + $extension_version = (Invoke-RestMethod https://blackfire.io/api/v1/releases).probe.php + } + } + if (Test-Path $ext_dir\blackfire.dll) { + Enable-PhpExtension -Extension blackfire -Path $php_dir + $status="Enabled" + } else { + $nts = if (!$installed.ThreadSafe) { "_nts" } else { "" } + Get-File -Url "https://packages.blackfire.io/binaries/blackfire-php/${extension_version}/blackfire-php-windows_${arch}-php-${no_dot_version}${nts}.dll" -OutFile $ext_dir\blackfire.dll > $null 2>&1 + Disable-Extension xdebug > $null 2>&1 + Disable-Extension pcov > $null 2>&1 + Enable-PhpExtension -Extension blackfire -Path $php_dir + $status="Installed and enabled" + } + Add-Log $tick $extension $status + } catch { + Add-Log $cross $extension "Could not install $extension on PHP $($installed.FullVersion)" + } +} diff --git a/src/scripts/extensions/blackfire.sh b/src/scripts/extensions/blackfire.sh new file mode 100644 index 0000000..bea20f2 --- /dev/null +++ b/src/scripts/extensions/blackfire.sh @@ -0,0 +1,24 @@ +# Function to install blackfire extension. +add_blackfire() { + local extension=$1 + version=${version:?} + no_dot_version=${version/./} + platform=$(uname -s | tr '[:upper:]' '[:lower:]') + extension_version=$(echo "$extension" | cut -d '-' -f 2) + status='Enabled' + if ! shared_extension blackfire; then + status='Installed and enabled' + if [ "$extension_version" = "blackfire" ]; then + if [[ ${version:?} =~ 5.[3-6] ]]; then + extension_version='1.50.0' + else + extension_version=$(get -s -n "" https://blackfire.io/api/v1/releases | grep -Eo 'php":"([0-9]+.[0-9]+.[0-9]+)' | cut -d '"' -f 3) + fi + fi + get -q -n "${ext_dir:?}/blackfire.so" https://packages.blackfire.io/binaries/blackfire-php/"$extension_version"/blackfire-php-"$platform"_amd64-php-"$no_dot_version".so >/dev/null 2>&1 + fi + disable_extension xdebug >/dev/null 2>&1 + disable_extension pcov >/dev/null 2>&1 + enable_extension blackfire extension + add_extension_log blackfire "$status" +} diff --git a/src/scripts/extensions/couchbase.sh b/src/scripts/extensions/couchbase.sh new file mode 100644 index 0000000..d93b2b4 --- /dev/null +++ b/src/scripts/extensions/couchbase.sh @@ -0,0 +1,75 @@ +# Function to install libraries required by couchbase +add_couchbase_clibs() { + ext=$1 + trunk="https://github.com/couchbase/libcouchbase/releases" + if [[ "$ext" =~ couchbase-2.+ ]]; then + release="2.10.9" + else + release=$(get -s -n "" "$trunk"/latest | grep -Eo -m 1 "[0-9]+\.[0-9]+\.[0-9]+" | head -n 1) + fi + [ "$VERSION_ID" = "22.04" ] && vid=20.04 || vid="$VERSION_ID" + [ "$VERSION_CODENAME" = "jammy" ] && vcn=focal || vcn="$VERSION_CODENAME" + deb_url="$trunk/download/$release/libcouchbase-${release}_ubuntu${vid/./}_${vcn}_amd64.tar" + get -q -n /tmp/libcouchbase.tar "$deb_url" + sudo tar -xf /tmp/libcouchbase.tar -C /tmp + install_packages libev4 libevent-dev + sudo dpkg -i /tmp/libcouchbase-*/*.deb +} + +add_couchbase_cxxlibs() { + if [ "${runner:?}" = "self-hosted" ]; then + add_list cmake https://apt.kitware.com/ubuntu/ https://apt.kitware.com/keys/kitware-archive-latest.asc "$VERSION_CODENAME" main + fi + install_packages cmake ccache +} + +get_couchbase_version() { + if [[ "${version:?}" =~ ${old_versions:?} ]]; then + echo couchbase-2.2.3 + elif [[ "${version:?}" =~ 5.6|7.[0-1] ]]; then + echo couchbase-2.6.2 + elif [ "${version:?}" = '7.2' ]; then + echo couchbase-3.0.4 + elif [ "${version:?}" = '7.3' ]; then + echo couchbase-3.2.2 + elif [ "${version:?}" = '7.4' ]; then + echo couchbase-4.1.0 + else + echo couchbase + fi +} + +# Function to add couchbase. +add_couchbase() { + ext=$1 + if [ "$(uname -s)" = "Linux" ]; then + if [ "$ext" = "couchbase" ]; then + ext=$(get_couchbase_version) + fi + if [[ "$ext" =~ couchbase-[2-3].+ ]]; then + add_couchbase_clibs "$ext" >/dev/null 2>&1 + else + add_couchbase_cxxlibs >/dev/null 2>&1 + fi + enable_extension "couchbase" "extension" + if check_extension "couchbase"; then + add_log "${tick:?}" "couchbase" "Enabled" + else + if [ "$ext" = "couchbase" ]; then + ext="couchbase-$(get_pecl_version "couchbase" "stable")" + n_proc="$(nproc)" + export COUCHBASE_SUFFIX_OPTS="CMAKE_BUILD_TYPE=Release" + export CMAKE_BUILD_PARALLEL_LEVEL="$n_proc" + add_extension_from_source couchbase https://pecl.php.net couchbase couchbase "${ext##*-}" extension pecl >/dev/null 2>&1 + else + pecl_install "${ext}" >/dev/null 2>&1 + fi + add_extension_log "couchbase" "Installed and enabled" + fi + else + if [ -e "${ext_dir:?}"/libcouchbase_php_core.dylib ]; then + sudo cp "${ext_dir:?}"/libcouchbase_php_core.dylib "${brew_prefix:?}"/lib + fi + add_brew_extension couchbase extension + fi +} diff --git a/src/scripts/extensions/cubrid.sh b/src/scripts/extensions/cubrid.sh new file mode 100644 index 0000000..201a667 --- /dev/null +++ b/src/scripts/extensions/cubrid.sh @@ -0,0 +1,60 @@ +# Function to log license details. +add_license_log() { + printf "$GROUP\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "$ext" "Click to read the $ext related license information" + printf "Cubrid CCI package is required for %s extension.\n" "$ext" + printf "The extension %s and Cubrid CCI are provided under the license linked below.\n" "$ext" + printf "Refer to: \033[35;1m%s \033[0m\n" "https://github.com/CUBRID/cubrid-cci/blob/develop/COPYING" + echo "$END_GROUP" +} + +# Function to setup gcc-7 and g++-7 +setup_compiler() { + if ! command -v gcc-7 >/dev/null || ! command -v g++-7 >/dev/null; then + add_ppa ubuntu-toolchain-r/test + add_packages gcc-7 g++-7 -y + fi + printf "gcc g++" | xargs -d ' ' -I {} sudo update-alternatives --install /usr/bin/{} {} /usr/bin/{}-7 7 +} + +# Function to set cubrid repo for the extension. +set_cubrid_repo() { + case "${ext:?}" in + "cubrid") cubrid_repo="cubrid-php";; + "pdo_cubrid") cubrid_repo="cubrid-pdo";; + esac +} + +# Function to set cubrid branch for a PHP version. +set_cubrid_branch() { + case "${version:?}" in + 5.[3-6]) cubrid_branch="RB-9.3.0";; + *) cubrid_branch="develop";; + esac +} + +add_cubrid_helper() { + ext=$1 + enable_extension "$ext" extension + if ! check_extension "$ext"; then + status='Installed and enabled' + set_cubrid_repo + set_cubrid_branch + patch_phpize + read -r "${ext}_PREFIX_CONFIGURE_OPTS" <<< "CFLAGS=-Wno-implicit-function-declaration" + read -r "${ext}_CONFIGURE_OPTS" <<< "--with-php-config=$(command -v php-config)" + add_extension_from_source "$ext" https://github.com CUBRID "$cubrid_repo" "$cubrid_branch" extension + restore_phpize + fi +} + +# Function to add cubrid and pdo_cubrid. +add_cubrid() { + ext=$1 + status='Enabled' + add_cubrid_helper "$ext" >/dev/null 2>&1 + add_extension_log "$ext" "$status" + check_extension "$ext" && add_license_log +} + +# shellcheck source=. +. "${scripts:?}"/extensions/patches/phpize.sh diff --git a/src/scripts/extensions/event.sh b/src/scripts/extensions/event.sh new file mode 100644 index 0000000..71820b2 --- /dev/null +++ b/src/scripts/extensions/event.sh @@ -0,0 +1,50 @@ +# Function to get event configure options +get_event_configure_opts() { + event_opts=( + --with-event-core + --with-event-extra + --with-event-openssl + --enable-event-sockets + ) + if [ "$os" = 'Linux' ]; then + event_opts+=( + --with-openssl-dir=yes + --with-event-libevent-dir=/usr + ) + else + event_opts+=( + --with-openssl-dir="$(brew --prefix openssl@3)" + --with-event-libevent-dir="$(brew --prefix libevent)" + ) + fi +} + +# Helper function to compile and install event +add_event_helper() { + local ext=$1 + [[ "$ext" =~ ^event$ ]] && ext="event-$(get_pecl_version "event" "stable")" + event_opts=() && get_event_configure_opts + export EVENT_LINUX_LIBS='libevent-dev' + export EVENT_DARWIN_LIBS='libevent' + event_configure_opts="--with-php-config=$(command -v php-config) ${event_opts[*]}" + export EVENT_CONFIGURE_OPTS="$event_configure_opts" + add_extension_from_source event https://pecl.php.net event event "${ext##*-}" extension pecl +} + +# Function to add event +add_event() { + local ext=$1 + enable_extension "event" "extension" + if check_extension "event"; then + add_log "${tick:?}" "event" "Enabled" + else + if ! [[ "${version:?}" =~ ${old_versions:?} ]] && [ "$os" = "Darwin" ]; then + add_brew_extension event extension >/dev/null 2>&1 + else + add_event_helper "$ext" >/dev/null 2>&1 + fi + add_extension_log "event" "Installed and enabled" + fi +} + +os="$(uname -s)" diff --git a/src/scripts/extensions/extension_map.php b/src/scripts/extensions/extension_map.php new file mode 100644 index 0000000..075b6c5 --- /dev/null +++ b/src/scripts/extensions/extension_map.php @@ -0,0 +1,132 @@ +extension_dir = ini_get('extension_dir'); + $this->file_extension = (PHP_OS == 'WINNT' ? '.dll' : '.so'); + $this->file_prefix = (PHP_OS == 'WINNT' ? 'php_' : ''); + $this->map = array(); + } + + /** + * Function to read the extension map. + */ + private function parseMap($path) { + if(file_exists($path)) { + $handle = fopen($path, "r"); + if ($handle) { + while (($line = fgets($handle)) !== false) { + $line_parts = explode(':', $line); + $this->map[$line_parts[0]] = explode(' ', trim($line_parts[1])); + } + fclose($handle); + } + } + } + + /** + * Function to check if a shared extension file exists. + * + * @param string $extension + * @return bool + */ + private function checkSharedExtension($extension) { + $extension_file = $this->extension_dir. DIRECTORY_SEPARATOR . $this->file_prefix . $extension . $this->file_extension; + return file_exists($extension_file); + } + + /** + * Function to get all shared extensions. + * + * @return string[] + */ + private function getSharedExtensions() { + $files = scandir($this->extension_dir); + $extensions = array_diff($files, array('.','..')); + $filter_pattern = "/$this->file_extension|$this->file_prefix/"; + return array_map(function ($extension) use($filter_pattern) { + return preg_replace($filter_pattern, '', $extension); + }, $extensions); + } + + /** + * Function to patch dependencies if there are any bugs in Reflection data. + * + * @param string $extension + * @param array $dependencies + * @return array + */ + private function patchDependencies($extension, $dependencies) { + // memcached 2.2.0 has no dependencies in reflection data. + if($extension == 'memcached') { + $dependencies = array_unique(array_merge($dependencies, array('igbinary', 'json', 'msgpack'))); + } + return $dependencies; + } + + /** + * Function to add extension to the map. + * + * @param string $extension + * @throws ReflectionException + */ + private function addExtensionToMap($extension) { + if($this->map && array_key_exists($extension, $this->map) && !empty($this->map[$extension])) { + return; + } + // PHP 5.3 does not allow using $this. + $self = $this; + + $ref = new ReflectionExtension($extension); + $dependencies = array_keys(array_map('strtolower', $ref->getDependencies())); + $dependencies = $this->patchDependencies($extension, $dependencies); + $dependencies = array_filter($dependencies, function ($dependency) use ($self) { + return $self->checkSharedExtension($dependency); + }); + $self->map[$extension] = $dependencies; + } + + /** + * Function to write the map of shared extensions and their dependent extensions. + */ + public function write() { + $path = $_SERVER['argv'][1]; + $this->parseMap($path); + $extensions = array_map('strtolower', $this->getSharedExtensions()); + foreach ($extensions as $extension) { + try { + $this->addExtensionToMap($extension); + } catch (ReflectionException $e) { + + } + } + $map_string = ''; + foreach($this->map as $extension => $dependencies) { + $map_string .= $extension . ': ' . implode(' ', $dependencies) . PHP_EOL; + } + file_put_contents($path, $map_string); + } +} + +$extension_map = new ExtensionMap(); +$extension_map->write(); diff --git a/src/scripts/extensions/firebird.ps1 b/src/scripts/extensions/firebird.ps1 new file mode 100644 index 0000000..af9ed8e --- /dev/null +++ b/src/scripts/extensions/firebird.ps1 @@ -0,0 +1,20 @@ +Function Add-Choco() { + try { + if($null -eq (Get-Command -Name choco.exe -ErrorAction SilentlyContinue)) { + # Source: https://docs.chocolatey.org/en-us/choco/setup + Set-ExecutionPolicy Bypass -Scope Process -Force + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 + Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) + } + } catch { } +} + +Function Add-Firebird() { + Add-Choco > $null 2>&1 + choco install firebird -params '/ClientAndDevTools' -y --force > $null 2>&1 + if((Get-ChildItem $env:ProgramFiles\**\**\fbclient.dll | Measure-Object).Count -eq 1) { + Add-Extension pdo_firebird + } else { + Add-Log $cross pdo_firebird "Could not install pdo_firebird on PHP $( $installed.FullVersion )" + } +} \ No newline at end of file diff --git a/src/scripts/extensions/firebird.sh b/src/scripts/extensions/firebird.sh new file mode 100644 index 0000000..065afb3 --- /dev/null +++ b/src/scripts/extensions/firebird.sh @@ -0,0 +1,40 @@ +add_firebird_client_darwin() { + firebird_tag='R3_0_7' + pkg_name=$(get -s -n "" https://api.github.com/repos/FirebirdSQL/firebird/releases/tags/"$firebird_tag" | grep -Eo "Firebird-.*.pkg" | head -n 1) + [ -z "$pkg_name" ] && pkg_name=$(get -s -n "" https://github.com/FirebirdSQL/firebird/releases/expanded_assets/"$firebird_tag" | grep -Eo "Firebird-.*.pkg" | head -n 1) + get -q -e "/tmp/firebird.pkg" https://github.com/FirebirdSQL/firebird/releases/download/"$firebird_tag"/"$pkg_name" + sudo installer -pkg /tmp/firebird.pkg -target / + sudo mkdir -p /opt/firebird/include /opt/firebird/lib + sudo find /Library/Frameworks/Firebird.framework -name '*.h' -exec cp "{}" /opt/firebird/include \; + sudo find /Library/Frameworks/Firebird.framework -name '*.dylib' -exec cp "{}" /opt/firebird/lib \; +} + +add_firebird_helper() { + firebird_dir=$1 + tag="$(php_src_tag)" + export PDO_FIREBIRD_CONFIGURE_OPTS="--with-pdo-firebird=$firebird_dir" + export PDO_FIREBIRD_LINUX_LIBS="firebird-dev" + export PDO_FIREBIRD_PATH="ext/pdo_firebird" + add_extension_from_source pdo_firebird https://github.com php php-src "$tag" extension get +} + +add_firebird() { + if [ "$(uname -s )" = "Darwin" ]; then + add_firebird_client_darwin >/dev/null 2>&1 + fi + enable_extension pdo_firebird extension + status="Enabled" + if ! check_extension pdo_firebird; then + status="Installed and enabled" + if [ "$(uname -s)" = "Linux" ]; then + if [[ "${version:?}" =~ 5.3|${nightly_versions:?} ]]; then + add_firebird_helper /usr >/dev/null 2>&1 + else + add_pdo_extension firebird >/dev/null 2>&1 + fi + else + add_firebird_helper /opt/firebird >/dev/null 2>&1 + fi + fi + add_extension_log pdo_firebird "$status" +} diff --git a/src/scripts/extensions/gearman.sh b/src/scripts/extensions/gearman.sh new file mode 100644 index 0000000..eb732dc --- /dev/null +++ b/src/scripts/extensions/gearman.sh @@ -0,0 +1,26 @@ +# Helper function to add gearman extension. +add_gearman_helper() { + add_ppa ondrej/pkg-gearman + install_packages libgearman-dev + enable_extension gearman extension + if ! check_extension gearman; then + status="Installed and enabled" + if [[ "${version:?}" =~ 5.[3-5] ]]; then + pecl_install gearman-1.1.2 + else + install_packages php"${version:?}"-gearman || pecl_install gearman + fi + enable_extension gearman extension + fi +} + +# Function to add gearman extension. +add_gearman() { + status="Enabled" + if [ "$(uname -s)" = 'Linux' ]; then + add_gearman_helper >/dev/null 2>&1 + add_extension_log "gearman" "$status" + else + add_brew_extension gearman extension + fi +} diff --git a/src/scripts/extensions/geos.sh b/src/scripts/extensions/geos.sh new file mode 100644 index 0000000..c685f86 --- /dev/null +++ b/src/scripts/extensions/geos.sh @@ -0,0 +1,17 @@ +# Helper function to compile and install geos +add_geos_helper() { + export GEOS_LINUX_LIBS='libgeos-dev' + export GEOS_DARWIN_LIBS='geos' + add_extension_from_source geos https://github.com libgeos php-geos 1.0.0 extension get +} + +# Function to add geos +add_geos() { + enable_extension "geos" "extension" + if check_extension "geos"; then + add_log "${tick:?}" "geos" "Enabled" + else + add_geos_helper >/dev/null 2>&1 + add_extension_log "geos" "Installed and enabled" + fi +} diff --git a/src/scripts/extensions/http.ps1 b/src/scripts/extensions/http.ps1 new file mode 100644 index 0000000..16d9da3 --- /dev/null +++ b/src/scripts/extensions/http.ps1 @@ -0,0 +1,51 @@ +Function Get-ICUUrl() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + $icu_version, + [Parameter(Position = 1, Mandatory = $true)] + [ValidateNotNull()] + $arch, + [Parameter(Position = 2, Mandatory = $true)] + [ValidateNotNull()] + $vs_version + ) + $trunk = "https://windows.php.net" + $urls=@("${trunk}/downloads/php-sdk/deps/${vs_version}/${arch}", "${trunk}/downloads/php-sdk/deps/archives/${vs_version}/${arch}") + foreach ($url in $urls) { + $web_content = Get-File -Url $url + foreach ($link in $web_content.Links) { + if ($link -match "/.*ICU-${icu_version}.*/") { + return $trunk + $link.HREF + } + } + } +} + +Function Repair-ICU() { + $icu = deplister $ext_dir\php_http.dll | Select-String "icu[a-z]+(\d+).dll,([A-Z]+)" | Foreach-Object { $_.Matches } + if($icu -and $icu.Groups[2].Value -ne 'OK') { + $vs = "vs" + $installed.VCVersion + if ($installed.VCVersion -lt 16) { + $vs = "vc" + $installed.VCVersion + } + $zip_url = Get-ICUUrl $icu.Groups[1].Value $installed.Architecture $vs + if ($zip_url -ne '') { + New-Item -Path "$php_dir" -Name "icu" -ItemType "directory" -Force > $null 2>&1 + Get-File -Url $zip_url -OutFile "$php_dir\icu\icu.zip" + Expand-Archive -Path $php_dir\icu\icu.zip -DestinationPath $php_dir\icu -Force + Get-ChildItem $php_dir\icu\bin -Filter *.dll | Copy-Item -Destination $php_dir -Force + } + } +} + +Function Add-Http() { + Add-Extension iconv >$null 2>&1 + Add-Extension raphf >$null 2>&1 + if($version -lt '8.0') { + Add-Extension propro >$null 2>&1 + } + Add-Extension pecl_http >$null 2>&1 + Repair-ICU + Add-ExtensionLog http "Installed and enabled" +} \ No newline at end of file diff --git a/src/scripts/extensions/http.sh b/src/scripts/extensions/http.sh new file mode 100644 index 0000000..6880298 --- /dev/null +++ b/src/scripts/extensions/http.sh @@ -0,0 +1,113 @@ +# Function to get http version for a PHP version. +get_http_version() { + if [[ ${version:?} =~ 5.[3-6] ]]; then + echo "pecl_http-2.6.0" + elif [[ ${version:?} =~ 7.[0-4] ]]; then + echo "pecl_http-3.2.4" + else + echo "pecl_http-$(get_pecl_version "pecl_http" "stable")" + fi +} + +# Function to enable http extension. +enable_http() { + enable_extension iconv extension + enable_extension propro extension + enable_extension raphf extension + if (! [[ ${version:?} =~ ${jit_versions:?} ]] && check_extension iconv && check_extension propro && check_extension raphf) || + ( [[ ${version:?} =~ ${jit_versions:?} ]] && check_extension iconv && check_extension raphf); then + enable_extension http extension + fi +} + +# Function to install http dependencies. +add_http_dependencies() { + if [[ ${version:?} =~ ${old_versions:?} ]]; then + add_pecl_extension raphf 1.1.2 extension + add_pecl_extension propro 1.0.2 extension + elif [[ ${version:?} =~ 5.6|7.[0-4] ]]; then + add_extension iconv extension + add_extension propro extension + add_extension raphf extension + else + add_extension iconv extension + add_extension raphf extension + fi +} + +# Function to get configure options for http. +get_http_configure_opts() { + if [ "$os" = 'Linux' ]; then + for lib in zlib libbrotli libcurl libevent libicu libidn2 libidn libidnkit2 libidnkit; do + http_opts+=( "--with-http-$lib-dir=/usr" ) + done + else + http_opts+=( "--with-http-zlib-dir=$(xcrun --show-sdk-path)/usr" ) + http_opts+=( "--with-http-libbrotli-dir=$(brew --prefix brotli)" ) + http_opts+=( "--with-http-libcurl-dir=$(brew --prefix curl)" ) + http_opts+=( "--with-http-libicu-dir=$(brew --prefix icu4c)" ) + http_opts+=( "--with-http-libevent-dir=$(brew --prefix libevent)" ) + http_opts+=( "--with-http-libidn2-dir=$(brew --prefix libidn2)" ) + fi +} + +# Compile and install http explicitly. +# This is done as pecl compiles raphf and propro as well. +add_http_helper() { + ext=$1 + http_opts=() && get_http_configure_opts + export HTTP_PREFIX_CONFIGURE_OPTS="CFLAGS=-Wno-implicit-function-declaration" + http_configure_opts="--with-http --with-php-config=$(command -v php-config) ${http_opts[*]}" + export HTTP_CONFIGURE_OPTS="$http_configure_opts" + export HTTP_LINUX_LIBS="zlib1g libbrotli-dev libcurl4-openssl-dev libevent-dev libicu-dev libidn2-dev" + export HTTP_DARWIN_LIBS="brotli curl icu4c libevent libidn2" + if [[ "${version:?}" =~ ${nightly_versions:?} ]]; then + add_extension_from_source http https://github.com m6w6 ext-http master extension + else + add_extension_from_source pecl_http https://pecl.php.net http http "${ext##*-}" extension pecl + fi +} + +# Function to setup latest http extension. +add_http_latest() { + enable_http + if ! check_extension http; then + if [ "$os" = "Linux" ]; then + add_http_dependencies + package="php$version-http" + add_ppa ondrej/php >/dev/null 2>&1 || update_ppa ondrej/php + (check_package "$package" && install_packages "$package") || add_http_helper "$(get_http_version)" "$os" + else + if ! [[ "${version:?}" =~ ${old_versions:?} ]]; then + add_brew_extension pecl_http extension + fi + fi + status="Installed and enabled" + fi +} + +# Function to setup http extension given a version. +add_http_version() { + ext=$1 + enable_http + if [ "x$(php -r "echo phpversion('http');")" != "x${ext##*-}" ]; then + add_http_dependencies + disable_extension_helper http >/dev/null + add_http_helper pecl_http-"${ext##*-}" "$os" + status="Installed and enabled" + fi +} + +# Function to setup http extension +add_http() { + ext=$1 + status="Enabled" + if [[ "$ext" =~ ^(pecl_http|http)$ ]]; then + add_http_latest >/dev/null 2>&1 + else + add_http_version "$ext" >/dev/null 2>&1 + fi + add_extension_log "http" "$status" +} + +os="$(uname -s)" diff --git a/src/scripts/extensions/intl.sh b/src/scripts/extensions/intl.sh new file mode 100644 index 0000000..a1ba481 --- /dev/null +++ b/src/scripts/extensions/intl.sh @@ -0,0 +1,24 @@ +# Function to install ICU +install_icu() { + icu=$1 + if [ "$(php -i | grep "ICU version =>" | sed -e "s|.*=> s*||")" != "$icu" ]; then + get -q -n /tmp/icu.tar.zst "https://github.com/shivammathur/icu-intl/releases/download/icu4c/icu4c-$icu.tar.zst" + sudo tar -I zstd -xf /tmp/icu.tar.zst -C /usr/local + sudo cp -r /usr/local/icu/lib/* /usr/lib/x86_64-linux-gnu/ + fi +} + +# Function to add ext-intl with the given version of ICU +add_intl() { + icu=$(echo "$1" | cut -d'-' -f 2) + supported_version=$(get -s -n "" https://api.github.com/repos/shivammathur/icu-intl/releases | grep -Po "${icu//./\\.}" | head -n 1) + if [ "$icu" != "$supported_version" ]; then + add_log "${cross:?}" "intl" "ICU $icu is not supported" + else + [ "${ts:?}" = 'zts' ] && suffix='-zts' + install_icu "$icu" >/dev/null 2>&1 + get -q -n "${ext_dir:?}/intl.so" "https://github.com/shivammathur/icu-intl/releases/download/intl/php${version:?}-intl-$icu$suffix.so" + enable_extension intl extension + add_extension_log intl "Installed and enabled with ICU $icu" + fi +} diff --git a/src/scripts/extensions/ioncube.ps1 b/src/scripts/extensions/ioncube.ps1 new file mode 100644 index 0000000..88b09e6 --- /dev/null +++ b/src/scripts/extensions/ioncube.ps1 @@ -0,0 +1,33 @@ +# Function to log result of a operation. +Function Add-LicenseLog() { + printf "$env:GROUP\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "ioncube" "Click to read the ioncube loader license information" + Get-Content $ext_dir\ioncube\LICENSE.txt + Write-Output "$env:END_GROUP" +} + +# Function to add ioncube extension. +Function Add-Ioncube() { + try { + $status = 'Enabled' + if (-not(Test-Path $ext_dir\php_ioncube.dll)) { + $status = 'Installed and enabled' + $arch_part = $arch + if ($arch -eq 'x64') { + $arch_part = 'x86-64' + } + $vc = $installed.VCVersion + $ts_part = "" + if (-not($installed.ThreadSafe)) { + $ts_part = "_nonts" + } + Get-File -Url "https://downloads.ioncube.com/loader_downloads/ioncube_loaders_win$ts_part`_vc$vc`_$arch_part.zip" -OutFile $ext_dir\ioncube.zip + Expand-Archive -Path $ext_dir\ioncube.zip -DestinationPath $ext_dir -Force + Copy-Item $ext_dir\ioncube\ioncube_loader_win_$version.dll $ext_dir\php_ioncube.dll + } + "zend_extension=$ext_dir\php_ioncube.dll`r`n" + (Get-Content $php_dir\php.ini -Raw) | Set-Content $php_dir\php.ini + Add-Log $tick "ioncube" $status + Add-LicenseLog + } catch { + Add-Log $cross "ioncube" "Could not install ioncube on PHP $($installed.FullVersion)" + } +} diff --git a/src/scripts/extensions/ioncube.sh b/src/scripts/extensions/ioncube.sh new file mode 100644 index 0000000..bfb038d --- /dev/null +++ b/src/scripts/extensions/ioncube.sh @@ -0,0 +1,21 @@ +# Function to log result of a operation. +add_license_log() { + printf "$GROUP\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "ioncube" "Click to read the ioncube loader license information" + cat "${ext_dir:?}"/IONCUBE_LICENSE.txt + echo "$END_GROUP" +} + +# Function to install ioncube. +add_ioncube() { + status='Enabled' + if ! shared_extension ioncube; then + status='Installed and enabled' + os_name='lin' && [ "$(uname -s)" = "Darwin" ] && os_name='mac' + get -s -n "" https://downloads.ioncube.com/loader_downloads/ioncube_loaders_"$os_name"_x86-64.tar.gz | tar -xzf - -C /tmp + sudo mv /tmp/ioncube/ioncube_loader_"$os_name"_"${version:?}".so "${ext_dir:?}/ioncube.so" + sudo cp /tmp/ioncube/LICENSE.txt "$ext_dir"/IONCUBE_LICENSE.txt + fi + echo "zend_extension=$ext_dir/ioncube.so" | sudo tee "${scan_dir:?}/00-ioncube.ini" >/dev/null 2>&1 + add_extension_log "ioncube" "$status" + check_extension "ioncube" && add_license_log +} diff --git a/src/scripts/extensions/oci.ps1 b/src/scripts/extensions/oci.ps1 new file mode 100644 index 0000000..3cd2130 --- /dev/null +++ b/src/scripts/extensions/oci.ps1 @@ -0,0 +1,85 @@ +# Function to log license information. +Function Add-LicenseLog() { + printf "$env:GROUP\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" $extension "Click to read the $extension related license information" + printf "Oracle Instant Client package is required for %s extension.\n" $extension + printf "It is provided under the Oracle Technology Network Development and Distribution License.\n" + printf "Refer to: \033[35;1m%s \033[0m\n" "https://www.oracle.com/downloads/licenses/instant-client-lic.html" + Write-Output "$env:END_GROUP" +} + +# Function to get instantclinet. +Function Add-InstantClient() { + if (-not(Test-Path $php_dir\oci.dll)) { + $suffix = 'windows' + if ($arch -eq 'x86') { + $suffix = 'nt' + } + Get-File -Url https://download.oracle.com/otn_software/nt/instantclient/instantclient-basiclite-$suffix.zip -OutFile $php_dir\instantclient.zip + Expand-Archive -Path $php_dir\instantclient.zip -DestinationPath $php_dir -Force + Copy-Item $php_dir\instantclient*\* $php_dir + } +} + +# Function to oci8 extension URL. +Function Get-Oci8Url() { + if($version -lt '8.0') { + $ociVersion = '2.2.0' + if ($version -eq '7.0') { + $ociVersion = '2.1.8' + } elseif ($version -lt '7.0') { + $ociVersion = '2.0.12' + } + return Get-PeclArchiveUrl oci8 $ociVersion $installed + } else { + $ociUrl = ''; + Get-PeclPackageVersion oci8 -MinimumStability stable -MaximumStability stable | ForEach-Object { + $ociUrl = Get-PeclArchiveUrl oci8 $_ $installed + if($ociUrl) { + return $ociUrl + } + } + } +} + +# Function to get OCI8 DLL. +Function Get-Oci8DLL() { + Get-ChildItem $ext_dir\php_oci8*.dll | ForEach-Object { + if((Get-PhpExtension -Path $_).PhpVersion -eq $version) { + return $_ + } + } +} + +# Function to install oci8 and pdo_oci. +Function Add-Oci() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateSet('oci8', 'pdo_oci')] + [string] + $extension + ) + try { + $status = 'Enabled' + Add-InstantClient + if ($extension -eq "pdo_oci") { + Enable-PhpExtension pdo_oci -Path $php_dir + } else { + if(-not(Test-Path $ext_dir\php_oci8.dll)) { + $oci8DLL = Get-Oci8DLL + if($oci8DLL) { + Copy-Item -Path $oci8DLL -Destination $ext_dir\php_oci8.dll + } else { + $status = 'Installed and enabled' + Get-File -Url (Get-Oci8Url) -OutFile $php_dir\oci8.zip + Expand-Archive -Path $php_dir\oci8.zip -DestinationPath $ext_dir -Force + } + } + Add-Content -Value "`r`nextension=php_oci8.dll" -Path $php_dir\php.ini + } + Add-Log $tick $extension $status + Add-LicenseLog + } catch { + Add-Log $cross $extension "Could not install $extension on PHP $( $installed.FullVersion )" + } +} diff --git a/src/scripts/extensions/oci.sh b/src/scripts/extensions/oci.sh new file mode 100644 index 0000000..838be60 --- /dev/null +++ b/src/scripts/extensions/oci.sh @@ -0,0 +1,65 @@ +# Function to log result of a operation. +add_license_log() { + printf "$GROUP\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "$ext" "Click to read the $ext related license information" + printf "Oracle Instant Client package is required for %s extension.\n" "$ext" + printf "It is provided under the Oracle Technology Network Development and Distribution License.\n" + printf "Refer to: \033[35;1m%s \033[0m\n" "https://www.oracle.com/downloads/licenses/instant-client-lic.html" + echo "$END_GROUP" +} + +# Function to install instantclient and SDK. +add_client() { + if [ ! -e "$oracle_client" ]; then + sudo mkdir -p -m 777 "$oracle_home" "$oracle_client" + for package in basiclite sdk; do + if [ "$os" = 'Linux' ]; then + libs='/usr/lib/' + os_name='linux' + arch='linuxx64' + lib_ext='so' + elif [ "$os" = 'Darwin' ]; then + libs='/usr/local/lib/' + os_name='mac' + arch='macos' + lib_ext='dylib' + fi + get -q -n "/opt/oracle/$package.zip" "https://download.oracle.com/otn_software/$os_name/instantclient/instantclient-$package-$arch.zip" + unzip -o "/opt/oracle/$package.zip" -d "$oracle_home" + done + for icdir in /opt/oracle/instantclient_*; do + sudo mv "$icdir"/* "$oracle_client"/ + done + sudo ln -sf /opt/oracle/instantclient/*.$lib_ext* $libs + fi +} + +# Function to install oci8 and pdo_oci. +add_oci_helper() { + if ! shared_extension "$ext"; then + status='Installed and enabled' + read -r "${ext}_LINUX_LIBS" <<< "libaio-dev" + read -r "${ext}_CONFIGURE_OPTS" <<< "--with-php-config=$(command -v php-config) --with-${ext/_/-}=instantclient,$oracle_client" + read -r "${ext}_PATH" <<< "ext/$ext" + patch_phpize + add_extension_from_source "$ext" https://github.com php php-src "$(php_src_tag)" extension get + restore_phpize + else + enable_extension "$ext" extension + fi +} + +# Function to add oci extension oci8 and pdo_oci. +add_oci() { + ext=$1 + status='Enabled' + oracle_home='/opt/oracle' + oracle_client=$oracle_home/instantclient + os=$(uname -s) + add_client >/dev/null 2>&1 + add_oci_helper >/dev/null 2>&1 + add_extension_log "$ext" "$status" + check_extension "$ext" && add_license_log +} + +# shellcheck source=. +. "${scripts:?}"/extensions/patches/phpize.sh diff --git a/src/scripts/extensions/patches/firebird.sh b/src/scripts/extensions/patches/firebird.sh new file mode 100644 index 0000000..0007d61 --- /dev/null +++ b/src/scripts/extensions/patches/firebird.sh @@ -0,0 +1,11 @@ +patch_firebird() { + if [[ "${version:?}" =~ ${old_versions:?} ]]; then + sudo sed -i '' '/PHP_CHECK_PDO_INCLUDES/d' config.m4 2>/dev/null || sudo sed -i '/PHP_CHECK_PDO_INCLUDES/d' config.m4 + fi + lib_arch=$(gcc -dumpmachine) + lib_dir=/usr/lib/"$lib_arch" + if [ -d "$lib_dir" ]; then + sudo ln -sf "$lib_dir"/libfbclient.so.2 /usr/lib/libfbclient.so + sudo ln -sf "$lib_dir"/libib_util.so /usr/lib/ + fi +} diff --git a/src/scripts/extensions/patches/geos.sh b/src/scripts/extensions/patches/geos.sh new file mode 100644 index 0000000..5f1a1c0 --- /dev/null +++ b/src/scripts/extensions/patches/geos.sh @@ -0,0 +1,9 @@ +patch_geos() { + if [ "$(php -r "echo PHP_VERSION_ID;")" -ge 70000 ]; then + sed -i~ -e "s/, ce->name/, ZSTR_VAL(ce->name)/; s/ulong /zend_ulong /" geos.c + fi + get -q -n /tmp/php8.patch https://git.remirepo.net/cgit/rpms/php/php-geos.git/plain/0003-add-all-arginfo-and-fix-build-with-PHP-8.patch + get -q -n /tmp/toString.patch https://git.remirepo.net/cgit/rpms/php/php-geos.git/plain/0006-fix-__toString-with-8.2.patch + patch -p1 < /tmp/php8.patch 2>/dev/null || true + patch -p1 < /tmp/toString.patch 2>/dev/null || true +} diff --git a/src/scripts/extensions/patches/http.sh b/src/scripts/extensions/patches/http.sh new file mode 100644 index 0000000..ca8bfac --- /dev/null +++ b/src/scripts/extensions/patches/http.sh @@ -0,0 +1,11 @@ +patch_pecl_http() { + if [ "$(uname -s)" = 'Darwin' ] && ! [[ ${version:?} =~ ${old_versions:?} ]]; then + if [[ ${version:?} =~ 5.6|7.[0-4] ]]; then + sed -i '' -e "s|ext/propro|$(brew --prefix propro@"${version:?}")/include/php/ext/propro@${version:?}|" "./src/php_http_api.h" + fi + sed -i '' -e "s|ext/raphf|$(brew --prefix raphf@"${version:?}")/include/php/ext/raphf@${version:?}|" "./src/php_http_api.h" + if [ "${version:?}" = "5.6" ]; then + sed -i '' -e "s|\$abs_srcdir|\$abs_srcdir ${brew_prefix:?}/include|" -e "s|/ext/propro|/php/ext/propro@5.6|" -e "s|/ext/raphf|/php/ext/raphf@5.6|" "./config9.m4" + fi + fi +} diff --git a/src/scripts/extensions/patches/pdo_oci.sh b/src/scripts/extensions/patches/pdo_oci.sh new file mode 100644 index 0000000..3eb903a --- /dev/null +++ b/src/scripts/extensions/patches/pdo_oci.sh @@ -0,0 +1,6 @@ +patch_pdo_oci() { + get -q -n config.m4 https://raw.githubusercontent.com/php/php-src/PHP-8.0/ext/pdo_oci/config.m4 + if [[ ${version:?} =~ 5.[3-6] ]]; then + sudo sed -i '' "/PHP_CHECK_PDO_INCLUDES/d" config.m4 2>/dev/null || sudo sed -i "/PHP_CHECK_PDO_INCLUDES/d" config.m4 + fi +} diff --git a/src/scripts/extensions/patches/phpize.sh b/src/scripts/extensions/patches/phpize.sh new file mode 100644 index 0000000..1db2ace --- /dev/null +++ b/src/scripts/extensions/patches/phpize.sh @@ -0,0 +1,26 @@ +# Function to get phpize location on darwin. +get_phpize() { + if [[ "${version:?}" =~ 5.[3-5] ]]; then + echo '/opt/local/bin/phpize' + else + echo "/usr/local/bin/$(readlink /usr/local/bin/phpize)" + fi +} + +# Function to patch phpize to link to php headers on darwin. +patch_phpize() { + if [ "$(uname -s)" = "Darwin" ]; then + sudo cp "$phpize_orig" "$phpize_orig.bck" + sudo sed -i '' 's~includedir=.*~includedir="$(xcrun --show-sdk-path)/usr/include/php"~g' "$phpize_orig" + fi +} + +# Function to restore phpize. +restore_phpize() { + if [ "$os" = "Darwin" ]; then + sudo mv "$phpize_orig.bck" "$phpize_orig" || true + fi +} + +os="$(uname -s)" +phpize_orig="$(get_phpize)" diff --git a/src/scripts/extensions/patches/protobuf.sh b/src/scripts/extensions/patches/protobuf.sh new file mode 100644 index 0000000..1289115 --- /dev/null +++ b/src/scripts/extensions/patches/protobuf.sh @@ -0,0 +1,4 @@ +patch_protobuf() { + mkdir -p third_party/wyhash + cp ../../../../third_party/wyhash/* third_party/wyhash +} diff --git a/src/scripts/extensions/phalcon.ps1 b/src/scripts/extensions/phalcon.ps1 new file mode 100644 index 0000000..3d00873 --- /dev/null +++ b/src/scripts/extensions/phalcon.ps1 @@ -0,0 +1,109 @@ +# Function to get the url of the phalcon release asset. +Function Get-PhalconReleaseAssetUrl() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [string] + $Semver + ) + $domain = 'https://api.github.com/repos' + $releases = 'phalcon/cphalcon/releases' + if($extension_version -match '[3-4]') { + $nts = if (!$installed.ThreadSafe) { "_nts" } else { "" } + try { + $match = (Invoke-RestMethod -Uri "$domain/$releases/tags/v$Semver").assets | Select-String -Pattern "browser_download_url=.*(phalcon_${arch}_.*_php${version}_${extension_version}.*[0-9]${nts}.zip)" + } catch { + $match = (Get-File -Url "$github/$releases/expanded_assets/v$Semver").Links.href | Select-String -Pattern "(phalcon_${arch}_.*_php${version}_${extension_version}.*[0-9]${nts}.zip)" + } + } else { + $nts = if (!$installed.ThreadSafe) { "-nts" } else { "-ts" } + try { + $match = (Invoke-RestMethod -Uri "$domain/$releases/tags/v$Semver").assets | Select-String -Pattern "browser_download_url=.*(phalcon-php${version}${nts}-windows.*-x64.zip)" + } catch { + $match = (Get-File -Url "$github/$releases/expanded_assets/v$Semver").Links.href | Select-String -Pattern "(phalcon-php${version}${nts}-windows.*-x64.zip)" + } + } + if($NULL -ne $match) { + return "$github/$releases/download/v$Semver/$($match.Matches[0].Groups[1].Value)" + } + return false; +} + +# Function to add phalcon using GitHub releases. +Function Add-PhalconFromGitHub() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [string] + $Semver + ) + $zip_url = Get-PhalconReleaseAssetUrl $Semver + if($zip_url) { + Get-File -Url $zip_url -OutFile $ENV:RUNNER_TOOL_CACHE\phalcon.zip > $null 2>&1 + Expand-Archive -Path $ENV:RUNNER_TOOL_CACHE\phalcon.zip -DestinationPath $ENV:RUNNER_TOOL_CACHE\phalcon -Force > $null 2>&1 + Copy-Item -Path "$ENV:RUNNER_TOOL_CACHE\phalcon\php_phalcon.dll" -Destination "$ext_dir\php_phalcon.dll" + Enable-PhpExtension -Extension phalcon -Path $php_dir + } else { + throw "Unable to get Phalcon release from the GitHub release" + } +} + +# Function to get phalcon semver. +Function Get-PhalconSemver() { + if($extension_version -eq '3') { + return '3.4.5' + } elseif (($extension_version -eq '4') -and ($version -eq '7.2')) { + return '4.1.0' + } + return Get-PeclPackageVersion phalcon $extension_version stable stable | Select-Object -First 1 +} + +# Function to install phalcon +Function Add-PhalconHelper() { + $semver = Get-PhalconSemver + if (($extension_version -eq '3') -or ($extension_version -eq '5')) { + Add-PhalconFromGitHub $semver + } elseif ($extension_version -eq '4') { + Add-Extension -Extension phalcon -Stability stable -Extension_version $semver + } +} + +# Function to add phalcon +Function Add-Phalcon() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateSet('phalcon3', 'phalcon4', 'phalcon5')] + [string] + $extension + ) + try { + $status = 'Enabled' + $extension_version = $extension.substring($extension.Length - 1) + + if($extension_version -eq '4') { + if (Test-Path $ext_dir\php_psr.dll) { + Enable-PhpExtension -Extension psr -Path $php_dir + } else { + Install-Phpextension -Extension psr -MinimumStability stable -Path $php_dir + } + } + + if(Test-Path $ext_dir\php_phalcon.dll) { + $phalcon = Get-PhpExtension $ext_dir\php_phalcon.dll + if($phalcon.Version[0] -eq $extension_version) { + Enable-PhpExtension -Extension phalcon -Path $php_dir + } else { + $status = 'Installed and enabled' + Remove-Item $ext_dir\php_phalcon.dll + Add-PhalconHelper + } + } else { + $status = 'Installed and enabled' + Add-PhalconHelper + } + Add-Log $tick $extension $status + } catch [Exception] { + Add-Log $cross $extension "Could not install $extension on PHP $($installed.FullVersion)" + } +} diff --git a/src/scripts/extensions/phalcon.sh b/src/scripts/extensions/phalcon.sh new file mode 100644 index 0000000..ea70f0c --- /dev/null +++ b/src/scripts/extensions/phalcon.sh @@ -0,0 +1,95 @@ +# Helper function to get phalcon version +get_phalcon_version() { + if [ "$extension" = "phalcon5" ]; then + get_pecl_version phalcon stable 5 + elif [ "$extension" = "phalcon4" ]; then + echo '4.1.2' + elif [ "$extension" = "phalcon3" ]; then + echo '3.4.5' + fi +} + +# Function to add phalcon from repo. +add_phalcon_from_repo(){ + version=${version:?} + if [ "$extension" = "phalcon5" ]; then + PHALCON_PATH=build/phalcon + else + PHALCON_PATH=build/php"${version%.*}"/64bits + fi + PHALCON_CONFIGURE_OPTS="--enable-phalcon --with-php-config=$(command -v php-config)" + export PHALCON_PATH + export PHALCON_CONFIGURE_OPTS + add_extension_from_source phalcon https://github.com phalcon cphalcon v"$(get_phalcon_version)" extension +} + +# Helper function to add phalcon. +add_phalcon_helper() { + status='Installed and enabled' + if [ "$(uname -s)" = "Darwin" ]; then + add_brew_extension "$extension" extension + else + package="php${version:?}-$extension" + add_ppa ondrej/php >/dev/null 2>&1 || update_ppa ondrej/php + [ "$extension" = "phalcon4" ] && (install_packages "php${version:?}-psr" || pecl_install psr || pecl_install psr-1.1.0) + (check_package "$package" && install_packages "$package") || pecl_install phalcon-"$(get_phalcon_version)" || add_phalcon_from_repo + fi +} + +# Function to add phalcon3. +add_phalcon3() { + if shared_extension phalcon; then + phalcon_version=$(php -d="extension=phalcon.so" -r "echo phpversion('phalcon');" | cut -d'.' -f 1) + if [ "$phalcon_version" != "$extension_major_version" ]; then + add_phalcon_helper + else + enable_extension phalcon extension + fi + else + add_phalcon_helper + fi +} + +# Function to add phalcon4. +add_phalcon4() { + enable_extension psr extension + if shared_extension phalcon; then + if check_extension psr; then + phalcon_version=$(php -d="extension=phalcon" -r "echo phpversion('phalcon');" | cut -d'.' -f 1) + if [ "$phalcon_version" != "$extension_major_version" ]; then + add_phalcon_helper + else + enable_extension phalcon extension + fi + else + add_phalcon_helper + fi + else + add_phalcon_helper + fi +} + +# Function to add phalcon3. +add_phalcon5() { + if shared_extension phalcon; then + phalcon_version=$(php -d="extension=phalcon.so" -r "echo phpversion('phalcon');" | cut -d'.' -f 1) + if [ "$phalcon_version" != "$extension_major_version" ]; then + add_phalcon_helper + else + enable_extension phalcon extension + fi + else + add_phalcon_helper + fi +} + +# Function to add phalcon. +add_phalcon() { + local extension=$1 + status='Enabled' + extension_major_version=${extension: -1} + if [[ "$extension_major_version" =~ [3-5] ]]; then + add_phalcon"$extension_major_version" >/dev/null 2>&1 + fi + add_extension_log "phalcon" "$status" +} diff --git a/src/scripts/extensions/relay.sh b/src/scripts/extensions/relay.sh new file mode 100644 index 0000000..368c0f0 --- /dev/null +++ b/src/scripts/extensions/relay.sh @@ -0,0 +1,146 @@ +# Get relay version +get_relay_version() { + local ext=$1 + if [[ "$ext" =~ ^relay$ ]]; then + get -s -n "" "${relay_releases:?}"/latest 2<&1 | grep -m 1 -Eo "tag/(v[0-9]+(\.[0-9]+)?(\.[0-9]+)?)" | head -n 1 | cut -d '/' -f 2 + else + relay_version="${ext##*-}" + echo "v${relay_version/v//}" + fi +} + +# Get OS suffix in relay artifact URL. +get_os_suffix() { + if [ "$os" = "Linux" ]; then + if [[ "$ID" =~ ubuntu|debian ]]; then + echo debian + elif [ "$ID" = "centos" ]; then + echo centos"$VERSION_ID" + else + echo "$ID" + fi + else + echo darwin + fi +} + +# Get openssl suffix in relay artifact URL. +get_openssl_suffix() { + openssl_3=$(php -r "echo strpos(OPENSSL_VERSION_TEXT, 'SSL 3') !== false;") + [ "$openssl_3" = "1" ] && echo '+libssl3' || echo '' +} + +# Change library paths in relay binary. +change_library_paths() { + if [ "$os" = "Darwin" ]; then + otool -L "${ext_dir:?}"/relay.so | grep -q 'ssl.1' && openssl_version='1.1' || openssl_version='3' + [ -e "${brew_prefix:?}"/opt/openssl@"$openssl_version" ] || brew install openssl@"$openssl_version" + dylibs="$(otool -L "${ext_dir:?}"/relay.so | grep -Eo '.*\.dylib' | cut -f1 -d ' ')" + install_name_tool -change "$(echo "${dylibs}" | grep -E "libzstd.*dylib" | xargs)" "$brew_prefix"/opt/zstd/lib/libzstd.dylib "$ext_dir"/relay.so + install_name_tool -change "$(echo "${dylibs}" | grep -E "liblz4.*dylib" | xargs)" "$brew_prefix"/opt/lz4/lib/liblz4.dylib "$ext_dir"/relay.so + install_name_tool -change "$(echo "${dylibs}" | grep -E "libssl.*dylib" | xargs)" "$brew_prefix"/opt/openssl@"$openssl_version"/lib/libssl.dylib "$ext_dir"/relay.so + install_name_tool -change "$(echo "${dylibs}" | grep -E "libcrypto.*dylib" | xargs)" "$brew_prefix"/opt/openssl@"$openssl_version"/lib/libcrypto.dylib "$ext_dir"/relay.so + fi +} + +# Add relay dependencies +add_relay_dependencies() { + add_extension json + add_extension msgpack + add_extension igbinary + if [ "$os" = "Darwin" ]; then + . "${0%/*}"/tools/brew.sh + configure_brew + brew install hiredis lz4 zstd + fi +} + +# Initialize relay extension ini configuration +init_relay_ini() { + relay_ini=$1 + if [ -e "$relay_ini" ]; then + if [[ -n "$RELAY_KEY" ]]; then + sudo sed -i.bak "s/^; relay.key =.*/relay.key = $RELAY_KEY/" "$relay_ini" + fi + if [[ -n "$RELAY_ENVIRONMENT" ]]; then + sudo sed -i.bak "s/^; relay.environment =.*/relay.environment = $RELAY_ENVIRONMENT/" "$relay_ini" + fi + if [[ -n "$RELAY_EVICTION_POLICY" ]]; then + sudo sed -i.bak "s/^; relay.eviction_policy =.*/relay.eviction_policy = $RELAY_EVICTION_POLICY/" "$relay_ini" + fi + if [[ -n "$RELAY_MAX_MEMORY" ]]; then + sudo sed -i.bak "s/^; relay.maxmemory =.*/relay.maxmemory = $RELAY_MAX_MEMORY/" "$relay_ini" + fi + sudo rm -rf "$relay_ini".bak + fi +} + +# Enable relay extension +enable_relay() { + relay_ini=$1 + if [ -e "$relay_ini" ]; then + init_relay_ini "$relay_ini" + if [ "$os" = "Linux" ]; then + sudo cp "$relay_ini" "${ini_dir:?}"/../mods-available/relay.ini + sudo phpenmod -v "${version:?}" relay + else + sudo cp "${relay_ini}" "${scan_dir:?}"/60-relay.ini + fi + fi +} + +# Patch binary id in relay extension +init_relay_binary_id() { + if [ -e "${ext_dir:?}"/relay.so ]; then + grep -aq 00000000 "${ext_dir:?}"/relay.so && \ + sudo LC_ALL=C sed -i.bak "s/00000000-0000-0000-0000-000000000000/$(uuidgen)/" "$ext_dir"/relay.so + fi +} + +# Configure relay extension +configure_relay() { + change_library_paths + init_relay_binary_id + enable_relay "${ext_dir}"/relay.ini +} + +# Helper function to add relay extension +add_relay_helper() { + arch="$(uname -m | sed 's/_/-/')" + os_suffix="$(get_os_suffix)" + openssl_suffix="$(get_openssl_suffix)" + artifact_file_name="relay-$relay_version-php${version:?}-$os_suffix-$arch$openssl_suffix.tar.gz" + url="$relay_trunk"/"$relay_version"/"$artifact_file_name" + get -q -n /tmp/relay.tar.gz "$url" + if (! [ -e /tmp/relay.tar.gz ] || ! file /tmp/relay.tar.gz | grep -q 'gzip'); then + if [ "$openssl_suffix" = '+libssl3' ]; then + get -q -n /tmp/relay.tar.gz "${url/+libssl3/}" + else + get -q -n /tmp/relay.tar.gz "${url/.tar/+libssl3.tar}" + fi + fi + if [ -e /tmp/relay.tar.gz ] && file /tmp/relay.tar.gz | grep -q 'gzip'; then + sudo tar --strip-components=1 -xzf /tmp/relay.tar.gz -C "${ext_dir:?}" + sudo mv "${ext_dir:?}"/relay-pkg.so "${ext_dir:?}"/relay.so + fi +} + +# Add relay extension +add_relay() { + local ext=$1 + local arch + local url + os=$(uname -s) + relay_releases=https://github.com/cachewerk/relay/releases + relay_trunk=https://builds.r2.relay.so + relay_version=$(get_relay_version "$ext") + add_relay_dependencies >/dev/null 2>&1 + if shared_extension relay; then + message="Enabled" + else + add_relay_helper >/dev/null 2>&1 + message="Installed and enabled" + fi + configure_relay >/dev/null 2>&1 + add_extension_log relay "$message" +} diff --git a/src/scripts/extensions/source.sh b/src/scripts/extensions/source.sh new file mode 100644 index 0000000..36d15fb --- /dev/null +++ b/src/scripts/extensions/source.sh @@ -0,0 +1,159 @@ +# Function to parse extension environment variables +parse_args() { + local extension=${1%-*} + suffix=$(echo "$2" | tr '[:lower:]' '[:upper:]') + up_ext_name=$(echo "$extension" | tr '[:lower:]' '[:upper:]') + var="${extension}_${suffix}" + up_var="${up_ext_name}_${suffix}" + ! [[ "$suffix" =~ .*PREFIX|LIBS|PATH.* ]] && hyp='-' + output=$(echo "${!var} ${!up_var}" | sed "s/, *$hyp/ $hyp/g" | sed -E "s/^,|,$//g") + echo "$output" | xargs -n 1 | sort | uniq | xargs +} + +# Function to parse configure options for pecl +# Make sure we have all options in name="value" form i.e XML properties. +parse_pecl_configure_options() { + configure_opts=$(echo "$1" | sed -E -e "s#['\"]|--##g") + IFS=' ' read -r -a opts_array <<< "$configure_opts" + output_opts=() + for opt in "${opts_array[@]}"; do + [ "${opt##*=}" != "${opt%=*}" ] && value="${opt##*=}" || value=yes + output_opts+=("${opt%=*}=\"$value\"") + done + echo "${output_opts[@]}" +} + +# Function to log if a library is installed +add_lib_log() { + local lib=$1 + if check_lib "$lib"; then + add_log "${tick:?}" "$lib" "Installed" + else + add_log "${cross:?}" "$lib" "Could not install $lib" + fi +} + +# Function to check if a library is installed +check_lib() { + local lib=$1 + if [ "$(uname -s)" = "Linux" ]; then + [ "x$(dpkg -s "$lib" 2>/dev/null | grep Status)" != "x" ] + else + [ "x$(find "${brew_prefix:?}"/Cellar -maxdepth 1 -name "$lib")" != "x" ] + fi +} + +# Function to add a library on linux +add_linux_libs() { + local lib=$1 + if ! check_lib "$lib"; then + install_packages "$lib" >/dev/null 2>&1 || true + fi + add_lib_log "$lib" +} + +# Function to add a library on macOS +add_darwin_libs() { + local lib=$1 + if ! check_lib "$lib"; then + brew install "$lib" >/dev/null 2>&1 || true + if [[ "$lib" = *@* ]]; then + brew link --overwrite --force "$lib" >/dev/null 2>&1 || true + fi + fi + add_lib_log "$lib" +} + +# Function to add required libraries +add_libs() { + local all_libs=("$@") + for lib in "${all_libs[@]}"; do + if [ "$(uname -s)" = "Linux" ]; then + add_linux_libs "$lib" + else + add_darwin_libs "$lib" + fi + done +} + +# Function to run command in a group +run_group() { + local command=$1 + local log=$2 + echo "$command" | sudo tee ./run_group.sh >/dev/null 2>&1 + echo "$GROUP$log" + . ./run_group.sh + rm ./run_group.sh + echo "$END_GROUP" +} + +patch_extension() { + local extension=$1 + if [ -e "${scripts:?}"/extensions/patches/"$extension".sh ]; then + # shellcheck source=. + . "${scripts:?}"/extensions/patches/"$extension".sh + patch_"${extension}" + fi +} + +fetch_extension() { + local extension=$1 + local fetch=$2 + if [ "$fetch" = "clone" ]; then + run_group "git clone -nv $url/$org/$repo /tmp/$repo-$release" "git clone" + cd /tmp/"$repo-$release" || exit 1 + git checkout -q "$release" + cd "$sub_dir" || exit 1 + if [ -e .gitmodules ]; then + jobs="$(grep -c "\[submodule" .gitmodules)" + run_group "git submodule update --jobs $jobs --init --recursive" "git submodule" + fi + elif [ "$fetch" = "get" ]; then + get -q -n /tmp/"$extension".tar.gz "$url/$org/$repo/archive/$release.tar.gz" + tar -xzf /tmp/"$extension".tar.gz -C /tmp + cd /tmp/"$repo"-"$release"/"$sub_dir" || exit + elif [ "$fetch" = "pecl" ]; then + source="pecl" + pecl_name=${extension/http/pecl_http} + get -q -n /tmp/"$pecl_name".tgz https://pecl.php.net/get/"$pecl_name"-"$release".tgz + tar -xzf /tmp/"$pecl_name".tgz -C /tmp + cd /tmp/"$pecl_name"-"$release" || exit + fi +} + +# Function to install extension from a git repository +add_extension_from_source() { + local extension="${1/pecl_/}" + local url=$2 + local org=$3 + local repo=$4 + local release=$5 + local prefix=$6 + local fetch=${7:-clone} + slug="$extension-$release" + source="$url/$org/$repo" + libraries="$(parse_args "$extension" LIBS) $(parse_args "$extension" "$(uname -s)"_LIBS)" + opts="$(parse_args "$extension" CONFIGURE_OPTS)" + prefix_opts="$(parse_args "$extension" CONFIGURE_PREFIX_OPTS)" + suffix_opts="$(parse_args "$extension" CONFIGURE_SUFFIX_OPTS)" + sub_dir="$(parse_args "$extension" PATH)" + step_log "Setup $slug" + ( + add_devtools phpize >/dev/null 2>&1 + disable_extension_helper "$extension" + fetch_extension "$extension" "$fetch" + if ! [ "$(find . -maxdepth 1 -name '*.m4' -exec grep -H 'PHP_NEW_EXTENSION' {} \; | wc -l)" != "0" ]; then + add_log "${cross:?}" "$source" "$source does not have a PHP extension" + else + [[ -n "${libraries// }" ]] && run_group "add_libs $libraries" "add libraries" + [ "${debug:?}" = "debug" ] && suffix_opts="$suffix_opts --enable-debug" + patch_extension "$extension" >/dev/null 2>&1 + run_group "phpize" "phpize" + run_group "sudo $prefix_opts ./configure $suffix_opts $opts" "configure" + run_group "sudo make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)" "make" + run_group "sudo make install" "make install" + enable_extension "$extension" "$prefix" + fi + ) + add_extension_log "$slug" "Installed from $source and enabled" +} diff --git a/src/scripts/extensions/sqlsrv.ps1 b/src/scripts/extensions/sqlsrv.ps1 new file mode 100644 index 0000000..00ae5df --- /dev/null +++ b/src/scripts/extensions/sqlsrv.ps1 @@ -0,0 +1,69 @@ +# Function to get sqlsrv extension version. +Function Get-SqlsrvReleaseVersion() { + if ($version -le '7.2') { + # Use the releases from PECL for these versions + return null; + } elseif($version -eq '7.3') { + return '5.9.0' + } elseif ($version -eq '7.4') { + return '5.10.1' + } else { + return 'latest' + } +} + +# Function to get sqlsrv extension release URL. +Function Get-SqlsrvReleaseUrl() +{ + $extensionVersion = Get-SqlsrvReleaseVersion + if($extensionVersion) { + $repo = "$github/microsoft/msphpsql" + if($extensionVersion -eq 'latest') { + return "$repo/releases/latest/download/Windows-$version.zip" + } else { + return "$repo/releases/download/v$extensionVersion/Windows-$version.zip" + } + } +} + +# Function to add sqlsrv extension from GitHub. +Function Add-SqlsrvFromGithub() +{ + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [string] + $extension + ) + $zipUrl = SqlsrvReleaseUrl + if($zipUrl) { + $nts = if (!$installed.ThreadSafe) { "nts" } else { "ts" } + $noDotVersion = $version.replace('.', '') + $extensionFilePath = "Windows-$version\$arch\php_${extension}_${noDotVersion}_${nts}.dll" + Get-File -Url $zipUrl -OutFile $ENV:RUNNER_TOOL_CACHE\sqlsrv.zip > $null 2>&1 + Expand-Archive -Path $ENV:RUNNER_TOOL_CACHE\sqlsrv.zip -DestinationPath $ENV:RUNNER_TOOL_CACHE\sqlsrv -Force > $null 2>&1 + Copy-Item -Path "$ENV:RUNNER_TOOL_CACHE\sqlsrv\$extensionFilePath" -Destination "$ext_dir\php_$extension.dll" + Enable-PhpExtension -Extension $extension -Path $php_dir + } +} + +# Function to add sqlsrv extension. +Function Add-Sqlsrv() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [string] + $extension + ) + $status = 'Enabled' + if (Test-Path $ext_dir\php_$extension.dll) { + Enable-PhpExtension -Extension $extension -Path $php_dir + } else { + Add-SqlsrvFromGithub $extension >$null 2>&1 + if (-not(Test-Extension $extension)) { + Add-Extension $extension >$null 2>&1 + } + $status = 'Installed and enabled' + } + Add-ExtensionLog $extension $status +} diff --git a/src/scripts/extensions/sqlsrv.sh b/src/scripts/extensions/sqlsrv.sh new file mode 100644 index 0000000..0b47c12 --- /dev/null +++ b/src/scripts/extensions/sqlsrv.sh @@ -0,0 +1,23 @@ +# Function to get sqlsrv and pdo_sqlsrv version. +get_sqlsrv_version() { + if [[ "${version:?}" =~ 7.[0-3] ]]; then + echo '5.9.0' + elif [[ "${version:?}" =~ 7.4 ]]; then + echo '5.10.1' + else + # Return an empty string so that pecl will install the latest version. + echo '' + fi +} + +# Function to install sqlsrv and pdo_sqlsrv. +add_sqlsrv() { + ext=$1 + ext_version=$(get_sqlsrv_version) + if [ "$(uname -s)" = 'Linux' ]; then + install_packages unixodbc-dev + add_pecl_extension "$ext" "$ext_version" extension + else + add_brew_extension "$ext" extension + fi +} diff --git a/src/scripts/extensions/zephir_parser.ps1 b/src/scripts/extensions/zephir_parser.ps1 new file mode 100644 index 0000000..53ac22d --- /dev/null +++ b/src/scripts/extensions/zephir_parser.ps1 @@ -0,0 +1,80 @@ +# Function to get the url of the phalcon release asset. +Function Get-ZephirParserReleaseAssetUrl() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [string] + $extension_version + ) + $repo = 'zephir-lang/php-zephir-parser' + $zp_releases = "$github/$repo/releases" + $nts = if (!$installed.ThreadSafe) { "nts" } else { "ts" } + try { + $match = (Invoke-RestMethod -Uri "https://api.github.com/repos/$repo/tags/$extension_version").assets | Select-String -Pattern "browser_download_url=.*(zephir_parser-php-${version}-$nts-windows.*.zip)" + } catch { + $match = (Get-File -Url "$zp_releases/expanded_assets/$extension_version").Links.href | Select-String -Pattern "(zephir_parser-php-${version}-$nts-windows.*.zip)" + } + if($NULL -ne $match) { + return "$zp_releases/download/$extension_version/$($match.Matches[0].Groups[1].Value)" + } + return false; +} + +# Function to get zephir parser version using GitHub releases. +Function Get-ZephirParserVersion() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [string] + $extension + ) + $repo = 'zephir-lang/php-zephir-parser' + $zp_releases = "$github/$repo/releases" + if($extension -eq 'zephir_parser') { + return (Get-File -Url $zp_releases/latest).BaseResponse.RequestMessage.RequestUri.Segments[-1] + } else { + return 'v' + ($extension.split('-')[1] -replace 'v') + } +} + +# Function to add zephir parser using GitHub releases. +Function Add-ZephirParserFromGitHub() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [string] + $extension + ) + $extension_version = Get-ZephirParserVersion $extension + $zip_url = Get-ZephirParserReleaseAssetUrl $extension_version + if($zip_url) { + Get-File -Url $zip_url -OutFile $ENV:RUNNER_TOOL_CACHE\zp.zip > $null 2>&1 + Expand-Archive -Path $ENV:RUNNER_TOOL_CACHE\zp.zip -DestinationPath $ENV:RUNNER_TOOL_CACHE\zp -Force > $null 2>&1 + Copy-Item -Path "$ENV:RUNNER_TOOL_CACHE\zp\php_zephir_parser.dll" -Destination "$ext_dir\php_zephir_parser.dll" + Enable-PhpExtension -Extension zephir_parser -Path $php_dir + } else { + throw "Unable to get zephir_parser release from the GitHub repo" + } +} + +# Function to add zephir parser. +Function Add-ZephirParser() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [string] + $extension + ) + try { + $status = 'Enabled' + if (Test-Path $ext_dir\php_zephir_parser.dll) { + Enable-PhpExtension -Extension zephir_parser -Path $php_dir + } else { + $status = 'Installed and enabled' + Add-ZephirParserFromGitHub $extension + } + Add-ExtensionLog zephir_parser $status + } catch { + Add-Log $cross $extension "Could not install $extension on PHP $($installed.FullVersion)" + } +} diff --git a/src/scripts/extensions/zephir_parser.sh b/src/scripts/extensions/zephir_parser.sh new file mode 100644 index 0000000..f1c9b5d --- /dev/null +++ b/src/scripts/extensions/zephir_parser.sh @@ -0,0 +1,38 @@ +# Get zephir_parser version +get_zephir_parser_version() { + local ext=$1 + if [[ "$ext" =~ ^zephir_parser$ ]]; then + get -s -n "" "${zp_releases:?}"/latest 2<&1 | grep -m 1 -Eo "tag/(v?[0-9]+(\.[0-9]+)?(\.[0-9]+)?)" | head -n 1 | cut -d '/' -f 2 + else + zp_version="${ext##*-}" + echo "v${zp_version/v//}" + fi +} + +# Add zephir_parser helper +add_zephir_parser_helper() { + local ext=$1 + nts="${ts:?}" && nts="${nts/z/}" + ext_version=$(get_zephir_parser_version "$ext") + [ "$(uname -s)" = "Linux" ] && os_suffix=ubuntu || os_suffix=macos + build_name=$(get -s -n "" https://api.github.com/repos/"$repo"/releases/tags/"$ext_version" | grep -Eo "zephir_parser-php-${version:?}-$nts-$os_suffix-.*.zip" | head -n 1) + [ -z "$build_name" ] && build_name=$(get -s -n "" "$zp_releases"/expanded_assets/"$ext_version" | grep -Eo "zephir_parser-php-${version:?}-$nts-$os_suffix-.*.zip" | head -n 1) + get -q -e "/tmp/zp.zip" "$zp_releases"/download/"$ext_version"/"$build_name" + sudo unzip -o "/tmp/zp.zip" -d "${ext_dir:?}" + enable_extension zephir_parser extension +} + +# Add zephir_parser +add_zephir_parser() { + ext=$1 + repo=zephir-lang/php-zephir-parser + zp_releases=https://github.com/"$repo"/releases + if ! shared_extension zephir_parser; then + message='Installed and enabled' + add_zephir_parser_helper "$ext" >/dev/null 2>&1 + else + message='Enabled' + enable_extension zephir_parser extension + fi + add_extension_log zephir_parser "$message" +} \ No newline at end of file diff --git a/src/scripts/linux.sh b/src/scripts/linux.sh new file mode 100644 index 0000000..e41bbc2 --- /dev/null +++ b/src/scripts/linux.sh @@ -0,0 +1,298 @@ +# Function to add sudo +add_sudo() { + if ! command -v sudo >/dev/null; then + check_package sudo || apt-get update + apt-get install -y sudo || (apt-get update && apt-get install -y sudo) + fi +} + +# Function to setup environment for self-hosted runners. +self_hosted_helper() { + if ! command -v apt-fast >/dev/null; then + sudo ln -sf /usr/bin/apt-get /usr/bin/apt-fast + trap "sudo rm -f /usr/bin/apt-fast 2>/dev/null" exit + fi + install_packages apt-transport-https ca-certificates curl file make jq unzip autoconf automake gcc g++ gnupg +} + +# Function to fix broken packages. +fix_broken_packages() { + sudo apt --fix-broken install >/dev/null 2>&1 +} + +# Function to install a package +install_packages() { + packages=("$@") + $apt_install "${packages[@]}" >/dev/null 2>&1 || (update_lists && fix_broken_packages && $apt_install "${packages[@]}" >/dev/null 2>&1) +} + +# Function to disable an extension. +disable_extension_helper() { + local extension=$1 + local disable_dependents=${2:-false} + get_extension_map + if [ "$disable_dependents" = "true" ]; then + disable_extension_dependents "$extension" + fi + sudo sed -Ei "/=(.*\/)?\"?$extension(.so)?\"?$/d" "${ini_file[@]}" "$pecl_file" + sudo find "$ini_dir"/.. -name "*-$extension.ini" -not -path "*phar.ini" -not -path "*pecl.ini" -not -path "*mods-available*" -delete >/dev/null 2>&1 || true + sudo rm -f /tmp/php"$version"_extensions + mkdir -p /tmp/extdisabled/"$version" + echo '' | sudo tee /tmp/extdisabled/"$version"/"$extension" >/dev/null 2>&1 +} + +# Function to add PDO extension. +add_pdo_extension() { + pdo_ext="pdo_$1" + if check_extension "$pdo_ext"; then + add_log "${tick:?}" "$pdo_ext" "Enabled" + else + ext=$1 + ext_name=$1 + if shared_extension pdo; then + disable_extension_helper pdo + echo "extension=pdo.so" | sudo tee "${ini_file[@]/php.ini/conf.d/10-pdo.ini}" >/dev/null 2>&1 + fi + if [ "$ext" = "mysql" ]; then + enable_extension "mysqlnd" "extension" + ext_name='mysqli' + elif [ "$ext" = "dblib" ]; then + ext_name="sybase" + elif [ "$ext" = "firebird" ]; then + install_packages libfbclient2 >/dev/null 2>&1 + enable_extension "pdo_firebird" "extension" + ext_name="interbase" + elif [ "$ext" = "sqlite" ]; then + ext="sqlite3" + ext_name="sqlite3" + fi + add_extension "$ext_name" "extension" >/dev/null 2>&1 + add_extension "$pdo_ext" "extension" >/dev/null 2>&1 + add_extension_log "$pdo_ext" "Enabled" + fi +} + +# Function to check if a package exists +check_package() { + apt-cache policy "$1" 2>/dev/null | grep -q 'Candidate' +} + +# Helper function to add an extension. +add_extension_helper() { + local extension=$1 + packages=(php"$version"-"$extension") + add_ppa ondrej/php >/dev/null 2>&1 || update_ppa ondrej/php + [ "${debug:?}" = "debug" ] && check_package php"$version"-"$extension"-dbgsym && packages+=(php"$version"-"$extension"-dbgsym) + (check_package "${packages[0]}" && install_packages "${packages[@]}") || pecl_install "$extension" + add_extension_log "$extension" "Installed and enabled" + sudo chmod 777 "${ini_file[@]}" +} + +# Function to setup phpize and php-config. +add_devtools() { + tool=$1 + if ! command -v "$tool$version" >/dev/null; then + install_packages "php$version-dev" + fi + switch_version "phpize" "php-config" + add_extension xml extension >/dev/null 2>&1 + add_log "${tick:?}" "$tool" "Added $tool $semver" +} + +# Function to setup the nightly build from shivammathur/php-builder +setup_nightly() { + run_script "php-builder" "${runner:?}" "$version" "${debug:?}" "${ts:?}" +} + +# Function to setup PHP 5.3, PHP 5.4 and PHP 5.5. +setup_old_versions() { + run_script "php5-ubuntu" "$version" +} + +# Function to setup PHP from the cached builds. +setup_cached_versions() { + run_script "php-ubuntu" "$version" "${debug:?}" "${ts:?}" +} + +# Function to add PECL. +add_pecl() { + add_devtools phpize >/dev/null 2>&1 + if ! command -v pecl >/dev/null; then + install_packages php-pear + fi + configure_pecl >/dev/null 2>&1 + pear_version=$(get_tool_version "pecl" "version") + add_log "${tick:?}" "PECL" "Added PECL $pear_version" +} + +# Function to switch versions of PHP binaries. +switch_version() { + tools=("$@") + to_wait=() + if ! (( ${#tools[@]} )); then + tools+=(pear pecl php phar phar.phar php-cgi php-config phpize phpdbg) + [ -e /usr/lib/cgi-bin/php"$version" ] && sudo update-alternatives --set php-cgi-bin /usr/lib/cgi-bin/php"$version" & to_wait+=($!) + [ -e /usr/sbin/php-fpm"$version" ] && sudo update-alternatives --set php-fpm /usr/sbin/php-fpm"$version" & to_wait+=($!) + [ -e /run/php/php"$version"-fpm.sock ] && sudo update-alternatives --set php-fpm.sock /run/php/php"$version"-fpm.sock & to_wait+=($!) + fi + for tool in "${tools[@]}"; do + if [ -e "/usr/bin/$tool$version" ]; then + sudo update-alternatives --set "$tool" /usr/bin/"$tool$version" & + to_wait+=($!) + fi + done + wait "${to_wait[@]}" +} + +# Function to get packages to install +get_php_packages() { + sed "s/[^ ]*/php$version-&/g" "$src"/configs/php_packages | tr '\n' ' ' + if [ "${debug:?}" = "debug" ]; then + sed "s/[^ ]*/php$version-&-dbgsym/g" "$src"/configs/php_debug_packages | tr '\n' ' ' + fi +} + +# Function to install packaged PHP +add_packaged_php() { + add_ppa ondrej/php >/dev/null 2>&1 || update_ppa ondrej/php + IFS=' ' read -r -a packages <<<"$(get_php_packages)" + install_packages "${packages[@]}" +} + +# Function to update PHP. +update_php() { + initial_version="$(php_semver)$(php_extra_version)" + add_php + updated_version="$(php_semver)$(php_extra_version)" + if [ "$updated_version" != "$initial_version" ]; then + status="Updated to" + else + status="Found" + fi +} + +# Function to install PHP. +add_php() { + if [ "${runner:?}" = "self-hosted" ] || [ "${use_package_cache:-true}" = "false" ]; then + if [[ "$version" =~ ${nightly_versions:?} ]]; then + setup_nightly + else + add_packaged_php + switch_version >/dev/null 2>&1 + add_pecl + fi + elif [[ "$version" =~ ${old_versions:?} ]]; then + setup_old_versions + else + setup_cached_versions + fi + status="Installed" +} + +# Function to ini file for pear and link it to each SAPI. +link_pecl_file() { + echo '' | sudo tee "$pecl_file" >/dev/null 2>&1 + for file in "${ini_file[@]}"; do + sapi_scan_dir="$(realpath -m "$(dirname "$file")")/conf.d" + if [ "$sapi_scan_dir" != "$scan_dir" ] && ! [ -h "$sapi_scan_dir" ]; then + sudo mkdir -p "$sapi_scan_dir" + sudo ln -sf "$pecl_file" "$sapi_scan_dir/99-pecl.ini" + fi + done +} + +# Function to get extra version. +php_extra_version() { + if [ -e /etc/php/"$version"/COMMIT ]; then + echo " ($(cat "/etc/php/$version/COMMIT"))" + fi +} + +# Function to set php.ini +add_php_config() { + php_lib_dir=/usr/lib/php/"$version" + current_ini="$php_lib_dir"/php.ini-current + current=$(cat "$current_ini" 2>/dev/null) + if [ "$current" = "$ini" ]; then + return; + fi + if [[ "$ini" = "production" && "x$current" != "xproduction" ]]; then + echo "${ini_file[@]}" | xargs -n 1 -P 6 sudo cp "$php_lib_dir"/php.ini-production + if [ -e "$php_lib_dir"/php.ini-production.cli ]; then + sudo cp "$php_lib_dir"/php.ini-production.cli "$ini_dir"/php.ini + fi + elif [ "$ini" = "development" ]; then + echo "${ini_file[@]}" | xargs -n 1 -P 6 sudo cp "$php_lib_dir"/php.ini-development + elif [ "$ini" = "none" ]; then + echo '' | sudo tee "${ini_file[@]}" >/dev/null 2>&1 + fi + echo "$ini" | sudo tee "$current_ini" >/dev/null 2>&1 +} + +# Function to Setup PHP +setup_php() { + step_log "Setup PHP" + sudo mkdir -m 777 -p /var/run /run/php + php_config="$(command -v php-config)" + if [[ -z "$php_config" ]] || [ "$(php_semver | cut -c 1-3)" != "$version" ]; then + if [ ! -e "/usr/bin/php$version" ] || [ ! -e "/usr/bin/php-config$version" ]; then + add_php >/dev/null 2>&1 + else + if ! [[ "$version" =~ ${old_versions:?} ]]; then + switch_version >/dev/null 2>&1 + fi + if [ "${update:?}" = "true" ]; then + update_php >/dev/null 2>&1 + else + status="Switched to" + fi + fi + php_config="$(command -v php-config)" + else + if [ "$update" = "true" ]; then + update_php >/dev/null 2>&1 + else + status="Found" + fi + fi + if ! command -v php"$version" >/dev/null; then + add_log "${cross:?}" "PHP" "Could not setup PHP $version" + exit 1 + fi + ext_dir="/usr/$(grep -Po "extension_dir=..[^/]*/\K[^'\"]*" "$php_config")" + ini_dir="$(php_ini_path)" + scan_dir="$ini_dir"/conf.d + pecl_file="$scan_dir"/99-pecl.ini + semver="$(php_semver)" + extra_version="$(php_extra_version)" + export ext_dir + mapfile -t ini_file < <(sudo find "$ini_dir/.." -name "php.ini" -exec readlink -m {} +) + link_pecl_file + configure_php + set_output "php-version" "$semver" + sudo rm -rf /usr/local/bin/phpunit >/dev/null 2>&1 + sudo chmod 777 "${ini_file[@]}" "$pecl_file" "${tool_path_dir:?}" + sudo cp "$src"/configs/pm/*.json "$RUNNER_TOOL_CACHE/" + add_log "${tick:?}" "PHP" "$status PHP $semver$extra_version" +} + +# Variables +version=${1:-'8.3'} +ini=${2:-'production'} +src=${0%/*}/.. +debconf_fix="DEBIAN_FRONTEND=noninteractive" +apt_install="sudo $debconf_fix apt-fast install -y --no-install-recommends" +scripts="$src"/scripts + +add_sudo >/dev/null 2>&1 + +. /etc/os-release +# shellcheck source=. +. "${scripts:?}"/unix.sh +. "${scripts:?}"/tools/ppa.sh +. "${scripts:?}"/tools/add_tools.sh +. "${scripts:?}"/extensions/source.sh +. "${scripts:?}"/extensions/add_extensions.sh +read_env +self_hosted_setup +setup_php diff --git a/src/scripts/tools/add_tools.ps1 b/src/scripts/tools/add_tools.ps1 new file mode 100644 index 0000000..b117d34 --- /dev/null +++ b/src/scripts/tools/add_tools.ps1 @@ -0,0 +1,284 @@ +# Variables +$composer_home = "$env:APPDATA\Composer" +$composer_bin = "$composer_home\vendor\bin" +$composer_json = "$composer_home\composer.json" +$composer_lock = "$composer_home\composer.lock" + +# Function to configure composer. +Function Edit-ComposerConfig() { + Param( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $tool_path + ) + Copy-Item $tool_path -Destination "$tool_path.phar" + php -r "try {`$p=new Phar('$tool_path.phar', 0);exit(0);} catch(Exception `$e) {exit(1);}" + if ($? -eq $False) { + Add-Log "$cross" "composer" "Could not download composer" + Write-Error "Could not download composer" -ErrorAction Stop + } + New-Item -ItemType Directory -Path $composer_bin -Force > $null 2>&1 + if (-not(Test-Path $composer_json)) { + Set-Content -Path $composer_json -Value "{}" + } + Add-EnvPATH $src\configs\composer.env + Add-Path $composer_bin + Set-ComposerAuth +} + +# Function to setup authentication in composer. +Function Set-ComposerAuth() { + if(Test-Path env:COMPOSER_AUTH_JSON) { + if(Test-Json -JSON $env:COMPOSER_AUTH_JSON) { + Set-Content -Path $composer_home\auth.json -Value $env:COMPOSER_AUTH_JSON + } else { + Add-Log "$cross" "composer" "Could not parse COMPOSER_AUTH_JSON as valid JSON" + } + } + $composer_auth = @() + if(Test-Path env:PACKAGIST_TOKEN) { + $composer_auth += '"http-basic": {"repo.packagist.com": { "username": "token", "password": "' + $env:PACKAGIST_TOKEN + '"}}' + } + if(-not(Test-Path env:GITHUB_TOKEN) -and (Test-Path env:COMPOSER_TOKEN)) { + $env:GITHUB_TOKEN = $env:COMPOSER_TOKEN + } + if (Test-Path env:GITHUB_TOKEN) { + $composer_auth += '"github-oauth": {"github.com": "' + $env:GITHUB_TOKEN + '"}' + } + if($composer_auth.length) { + Add-Env COMPOSER_AUTH ('{' + ($composer_auth -join ',') + '}') + } +} + +# Function to extract tool version. +Function Get-ToolVersion() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + $tool, + [Parameter(Position = 1, Mandatory = $false)] + $param + ) + $alp = "[a-zA-Z0-9\.]" + $version_regex = "[0-9]+((\.{1}$alp+)+)(\.{0})(-$alp+){0,1}" + if($tool -eq 'composer') { + $composer_branch_alias = Select-String -Pattern "const\sBRANCH_ALIAS_VERSION" -Path $bin_dir\composer -Raw | Select-String -Pattern $version_regex | ForEach-Object { $_.matches.Value } + if ($composer_branch_alias) { + $composer_version = $composer_branch_alias + '+' + (Select-String -Pattern "const\sVERSION" -Path $bin_dir\composer -Raw | Select-String -Pattern "[a-zA-Z0-9]+" -AllMatches | ForEach-Object { $_.matches[2].Value }) + } else { + $composer_version = Select-String -Pattern "const\sVERSION" -Path $bin_dir\composer -Raw | Select-String -Pattern $version_regex | ForEach-Object { $_.matches.Value } + } + Set-Variable -Name 'composer_version' -Value $composer_version -Scope Global + return "$composer_version" + } + if($null -ne $param) { + return . $tool $param 2> $null | ForEach-Object { $_ -replace "composer $version_regex", '' } | Select-String -Pattern $version_regex | Select-Object -First 1 | ForEach-Object { $_.matches.Value } + } +} + +# Helper function to configure tools. +Function Add-ToolsHelper() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + $tool + ) + $extensions = @(); + if($tool -eq "box") { + $extensions += @('iconv', 'mbstring', 'phar', 'sodium') + } elseif($tool -eq "codeception") { + $extensions += @('json', 'mbstring') + Copy-Item $env:codeception_bin\codecept.bat -Destination $env:codeception_bin\codeception.bat + } elseif($tool -eq "composer") { + Edit-ComposerConfig $bin_dir\$tool + } elseif($tool -eq "cs2pr") { + (Get-Content $bin_dir/cs2pr).replace('exit(9)', 'exit(0)') | Set-Content $bin_dir/cs2pr + } elseif($tool -eq "deployer") { + if(Test-Path $composer_bin\deployer.phar.bat) { + Copy-Item $composer_bin\deployer.phar.bat -Destination $composer_bin\dep.bat + } + if(Test-Path $composer_bin\dep.bat) { + Copy-Item $composer_bin\dep.bat -Destination $composer_bin\deployer.bat + } + } elseif($tool -eq "phan") { + $extensions += @('fileinfo', 'ast') + } elseif($tool -eq "phinx") { + $extensions += @('mbstring') + } elseif($tool -eq "phive") { + $extensions += @('curl', 'mbstring', 'xml') + } elseif($tool -match "phpc(df|s)") { + $extensions += @('tokenizer', 'xmlwriter', 'simplexml') + } elseif($tool -match "php-cs-fixer") { + $extensions += @('json', 'tokenizer') + } elseif($tool -eq "phpDocumentor") { + $extensions+=('ctype', 'hash', 'json', 'fileinfo', 'iconv', 'mbstring', 'simplexml', 'xml') + Add-Extension fileinfo >$null 2>&1 + Copy-Item $bin_dir\phpDocumentor.bat -Destination $bin_dir\phpdoc.bat + } elseif($tool -eq "phpunit") { + $extensions += @('dom', 'json', 'libxml', 'mbstring', 'xml', 'xmlwriter') + } elseif($tool -eq "phpunit-bridge") { + $extensions += @('dom', 'pdo', 'tokenizer', 'xmlwriter') + } elseif($tool -eq "vapor-cli") { + $extensions += @('fileinfo', 'json', 'mbstring', 'zip', 'simplexml') + Copy-Item $env:vapor_cli_bin\vapor.bat -Destination $env:vapor_cli_bin\vapor-cli.bat + } elseif($tool -eq "wp-cli") { + Copy-Item $bin_dir\wp-cli.bat -Destination $bin_dir\wp.bat + } + foreach($extension in $extensions) { + Add-Extension $extension >$null 2>&1 + } +} + +# Function to add tools. +Function Add-Tool() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + $urls, + [Parameter(Position = 1, Mandatory = $true)] + [ValidateNotNull()] + $tool, + [Parameter(Position = 2, Mandatory = $false)] + $ver_param + ) + if (Test-Path $bin_dir\$tool) { + Copy-Item $bin_dir\$tool -Destination $bin_dir\$tool.old -Force + } + $tool_path = "$bin_dir\$tool" + foreach ($url in $urls){ + if (($url | Split-Path -Extension) -eq ".exe") { + $tool_path = "$tool_path.exe" + } + try { + $status_code = (Invoke-WebRequest -Passthru -Uri $url -OutFile $tool_path).StatusCode + } catch { + if($url -match '.*github.com.*releases.*latest.*') { + try { + $url = $url.replace("releases/latest/download", "releases/download/" + ([regex]::match((Get-File -Url ($url.split('/release')[0] + "/releases")).Content, "([0-9]+\.[0-9]+\.[0-9]+)/" + ($url.Substring($url.LastIndexOf("/") + 1))).Groups[0].Value).split('/')[0]) + $status_code = (Invoke-WebRequest -Passthru -Uri $url -OutFile $tool_path).StatusCode + } catch { } + } + } + if($status_code -eq 200 -and (Test-Path $tool_path)) { + break + } + } + + if (((Get-ChildItem -Path $bin_dir/* | Where-Object Name -Match "^$tool(.exe|.phar)*$").Count -gt 0)) { + $bat_content = @() + $bat_content += "@ECHO off" + $bat_content += "setlocal DISABLEDELAYEDEXPANSION" + $bat_content += "SET BIN_TARGET=%~dp0/" + $tool + $bat_content += "php %BIN_TARGET% %*" + Set-Content -Path $bin_dir\$tool.bat -Value $bat_content + Add-ToolsHelper $tool + Add-ToProfile $current_profile $tool "New-Alias $tool $bin_dir\$tool.bat" >$null 2>&1 + $tool_version = Get-ToolVersion $tool $ver_param + Add-Log $tick $tool "Added $tool $tool_version" + } else { + if($tool -eq "composer") { + $env:fail_fast = 'true' + } elseif (Test-Path $bin_dir\$tool.old) { + Copy-Item $bin_dir\$tool.old -Destination $bin_dir\$tool -Force + } + Add-Log $cross $tool "Could not add $tool" + } +} + +Function Add-ComposerToolHelper() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [string] + $tool, + [Parameter(Position = 1, Mandatory = $true)] + [string] + $release, + [Parameter(Position = 2, Mandatory = $true)] + [string] + $prefix, + [Parameter(Position = 3, Mandatory = $true)] + [string] + $scope, + [Parameter(Position = 4, Mandatory = $false)] + [string] + $composer_args + ) + $tool_version = $release.split(':')[1] + if($NULL -eq $tool_version) { + $tool_version = '*' + } + if($scope -eq 'global') { + if(Test-Path $composer_lock) { + Remove-Item -Path $composer_lock -Force + } + if((composer global show $prefix$tool $tool_version -a 2>&1 | findstr '^type *: *composer-plugin') -and ($composer_args -ne '')) { + composer global config --no-plugins allow-plugins."$prefix$tool" true >$null 2>&1 + } + composer global require $prefix$release $composer_args >$null 2>&1 + return composer global show $prefix$tool 2>&1 | findstr '^versions' + } else { + $release_stream = [System.IO.MemoryStream]::New([System.Text.Encoding]::ASCII.GetBytes($release)) + $scoped_dir_suffix = (Get-FileHash -InputStream $release_stream -Algorithm sha256).Hash + $scoped_dir = "$composer_bin\_tools\$tool-$scoped_dir_suffix" + $unix_scoped_dir = $scoped_dir.replace('\', '/') + if(-not(Test-Path $scoped_dir)) { + New-Item -ItemType Directory -Force -Path $scoped_dir > $null 2>&1 + Set-Content -Path $scoped_dir\composer.json -Value "{}" + if((composer show $prefix$tool $tool_version -d $unix_scoped_dir -a 2>&1 | findstr '^type *: *composer-plugin') -and ($composer_args -ne '')) { + composer config -d $unix_scoped_dir --no-plugins allow-plugins."$prefix$tool" true >$null 2>&1 + } + composer require $prefix$release -d $unix_scoped_dir $composer_args >$null 2>&1 + } + [System.Environment]::SetEnvironmentVariable(($tool.replace('-', '_') + '_bin'), "$scoped_dir\vendor\bin") + Add-Path $scoped_dir\vendor\bin + return composer show $prefix$tool -d $unix_scoped_dir 2>&1 | findstr '^versions' + } +} + +# Function to setup a tool using composer. +Function Add-ComposerTool() { + Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $tool, + [Parameter(Position = 1, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $release, + [Parameter(Position = 2, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $prefix, + [Parameter(Position = 3, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $scope + ) + $composer_args = "" + if($composer_version.split('.')[0] -ne "1") { + $composer_args = "--ignore-platform-req=ext-*" + if($tool -match "prestissimo|composer-prefetcher") { + Write-Output "::warning:: Skipping $tool, as it does not support Composer $composer_version. Specify composer:v1 in tools to use $tool" + Add-Log $cross $tool "Skipped" + Return + } + } + Enable-PhpExtension -Extension curl, mbstring, openssl -Path $php_dir + $log = Add-ComposerToolHelper $tool $release $prefix $scope $composer_args + if(Test-Path $composer_bin\composer) { + Copy-Item -Path "$bin_dir\composer" -Destination "$composer_bin\composer" -Force + } + Add-ToolsHelper $tool + if($log) { + $tool_version = Get-ToolVersion "Write-Output" "$log" + Add-Log $tick $tool "Added $tool $tool_version" + } else { + Add-Log $cross $tool "Could not setup $tool" + } +} diff --git a/src/scripts/tools/add_tools.sh b/src/scripts/tools/add_tools.sh new file mode 100644 index 0000000..0ffbba5 --- /dev/null +++ b/src/scripts/tools/add_tools.sh @@ -0,0 +1,217 @@ +# Variables +export tool_path_dir="/usr/local/bin" +export composer_home="$HOME/.composer" +export composer_bin="$composer_home/vendor/bin" +export composer_json="$composer_home/composer.json" +export composer_lock="$composer_home/composer.lock" + +# Function to extract tool version. +get_tool_version() { + tool=$1 + param=$2 + alp="[a-zA-Z0-9\.]" + version_regex="[0-9]+((\.{1}$alp+)+)(\.{0})(-$alp+){0,1}" + if [ "$tool" = "composer" ]; then + composer_alias_version="$(grep -Ea "const\sBRANCH_ALIAS_VERSION" "$tool_path_dir/composer" | grep -Eo "$version_regex")" + if [[ -n "$composer_alias_version" ]]; then + composer_version="$composer_alias_version+$(grep -Ea "const\sVERSION" "$tool_path_dir/composer" | grep -Eo "$alp+" | tail -n 1)" + else + composer_version="$(grep -Ea "const\sVERSION" "$tool_path_dir/composer" | grep -Eo "$version_regex")" + fi + echo "$composer_version" | sudo tee /tmp/composer_version + elif [ -n "$param" ]; then + $tool "$param" 2>/dev/null | sed -Ee "s/[Cc]omposer(.)?$version_regex//g" | grep -Eo "$version_regex" | head -n 1 + fi +} + +# Function to configure composer +configure_composer() { + tool_path=$1 + sudo ln -sf "$tool_path" "$tool_path.phar" + php -r "try {\$p=new Phar('$tool_path.phar', 0);exit(0);} catch(Exception \$e) {exit(1);}" + if [ $? -eq 1 ]; then + add_log "${cross:?}" "composer" "Could not download composer" + exit 1 + fi + if ! [ -d "$composer_home" ]; then + sudo -u "$(id -un)" -g "$(id -gn)" mkdir -p -m=00755 "$composer_home" + else + sudo chown -R "$(id -un)":"$(id -gn)" "$composer_home" + fi + if ! [ -e "$composer_json" ]; then + echo '{}' | tee "$composer_json" >/dev/null + chmod 644 "$composer_json" + fi + add_env_path "${src:?}"/configs/composer.env + add_path "$composer_bin" + set_composer_auth +} + +# Function to setup authentication in composer. +set_composer_auth() { + if [ -n "$COMPOSER_AUTH_JSON" ]; then + if php -r "json_decode('$COMPOSER_AUTH_JSON'); if(json_last_error() !== JSON_ERROR_NONE) { throw new Exception('invalid json'); }"; then + echo "$COMPOSER_AUTH_JSON" | tee "$composer_home/auth.json" >/dev/null + else + add_log "${cross:?}" "composer" "Could not parse COMPOSER_AUTH_JSON as valid JSON" + fi + fi + composer_auth=() + if [ -n "$PACKAGIST_TOKEN" ]; then + composer_auth+=( '"http-basic": {"repo.packagist.com": { "username": "token", "password": "'"$PACKAGIST_TOKEN"'"}}' ) + fi + if [ -n "${GITHUB_TOKEN:-$COMPOSER_TOKEN}" ]; then + composer_auth+=( '"github-oauth": {"github.com": "'"${GITHUB_TOKEN:-$COMPOSER_TOKEN}"'"}' ) + fi + if ((${#composer_auth[@]})); then + add_env COMPOSER_AUTH "{$(IFS=$','; echo "${composer_auth[*]}")}" + fi +} + +# Helper function to configure tools. +add_tools_helper() { + tool=$1 + extensions=() + if [ "$tool" = "blackfire-player" ]; then + extensions+=(uuid) + elif [ "$tool" = "box" ]; then + extensions+=(iconv mbstring phar sodium) + elif [ "$tool" = "codeception" ]; then + extensions+=(json mbstring) + sudo ln -s "$scoped_dir"/vendor/bin/codecept "$scoped_dir"/vendor/bin/codeception + elif [ "$tool" = "composer" ]; then + configure_composer "$tool_path" + elif [ "$tool" = "cs2pr" ]; then + sudo sed -i 's/\r$//; s/exit(9)/exit(0)/' "$tool_path" 2>/dev/null || + sudo sed -i '' 's/\r$//; s/exit(9)/exit(0)/' "$tool_path" + elif [ "$tool" = "deployer" ]; then + if [ -e "$composer_bin"/deployer.phar ]; then + sudo ln -s "$composer_bin"/deployer.phar "$composer_bin"/dep + fi + if [ -e "$composer_bin"/dep ]; then + sudo ln -s "$composer_bin"/dep "$composer_bin"/deployer + fi + elif [ "$tool" = "phan" ]; then + extensions+=(fileinfo ast) + elif [ "$tool" = "phinx" ]; then + extensions+=(mbstring) + elif [ "$tool" = "phive" ]; then + extensions+=(curl mbstring xml) + elif [[ "$tool" =~ phpc(bf|s) ]]; then + extensions+=(tokenizer simplexml xmlwriter) + elif [[ "$tool" =~ phpc(bf|s) ]]; then + extensions+=(tokenizer xmlwriter simplexml) + elif [ "$tool" = "php-cs-fixer" ]; then + extensions+=(json tokenizer) + elif [ "$tool" = "phpDocumentor" ]; then + extensions+=(ctype hash json fileinfo iconv mbstring simplexml xml) + sudo ln -s "$tool_path" "$tool_path_dir"/phpdocumentor 2>/dev/null || true + sudo ln -s "$tool_path" "$tool_path_dir"/phpdoc + elif [ "$tool" = "phpunit" ]; then + extensions+=(dom json libxml mbstring xml xmlwriter) + elif [ "$tool" = "phpunit-bridge" ]; then + extensions+=(dom pdo tokenizer xmlwriter xmlreader) + elif [[ "$tool" =~ phpunit(-polyfills)?$ ]]; then + if [ -e "$tool_path_dir"/phpunit ] && [ -d "$composer_bin" ]; then + sudo cp "$tool_path_dir"/phpunit "$composer_bin" + fi + elif [ "$tool" = "vapor-cli" ]; then + extensions+=(fileinfo json mbstring zip simplexml) + sudo ln -s "$scoped_dir"/vendor/bin/vapor "$scoped_dir"/vendor/bin/vapor-cli + elif [ "$tool" = wp-cli ]; then + sudo ln -s "$tool_path" "$tool_path_dir"/"${tool%-*}" + fi + for extension in "${extensions[@]}"; do + add_extension "$extension" extension >/dev/null 2>&1 + done +} + +# Function to setup a remote tool. +add_tool() { + url=$1 + tool=$2 + ver_param=$3 + tool_path="$tool_path_dir/$tool" + if ! [ -d "$tool_path_dir" ]; then + sudo mkdir -p "$tool_path_dir" + fi + add_path "$tool_path_dir" + if [ -e "$tool_path" ]; then + sudo cp -aL "$tool_path" /tmp/"$tool" + fi + IFS="," read -r -a url <<<"$url" + status_code=$(get -v -e "$tool_path" "${url[@]}") + if [ "$status_code" != "200" ] && [[ "${url[0]}" =~ .*github.com.*releases.*latest.* ]]; then + url[0]="${url[0]//releases\/latest\/download/releases/download/$(get -s -n "" "$(echo "${url[0]}" | cut -d '/' -f '1-5')/releases" | grep -Eo -m 1 "([0-9]+\.[0-9]+\.[0-9]+)/$(echo "${url[0]}" | sed -e "s/.*\///")" | cut -d '/' -f 1)}" + status_code=$(get -v -e "$tool_path" "${url[0]}") + fi + if [ "$status_code" = "200" ]; then + add_tools_helper "$tool" + tool_version=$(get_tool_version "$tool" "$ver_param") + add_log "${tick:?}" "$tool" "Added $tool $tool_version" + else + if [ "$tool" = "composer" ]; then + export fail_fast=true + elif [ -e /tmp/"$tool" ]; then + sudo cp -a /tmp/"$tool" "$tool_path" + fi + add_log "$cross" "$tool" "Could not setup $tool" + fi +} + +# Function to setup a tool using composer in a different scope. +add_composer_tool_helper() { + tool=$1 + release=$2 + prefix=$3 + scope=$4 + composer_args=$5 + enable_extensions curl mbstring openssl + tool_version=${release##*:}; [ "$tool_version" = "$tool" ] && tool_version="*" + if [ "$scope" = "global" ]; then + sudo rm -f "$composer_lock" >/dev/null 2>&1 || true + if composer global show "$prefix$tool" "$tool_version" -a 2>&1 | grep -qE '^type *: *composer-plugin' && [ -n "$composer_args" ]; then + composer global config --no-plugins allow-plugins."$prefix$tool" true >/dev/null 2>&1 + fi + composer global require "$prefix$release" "$composer_args" >/dev/null 2>&1 + composer global show "$prefix$tool" 2>&1 | grep -E ^versions | sudo tee /tmp/composer.log >/dev/null 2>&1 + else + scoped_dir="$composer_bin/_tools/$tool-$(echo -n "$release" | shasum -a 256 | cut -d ' ' -f 1)" + if ! [ -d "$scoped_dir" ]; then + mkdir -p "$scoped_dir" + echo '{}' | tee "$scoped_dir/composer.json" >/dev/null + if composer show "$prefix$tool" "$tool_version" -d "$scoped_dir" -a 2>&1 | grep -qE '^type *: *composer-plugin' && [ -n "$composer_args" ]; then + composer config -d "$scoped_dir" --no-plugins allow-plugins."$prefix$tool" true >/dev/null 2>&1 + fi + composer require "$prefix$release" -d "$scoped_dir" "$composer_args" >/dev/null 2>&1 + composer show "$prefix$tool" -d "$scoped_dir" 2>&1 | grep -E ^versions | sudo tee /tmp/composer.log >/dev/null 2>&1 + fi + add_path "$scoped_dir"/vendor/bin + fi +} + +# Function to setup a tool using composer. +add_composer_tool() { + tool=$1 + release=$2 + prefix=$3 + scope=$4 + composer_args= + composer_major_version=$(cut -d'.' -f 1 /tmp/composer_version) + if [ "$composer_major_version" != "1" ]; then + composer_args="--ignore-platform-req=ext-*" + if [[ "$tool" =~ prestissimo|composer-prefetcher ]]; then + echo "::warning:: Skipping $tool, as it does not support Composer $composer_version. Specify composer:v1 in tools to use $tool" + add_log "$cross" "$tool" "Skipped" + return + fi + fi + add_composer_tool_helper "$tool" "$release" "$prefix" "$scope" "$composer_args" + tool_version=$(get_tool_version cat /tmp/composer.log) + ([ -s /tmp/composer.log ] && add_log "$tick" "$tool" "Added $tool $tool_version" + ) || add_log "$cross" "$tool" "Could not setup $tool" + add_tools_helper "$tool" + if [ -e "$composer_bin/composer" ]; then + sudo cp -a "$tool_path_dir/composer" "$composer_bin" + fi +} diff --git a/src/scripts/tools/blackfire.ps1 b/src/scripts/tools/blackfire.ps1 new file mode 100644 index 0000000..4427ef7 --- /dev/null +++ b/src/scripts/tools/blackfire.ps1 @@ -0,0 +1,19 @@ +# Function to add blackfire cli. +Function Add-Blackfire() { + $arch_name ='amd64' + if(-not([Environment]::Is64BitOperatingSystem) -or $version -lt '7.0') { + $arch_name = '386' + } + $cli_version = (Invoke-RestMethod https://blackfire.io/api/v1/releases).cli + $url = "https://packages.blackfire.io/binaries/blackfire/${cli_version}/blackfire-windows_${arch_name}.zip" + Get-File -Url $url -OutFile $bin_dir\blackfire.zip >$null 2>&1 + Expand-Archive -Path $bin_dir\blackfire.zip -DestinationPath $bin_dir -Force >$null 2>&1 + Add-ToProfile $current_profile 'blackfire' "New-Alias blackfire $bin_dir\blackfire.exe" + if ((Test-Path env:BLACKFIRE_SERVER_ID) -and (Test-Path env:BLACKFIRE_SERVER_TOKEN)) { + blackfire agent:config --server-id=$env:BLACKFIRE_SERVER_ID --server-token=$env:BLACKFIRE_SERVER_TOKEN >$null 2>&1 + } + if ((Test-Path env:BLACKFIRE_CLIENT_ID) -and (Test-Path env:BLACKFIRE_CLIENT_TOKEN)) { + blackfire client:config --client-id=$env:BLACKFIRE_CLIENT_ID --client-token=$env:BLACKFIRE_CLIENT_TOKEN --ca-cert=$php_dir\ssl\cacert.pem >$null 2>&1 + } + Add-Log $tick "blackfire" "Added blackfire $cli_version" +} diff --git a/src/scripts/tools/blackfire.sh b/src/scripts/tools/blackfire.sh new file mode 100644 index 0000000..70fa4f6 --- /dev/null +++ b/src/scripts/tools/blackfire.sh @@ -0,0 +1,40 @@ +add_blackfire_linux() { + sudo mkdir -p /var/run/blackfire /etc/blackfire + add_list debian/blackfire http://packages.blackfire.io/debian https://packages.blackfire.io/gpg.key any main + install_packages blackfire + sudo chmod 777 /etc/blackfire/agent +} + +add_blackfire_darwin() { + sudo mkdir -p /usr/local/var/run + add_brew_tap blackfireio/homebrew-blackfire + brew install blackfire +} + +blackfire_config() { + if [[ -n $BLACKFIRE_SERVER_ID ]] && [[ -n $BLACKFIRE_SERVER_TOKEN ]]; then + blackfire agent:config --server-id="$BLACKFIRE_SERVER_ID" --server-token="$BLACKFIRE_SERVER_TOKEN" + if [ "$os" = "Linux" ]; then + if [ -d /run/systemd/system ]; then + sudo systemctl start blackfire-agent + else + sudo service blackfire-agent start + fi + elif [ "$os" = "Darwin" ]; then + brew services start blackfire + fi + fi + if [[ -n $BLACKFIRE_CLIENT_ID ]] && [[ -n $BLACKFIRE_CLIENT_TOKEN ]]; then + blackfire client:config --client-id="$BLACKFIRE_CLIENT_ID" --client-token="$BLACKFIRE_CLIENT_TOKEN" + fi +} + +# Function to add blackfire cli. +add_blackfire() { + os="$(uname -s)" + [ "$os" = "Linux" ] && add_blackfire_linux >/dev/null 2>&1 + [ "$os" = "Darwin" ] && add_blackfire_darwin >/dev/null 2>&1 + blackfire_config >/dev/null 2>&1 + tool_version=$(get_tool_version "blackfire" "version") + add_log "${tick:?}" "blackfire" "Added blackfire $tool_version" +} diff --git a/src/scripts/tools/brew.sh b/src/scripts/tools/brew.sh new file mode 100644 index 0000000..efddc9f --- /dev/null +++ b/src/scripts/tools/brew.sh @@ -0,0 +1,83 @@ +# Function to fetch a brew tap. +fetch_brew_tap() { + tap=$1 + tap_user=$(dirname "$tap") + tap_name=$(basename "$tap") + mkdir -p "$tap_dir/$tap_user" + branch="$(git ls-remote --symref "https://github.com/$tap" HEAD | grep -Eo 'refs/heads/.*' | tr '\t' '\n' | head -1 | cut -d '/' -f 3)" + get -s -n "" "https://github.com/$tap/archive/$branch.tar.gz" | sudo tar -xzf - -C "$tap_dir/$tap_user" + sudo mv "$tap_dir/$tap_user/$tap_name-$branch" "$tap_dir/$tap_user/$tap_name" +} + +# Function to add a brew tap. +add_brew_tap() { + tap=$1 + if ! [ -d "$tap_dir/$tap" ]; then + if [ "${runner:?}" = "self-hosted" ]; then + brew tap "$tap" >/dev/null 2>&1 + else + fetch_brew_tap "$tap" >/dev/null 2>&1 + if ! [ -d "$tap_dir/$tap" ]; then + brew tap "$tap" >/dev/null 2>&1 + fi + fi + fi +} + +# Function to get brew prefix. +get_brew_prefix() { + if [ "$(uname -s)" = "Linux" ]; then + echo /home/linuxbrew/.linuxbrew + else + if [ "$(uname -m)" = "arm64" ]; then + echo /opt/homebrew + else + echo /usr/local + fi + fi +} + +# Function to add brew's bin directories to the PATH. +add_brew_bins_to_path() { + local brew_prefix=${1:-$(get_brew_prefix)} + add_path "$brew_prefix"/bin + add_path "$brew_prefix"/sbin +} + +# Function to add brew. +add_brew() { + brew_prefix="$(get_brew_prefix)" + if ! [ -d "$brew_prefix"/bin ]; then + step_log "Setup Brew" + get -s "" "/tmp/install.sh" "https://raw.githubusercontent.com/Homebrew/install/master/install.sh" | bash -s >/dev/null 2>&1 + add_log "${tick:?}" "Brew" "Installed Homebrew" + fi + add_brew_bins_to_path "$brew_prefix" +} + +# Function to configure brew constants. +configure_brew() { + brew_path="$(command -v brew)" + if [ -z "$brew_path" ]; then + add_brew + brew_path="$(command -v brew)" + fi + brew_path_dir="$(dirname "$brew_path")" + brew_prefix="$brew_path_dir"/.. + brew_repo="$brew_path_dir/$(dirname "$(readlink "$brew_path")")"/.. + tap_dir="$brew_repo"/Library/Taps + core_repo="$tap_dir"/homebrew/homebrew-core + + export HOMEBREW_CHANGE_ARCH_TO_ARM=1 + export HOMEBREW_DEVELOPER=1 + export HOMEBREW_NO_AUTO_UPDATE=1 + export HOMEBREW_NO_ENV_HINTS=1 + export HOMEBREW_NO_INSTALL_CLEANUP=1 + export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 + export brew_path + export brew_path_dir + export brew_prefix + export brew_repo + export tap_dir + export core_repo +} diff --git a/src/scripts/tools/grpc_php_plugin.ps1 b/src/scripts/tools/grpc_php_plugin.ps1 new file mode 100644 index 0000000..f40bf28 --- /dev/null +++ b/src/scripts/tools/grpc_php_plugin.ps1 @@ -0,0 +1,21 @@ +Function Add-Msys2() { + $msys_location = 'C:\msys64' + if (-not(Test-Path $msys_location)) { + choco install msys2 -y >$null 2>&1 + $msys_location = 'C:\tools\msys64' + } + return $msys_location +} + +Function Add-GrpcPhpPlugin() { + $msys_location = Add-Msys2 + $logs = . $msys_location\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-grpc" >$null 2>&1 + $grpc_version = Get-ToolVersion 'Write-Output' "$logs" + Add-Path $msys_location\mingw64\bin + Set-Output grpc_php_plugin_path "$msys_location\mingw64\bin\grpc_php_plugin.exe" + Add-ToProfile $current_profile 'grpc_php_plugin' "New-Alias grpc_php_plugin $msys_location\mingw64\bin\grpc_php_plugin.exe" + Add-Log $tick "grpc_php_plugin" "Added grpc_php_plugin $grpc_version" + printf "$env:GROUP\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "grpc_php_plugin" "Click to read the grpc_php_plugin related license information" + Write-Output (Invoke-WebRequest https://raw.githubusercontent.com/grpc/grpc/master/LICENSE).Content + Write-Output "$env:END_GROUP" +} diff --git a/src/scripts/tools/grpc_php_plugin.sh b/src/scripts/tools/grpc_php_plugin.sh new file mode 100644 index 0000000..9434bb1 --- /dev/null +++ b/src/scripts/tools/grpc_php_plugin.sh @@ -0,0 +1,62 @@ +add_bazel() { + if ! command -v bazel; then + if [ "$(uname -s)" = "Linux" ]; then + add_list bazel/apt https://storage.googleapis.com/bazel-apt https://bazel.build/bazel-release.pub.gpg stable jdk1.8 + install_packages bazel + else + brew install bazel + fi + fi +} + +get_grpc_tag() { + if [ "$grpc_tag" = "latest" ]; then + grpc_tag=$(get -s -n "" https://github.com/grpc/grpc/releases/latest | grep -Eo -m 1 "v[0-9]+\.[0-9]+\.[0-9]+" | head -n 1) + else + if [[ ${grpc_tag:0:1} != "v" ]] ; then grpc_tag="v$grpc_tag"; fi + status_code=$(get -v -n /tmp/grpc.tmp "https://github.com/grpc/grpc/releases/tag/$grpc_tag") + if [ "$status_code" != "200" ]; then + grpc_tag=$(get -s -n "" https://github.com/grpc/grpc/releases/latest | grep -Eo -m 1 "v[0-9]+\.[0-9]+\.[0-9]+" | head -n 1) + fi + fi +} + +add_grpc_php_plugin_brew() { + . "${0%/*}"/tools/brew.sh + configure_brew + [ -e /usr/local/bin/protoc ] && sudo mv /usr/local/bin/protoc /tmp/protoc && sudo mv /usr/local/include/google /tmp + brew install grpc + brew link --force --overwrite grpc >/dev/null 2>&1 + [ -e /tmp/protoc ] && sudo mv /tmp/protoc /usr/local/bin/protoc && sudo mv /tmp/google /usr/local/include/ + grpc_tag="v$(brew info grpc | grep "grpc:" | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+")" + license_path="$(brew --prefix grpc)/LICENSE" +} + +add_grpc_php_plugin_compile() { + get_grpc_tag + get -s -n "" "https://github.com/grpc/grpc/archive/$grpc_tag.tar.gz" | tar -xz -C /tmp + export DISABLE_BAZEL_WRAPPER=1 + ( + cd "/tmp/grpc-${grpc_tag:1}" || exit + add_bazel + ./tools/bazel build src/compiler:grpc_php_plugin + sudo mv ./bazel-bin/src/compiler/grpc_php_plugin /usr/local/bin/grpc_php_plugin + sudo chmod a+x /usr/local/bin/grpc_php_plugin + license_path="/tmp/grpc-${grpc_tag:1}/LICENSE" + ) +} + +add_grpc_php_plugin() { + grpc_tag=$1 + license_path="" + if [ "$grpc_tag" = "latest" ]; then + add_grpc_php_plugin_brew >/dev/null 2>&1 + else + add_grpc_php_plugin_compile >/dev/null 2>&1 + fi + set_output grpc_php_plugin_path "$(command -v grpc_php_plugin)" + add_log "${tick:?}" "grpc_php_plugin" "Added grpc_php_plugin ${grpc_tag:1}" + printf "$GROUP\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "grpc_php_plugin" "Click to read the grpc_php_plugin related license information" + cat "$license_path" + echo "$END_GROUP" +} diff --git a/src/scripts/tools/ppa.sh b/src/scripts/tools/ppa.sh new file mode 100644 index 0000000..b3d8d04 --- /dev/null +++ b/src/scripts/tools/ppa.sh @@ -0,0 +1,204 @@ +# Function to try to set ubuntu or debian version. +set_base_version_id() { + [[ "$ID" =~ ubuntu|debian ]] && return; + if ! [ -d "$dist_info_dir" ]; then + sudo mkdir -p "$dist_info_dir" + get -q -n "$dist_info_dir"/os_releases.csv https://raw.githubusercontent.com/shivammathur/setup-php/develop/src/configs/os_releases.csv + fi + for base in ubuntu debian; do + [[ "$ID_LIKE" =~ $base ]] && ID="$base" && VERSION_ID="$(grep -hr -m 1 "$VERSION_CODENAME" /usr/share/distro-info | cut -d ',' -f 1 | cut -d ' ' -f 1)" && break + done +} + +# Function to try to set ubuntu or debian codename. +set_base_version_codename() { + [[ "$ID" =~ ubuntu|debian ]] && return; + if [[ "$ID_LIKE" =~ ubuntu ]]; then + [[ -n "$UBUNTU_CODENAME" ]] && VERSION_CODENAME="$UBUNTU_CODENAME" && return; + [ -e "$upstream_lsb" ] && VERSION_CODENAME=$(grep 'CODENAME' "$upstream_lsb" | cut -d '=' -f 2) && return; + VERSION_CODENAME=$(grep -E -m1 'deb .*ubuntu.com' "$list_file" | cut -d ' ' -f 3) && VERSION_CODENAME=${VERSION_CODENAME%-*} + elif [[ "$ID_LIKE" =~ debian ]] || command -v dpkg >/dev/null; then + ID_LIKE=debian + [[ -n "$DEBIAN_CODENAME" ]] && VERSION_CODENAME="$DEBIAN_CODENAME" && return; + update_lists && VERSION_CODENAME=$(apt-cache show tzdata | grep -m 1 Provides | cut -d '-' -f 2) + fi +} + +# Function to set base os details +set_base_version() { + if [ -e /tmp/os-release ]; then + . /tmp/os-release + else + set_base_version_codename + set_base_version_id + printf "ID=%s\nVERSION_ID=%s\nVERSION_CODENAME=%s\n" "$ID" "$VERSION_ID" "$VERSION_CODENAME" | tee /tmp/os-release >/dev/null 2>&1 + fi +} + +# Helper function to update package lists. +update_lists_helper() { + list=$1 + command -v sudo >/dev/null && SUDO=sudo + if [[ -n "$list" ]]; then + ${SUDO} apt-get update -o Dir::Etc::sourcelist="$list" -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0" + else + ${SUDO} apt-get update + fi +} + +# Function to update the package lists. +update_lists() { + local ppa=${1:-} + local ppa_search=${2:-} + local list= + status_file=/tmp/os_lists + if [[ -n "$ppa" && -n "$ppa_search" ]]; then + list="$list_dir"/"$(basename "$(grep -lr "$ppa_search" "$list_dir")")" + status_file=/tmp/"${ppa/\//_}" + elif [ -e "$list_file" ] && grep -Eq '^deb ' "$list_file"; then + list="$list_file" + fi + if [ ! -e "$status_file" ]; then + update_lists_helper "$list" >/dev/null 2>&1 + echo '' | tee "$status_file" >/dev/null 2>&1 + fi +} + +# Function to get fingerprint from an Ubuntu PPA. +ubuntu_fingerprint() { + ppa=$1 + get -s -n "" "$lp_api"/~"${ppa%/*}"/+archive/"${ppa##*/}" | jq -r '.signing_key_fingerprint' +} + +# Function to get fingerprint from a Debian PPA. +debian_fingerprint() { + ppa=$1 + ppa_url=$2 + package_dist=$3 + release_pub=/tmp/"${ppa/\//-}".gpg + get -q -n "$release_pub" "$ppa_url"/dists/"$package_dist"/Release.gpg + gpg --list-packets "$release_pub" | grep -Eo 'fpr\sv4\s.*[a-zA-Z0-9]+' | head -n 1 | cut -d ' ' -f 3 +} + +# Function to add a GPG key. +add_key() { + ppa=${1:-ondrej/php} + ppa_url=$2 + package_dist=$3 + key_source=$4 + key_file=$5 + key_urls=("$key_source") + if [[ "$key_source" =~ launchpad.net|debian.org|setup-php.com ]]; then + fingerprint="$("${ID}"_fingerprint "$ppa" "$ppa_url" "$package_dist")" + sks_params="op=get&options=mr&exact=on&search=0x$fingerprint" + key_urls=("${sks[@]/%/\/pks\/lookup\?"$sks_params"}") + fi + [ ! -e "$key_source" ] && get -q -n "$key_file" "${key_urls[@]}" + if [[ "$(file "$key_file")" =~ .*('Public-Key (old)'|'Secret-Key') ]]; then + sudo gpg --batch --yes --dearmor "$key_file" >/dev/null 2>&1 && sudo mv "$key_file".gpg "$key_file" + fi +} + +# Function to check if a PPA and its lists exist +check_lists() { + ppa=$1 + ppa_search=$2 + if grep -Eqr "$ppa_search" "$list_dir"; then + list_count="$(sudo find /var/lib/apt/lists -type f -name "*${ppa/\//_}*" | wc -l)" + if [ "$list_count" = "0" ]; then + update_lists "$ppa" "$ppa_search" + fi + return 0; + else + return 1; + fi +} + +# Function to add a sources list. +add_list() { + ppa=${1-ondrej/php} + ppa_url=${2:-"$lp_ppa/$ppa/ubuntu"} + key_source=${3:-"$ppa_url"} + package_dist=${4:-"$VERSION_CODENAME"} + branches=${5:-main} + ppa_search="deb .*$ppa_url $package_dist .*$branches" + if check_lists "$ppa" "$ppa_search"; then + echo "Repository $ppa already exists"; + return 1; + else + arch=$(dpkg --print-architecture) + [ -e "$key_source" ] && key_file=$key_source || key_file="$key_dir"/"${ppa/\//-}"-keyring.gpg + add_key "$ppa" "$ppa_url" "$package_dist" "$key_source" "$key_file" + echo "deb [arch=$arch signed-by=$key_file] $ppa_url $package_dist $branches" | sudo tee -a "$list_dir"/"${ppa/\//-}".list >/dev/null 2>&1 + update_lists "$ppa" "$ppa_search" + . /etc/os-release + fi + return 0; +} + +# Function to check if a PPA exists +check_ppa() { + ppa=$1 + ppa_url=${2:-"$lp_ppa/$ppa/ubuntu"} + package_dist=${3:-"$VERSION_CODENAME"} + branches=${4:-main} + ppa_search="deb .*$ppa_url $package_dist .*$branches" + if check_lists "$ppa" "$ppa_search"; then + return 0; + else + return 1; + fi +} + +# Function to remove a PPA. +remove_list() { + ppa=${1-ondrej/php} + ppa_url=${2:-"$lp_ppa/$ppa/ubuntu"} + grep -lr "$ppa_url" "$list_dir" | xargs -n1 sudo rm -f + sudo rm -f "$key_dir"/"${ppa/\//-}"-keyring || true +} + +# Function to add a PPA. +add_ppa() { + set_base_version + ppa=${1:-ondrej/php} + if [[ "$ID" = "ubuntu" || "$ID_LIKE" =~ ubuntu ]] && [[ "$ppa" =~ "ondrej/" ]]; then + [ "${debug:?}" = "debug" ] && add_list "$ppa" "$lp_ppa/$ppa/ubuntu" "$lp_ppa/$ppa/ubuntu" "$VERSION_CODENAME" "main/debug" + add_list "$ppa" + elif [[ "$ID" = "debian" || "$ID_LIKE" =~ debian ]] && [[ "$ppa" =~ "ondrej/" ]]; then + [ "${debug:?}" = "debug" ] && add_list "$ppa" "$sury"/"${ppa##*/}"/ "$sury"/"${ppa##*/}"/apt.gpg "$VERSION_CODENAME" "main/debug" + add_list "$ppa" "$sury"/"${ppa##*/}"/ "$sury"/"${ppa##*/}"/apt.gpg + else + add_list "$ppa" + fi + exit_code="$?" + . /etc/os-release + return $exit_code +} + +# Function to update a PPA. +update_ppa() { + set_base_version + ppa=${1:-ondrej/php} + ppa_url=${2:-"$lp_ppa/$ppa/ubuntu"} + package_dist=${4:-"$VERSION_CODENAME"} + branches=${5:-main} + ppa_search="deb .*$ppa_url $package_dist .*$branches" + update_lists "$ppa" "$ppa_search" + . /etc/os-release +} + +# Variables +list_file='/etc/apt/sources.list' +list_dir="$list_file.d" +upstream_lsb='/etc/upstream-release/lsb-release' +lp_api='https://api.launchpad.net/1.0' +lp_ppa='http://ppa.launchpad.net' +key_dir='/usr/share/keyrings' +dist_info_dir='/usr/share/distro-info' +sury='https://packages.sury.org' +sks=( + 'https://keyserver.ubuntu.com' + 'https://pgp.mit.edu' + 'https://keys.openpgp.org' +) diff --git a/src/scripts/tools/protoc.ps1 b/src/scripts/tools/protoc.ps1 new file mode 100644 index 0000000..ea5e617 --- /dev/null +++ b/src/scripts/tools/protoc.ps1 @@ -0,0 +1,40 @@ +Function Get-ProtobufTag() { + $releases = 'https://github.com/protocolbuffers/protobuf/releases' + if("$protobuf_tag" -eq "latest") { + $protobuf_tag = (Get-File -Url $releases/latest).BaseResponse.RequestMessage.RequestUri.Segments[-1] + } else { + try { + $protobuf_tag = $protobuf_tag -replace '^v', '' + [net.httpWebRequest] $request = [net.webRequest]::create("$releases/tag/v$protobuf_tag") + $request.Method = "HEAD" + [net.httpWebResponse] $response = $request.getResponse() + $response.Close() + $protobuf_tag = "v$protobuf_tag" + } catch { + $protobuf_tag = (Get-File -Url $releases/latest).BaseResponse.RequestMessage.RequestUri.Segments[-1] + } + } + return $protobuf_tag +} + +Function Add-Protoc() { + param( + [Parameter(Mandatory = $true, Position = 0, HelpMessage = 'The PHP version to be installed')] + [ValidatePattern('^latest$|^(v?)\d+\.\d+(\.\d+)?$')] + [string] $protobuf_tag + ) + $protobuf_tag = Get-ProtobufTag + $arch_num = '64' + if(-not([Environment]::Is64BitOperatingSystem)) { + $arch_num = '32' + } + $url = "https://github.com/protocolbuffers/protobuf/releases/download/$protobuf_tag/protoc-$($protobuf_tag -replace 'v', '')-win$arch_num.zip" + Get-File -Url $url -OutFile $bin_dir\protoc.zip >$null 2>&1 + Expand-Archive -Path $bin_dir\protoc.zip -DestinationPath $bin_dir\protoc -Force >$null 2>&1 + Move-Item -Path $bin_dir\protoc\bin\protoc.exe -Destination $bin_dir\protoc.exe + Add-ToProfile $current_profile 'protoc' "New-Alias protoc $bin_dir\protoc.exe" + Add-Log $tick "protoc" "Added protoc $($protobuf_tag -replace 'v', '')" + printf "$env:GROUP\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "protoc" "Click to read the protoc related license information" + Write-Output (Invoke-WebRequest https://raw.githubusercontent.com/protocolbuffers/protobuf/master/LICENSE).Content + Write-Output "$env:END_GROUP" +} diff --git a/src/scripts/tools/protoc.sh b/src/scripts/tools/protoc.sh new file mode 100644 index 0000000..ad00fb6 --- /dev/null +++ b/src/scripts/tools/protoc.sh @@ -0,0 +1,28 @@ +get_protobuf_tag() { + if [ "$protobuf_tag" = "latest" ]; then + protobuf_tag=$(get -s -n "" https://github.com/protocolbuffers/protobuf/releases/latest 2<&1 | grep -m 1 -Eo "tag/(v[0-9]+(\.[0-9]+)?(\.[0-9]+)?)" | head -n 1 | cut -d '/' -f 2) + else + status_code=$(get -v -n /tmp/protobuf.tmp "https://github.com/protocolbuffers/protobuf/releases/tag/v$protobuf_tag") + if [ "$status_code" = "200" ]; then + protobuf_tag="v$protobuf_tag" + else + protobuf_tag=$(get -s -n "" https://github.com/protocolbuffers/protobuf/releases/latest 2<&1 | grep -m 1 -Eo "tag/(v[0-9]+(\.[0-9]+)?(\.[0-9]+)?)" | head -n 1 | cut -d '/' -f 2) + fi + fi +} + +add_protoc() { + protobuf_tag=$1 + get_protobuf_tag + ( + platform='linux' + [ "$(uname -s)" = "Darwin" ] && platform='osx' + get -q -n /tmp/protobuf.zip "https://github.com/protocolbuffers/protobuf/releases/download/$protobuf_tag/protoc-${protobuf_tag:1}-$platform-x86_64.zip" + sudo unzip /tmp/protobuf.zip -d /usr/local/ + sudo chmod -R 777 /usr/local/bin/protoc /usr/local/include/google + ) >/dev/null 2>&1 + add_log "${tick:?}" "protoc" "Added protoc ${protobuf_tag:1}" + printf "$GROUP\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "protoc" "Click to read the protoc related license information" + curl "${curl_opts[@]:?}" https://raw.githubusercontent.com/protocolbuffers/protobuf/master/LICENSE + echo "$END_GROUP" +} diff --git a/src/scripts/tools/symfony.ps1 b/src/scripts/tools/symfony.ps1 new file mode 100644 index 0000000..3c334d2 --- /dev/null +++ b/src/scripts/tools/symfony.ps1 @@ -0,0 +1,18 @@ +Function Add-Symfony() { + $arch_name ='amd64' + if(-not([Environment]::Is64BitOperatingSystem) -or $version -lt '7.0') { + $arch_name = '386' + } + $url = "https://github.com/symfony-cli/symfony-cli/releases/latest/download/symfony-cli_windows_${arch_name}.zip" + Get-File -Url $url -OutFile $bin_dir\symfony.zip >$null 2>&1 + Expand-Archive -Path $bin_dir\symfony.zip -DestinationPath $bin_dir -Force >$null 2>&1 + if(Test-Path $bin_dir\symfony.exe) { + Copy-Item -Path $bin_dir\symfony.exe -Destination $bin_dir\symfony-cli.exe > $null 2>&1 + Add-ToProfile $current_profile 'symfony' "New-Alias symfony $bin_dir\symfony.exe" + Add-ToProfile $current_profile 'symfony_cli' "New-Alias symfony-cli $bin_dir\symfony-cli.exe" + $tool_version = Get-ToolVersion symfony "-V" + Add-Log $tick "symfony-cli" "Added symfony-cli $tool_version" + } else { + Add-Log $cross "symfony-cli" "Could not setup symfony-cli" + } +} diff --git a/src/scripts/tools/symfony.sh b/src/scripts/tools/symfony.sh new file mode 100644 index 0000000..03d2de2 --- /dev/null +++ b/src/scripts/tools/symfony.sh @@ -0,0 +1,41 @@ +add_symfony_with_brew() { + add_brew_tap symfony-cli/homebrew-tap + brew install symfony-cli/tap/symfony-cli +} + +get_symfony_artifact_url() { + arch=$(dpkg --print-architecture) + url=$(get -s -n "" https://raw.githubusercontent.com/symfony-cli/homebrew-tap/main/Formula/symfony-cli.rb 2<&1 | grep -m 1 "url.*linux.*${arch}" | cut -d\" -f 2) + if [ -z "$url" ]; then + url=$(get -s -n "" https://api.github.com/repos/symfony-cli/symfony-cli/releases 2<&1 | grep -m 1 "url.*linux.*${arch}.*gz\"" | cut -d\" -f 4) + fi + echo "$url" +} + +add_symfony_helper() { + if [ "$(uname -s)" = "Linux" ]; then + url="$(get_symfony_artifact_url)" + if [ -z "$url" ]; then + . "${0%/*}"/tools/brew.sh + configure_brew + add_symfony_with_brew + else + get -s -n "" "$url" | sudo tar -xz -C "${tool_path_dir:?}" 2>/dev/null + sudo chmod a+x /usr/local/bin/symfony + fi + elif [ "$(uname -s)" = "Darwin" ]; then + add_symfony_with_brew + fi +} + +add_symfony() { + add_symfony_helper >/dev/null 2>&1 + symfony_path="$(command -v symfony)" + if [[ -n "$symfony_path" ]]; then + sudo ln -s "$symfony_path" "${tool_path_dir:?}"/symfony-cli + tool_version=$(get_tool_version "symfony" "-V") + add_log "${tick:?}" "symfony-cli" "Added symfony-cli $tool_version" + else + add_log "${cross:?}" "symfony-cli" "Could not setup symfony-cli" + fi +} diff --git a/src/scripts/unix.sh b/src/scripts/unix.sh new file mode 100644 index 0000000..f890502 --- /dev/null +++ b/src/scripts/unix.sh @@ -0,0 +1,200 @@ +# Variables +export tick="✓" +export cross="✗" +export curl_opts=(-sL) +export old_versions="5.[3-5]" +export jit_versions="8.[0-9]" +export nightly_versions="8.[3-9]" +export xdebug3_versions="7.[2-4]|8.[0-9]" +export latest="releases/latest/download" +export github="https://github.com/shivammathur" +export jsdeliver="https://cdn.jsdelivr.net/gh/shivammathur" +export setup_php="https://setup-php.com" + +if [ -n "${GITHUB_ACTIONS}" ]; then + export GROUP='::group::' + export END_GROUP='::endgroup::' +else + export GROUP='' + export END_GROUP='' +fi + +# Function to log start of a operation. +step_log() { + local message=$1 + printf "\n\033[90;1m==> \033[0m\033[37;1m%s\033[0m\n" "$message" +} + +# Function to log result of a operation. +add_log() { + local mark=$1 + local subject=$2 + local message=$3 + if [ "$mark" = "$tick" ]; then + printf "\033[32;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s\033[0m\n" "$mark" "$subject" "$message" + else + printf "\033[31;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s\033[0m\n" "$mark" "$subject" "$message" + [ "$fail_fast" = "true" ] && exit 1 + fi +} + +# Function to set output on GitHub Actions. +set_output() { + name=$1 + value=$2 + if [ "${GITHUB_ACTIONS}" = "true" ]; then + echo "${name}=${value}" | tee -a "$GITHUB_OUTPUT" >/dev/null 2>&1 + fi +} + +# Function to read env inputs. +read_env() { + update="${update:-${UPDATE:-false}}" + [ "${debug:-${DEBUG:-false}}" = "true" ] && debug=debug && update=true || debug=release + [[ "${phpts:-${PHPTS:-nts}}" = "ts" || "${phpts:-${PHPTS:-nts}}" = "zts" ]] && ts=zts && update=true || ts=nts + fail_fast="${fail_fast:-${FAIL_FAST:-false}}" + [[ -z "${ImageOS}" && -z "${ImageVersion}" || -n ${ACT} ]] && _runner=self-hosted || _runner=github + runner="${runner:-${RUNNER:-$_runner}}" + + if [[ "$runner" = "github" && $_runner = "self-hosted" ]]; then + fail_fast=true + add_log "$cross" "Runner" "Runner set as github in self-hosted environment" + fi + + # Set Update to true if the ubuntu github image does not have PHP PPA. + if [[ "$runner" = "github" && "${ImageOS}" =~ ubuntu.* ]]; then + check_ppa ondrej/php || update=true + fi + + export fail_fast + export runner + export update + export ts +} + +# Function to download a file using cURL. +# mode: -s pipe to stdout, -v save file and return status code +# execute: -e save file as executable +get() { + mode=$1 + execute=$2 + file_path=$3 + shift 3 + links=("$@") + if [ "$mode" = "-s" ]; then + sudo curl "${curl_opts[@]}" "${links[0]}" + else + for link in "${links[@]}"; do + status_code=$(sudo curl -w "%{http_code}" -o "$file_path" "${curl_opts[@]}" "$link") + [ "$status_code" = "200" ] && break + done + [ "$execute" = "-e" ] && sudo chmod a+x "$file_path" + [ "$mode" = "-v" ] && echo "$status_code" + fi +} + +# Function to get shell profile. +get_shell_profile() { + case "$SHELL" in + *bash*) + echo "${HOME}/.bashrc" + ;; + *zsh*) + echo "${HOME}/.zshrc" + ;; + *) + echo "${HOME}/.profile" + ;; + esac +} + +# Function to add a path to the PATH variable. +add_path() { + path_to_add=$1 + [[ ":$PATH:" == *":$path_to_add:"* ]] && return + if [[ -n "$GITHUB_PATH" ]]; then + echo "$path_to_add" | tee -a "$GITHUB_PATH" >/dev/null 2>&1 + else + profile=$(get_shell_profile) + ([ -e "$profile" ] && grep -q ":$path_to_add\"" "$profile" 2>/dev/null) || echo "export PATH=\"\${PATH:+\${PATH}:}\"$path_to_add" | sudo tee -a "$profile" >/dev/null 2>&1 + fi + export PATH="${PATH:+${PATH}:}$path_to_add" +} + +# Function to add environment variables using a PATH. +add_env_path() { + env_path=$1 + [ -e "$env_path" ] || return + if [[ -n "$GITHUB_ENV" ]]; then + cat "$env_path" >> "$GITHUB_ENV" + else + profile=$(get_shell_profile) + cat "$env_path" >> "$profile" + fi +} + +# Function to add an environment variable. +add_env() { + env_name=$1 + env_value=$2 + if [[ -n "$GITHUB_ENV" ]]; then + echo "$env_name=$env_value" | tee -a "$GITHUB_ENV" >/dev/null 2>&1 + else + profile=$(get_shell_profile) + echo "export $env_name=\"$env_value\"" | sudo tee -a "$profile" >/dev/null 2>&1 + fi + export "$env_name"="$env_value" +} + +# Function to download and run scripts from GitHub releases with jsdeliver fallback. +run_script() { + repo=$1 + shift + args=("$@") + get -q -e /tmp/install.sh "$github/$repo/$latest/install.sh" "$jsdeliver/$repo@main/scripts/install.sh" "$setup_php/$repo/install.sh" + bash /tmp/install.sh "${args[@]}" +} + +# Function to install required packages on self-hosted runners. +self_hosted_setup() { + if [ "$runner" = "self-hosted" ]; then + if [[ "${version:?}" =~ $old_versions ]]; then + add_log "$cross" "PHP" "PHP $version is not supported on self-hosted runner" + exit 1 + else + self_hosted_helper >/dev/null 2>&1 + add_env RUNNER_TOOL_CACHE /tmp + fi + fi +} + +# Function to configure PHP +configure_php() { + add_php_config + ini_config_dir="${src:?}"/configs/ini + ini_config_files=("$ini_config_dir"/php.ini) + jit_config_files=("$ini_config_dir"/jit.ini) + [[ "$version" =~ $xdebug3_versions ]] && ini_config_files+=("$ini_config_dir"/xdebug.ini) + cat "${ini_config_files[@]}" | sudo tee -a "${ini_file[@]:?}" >/dev/null 2>&1 + [[ "$version" =~ $jit_versions ]] && cat "${jit_config_files[@]}" | sudo tee -a "${pecl_file:-${ini_file[@]}}" >/dev/null 2>&1 +} + +# Function to get PHP version in semver format. +php_semver() { + grep -Eo 'version="[0-9]+(\.[0-9]+){2}((-?[a-zA-Z]+([0-9]+)?)?){2}' "${php_config:?}" | cut -d '"' -f 2 +} + +# Function to get ini_path. +php_ini_path() { + cut -d '"' -f 2 < <(grep "ini_path=" "$php_config" || php --ini | grep '(php.ini)' | sed -e "s|.*: s*||") +} + +# Function to get the tag for a php version. +php_src_tag() { + commit=$(php_extra_version | grep -Eo "[0-9a-zA-Z]+") + if [[ -n "${commit}" ]]; then + echo "$commit" + else + echo "php-${semver:?}" + fi +} diff --git a/src/scripts/win32.ps1 b/src/scripts/win32.ps1 new file mode 100644 index 0000000..fa23445 --- /dev/null +++ b/src/scripts/win32.ps1 @@ -0,0 +1,446 @@ +param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $version = '8.2', + [Parameter(Position = 1, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $ini = 'production' +) + +# Function to log start of a operation. +Function Step-Log($message) { + printf "\n\033[90;1m==> \033[0m\033[37;1m%s \033[0m\n" $message +} + +# Function to log result of a operation. +Function Add-Log($mark, $subject, $message) { + if ($mark -eq $tick) { + printf "\033[32;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" $mark $subject $message + } else { + printf "\033[31;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" $mark $subject $message + if($env:fail_fast -eq 'true') { + Write-Error $message -ErrorAction Stop + } + } +} + +# Function to set output on GitHub Actions. +Function Set-Output() { + param( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $output, + [Parameter(Position = 1, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $value + ) + if ($env:GITHUB_ACTIONS -eq 'true') { + Add-Content "$output=$value" -Path $env:GITHUB_OUTPUT -Encoding utf8 + } +} + +# Function to add a line to a powershell profile safely. +Function Add-ToProfile { + param( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $input_profile, + [Parameter(Position = 1, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $search, + [Parameter(Position = 2, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $value + ) + if($null -eq (Get-Content $input_profile | findstr $search)) { + Add-Content -Path $input_profile -Value $value + } +} + +# Function to fetch PATH from the registry. +Function Get-PathFromRegistry { + $env:Path = [System.Environment]::GetEnvironmentVariable("Path","User") + ";" + + [System.Environment]::GetEnvironmentVariable("Path","Machine") + Add-ToProfile $current_profile 'Get-PathFromRegistry' 'Function Get-PathFromRegistry { $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "User") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "Machine") }; Get-PathFromRegistry' +} + +# Function to add a location to PATH. +Function Add-Path { + param( + [string]$PathItem + ) + if("$env:PATH;".contains("$PathItem;")) { + return + } + if ($env:GITHUB_PATH) { + Add-Content $PathItem -Path $env:GITHUB_PATH -Encoding utf8 + $env:PATH += "$PathItem;" + } else { + $newPath = (Get-ItemProperty -Path 'hkcu:\Environment' -Name PATH).Path.replace("$PathItem;", '') + $newPath = $PathItem + ';' + $newPath + Set-ItemProperty -Path 'hkcu:\Environment' -Name Path -Value $newPath + Get-PathFromRegistry + } +} + +# Function to add an environment variable. +Function Add-Env { + param( + [string]$EnvName, + [string]$EnvValue + ) + if ($env:GITHUB_ENV) { + Add-Content "$EnvName=$EnvValue" -Path $env:GITHUB_ENV -Encoding utf8 + } else { + Set-ItemProperty -Path 'hkcu:\Environment' -Name $EnvName -Value $EnvValue + Add-ToProfile $current_profile $EnvName "`$env:$EnvName=`"$EnvValue`"" + } +} + +# Function to add environment variables using a PATH. +Function Add-EnvPATH { + param( + [string]$EnvPATH + ) + if(-not(Test-Path $EnvPATH)) { + return + } + $env_file = $env:GITHUB_ENV + $env_data = Get-Content -Path $EnvPATH + if (-not($env:GITHUB_ENV)) { + $env_file = $current_profile + $env_data = $env_data | ForEach-Object { '$env:' + $_ } + } + $env_data | Add-Content -Path $env_file -Encoding utf8 +} + +# Function to fetch a file from a URL. +Function Get-File { + param ( + [string]$Url, + [string]$FallbackUrl, + [string]$OutFile, + [int]$Retries = 3, + [int]$TimeoutSec = 0 + ) + + for ($i = 0; $i -lt $Retries; $i++) { + try { + if($null -ne $OutFile) { + Invoke-WebRequest -Uri $Url -OutFile $OutFile -TimeoutSec $TimeoutSec + } else { + Invoke-WebRequest -Uri $Url -TimeoutSec $TimeoutSec + } + break; + } catch { + if ($i -eq ($Retries - 1)) { + if($FallbackUrl) { + try { + if($null -ne $OutFile) { + Invoke-WebRequest -Uri $FallbackUrl -OutFile $OutFile -TimeoutSec $TimeoutSec + } else { + Invoke-WebRequest -Uri $FallbackUrl -TimeoutSec $TimeoutSec + } + } catch { + throw "Failed to download the assets from $Url and $FallbackUrl" + } + } else { + throw "Failed to download the assets from $Url" + } + } + } + } +} + +# Function to make sure printf is in PATH. +Function Add-Printf { + if (-not(Test-Path "C:\Program Files\Git\usr\bin\printf.exe")) { + if(Test-Path "C:\msys64\usr\bin\printf.exe") { + New-Item -Path $bin_dir\printf.exe -ItemType SymbolicLink -Value C:\msys64\usr\bin\printf.exe -Force > $null 2>&1 + } else { + Get-File -Url "$github/shivammathur/printf/releases/latest/download/printf-x64.zip" -OutFile "$bin_dir\printf.zip" + Expand-Archive -Path $bin_dir\printf.zip -DestinationPath $bin_dir -Force + } + } else { + New-Item -Path $bin_dir\printf.exe -ItemType SymbolicLink -Value "C:\Program Files\Git\usr\bin\printf.exe" -Force > $null 2>&1 + } +} + +# Function to get a clean Powershell profile. +Function Get-CleanPSProfile { + if(-not(Test-Path -LiteralPath $profile)) { + New-Item -Path $profile -ItemType "file" -Force > $null 2>&1 + } + Set-Content $current_profile -Value '' + Add-ToProfile $profile $current_profile.replace('\', '\\') ". $current_profile" +} + +# Function to install a powershell package from GitHub. +Function Install-PSPackage() { + param( + [Parameter(Position = 0, Mandatory = $true)] + $package, + [Parameter(Position = 1, Mandatory = $true)] + $psm1_path, + [Parameter(Position = 2, Mandatory = $true)] + $url, + [Parameter(Position = 3, Mandatory = $true)] + $cmdlet + ) + $module_path = "$bin_dir\$psm1_path.psm1" + if(-not (Test-Path $module_path -PathType Leaf)) { + $zip_file = "$bin_dir\$package.zip" + Get-File -Url $url -OutFile $zip_file + Expand-Archive -Path $zip_file -DestinationPath $bin_dir -Force + } + Import-Module $module_path + if($null -eq (Get-Command $cmdlet -ErrorAction SilentlyContinue)) { + Install-Module -Name $package -Force + } else { + Add-ToProfile $current_profile "$package-search" "Import-Module $module_path" + } +} + +# Function to add CA certificates to PHP. +Function Add-PhpCAInfo { + try { + Update-PhpCAInfo -Path $php_dir -Source Curl + } catch { + Add-Log $cross PHP "Could not fetch CA certificate bundle from Curl" + Update-PhpCAInfo -Path $php_dir -Source CurrentUser + } +} + +# Function to set OpenSSL config. +Function Add-OpenSSLConf { + try { + Set-OpenSSLConf -Target User + } catch { + New-Item $php_dir\extras\openssl.cnf -Type File -Force > $null 2>&1 + Set-OpenSSLConf -Path $php_dir\extras\openssl.cnf -Target User + } + Add-Env -EnvName OPENSSL_CONF -EnvValue $env:OPENSSL_CONF +} + +# Function to set PHP config. +Function Add-PhpConfig { + $current = Get-Content -Path $php_dir\php.ini-current -ErrorAction SilentlyContinue + if($ini -eq 'development' -or ($ini -eq 'production' -and $current -and $current -ne 'production')) { + Copy-Item -Path $php_dir\php.ini-$ini -Destination $php_dir\php.ini -Force + } elseif ($ini -eq 'none') { + Set-Content -Path $php_dir\php.ini -Value '' + } + Set-Content -Path $php_dir\php.ini-current -Value $ini + $ini_config_dir = "$src\configs\ini" + $ini_files = @("$ini_config_dir\php.ini") + $version -match $jit_versions -and ($ini_files += ("$ini_config_dir\jit.ini")) > $null 2>&1 + $version -match $xdebug3_versions -and ($ini_files += ("$ini_config_dir\xdebug.ini")) > $null 2>&1 + Add-Content -Path $ini_config_dir\php.ini -Value extension_dir=$ext_dir + Get-Content -Path $ini_files | Add-Content -Path $php_dir\php.ini +} + +# Function to get PHP from GitHub releases cache +Function Set-PhpCache { + try { + try { + $release = Invoke-RestMethod https://api.github.com/repos/shivammathur/php-builder-windows/releases/tags/php$version + $asset = $release.assets | ForEach-Object { + if($_.name -match "php-$version.[0-9]+$env:PHPTS-Win32-.*-$arch.zip") { + return $_.name + } + } | Select-Object -Last 1 + if($null -eq $asset) { + throw "Asset not found" + } + } catch { + $release = Get-File -Url $php_builder/releases/expanded_assets/php$version + $asset = $release.links.href | ForEach-Object { + if($_ -match "php-$version.[0-9]+$env:PHPTS-Win32-.*-$arch.zip") { + return $_.split('/')[-1] + } + } | Select-Object -Last 1 + } + Get-File -Url $php_builder/releases/download/php$version/$asset -OutFile $php_dir\$asset + Set-PhpDownloadCache -Path $php_dir CurrentUser + } catch { } +} + +# Function to add debug symbols to PHP. +Function Add-DebugSymbols { + $dev = if ($version -match $nightly_versions) { '-dev' } else { '' } + try { + $release = Invoke-RestMethod https://api.github.com/repos/shivammathur/php-builder-windows/releases/tags/php$version + $asset = $release.assets | ForEach-Object { + if($_.name -match "php-debug-pack-$version.[0-9]+$dev$env:PHPTS-Win32-.*-$arch.zip") { + return $_.name + } + } | Select-Object -Last 1 + } catch { + $release = Get-File -Url $php_builder/releases/expanded_assets/php$version + $asset = $release.links.href | ForEach-Object { + if($_ -match "php-debug-pack-$version.[0-9]+$dev$env:PHPTS-Win32-.*-$arch.zip") { + return $_.split('/')[-1] + } + } | Select-Object -Last 1 + } + Get-File -Url $php_builder/releases/download/php$version/$asset -OutFile $php_dir\$asset + Expand-Archive -Path $php_dir\$asset -DestinationPath $php_dir -Force + Get-ChildItem -Path $php_dir -Filter php_*.pdb | Move-Item -Destination $ext_dir +} + +# Function to install nightly version of PHP +Function Install-PhpNightly { + Get-File -Url $php_builder/releases/latest/download/Get-PhpNightly.ps1 -FallbackUrl https://dl.cloudsmith.io/public/shivammathur/php-builder-windows/raw/files/Get-PhpNightly.ps1 -OutFile $php_dir\Get-PhpNightly.ps1 > $null 2>&1 + & $php_dir\Get-PhpNightly.ps1 -Architecture $arch -ThreadSafe $ts -Path $php_dir -Version $version > $null 2>&1 + if(Test-Path $php_dir\COMMIT) { + return " ($( Get-Content $php_dir\COMMIT ))" + } + return; +} + +# Variables +$tick = ([char]8730) +$cross = ([char]10007) +$php_dir = 'C:\tools\php' +$ext_dir = "$php_dir\ext" +$bin_dir = $php_dir +$github = 'https://github.com' +$php_builder = "$github/shivammathur/php-builder-windows" +$current_profile = "$env:TEMP\setup-php.ps1" +$ProgressPreference = 'SilentlyContinue' +$jit_versions = '8.[0-9]' +$nightly_versions = '8.[2-9]' +$xdebug3_versions = "7.[2-4]|8.[0-9]" +$enable_extensions = ('openssl', 'curl', 'mbstring') + +$arch = 'x64' +if(-not([Environment]::Is64BitOperatingSystem) -or $version -lt '7.0') { + $arch = 'x86' +} + +$ts = ($env:PHPTS -match '^z?ts$') +if(-not($ts)) { + $env:PHPTS = '-nts' +} else { + $env:PHPTS = '' +} + +if ( $env:GITHUB_ACTIONS -eq 'true') { + $env:GROUP = '::group::' + $env:END_GROUP = '::endgroup::' +} else { + $env:GROUP = '' + $env:END_GROUP = '' +} + +if(-not($env:ImageOS) -and -not($env:ImageVersion)) { + if($env:RUNNER -eq 'github') { + Add-Log $cross "Runner" "Runner set as github in self-hosted environment" + Write-Error "Runner set as github in self-hosted environment" -ErrorAction Stop + } + $bin_dir = 'C:\tools\bin' + $php_dir = "$php_dir$version" + $ext_dir = "$php_dir\ext" + Get-CleanPSProfile >$null 2>&1 + New-Item $bin_dir -Type Directory -Force > $null 2>&1 + Add-Path -PathItem $bin_dir + if($version -lt 5.6) { + Add-Log $cross "PHP" "PHP $version is not supported on self-hosted runner" + Start-Sleep 1 + Write-Error "PHP $version is not supported on self-hosted runner" -ErrorAction Stop + } + if ($null -eq (Get-Module -ListAvailable -Name VcRedist)) { + Install-Module -Name VcRedist -Force + } + New-Item $php_dir -Type Directory -Force > $null 2>&1 + Add-Path -PathItem $php_dir + setx PHPROOT $php_dir >$null 2>&1 + Add-Env -EnvName RUNNER_TOOL_CACHE -EnvValue $env:TEMP +} else { + $current_profile = "$PSHOME\Profile.ps1" + if(-not(Test-Path -LiteralPath $current_profile)) { + New-Item -Path $current_profile -ItemType "file" -Force >$null 2>&1 + } +} + +$src = Join-Path -Path $PSScriptRoot -ChildPath \.. +. $src\scripts\tools\add_tools.ps1 +. $src\scripts\extensions\add_extensions.ps1 + +Add-Printf >$null 2>&1 +Step-Log "Setup PhpManager" +Install-PSPackage PhpManager PhpManager\PhpManager "$github/mlocati/powershell-phpmanager/releases/latest/download/PhpManager.zip" Get-Php >$null 2>&1 +Add-Log $tick "PhpManager" "Installed" + +Step-Log "Setup PHP" +$installed = $null +if (Test-Path -LiteralPath $php_dir -PathType Container) { + try { + if(Test-Path $php_dir\php.ini) { + Rename-Item -Path $php_dir\php.ini -NewName 'php.ini.bak' + } + $installed = Get-Php -Path $php_dir -ErrorAction SilentlyContinue 2>$null 3>$null + if(Test-Path $php_dir\php.ini.bak) { + Rename-Item -Path $php_dir\php.ini.bak -NewName 'php.ini' + } + } catch { } +} +$status = "Installed" +$extra_version = "" +if ($null -eq $installed -or -not("$($installed.Version).".StartsWith(($version -replace '^(\d+(\.\d+)*).*', '$1.'))) -or $ts -ne $installed.ThreadSafe) { + if ($version -lt '7.0' -and ($null -eq (Get-Module -ListAvailable -Name VcRedist))) { + Install-PSPackage VcRedist VcRedist-main\VcRedist\VcRedist "$github/aaronparker/VcRedist/archive/main.zip" Get-VcList >$null 2>&1 + } + try { + if ($version -match $nightly_versions) { + $extra_version = Install-PhpNightly + } else { + Set-PhpCache + Install-Php -Version $version -Architecture $arch -ThreadSafe $ts -InstallVC -Path $php_dir -TimeZone UTC -InitialPhpIni production -Force > $null 2>&1 + } + Add-PhpConfig + } catch { } +} else { + if($env:update -eq 'true') { + Update-Php $php_dir >$null 2>&1 + $status = "Updated to" + } else { + $status = "Found" + } + Add-PhpConfig +} + +if($env:DEBUG -eq 'true') { + Add-DebugSymbols +} + +$installed = Get-Php -Path $php_dir +if($installed.MajorMinorVersion -ne $version) { + Add-Log $cross "PHP" "Could not setup PHP $version" + Write-Error "Could not setup PHP $version" -ErrorAction Stop +} +if($version -lt "5.5") { + ('libeay32.dll', 'ssleay32.dll') | ForEach-Object -Parallel { Get-File -Url "$using:php_builder/releases/download/openssl-1.0.2u/$_" -OutFile $using:php_dir\$_ >$null 2>&1 } +} else { + $enable_extensions += ('opcache') +} +Enable-PhpExtension -Extension $enable_extensions -Path $php_dir +Add-PhpCAInfo +Add-OpenSSLConf +Copy-Item -Path $src\configs\pm\*.json -Destination $env:RUNNER_TOOL_CACHE +Set-Output php-version $($installed.FullVersion) +Add-Log $tick "PHP" "$status PHP $($installed.FullVersion)$extra_version" diff --git a/src/tools.ts b/src/tools.ts new file mode 100644 index 0000000..d02da9a --- /dev/null +++ b/src/tools.ts @@ -0,0 +1,583 @@ +import path from 'path'; +import fs from 'fs'; +import * as fetch from './fetch'; +import * as packagist from './packagist'; +import * as utils from './utils'; + +type RS = Record; +type RSRS = Record; + +interface IRef { + ref: string; + node_id: string; + url: string; + object: RS; +} + +/** + * Function to get version in semver format. + * + * @param data + */ +export async function getSemverVersion(data: RS): Promise { + const search: string = data['version_prefix'] + data['version']; + const url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${search}.`; + let github_token: string = await utils.readEnv('GITHUB_TOKEN'); + const composer_token: string = await utils.readEnv('COMPOSER_TOKEN'); + if (composer_token && !github_token) { + github_token = composer_token; + } + const response: RS = await fetch.fetch(url, github_token); + if (response.error || response.data === '[]') { + data['error'] = response.error ?? `No version found with prefix ${search}.`; + return data['version']; + } else { + const refs = JSON.parse(response['data']).reverse(); + const ref = refs.find((i: IRef) => /.*\d+.\d+.\d+$/.test(i['ref'])); + const tag: string = (ref || refs[0])['ref'].split('/').pop(); + return tag.replace(/^v(\d)/, '$1'); + } +} + +/** + * Function to get latest version from releases.atom + * + * @param data + */ +export async function getLatestVersion(data: RS): Promise { + if (!data['version'] && data['fetch_latest'] === 'false') { + return 'latest'; + } + const resp: Record = await fetch.fetch( + `${data['github']}/${data['repository']}/releases.atom` + ); + if (resp['data']) { + const releases: string[] = [ + ...resp['data'].matchAll(/releases\/tag\/([a-zA-Z]*)?(\d+.\d+.\d+)"/g) + ].map(match => match[2]); + + return ( + releases + .sort((a: string, b: string) => + a.localeCompare(b, undefined, {numeric: true}) + ) + .pop() || 'latest' + ); + } + return 'latest'; +} + +/** + * Function to get tool version + * + * @param version + * @param data + */ +export async function getVersion(version: string, data: RS): Promise { + // semver_regex - https://semver.org/ + const semver_regex = + /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/; + const composer_regex = /^composer:(stable|preview|snapshot|[1|2])$/; + const constraint_regex = /[><=^~]+.*/; + const major_minor_regex = /^\d+(\.\d+)?$/; + data['version'] = version.replace(/v?(\d)/, '$1').replace(/\.x/, ''); + switch (true) { + case composer_regex.test(data['release']): + case semver_regex.test(data['version']): + case constraint_regex.test(data['version']) && data['type'] === 'composer': + return data['version']; + case major_minor_regex.test(data['version']) && data['type'] === 'composer': + data['release'] = `${data['tool']}:${data['version']}.*`; + return `${data['version']}.*`; + case data['repository'] && major_minor_regex.test(data['version']): + return await getSemverVersion(data); + default: + return data['version'].replace(/[><=^~]*/, ''); + } +} + +/** + * Function to parse the release tool:version + * + * @param release + * @param data + */ +export async function getRelease(release: string, data: RS): Promise { + release = release.includes('/') ? release.split('/')[1] : release; + return release.includes(':') + ? [data['tool'], release.split(':')[1]].join(':') + : data['tool']; +} + +/** + * Function to add/move composer in the tools list + * + * @param tools_list + */ +export async function filterList(tools_list: string[]): Promise { + const regex_any = /^composer($|:.*)/; + const regex_valid = + /^composer:?($|preview$|snapshot$|v?\d+(\.\d+)?$|v?\d+\.\d+\.\d+[\w-]*$)/; + const matches: string[] = tools_list.filter(tool => regex_valid.test(tool)); + let composer = 'composer'; + tools_list = tools_list.filter(tool => !regex_any.test(tool)); + switch (true) { + case matches[0] == undefined: + break; + default: + composer = matches[matches.length - 1].replace(/v(\d\S*)/, '$1'); + break; + } + tools_list.unshift(composer); + return tools_list; +} + +/** + * Function to get the url of tool with the given version + * + * @param data + */ +export async function getUrl(data: RS): Promise { + if (data['version'] === 'latest') { + return [ + data['domain'], + data['repository'], + data['prefix'], + data['version'], + data['verb'], + data['tool'] + data['extension'] + ] + .filter(Boolean) + .join('/'); + } else { + return [ + data['domain'], + data['repository'], + data['prefix'], + data['verb'], + data['version_prefix'] + data['version'], + data['tool'] + data['extension'] + ] + .filter(Boolean) + .join('/'); + } +} + +/** + * Function to get the phar url in domain/tool-version.phar format + * + * @param data + */ +export async function getPharUrl(data: RS): Promise { + if (data['version'] === 'latest') { + return data['domain'] + '/' + data['tool'] + '.phar'; + } else { + return ( + data['domain'] + + '/' + + data['tool'] + + '-' + + data['version_prefix'] + + data['version'] + + '.phar' + ); + } +} + +/** + * Helper function to get script to setup a tool using a phar url + * + * @param data + */ +export async function addArchive(data: RS): Promise { + return ( + (await utils.getCommand(data['os'], 'tool')) + + (await utils.joins(data['url'], data['tool'], data['version_parameter'])) + ); +} + +/** + * Helper function to get script to setup a tool using composer + * + * @param data + */ +export async function addPackage(data: RS): Promise { + const command = await utils.getCommand(data['os'], 'composer_tool'); + const parts: string[] = data['repository'].split('/'); + const args: string = await utils.joins( + parts[1], + data['release'], + parts[0] + '/', + data['scope'] + ); + return command + args; +} + +/** + * Function to add blackfire-player + * + * @param data + */ +export async function addBlackfirePlayer(data: RS): Promise { + switch (data['os']) { + case 'win32': + return await utils.addLog( + '$cross', + data['tool'], + data['tool'] + ' is not a windows tool', + 'win32' + ); + default: + if (data['version'] == 'latest') { + if (/5\.[5-6]|7\.0/.test(data['php_version'])) { + data['version'] = '1.9.3'; + } else if (/7\.[1-4]|8\.0/.test(data['php_version'])) { + data['version'] = '1.22.0'; + } + } + data['url'] = await getPharUrl(data); + return addArchive(data); + } +} + +/** + * Function to add Castor + * + * @param data + */ +export async function addCastor(data: RS): Promise { + data['tool'] = 'castor.' + data['os'].replace('win32', 'windows') + '-amd64'; + data['url'] = await getUrl(data); + data['tool'] = 'castor'; + data['version_parameter'] = fs.existsSync('castor.php') + ? data['version_parameter'] + : ''; + return await addArchive(data); +} + +/** + * Function to add composer + * + * @param data + */ +export async function addComposer(data: RS): Promise { + const channel = data['version'].replace('latest', 'stable'); + const github = data['github']; + const getcomposer = data['domain']; + const cds = 'https://dl.cloudsmith.io'; + const filename = `composer-${data['php_version']}-${channel}.phar`; + const releases_url = `${github}/shivammathur/composer-cache/releases/latest/download/${filename}`; + const cds_url = `${cds}/public/shivammathur/composer-cache/raw/files/${filename}`; + const lts_url = `${getcomposer}/download/latest-2.2.x/composer.phar`; + const is_lts = /^5\.[3-6]$|^7\.[0-1]$/.test(data['php_version']); + const version_source_url = `${getcomposer}/composer-${channel}.phar`; + let cache_url = `${releases_url},${cds_url}`; + let source_url = `${getcomposer}/composer.phar`; + switch (true) { + case /^snapshot$/.test(channel): + source_url = is_lts ? lts_url : source_url; + break; + case /^preview$|^2$/.test(channel): + source_url = is_lts ? lts_url : version_source_url; + break; + case /^1$/.test(channel): + source_url = version_source_url; + break; + case /^\d+\.\d+\.\d+[\w-]*$/.test(data['version']): + cache_url = `${github}/${data['repository']}/releases/download/${data['version']}/composer.phar`; + source_url = version_source_url; + break; + default: + source_url = is_lts ? lts_url : version_source_url; + } + const use_cache: boolean = (await utils.readEnv('NO_TOOLS_CACHE')) !== 'true'; + data['url'] = use_cache ? `${cache_url},${source_url}` : source_url; + data['version_parameter'] = data['version']; + return await addArchive(data); +} + +/** + * Function to add Deployer + * + * @param data + */ +export async function addDeployer(data: RS): Promise { + if (data['version'] === 'latest') { + data['url'] = data['domain'] + '/deployer.phar'; + } else { + const manifest: RS = await fetch.fetch( + 'https://deployer.org/manifest.json' + ); + const version_data: RSRS = JSON.parse(manifest.data); + const version_key: string | undefined = Object.keys(version_data).find( + (key: string) => { + return version_data[key]['version'] === data['version']; + } + ); + if (version_key) { + data['url'] = version_data[version_key]['url']; + } else { + return await utils.addLog( + '$cross', + 'deployer', + 'Version missing in deployer manifest', + data['os'] + ); + } + } + return await addArchive(data); +} + +/** + * Function to add php-config and phpize + * + * @param data + */ +export async function addDevTools(data: RS): Promise { + switch (data['os']) { + case 'linux': + case 'darwin': + return 'add_devtools ' + data['tool']; + case 'win32': + return await utils.addLog( + '$tick', + data['tool'], + data['tool'] + ' is not a windows tool', + 'win32' + ); + default: + return await utils.log( + 'Platform ' + data['os'] + ' is not supported', + data['os'], + 'error' + ); + } +} + +/** + * Function to add PECL + * + * @param data + */ +export async function addPECL(data: RS): Promise { + return await utils.getCommand(data['os'], 'pecl'); +} + +/** + * Function to add Phing + * + * @param data + */ +export async function addPhing(data: RS): Promise { + data['url'] = + data['domain'] + '/get/phing-' + data['version'] + data['extension']; + if (data['version'] != 'latest') { + [data['prefix'], data['verb']] = ['releases', 'download']; + data['domain'] = data['github']; + data['extension'] = '-' + data['version'] + data['extension']; + data['url'] += ',' + (await getUrl(data)); + } + return await addArchive(data); +} + +/** + * Helper function to add Phive + * + * @param data + */ +export async function addPhive(data: RS): Promise { + switch (true) { + case /5\.[3-5]/.test(data['php_version']): + return await utils.addLog( + '$cross', + 'phive', + 'Phive is not supported on PHP ' + data['php_version'], + data['os'] + ); + case /5\.6|7\.0/.test(data['php_version']): + data['version'] = '0.12.1'; + break; + case /7\.1/.test(data['php_version']): + data['version'] = '0.13.5'; + break; + case /7\.2/.test(data['php_version']): + data['version'] = '0.14.5'; + break; + case /^latest$/.test(data['version']): + data['version'] = await getLatestVersion(data); + break; + } + data['extension'] = '-' + data['version'] + data['extension']; + data['url'] = await getUrl(data); + return await addArchive(data); +} + +/** + * Function to add PHPUnit and related tools + * + * @param data + */ +export async function addPHPUnitTools(data: RS): Promise { + if (data['version'] === 'latest') { + data['version'] = + (await packagist.search(data['packagist'], data['php_version'])) ?? + 'latest'; + } + data['url'] = await getPharUrl(data); + return await addArchive(data); +} + +/** + * Function to add WP-CLI + * + * @param data + */ +export async function addWPCLI(data: RS): Promise { + if (data['version'] === 'latest') { + data['uri'] = 'wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true'; + data['url'] = [data['domain'], data['uri']].join('/'); + } else { + data['extension'] = '-' + data['version'] + data['extension']; + data['url'] = await getUrl(data); + } + return await addArchive(data); +} + +/** + * Function to get information about a tool + * + * @param release + * @param php_version + * @param os + */ +export async function getData( + release: string, + php_version: string, + os: string +): Promise { + const json_file_path = path.join(__dirname, '../src/configs/tools.json'); + const json_file: string = fs.readFileSync(json_file_path, 'utf8'); + const json_objects: RSRS = JSON.parse(json_file); + release = release.replace(/\s+/g, ''); + const parts: string[] = release.split(':'); + const tool = parts[0]; + const version = parts[1]; + let data: RS; + if (Object.keys(json_objects).includes(tool)) { + data = json_objects[tool]; + data['tool'] = tool; + } else { + const key: string | undefined = Object.keys(json_objects).find( + (key: string) => { + return json_objects[key]['alias'] == tool; + } + ); + if (key) { + data = json_objects[key]; + data['tool'] = key; + } else { + data = { + tool: tool.split('/')[1], + repository: tool, + type: 'composer' + }; + data = !tool.includes('/') ? {tool: tool} : data; + } + } + data['github'] = 'https://github.com'; + data['domain'] ??= data['github']; + data['extension'] ??= '.phar'; + data['os'] = os; + data['php_version'] = php_version; + data['packagist'] ??= data['repository']; + data['prefix'] = data['github'] === data['domain'] ? 'releases' : ''; + data['verb'] = data['github'] === data['domain'] ? 'download' : ''; + data['fetch_latest'] ??= 'false'; + data['scope'] ??= 'global'; + data['version_parameter'] = JSON.stringify(data['version_parameter']) || ''; + data['version_prefix'] ??= ''; + data['release'] = await getRelease(release, data); + data['version'] = version + ? await getVersion(version, data) + : await getLatestVersion(data); + return data; +} + +export const functionRecord: Record Promise> = { + castor: addCastor, + composer: addComposer, + deployer: addDeployer, + dev_tools: addDevTools, + phive: addPhive, + blackfire_player: addBlackfirePlayer, + pecl: addPECL, + phing: addPhing, + phpunit: addPHPUnitTools, + phpcpd: addPHPUnitTools, + wp_cli: addWPCLI +}; + +/** + * Setup tools + * + * @param tools_csv + * @param php_version + * @param os + */ +export async function addTools( + tools_csv: string, + php_version: string, + os: string +): Promise { + let script = '\n'; + if (tools_csv === 'none') { + return ''; + } else { + script += await utils.stepLog('Setup Tools', os); + } + const tools_list = await filterList(await utils.CSVArray(tools_csv)); + await utils.asyncForEach(tools_list, async function (release: string) { + const data: RS = await getData(release, php_version, os); + script += '\n'; + switch (true) { + case data['error'] !== undefined: + script += await utils.addLog( + '$cross', + data['tool'], + data['error'], + data['os'] + ); + break; + case 'phar' === data['type']: + data['url'] = await getUrl(data); + script += await addArchive(data); + break; + case 'composer' === data['type']: + script += await addPackage(data); + break; + case 'custom-package' === data['type']: + script += await utils.customPackage( + data['tool'].split('-')[0], + 'tools', + data['version'], + data['os'] + ); + break; + case 'custom-function' === data['type']: + script += await functionRecord[data['function']](data); + break; + case /^none$/.test(data['tool']): + break; + default: + script += await utils.addLog( + '$cross', + data['tool'], + 'Tool ' + data['tool'] + ' is not supported', + data['os'] + ); + break; + } + }); + + return script; +} diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..c42b931 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,493 @@ +import fs from 'fs'; +import * as path from 'path'; +import * as core from '@actions/core'; +import * as fetch from './fetch'; + +/** + * Function to read environment variable and return a string value. + * + * @param property + */ +export async function readEnv(property: string): Promise { + const property_lc: string = property.toLowerCase(); + const property_uc: string = property.toUpperCase(); + return ( + process.env[property] || + process.env[property_lc] || + process.env[property_uc] || + process.env[property_lc.replace('_', '-')] || + process.env[property_uc.replace('_', '-')] || + '' + ); +} + +/** + * Function to get inputs from both with and env annotations. + * + * @param name + * @param mandatory + */ +export async function getInput( + name: string, + mandatory: boolean +): Promise { + const input = core.getInput(name); + const env_input = await readEnv(name); + switch (true) { + case input != '': + return input; + case input == '' && env_input != '': + return env_input; + case input == '' && env_input == '' && mandatory: + throw new Error(`Input required and not supplied: ${name}`); + default: + return ''; + } +} + +/** + * Function to get manifest URL + */ +export async function getManifestURL(): Promise { + return 'https://raw.githubusercontent.com/shivammathur/setup-php/develop/src/configs/php-versions.json'; +} + +/** + * Function to parse PHP version. + * + * @param version + */ +export async function parseVersion(version: string): Promise { + switch (true) { + case /^(latest|nightly|\d+\.x)$/.test(version): + return JSON.parse((await fetch.fetch(await getManifestURL()))['data'])[ + version + ]; + default: + switch (true) { + case version.length > 1: + return version.slice(0, 3); + default: + return version + '.0'; + } + } +} + +/** + * Function to parse ini file. + * + * @param ini_file + */ +export async function parseIniFile(ini_file: string): Promise { + switch (true) { + case /^(production|development|none)$/.test(ini_file): + return ini_file; + case /php\.ini-(production|development)$/.test(ini_file): + return ini_file.split('-')[1]; + default: + return 'production'; + } +} + +/** + * Async foreach loop + * + * @author https://github.com/Atinux + * @param array + * @param callback + */ +export async function asyncForEach( + array: Array, + callback: ( + element: string, + index: number, + array: Array + ) => Promise +): Promise { + for (let index = 0; index < array.length; index++) { + await callback(array[index], index, array); + } +} + +/** + * Get color index + * + * @param type + */ +export async function color(type: string): Promise { + switch (type) { + case 'error': + return '31'; + default: + case 'success': + return '32'; + case 'warning': + return '33'; + } +} + +/** + * Log to console + * + * @param message + * @param os + * @param log_type + */ +export async function log( + message: string, + os: string, + log_type: string +): Promise { + switch (os) { + case 'win32': + return ( + 'printf "\\033[' + + (await color(log_type)) + + ';1m' + + message + + ' \\033[0m"' + ); + + case 'linux': + case 'darwin': + default: + return ( + 'echo "\\033[' + (await color(log_type)) + ';1m' + message + '\\033[0m"' + ); + } +} + +/** + * Function to log a step + * + * @param message + * @param os + */ +export async function stepLog(message: string, os: string): Promise { + switch (os) { + case 'win32': + return 'Step-Log "' + message + '"'; + case 'linux': + case 'darwin': + return 'step_log "' + message + '"'; + default: + return await log('Platform ' + os + ' is not supported', os, 'error'); + } +} + +/** + * Function to log a result + * @param mark + * @param subject + * @param message + * @param os + */ +export async function addLog( + mark: string, + subject: string, + message: string, + os: string +): Promise { + switch (os) { + case 'win32': + return 'Add-Log "' + mark + '" "' + subject + '" "' + message + '"'; + case 'linux': + case 'darwin': + return 'add_log "' + mark + '" "' + subject + '" "' + message + '"'; + default: + return await log('Platform ' + os + ' is not supported', os, 'error'); + } +} + +/** + * Function to break extension csv into an array + * + * @param extension_csv + */ +export async function extensionArray( + extension_csv: string +): Promise> { + switch (extension_csv) { + case '': + case ' ': + return []; + default: + return [ + extension_csv.match(/(^|,\s?)none(\s?,|$)/) ? 'none' : '', + ...extension_csv + .split(',') + + .map(function (extension: string) { + if (/.+-.+\/.+@.+/.test(extension)) { + return extension; + } + return extension + .trim() + .toLowerCase() + .replace(/^(:)?(php[-_]|none|zend )|(-[^-]*)-/, '$1$3'); + }) + ].filter(Boolean); + } +} + +/** + * Function to break csv into an array + * + * @param values_csv + * @constructor + */ +export async function CSVArray(values_csv: string): Promise> { + switch (values_csv) { + case '': + case ' ': + return []; + default: + return values_csv + .split(/,(?=(?:(?:[^"']*["']){2})*[^"']*$)/) + .map(function (value) { + return value + .trim() + .replace(/^["']|["']$|(?<==)["']/g, '') + .replace(/=(((?!E_).)*[?{}|&~![()^]+((?!E_).)+)/, "='$1'") + .replace(/=(.*?)(=.*)/, "='$1$2'") + .replace(/:\s*["'](.*?)/g, ':$1'); + }) + .filter(Boolean); + } +} + +/** + * Function to get prefix required to load an extension. + * + * @param extension + */ +export async function getExtensionPrefix(extension: string): Promise { + switch (true) { + default: + return 'extension'; + case /xdebug([2-3])?$|opcache|ioncube|eaccelerator/.test(extension): + return 'zend_extension'; + } +} + +/** + * Function to get the suffix to suppress console output + * + * @param os + */ +export async function suppressOutput(os: string): Promise { + switch (os) { + case 'win32': + return ' >$null 2>&1'; + case 'linux': + case 'darwin': + return ' >/dev/null 2>&1'; + default: + return await log('Platform ' + os + ' is not supported', os, 'error'); + } +} + +/** + * Function to get script to log unsupported extensions. + * + * @param extension + * @param version + * @param os + */ +export async function getUnsupportedLog( + extension: string, + version: string, + os: string +): Promise { + return ( + '\n' + + (await addLog( + '$cross', + extension, + [extension, 'is not supported on PHP', version].join(' '), + os + )) + + '\n' + ); +} + +/** + * Function to get command to setup tools + * + * @param os + * @param suffix + */ +export async function getCommand(os: string, suffix: string): Promise { + switch (os) { + case 'linux': + case 'darwin': + return 'add_' + suffix + ' '; + case 'win32': + return ( + 'Add-' + + suffix + .split('_') + .map((part: string) => part.charAt(0).toUpperCase() + part.slice(1)) + .join('') + + ' ' + ); + default: + return await log('Platform ' + os + ' is not supported', os, 'error'); + } +} + +/** + * Function to join strings with space + * + * @param str + */ +export async function joins(...str: string[]): Promise { + return [...str].join(' '); +} + +/** + * Function to get script extensions + * + * @param os + */ +export async function scriptExtension(os: string): Promise { + switch (os) { + case 'win32': + return '.ps1'; + case 'linux': + case 'darwin': + return '.sh'; + default: + return await log('Platform ' + os + ' is not supported', os, 'error'); + } +} + +/** + * Function to get script tool + * + * @param os + */ +export async function scriptTool(os: string): Promise { + switch (os) { + case 'win32': + return 'pwsh '; + case 'linux': + case 'darwin': + return 'bash '; + default: + return await log('Platform ' + os + ' is not supported', os, 'error'); + } +} + +/** + * Function to get script to add tools with custom support. + * + * @param pkg + * @param type + * @param version + * @param os + */ +export async function customPackage( + pkg: string, + type: string, + version: string, + os: string +): Promise { + const pkg_name: string = pkg.replace(/\d+|(pdo|pecl)[_-]/, ''); + const script_extension: string = await scriptExtension(os); + const script: string = path.join( + __dirname, + '../src/scripts/' + type + '/' + pkg_name + script_extension + ); + const command: string = await getCommand(os, pkg_name); + return '\n. ' + script + '\n' + command + version; +} + +/** + * Function to extension input for installation from source. + * + * @param extension + * @param prefix + */ +export async function parseExtensionSource( + extension: string, + prefix: string +): Promise { + // Groups: extension, domain url, org, repo, release + const regex = + /(\w+)-(\w+:\/\/.{1,253}(?:[.:][^:/\s]{2,63})+\/)?([\w.-]+)\/([\w.-]+)@(.+)/; + const matches = regex.exec(extension) as RegExpExecArray; + matches[2] = matches[2] ? matches[2].slice(0, -1) : 'https://github.com'; + return await joins( + '\nadd_extension_from_source', + ...matches.splice(1, matches.length), + prefix + ); +} + +/** + * Read php version from input or file + */ +export async function readPHPVersion(): Promise { + const version = await getInput('php-version', false); + if (version) { + return version; + } + const versionFile = + (await getInput('php-version-file', false)) || '.php-version'; + if (fs.existsSync(versionFile)) { + return fs.readFileSync(versionFile, 'utf8').replace(/[\r\n]/g, ''); + } else if (versionFile !== '.php-version') { + throw new Error(`Could not find '${versionFile}' file.`); + } + + const composerLock = 'composer.lock'; + if (fs.existsSync(composerLock)) { + const lockFileContents = JSON.parse(fs.readFileSync(composerLock, 'utf8')); + if ( + lockFileContents['platform-overrides'] && + lockFileContents['platform-overrides']['php'] + ) { + return lockFileContents['platform-overrides']['php']; + } + } + + const composerJson = 'composer.json'; + if (fs.existsSync(composerJson)) { + const composerFileContents = JSON.parse( + fs.readFileSync(composerJson, 'utf8') + ); + if ( + composerFileContents['config'] && + composerFileContents['config']['platform'] && + composerFileContents['config']['platform']['php'] + ) { + return composerFileContents['config']['platform']['php']; + } + } + + return 'latest'; +} + +/** + * Log to console + * + * @param variable + * @param command + * @param os + */ +export async function setVariable( + variable: string, + command: string, + os: string +): Promise { + switch (os) { + case 'win32': + return '\n$' + variable + ' = ' + command + '\n'; + + case 'linux': + case 'darwin': + default: + return '\n' + variable + '="$(' + command + ')"\n'; + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..f716916 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "declaration": true, + "esModuleInterop": true, + "lib": [ + "ES2021" + ], + "module": "commonjs", + "moduleResolution": "node", + "noImplicitAny": true, + "outDir": "./lib", + "removeComments": true, + "rootDir": "./src", + "sourceMap": true, + "strict": true, + "target": "ES2021" + }, + "exclude": ["__tests__", "lib", "node_modules"] +} \ No newline at end of file