diff --git a/.distignore b/.distignore new file mode 100644 index 000000000..7ad587da2 --- /dev/null +++ b/.distignore @@ -0,0 +1,33 @@ +.distignore +.editorconfig +.gitattributes +.gitignore +.eslintrc +.ddev +.git* +.phpstorm* +.idea +*.env* +.psalm* +tests +*.xml* +.phpunit.result.cache +babel.config.json +node_modules +resources +*.lock +webpack.config.js +wp-cli.yml +ngrok.yml +composer.json +package.json +package-lock.json +.composer_compiled_assets +assets-compiler.json +patchwork.json +.babelrc +README.md +wordpress_org_assets +.DS_Store +auth.json +*.log diff --git a/.github/workflows/package-new.yml b/.github/workflows/package-new.yml new file mode 100644 index 000000000..3d9a96975 --- /dev/null +++ b/.github/workflows/package-new.yml @@ -0,0 +1,36 @@ +name: Build package (New) + +on: + workflow_dispatch: + inputs: + packageVersion: + description: 'Package version' + required: false + type: string + +jobs: + check_version: + runs-on: ubuntu-latest + env: + PACKAGE_VERSION: ${{ github.event.inputs.packageVersion }} + outputs: + version: ${{ env.PACKAGE_VERSION }} + name: Check version + steps: + - uses: actions/checkout@v4 + - name: Fix plugin version input # Add the version number if only suffix entered + run: echo "PACKAGE_VERSION=$(sed -nE '/Version:/s/.* ([0-9.]+).*/\1/p' woocommerce-paypal-payments.php)-$PACKAGE_VERSION" >> $GITHUB_ENV + if: env.PACKAGE_VERSION && !contains(env.PACKAGE_VERSION, '.') + - name: Fill plugin version # If the version number was not set, retrieve it from the file + run: echo "PACKAGE_VERSION=$(sed -nE '/Version:/s/.* ([0-9.]+).*/\1/p' woocommerce-paypal-payments.php)" >> $GITHUB_ENV + if: "!env.PACKAGE_VERSION" + + create_archive: + needs: check_version + uses: inpsyde/reusable-workflows/.github/workflows/build-plugin-archive.yml@feature/prefixed-archives + with: + PHP_VERSION: 7.2 + PLUGIN_MAIN_FILE: ./woocommerce-paypal-payments.php + PLUGIN_VERSION: ${{ needs.check_version.outputs.version }} + ARCHIVE_NAME: woocommerce-paypal-payments-${{ needs.check_version.outputs.version }} + COMPILE_ASSETS_ARGS: '-vv --env=root' diff --git a/.gitignore b/.gitignore index 9ffcb360b..0da873dac 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ modules/*/assets/* auth.json .DS_Store tests/.DS_Store +.composer_compiled_assets diff --git a/.megaignore b/.megaignore deleted file mode 100644 index 6ad02d892..000000000 --- a/.megaignore +++ /dev/null @@ -1 +0,0 @@ --s:* \ No newline at end of file diff --git a/assets-compiler.json b/assets-compiler.json new file mode 100644 index 000000000..9badf65f8 --- /dev/null +++ b/assets-compiler.json @@ -0,0 +1,4 @@ +{ + "dependencies": "install", + "commands": "yarn" +} diff --git a/changelog.txt b/changelog.txt index 8d811ad35..8fee175c0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,25 @@ *** Changelog *** += 2.9.0 - 2024-09-02 = +* Fix - Fatal error in Block Editor when using WooCommerce blocks #2534 +* Fix - Can't pay from block pages when the shipping callback is enabled and no shipping methods defined #2429 +* Fix - Various Google Pay button fixes #2496 +* Fix - Buying a free trial subscription with ACDC results in a $1 charge in the API call #2465 +* Fix - Problem with Google Pay and Apple Pay button placement on Pay for Order page #2542 +* Fix - When there isn't any shipping option for the address the order is still created from classic cart #2437 +* Fix - Patch the order with no shipping methods, instead of throwing an error #2435 +* Enhancement - Separate Apple Pay button for Classic Checkout #2457 +* Enhancement - Remove AMEX support for ACDC when store location is set to China #2526 +* Enhancement - Inform users of Pay Later messaging configuration when Pay Later wasn't recently enabled #2529 +* Enhancement - Update ACDC signup URLs #2475 +* Enhancement - Implement country based APMs via Orders API #2511 +* Enhancement - Update PaymentsStatusHandlingTrait.php (author @callmeahmedr) #2523 +* Enhancement - Disable PayPal Shipping callback by default #2527 +* Enhancement - Change Apple Pay and Google Pay default button labels to plain #2476 +* Enhancement - Add Package Tracking compatibility with DHL Shipping plugin #2463 +* Enhancement - Add support for WC Bookings when skipping checkout confirmation #2452 +* Enhancement - Remove currencies from country-currency matrix in card fields module #2441 + = 2.8.3 - 2024-08-12 = * Fix - Google Pay: Prevent field validation from being triggered on checkout page load #2474 * Fix - Do not add tax info into order meta during order creation #2471 diff --git a/composer.json b/composer.json index e378de009..1bba16f04 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,7 @@ "symfony/polyfill-php80": "^1.19" }, "require-dev": { + "inpsyde/composer-assets-compiler": "^2.5", "psr/container": "^1.0", "dhii/module-interface": "^0.2 || ^0.3", "container-interop/service-provider": "^0.4.0", @@ -69,6 +70,15 @@ "vendor/bin/phpcbf" ] }, + "composer-asset-compiler": { + "auto-run": false, + "packages": { + "inpsyde/*": { + "dependencies": "install", + "script": "build" + } + } + }, "mozart": { "dep_namespace": "WooCommerce\\PayPalCommerce\\Vendor\\", "dep_directory": "/lib/packages/", @@ -84,6 +94,7 @@ }, "config": { "allow-plugins": { + "inpsyde/composer-assets-compiler": true, "dealerdirect/phpcodesniffer-composer-installer": true, "wikimedia/composer-merge-plugin": true } diff --git a/composer.lock b/composer.lock index 528b9224e..86ea6d5e7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8d6d274f3742efb3f1278eee713257b4", + "content-hash": "53a82a4045af3ab9f83e4e4cde7aa5bf", "packages": [ { "name": "container-interop/service-provider", @@ -438,16 +438,16 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/77fa7995ac1b21ab60769b7323d600a991a90433", + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433", "shasum": "" }, "require": { @@ -498,7 +498,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.30.0" }, "funding": [ { @@ -514,7 +514,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "wikimedia/composer-merge-plugin", @@ -979,30 +979,38 @@ }, { "name": "composer/pcre", - "version": "2.1.3", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "540af382c97b83c628227d5f87cf56466d476191" + "reference": "06d0e49d6e136e4521c6bad18598bf0f6062ae37" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/540af382c97b83c628227d5f87cf56466d476191", - "reference": "540af382c97b83c628227d5f87cf56466d476191", + "url": "https://api.github.com/repos/composer/pcre/zipball/06d0e49d6e136e4521c6bad18598bf0f6062ae37", + "reference": "06d0e49d6e136e4521c6bad18598bf0f6062ae37", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, "require-dev": { - "phpstan/phpstan": "^1.3", + "phpstan/phpstan": "^1.11.10", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" + "phpunit/phpunit": "^8 || ^9" }, "type": "library", "extra": { "branch-alias": { "dev-main": "2.x-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] } }, "autoload": { @@ -1030,7 +1038,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/2.1.3" + "source": "https://github.com/composer/pcre/tree/2.3.0" }, "funding": [ { @@ -1046,20 +1054,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T09:03:05+00:00" + "time": "2024-08-19T19:14:31+00:00" }, { "name": "composer/semver", - "version": "3.4.0", + "version": "3.4.2", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6", + "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6", "shasum": "" }, "require": { @@ -1111,7 +1119,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.0" + "source": "https://github.com/composer/semver/tree/3.4.2" }, "funding": [ { @@ -1127,7 +1135,7 @@ "type": "tidelift" } ], - "time": "2023-08-31T09:50:34+00:00" + "time": "2024-07-12T11:35:52+00:00" }, { "name": "composer/xdebug-handler", @@ -1595,24 +1603,24 @@ }, { "name": "graham-campbell/result-type", - "version": "v1.1.2", + "version": "v1.1.3", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862" + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/fbd48bce38f73f8a4ec8583362e732e4095e5862", - "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.2" + "phpoption/phpoption": "^1.9.3" }, "require-dev": { - "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "autoload": { @@ -1641,7 +1649,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.2" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" }, "funding": [ { @@ -1653,7 +1661,7 @@ "type": "tidelift" } ], - "time": "2023-11-12T22:16:48+00:00" + "time": "2024-07-20T21:45:45+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -1706,6 +1714,71 @@ }, "time": "2020-07-09T08:09:16+00:00" }, + { + "name": "inpsyde/composer-assets-compiler", + "version": "2.5.3", + "source": { + "type": "git", + "url": "https://github.com/inpsyde/composer-asset-compiler.git", + "reference": "3db3bea66088421377b725d110bd16ee23716c05" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/inpsyde/composer-asset-compiler/zipball/3db3bea66088421377b725d110bd16ee23716c05", + "reference": "3db3bea66088421377b725d110bd16ee23716c05", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1 || ^2", + "ext-json": "*", + "php": ">= 7.2" + }, + "require-dev": { + "composer/composer": "^2.1.9", + "inpsyde/php-coding-standards": "^1@dev", + "mikey179/vfsstream": "^1.6.10", + "mockery/mockery": "^1.3.5", + "phpunit/phpunit": "^8.5.21", + "vimeo/psalm": "^4.16.1" + }, + "type": "composer-plugin", + "extra": { + "class": "Inpsyde\\AssetsCompiler\\Composer\\Plugin", + "branch-alias": { + "dev-master": "2.x-dev", + "dev-v1.x": "1.x-dev", + "dev-v2.x": "2.x-dev", + "dev-v3.x": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Inpsyde\\AssetsCompiler\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Inpsyde GmbH", + "email": "hello@inpsyde.com", + "homepage": "https://inpsyde.com/", + "role": "Company" + }, + { + "name": "Giuseppe Mazzapica", + "email": "g.mazzapica@inpsyde.com" + } + ], + "description": "Composer plugin that installs and compile frontend dependencies for installed Composer packages based on configuration.", + "support": { + "issues": "https://github.com/inpsyde/composer-asset-compiler/issues", + "source": "https://github.com/inpsyde/composer-asset-compiler/tree/2.5.3" + }, + "time": "2024-03-07T12:11:10+00:00" + }, { "name": "mockery/mockery", "version": "1.3.6", @@ -1777,16 +1850,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { @@ -1794,11 +1867,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -1824,7 +1898,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" }, "funding": [ { @@ -1832,7 +1906,7 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-06-12T14:39:25+00:00" }, { "name": "netresearch/jsonmapper", @@ -2114,16 +2188,16 @@ }, { "name": "php-stubs/woocommerce-stubs", - "version": "v8.9.0", + "version": "v8.9.1", "source": { "type": "git", "url": "https://github.com/php-stubs/woocommerce-stubs.git", - "reference": "2c0bb50a76a703206151fac3123faec6ba7d5879" + "reference": "2f5be3f363ff3d02b4e29404c7895d9d15fd3e73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-stubs/woocommerce-stubs/zipball/2c0bb50a76a703206151fac3123faec6ba7d5879", - "reference": "2c0bb50a76a703206151fac3123faec6ba7d5879", + "url": "https://api.github.com/repos/php-stubs/woocommerce-stubs/zipball/2f5be3f363ff3d02b4e29404c7895d9d15fd3e73", + "reference": "2f5be3f363ff3d02b4e29404c7895d9d15fd3e73", "shasum": "" }, "require": { @@ -2152,9 +2226,9 @@ ], "support": { "issues": "https://github.com/php-stubs/woocommerce-stubs/issues", - "source": "https://github.com/php-stubs/woocommerce-stubs/tree/v8.9.0" + "source": "https://github.com/php-stubs/woocommerce-stubs/tree/v8.9.1" }, - "time": "2024-05-14T16:07:36+00:00" + "time": "2024-05-21T11:47:54+00:00" }, { "name": "php-stubs/wordpress-stubs", @@ -2569,16 +2643,16 @@ }, { "name": "phpoption/phpoption", - "version": "1.9.2", + "version": "1.9.3", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820" + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/80735db690fe4fc5c76dfa7f9b770634285fa820", - "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", "shasum": "" }, "require": { @@ -2586,13 +2660,13 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { "dev-master": "1.9-dev" @@ -2628,7 +2702,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.2" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" }, "funding": [ { @@ -2640,7 +2714,7 @@ "type": "tidelift" } ], - "time": "2023-11-12T21:59:55+00:00" + "time": "2024-07-20T21:41:07+00:00" }, { "name": "phpunit/php-code-coverage", @@ -2941,42 +3015,42 @@ }, { "name": "phpunit/phpunit", - "version": "8.5.38", + "version": "8.5.39", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1ecad678646c817a29e55a32c930f3601c3f5a8c" + "reference": "172ba97bcf97ae6ef86ca256adf77aece8a143fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1ecad678646c817a29e55a32c930f3601c3f5a8c", - "reference": "1ecad678646c817a29e55a32c930f3601c3f5a8c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/172ba97bcf97ae6ef86ca256adf77aece8a143fe", + "reference": "172ba97bcf97ae6ef86ca256adf77aece8a143fe", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.5.0", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.0", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=7.2", - "phpunit/php-code-coverage": "^7.0.12", - "phpunit/php-file-iterator": "^2.0.4", + "phpunit/php-code-coverage": "^7.0.17", + "phpunit/php-file-iterator": "^2.0.6", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1.2", + "phpunit/php-timer": "^2.1.4", "sebastian/comparator": "^3.0.5", - "sebastian/diff": "^3.0.2", - "sebastian/environment": "^4.2.3", - "sebastian/exporter": "^3.1.5", - "sebastian/global-state": "^3.0.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^2.0.1", - "sebastian/type": "^1.1.3", + "sebastian/diff": "^3.0.6", + "sebastian/environment": "^4.2.5", + "sebastian/exporter": "^3.1.6", + "sebastian/global-state": "^3.0.5", + "sebastian/object-enumerator": "^3.0.5", + "sebastian/resource-operations": "^2.0.3", + "sebastian/type": "^1.1.5", "sebastian/version": "^2.0.1" }, "suggest": { @@ -3019,7 +3093,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.38" + "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.39" }, "funding": [ { @@ -3035,7 +3109,7 @@ "type": "tidelift" } ], - "time": "2024-04-05T04:31:23+00:00" + "time": "2024-07-10T11:43:00+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -3767,16 +3841,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.9.2", + "version": "3.10.2", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480" + "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/aac1f6f347a5c5ac6bc98ad395007df00990f480", - "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/86e5f5dd9a840c46810ebe5ff1885581c42a3017", + "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017", "shasum": "" }, "require": { @@ -3843,20 +3917,20 @@ "type": "open_collective" } ], - "time": "2024-04-23T20:25:34+00:00" + "time": "2024-07-21T23:26:44+00:00" }, { "name": "symfony/console", - "version": "v5.4.39", + "version": "v5.4.42", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "f3e591c48688a0cfa1a3296205926c05e84b22b1" + "reference": "cef62396a0477e94fc52e87a17c6e5c32e226b7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/f3e591c48688a0cfa1a3296205926c05e84b22b1", - "reference": "f3e591c48688a0cfa1a3296205926c05e84b22b1", + "url": "https://api.github.com/repos/symfony/console/zipball/cef62396a0477e94fc52e87a17c6e5c32e226b7f", + "reference": "cef62396a0477e94fc52e87a17c6e5c32e226b7f", "shasum": "" }, "require": { @@ -3926,7 +4000,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.39" + "source": "https://github.com/symfony/console/tree/v5.4.42" }, "funding": [ { @@ -3942,7 +4016,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T08:26:06+00:00" + "time": "2024-07-26T12:21:55+00:00" }, { "name": "symfony/deprecation-contracts", @@ -4013,16 +4087,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + "reference": "0424dff1c58f028c451efff2045f5d92410bd540" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", + "reference": "0424dff1c58f028c451efff2045f5d92410bd540", "shasum": "" }, "require": { @@ -4072,7 +4146,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" }, "funding": [ { @@ -4088,20 +4162,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", "shasum": "" }, "require": { @@ -4150,7 +4224,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" }, "funding": [ { @@ -4166,20 +4240,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", "shasum": "" }, "require": { @@ -4231,7 +4305,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" }, "funding": [ { @@ -4247,20 +4321,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", "shasum": "" }, "require": { @@ -4311,7 +4385,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" }, "funding": [ { @@ -4327,20 +4401,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-06-19T12:30:46+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "21bd091060673a1177ae842c0ef8fe30893114d2" + "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2", - "reference": "21bd091060673a1177ae842c0ef8fe30893114d2", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/ec444d3f3f6505bb28d11afa41e75faadebc10a1", + "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1", "shasum": "" }, "require": { @@ -4387,7 +4461,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.30.0" }, "funding": [ { @@ -4403,7 +4477,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/service-contracts", @@ -4490,16 +4564,16 @@ }, { "name": "symfony/string", - "version": "v5.4.39", + "version": "v5.4.42", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "495e71bae5862308051b9e63cc3e34078eed83ef" + "reference": "909cec913edea162a3b2836788228ad45fcab337" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/495e71bae5862308051b9e63cc3e34078eed83ef", - "reference": "495e71bae5862308051b9e63cc3e34078eed83ef", + "url": "https://api.github.com/repos/symfony/string/zipball/909cec913edea162a3b2836788228ad45fcab337", + "reference": "909cec913edea162a3b2836788228ad45fcab337", "shasum": "" }, "require": { @@ -4556,7 +4630,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.39" + "source": "https://github.com/symfony/string/tree/v5.4.42" }, "funding": [ { @@ -4572,7 +4646,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T08:26:06+00:00" + "time": "2024-07-20T18:38:32+00:00" }, { "name": "theseer/tokenizer", @@ -4734,23 +4808,23 @@ }, { "name": "vlucas/phpdotenv", - "version": "v5.6.0", + "version": "v5.6.1", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4" + "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", - "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2", + "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.1.2", + "graham-campbell/result-type": "^1.1.3", "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.2", + "phpoption/phpoption": "^1.9.3", "symfony/polyfill-ctype": "^1.24", "symfony/polyfill-mbstring": "^1.24", "symfony/polyfill-php80": "^1.24" @@ -4767,7 +4841,7 @@ "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { "dev-master": "5.6-dev" @@ -4802,7 +4876,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.0" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1" }, "funding": [ { @@ -4814,7 +4888,7 @@ "type": "tidelift" } ], - "time": "2023-11-12T22:43:29+00:00" + "time": "2024-07-20T21:52:34+00:00" }, { "name": "webmozart/assert", diff --git a/modules.php b/modules.php index ee5830d5b..f5d8dc00b 100644 --- a/modules.php +++ b/modules.php @@ -31,6 +31,7 @@ return function ( string $root_dir ): iterable { ( require "$modules_dir/ppcp-uninstall/module.php" )(), ( require "$modules_dir/ppcp-blocks/module.php" )(), ( require "$modules_dir/ppcp-paypal-subscriptions/module.php" )(), + ( require "$modules_dir/ppcp-local-alternative-payment-methods/module.php" )(), ); // phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores @@ -88,12 +89,5 @@ return function ( string $root_dir ): iterable { $modules[] = ( require "$modules_dir/ppcp-axo/module.php" )(); } - if ( apply_filters( - 'woocommerce.feature-flags.woocommerce_paypal_payments.local_apms_enabled', - getenv( 'PCP_LOCAL_APMS_ENABLED' ) === '1' - ) ) { - $modules[] = ( require "$modules_dir/ppcp-local-alternative-payment-methods/module.php" )(); - } - return $modules; }; diff --git a/modules/ppcp-admin-notices/.babelrc b/modules/ppcp-admin-notices/.babelrc new file mode 100644 index 000000000..822778e6c --- /dev/null +++ b/modules/ppcp-admin-notices/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "useBuiltIns": "usage", + "corejs": "3.25.0" + } + ], + [ + "@babel/preset-react" + ] + ] +} diff --git a/modules/ppcp-admin-notices/package.json b/modules/ppcp-admin-notices/package.json new file mode 100644 index 000000000..7e6599e52 --- /dev/null +++ b/modules/ppcp-admin-notices/package.json @@ -0,0 +1,31 @@ +{ + "name": "ppcp-admin-notices", + "version": "1.0.0", + "license": "GPL-3.0-or-later", + "browserslist": [ + "> 0.5%", + "Safari >= 8", + "Chrome >= 41", + "Firefox >= 43", + "Edge >= 14" + ], + "dependencies": { + "core-js": "^3.25.0" + }, + "devDependencies": { + "@babel/core": "^7.19", + "@babel/preset-env": "^7.19", + "babel-loader": "^8.2", + "cross-env": "^7.0.3", + "file-loader": "^6.2.0", + "sass": "^1.42.1", + "sass-loader": "^12.1.0", + "webpack": "^5.76", + "webpack-cli": "^4.10" + }, + "scripts": { + "build": "cross-env BABEL_ENV=default NODE_ENV=production webpack", + "watch": "cross-env BABEL_ENV=default NODE_ENV=production webpack --watch", + "dev": "cross-env BABEL_ENV=default webpack --watch" + } +} diff --git a/modules/ppcp-admin-notices/resources/css/styles.scss b/modules/ppcp-admin-notices/resources/css/styles.scss new file mode 100644 index 000000000..4263c30ea --- /dev/null +++ b/modules/ppcp-admin-notices/resources/css/styles.scss @@ -0,0 +1,10 @@ +.notice.is-dismissible { + .spinner.doing-ajax { + position: absolute; + z-index: 1; + right: 0; + top: 0; + margin: 9px; + pointer-events: none; + } +} diff --git a/modules/ppcp-admin-notices/resources/js/DismissibleMessage.js b/modules/ppcp-admin-notices/resources/js/DismissibleMessage.js new file mode 100644 index 000000000..dd5ae9ba5 --- /dev/null +++ b/modules/ppcp-admin-notices/resources/js/DismissibleMessage.js @@ -0,0 +1,137 @@ +export default class DismissibleMessage { + #notice = null; + + #muteConfig = {}; + + #closeButton = null; + + #msgId = ''; + + constructor( noticeElement, muteConfig ) { + this.#notice = noticeElement; + this.#muteConfig = muteConfig; + this.#msgId = this.#notice.dataset.ppcpMsgId; + + // Quick sanitation. + if ( ! this.#muteConfig?.endpoint || ! this.#muteConfig?.nonce ) { + console.error( 'Ajax config (Mute):', this.#muteConfig ); + throw new Error( + 'Invalid ajax configuration for DismissibleMessage. Nonce/Endpoint missing' + ); + } + if ( ! this.#msgId ) { + console.error( 'Notice Element:', this.#notice ); + throw new Error( + 'Invalid notice element passed to DismissibleMessage. No MsgId defined' + ); + } + + this.onDismissClickProxy = this.onDismissClickProxy.bind( this ); + this.enableCloseButtons = this.enableCloseButtons.bind( this ); + this.disableCloseButtons = this.disableCloseButtons.bind( this ); + this.dismiss = this.dismiss.bind( this ); + + this.addEventListeners(); + } + + get id() { + return this.#msgId; + } + + get closeButton() { + if ( ! this.#closeButton ) { + this.#closeButton = this.#notice.querySelector( + 'button.notice-dismiss' + ); + } + + return this.#closeButton; + } + + addEventListeners() { + this.#notice.addEventListener( + 'click', + this.onDismissClickProxy, + true + ); + } + + removeEventListeners() { + this.#notice.removeEventListener( + 'click', + this.onDismissClickProxy, + true + ); + } + + onDismissClickProxy( event ) { + if ( ! event.target?.matches( 'button.notice-dismiss' ) ) { + return; + } + + this.disableCloseButtons(); + this.muteMessage(); + + event.preventDefault(); + event.stopPropagation(); + return false; + } + + disableCloseButtons() { + this.closeButton.setAttribute( 'disabled', 'disabled' ); + this.closeButton.style.pointerEvents = 'none'; + this.closeButton.style.opacity = 0; + } + + enableCloseButtons() { + this.closeButton.removeAttribute( 'disabled', 'disabled' ); + this.closeButton.style.pointerEvents = ''; + this.closeButton.style.opacity = ''; + } + + showSpinner() { + const spinner = document.createElement( 'span' ); + spinner.classList.add( 'spinner', 'is-active', 'doing-ajax' ); + + this.#notice.appendChild( spinner ); + } + + /** + * Mute the message (on server side) and dismiss it (in browser). + */ + muteMessage() { + this.#ajaxMuteMessage().then( this.dismiss ); + } + + /** + * Start an ajax request that marks the message as "muted" on server side. + * + * @return {Promise} Resolves after the ajax request is completed. + */ + #ajaxMuteMessage() { + this.showSpinner(); + + const ajaxData = { + id: this.id, + nonce: this.#muteConfig.nonce, + }; + + return fetch( this.#muteConfig.endpoint, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify( ajaxData ), + } ).then( ( response ) => response.json() ); + } + + /** + * Proxy to the original dismiss logic provided by WP core JS. + */ + dismiss() { + this.removeEventListeners(); + this.enableCloseButtons(); + + this.closeButton.dispatchEvent( new Event( 'click' ) ); + } +} diff --git a/modules/ppcp-admin-notices/resources/js/boot-admin.js b/modules/ppcp-admin-notices/resources/js/boot-admin.js new file mode 100644 index 000000000..c9e803824 --- /dev/null +++ b/modules/ppcp-admin-notices/resources/js/boot-admin.js @@ -0,0 +1,27 @@ +import DismissibleMessage from './DismissibleMessage'; + +class AdminMessageHandler { + #config = {}; + + constructor( config ) { + this.#config = config; + this.setupDismissibleMessages(); + } + + /** + * Finds all mutable admin messages in the DOM and initializes them. + */ + setupDismissibleMessages() { + const muteConfig = this.#config?.ajax?.mute_message; + + const addDismissibleMessage = ( element ) => { + new DismissibleMessage( element, muteConfig ); + }; + + document + .querySelectorAll( '.notice[data-ppcp-msg-id]' ) + .forEach( addDismissibleMessage ); + } +} + +new AdminMessageHandler( window.wc_admin_notices ); diff --git a/modules/ppcp-admin-notices/services.php b/modules/ppcp-admin-notices/services.php index 877092e26..1d9f22b8b 100644 --- a/modules/ppcp-admin-notices/services.php +++ b/modules/ppcp-admin-notices/services.php @@ -14,15 +14,33 @@ use WooCommerce\PayPalCommerce\AdminNotices\Renderer\Renderer; use WooCommerce\PayPalCommerce\AdminNotices\Renderer\RendererInterface; use WooCommerce\PayPalCommerce\AdminNotices\Repository\Repository; use WooCommerce\PayPalCommerce\AdminNotices\Repository\RepositoryInterface; +use WooCommerce\PayPalCommerce\AdminNotices\Endpoint\MuteMessageEndpoint; return array( - 'admin-notices.renderer' => static function ( ContainerInterface $container ): RendererInterface { - - $repository = $container->get( 'admin-notices.repository' ); - return new Renderer( $repository ); + 'admin-notices.url' => static function ( ContainerInterface $container ): string { + $path = realpath( __FILE__ ); + if ( false === $path ) { + return ''; + } + return plugins_url( + '/modules/ppcp-admin-notices/', + dirname( $path, 3 ) . '/woocommerce-paypal-payments.php' + ); }, - 'admin-notices.repository' => static function ( ContainerInterface $container ): RepositoryInterface { - + 'admin-notices.renderer' => static function ( ContainerInterface $container ): RendererInterface { + return new Renderer( + $container->get( 'admin-notices.repository' ), + $container->get( 'admin-notices.url' ), + $container->get( 'ppcp.asset-version' ) + ); + }, + 'admin-notices.repository' => static function ( ContainerInterface $container ): RepositoryInterface { return new Repository(); }, + 'admin-notices.mute-message-endpoint' => static function ( ContainerInterface $container ): MuteMessageEndpoint { + return new MuteMessageEndpoint( + $container->get( 'button.request-data' ), + $container->get( 'admin-notices.repository' ) + ); + }, ); diff --git a/modules/ppcp-admin-notices/src/AdminNotices.php b/modules/ppcp-admin-notices/src/AdminNotices.php index 0489df02c..5980886d6 100644 --- a/modules/ppcp-admin-notices/src/AdminNotices.php +++ b/modules/ppcp-admin-notices/src/AdminNotices.php @@ -9,12 +9,14 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\AdminNotices; -use WooCommerce\PayPalCommerce\AdminNotices\Entity\Message; use WooCommerce\PayPalCommerce\AdminNotices\Repository\Repository; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; +use WooCommerce\PayPalCommerce\AdminNotices\Endpoint\MuteMessageEndpoint; +use WooCommerce\PayPalCommerce\AdminNotices\Renderer\RendererInterface; +use WooCommerce\PayPalCommerce\AdminNotices\Entity\PersistentMessage; /** * Class AdminNotices @@ -35,10 +37,12 @@ class AdminNotices implements ModuleInterface { * {@inheritDoc} */ public function run( ContainerInterface $c ): void { + $renderer = $c->get( 'admin-notices.renderer' ); + assert( $renderer instanceof RendererInterface ); + add_action( 'admin_notices', - function() use ( $c ) { - $renderer = $c->get( 'admin-notices.renderer' ); + function() use ( $renderer ) { $renderer->render(); } ); @@ -70,6 +74,35 @@ class AdminNotices implements ModuleInterface { return $notices; } ); + + /** + * Since admin notices are rendered after the initial `admin_enqueue_scripts` + * action fires, we use the `admin_footer` hook to enqueue the optional assets + * for admin-notices in the page footer. + */ + add_action( + 'admin_footer', + static function () use ( $renderer ) { + $renderer->enqueue_admin(); + } + ); + + add_action( + 'wp_ajax_' . MuteMessageEndpoint::ENDPOINT, + static function () use ( $c ) { + $endpoint = $c->get( 'admin-notices.mute-message-endpoint' ); + assert( $endpoint instanceof MuteMessageEndpoint ); + + $endpoint->handle_request(); + } + ); + + add_action( + 'woocommerce_paypal_payments_uninstall', + static function () { + PersistentMessage::clear_all(); + } + ); } /** diff --git a/modules/ppcp-admin-notices/src/Endpoint/MuteMessageEndpoint.php b/modules/ppcp-admin-notices/src/Endpoint/MuteMessageEndpoint.php new file mode 100644 index 000000000..9a67b8511 --- /dev/null +++ b/modules/ppcp-admin-notices/src/Endpoint/MuteMessageEndpoint.php @@ -0,0 +1,89 @@ +request_data = $request_data; + $this->message_repository = $message_repository; + } + + /** + * Returns the nonce. + * + * @return string + */ + public static function nonce() : string { + return self::ENDPOINT; + } + + /** + * Handles the request. + * + * @return void + */ + public function handle_request() : void { + try { + $data = $this->request_data->read_request( $this->nonce() ); + } catch ( RuntimeException $ex ) { + wp_send_json_error(); + } + + $id = $data['id'] ?? ''; + if ( ! $id || ! is_string( $id ) ) { + wp_send_json_error(); + } + + /** + * Create a dummy message with the provided ID and mark it as muted. + * + * This helps to keep code cleaner and make the mute-endpoint more reliable, + * as other modules do not need to register the PersistentMessage on every + * ajax request. + */ + $message = new PersistentMessage( $id, '', '', '' ); + $message->mute(); + + wp_send_json_success(); + } +} diff --git a/modules/ppcp-admin-notices/src/Entity/Message.php b/modules/ppcp-admin-notices/src/Entity/Message.php index 97624d872..c41bc131c 100644 --- a/modules/ppcp-admin-notices/src/Entity/Message.php +++ b/modules/ppcp-admin-notices/src/Entity/Message.php @@ -5,7 +5,7 @@ * @package WooCommerce\PayPalCommerce\AdminNotices\Entity */ -declare(strict_types=1); +declare( strict_types = 1 ); namespace WooCommerce\PayPalCommerce\AdminNotices\Entity; @@ -15,7 +15,7 @@ namespace WooCommerce\PayPalCommerce\AdminNotices\Entity; class Message { /** - * The messagte text. + * The message text. * * @var string */ @@ -29,11 +29,11 @@ class Message { private $type; /** - * Whether the message is dismissable. + * Whether the message is dismissible. * * @var bool */ - private $dismissable; + private $dismissible; /** * The wrapper selector that will contain the notice. @@ -45,15 +45,15 @@ class Message { /** * Message constructor. * - * @param string $message The message text. - * @param string $type The message type. - * @param bool $dismissable Whether the message is dismissable. - * @param string $wrapper The wrapper selector that will contain the notice. + * @param string $message The message text. + * @param string $type The message type. + * @param bool $dismissible Whether the message is dismissible. + * @param string $wrapper The wrapper selector that will contain the notice. */ - public function __construct( string $message, string $type, bool $dismissable = true, string $wrapper = '' ) { + public function __construct( string $message, string $type, bool $dismissible = true, string $wrapper = '' ) { $this->type = $type; $this->message = $message; - $this->dismissable = $dismissable; + $this->dismissible = $dismissible; $this->wrapper = $wrapper; } @@ -62,7 +62,7 @@ class Message { * * @return string */ - public function message(): string { + public function message() : string { return $this->message; } @@ -71,17 +71,17 @@ class Message { * * @return string */ - public function type(): string { + public function type() : string { return $this->type; } /** - * Returns whether the message is dismissable. + * Returns whether the message is dismissible. * * @return bool */ - public function is_dismissable(): bool { - return $this->dismissable; + public function is_dismissible() : bool { + return $this->dismissible; } /** @@ -89,21 +89,37 @@ class Message { * * @return string */ - public function wrapper(): string { + public function wrapper() : string { return $this->wrapper; } /** - * Returns the object as array. + * Returns the object as array, for serialization. * * @return array */ - public function to_array(): array { + public function to_array() : array { return array( 'type' => $this->type, 'message' => $this->message, - 'dismissable' => $this->dismissable, + 'dismissible' => $this->dismissible, 'wrapper' => $this->wrapper, ); } + + /** + * Converts a plain array to a full Message instance, during deserialization. + * + * @param array $data Data generated by `Message::to_array()`. + * + * @return Message + */ + public static function from_array( array $data ) : Message { + return new Message( + (string) ( $data['message'] ?? '' ), + (string) ( $data['type'] ?? '' ), + (bool) ( $data['dismissible'] ?? true ), + (string) ( $data['wrapper'] ?? '' ) + ); + } } diff --git a/modules/ppcp-admin-notices/src/Entity/PersistentMessage.php b/modules/ppcp-admin-notices/src/Entity/PersistentMessage.php new file mode 100644 index 000000000..4a173a02d --- /dev/null +++ b/modules/ppcp-admin-notices/src/Entity/PersistentMessage.php @@ -0,0 +1,125 @@ +message_id = sanitize_key( $id ); + } + + /** + * Returns the sanitized ID that identifies a permanently dismissible message. + * + * @param bool $with_db_prefix Whether to add the user-meta prefix. + * + * @return string + */ + public function id( bool $with_db_prefix = false ) : string { + if ( ! $this->message_id ) { + return ''; + } + + return $with_db_prefix ? self::USER_META_PREFIX . $this->message_id : $this->message_id; + } + + /** + * {@inheritDoc} + */ + public function to_array() : array { + $data = parent::to_array(); + $data['id'] = $this->message_id; + + return $data; + } + + /** + * {@inheritDoc} + * + * @return PersistentMessage + */ + public static function from_array( array $data ) : Message { + return new PersistentMessage( + (string) ( $data['id'] ?? '' ), + (string) ( $data['message'] ?? '' ), + (string) ( $data['type'] ?? '' ), + (string) ( $data['wrapper'] ?? '' ) + ); + } + + /** + * Whether the message was permanently muted by the current user. + * + * @return bool + */ + public function is_muted() : bool { + $user_id = get_current_user_id(); + + if ( ! $this->message_id || ! $user_id ) { + return false; + } + + return 0 < (int) get_user_meta( $user_id, $this->id( true ), true ); + } + + /** + * Mark the message as permanently muted by the current user. + * + * @return void + */ + public function mute() : void { + $user_id = get_current_user_id(); + + if ( $this->message_id && $user_id && ! $this->is_muted() ) { + update_user_meta( $user_id, $this->id( true ), time() ); + } + } + + /** + * Removes all user-meta flags for muted messages. + * + * @return void + */ + public static function clear_all() : void { + global $wpdb; + + $wpdb->query( + $wpdb->prepare( + "DELETE FROM $wpdb->usermeta WHERE meta_key LIKE %s", + $wpdb->esc_like( self::USER_META_PREFIX ) . '%' + ) + ); + } +} diff --git a/modules/ppcp-admin-notices/src/Renderer/Renderer.php b/modules/ppcp-admin-notices/src/Renderer/Renderer.php index 1202d2ab4..d1bc3ddf6 100644 --- a/modules/ppcp-admin-notices/src/Renderer/Renderer.php +++ b/modules/ppcp-admin-notices/src/Renderer/Renderer.php @@ -10,6 +10,8 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\AdminNotices\Renderer; use WooCommerce\PayPalCommerce\AdminNotices\Repository\RepositoryInterface; +use WooCommerce\PayPalCommerce\AdminNotices\Endpoint\MuteMessageEndpoint; +use WooCommerce\PayPalCommerce\AdminNotices\Entity\PersistentMessage; /** * Class Renderer @@ -23,32 +25,123 @@ class Renderer implements RendererInterface { */ private $repository; + /** + * Used to enqueue assets. + * + * @var string + */ + private $module_url; + + /** + * Used to enqueue assets. + * + * @var string + */ + private $version; + + /** + * Whether the current page contains at least one message that can be muted. + * + * @var bool + */ + private $can_mute_message = false; + /** * Renderer constructor. * * @param RepositoryInterface $repository The message repository. + * @param string $module_url The module URL. + * @param string $version The module version. */ - public function __construct( RepositoryInterface $repository ) { + public function __construct( + RepositoryInterface $repository, + string $module_url, + string $version + ) { $this->repository = $repository; + $this->module_url = untrailingslashit( $module_url ); + $this->version = $version; } /** - * Renders the current messages. - * - * @return bool + * {@inheritDoc} */ public function render(): bool { $messages = $this->repository->current_message(); + foreach ( $messages as $message ) { + $mute_message_id = ''; + + if ( $message instanceof PersistentMessage ) { + $this->can_mute_message = true; + + $mute_message_id = $message->id(); + } + printf( - '

%s

', + '

%s

', $message->type(), - ( $message->is_dismissable() ) ? 'is-dismissible' : '', + ( $message->is_dismissible() ) ? 'is-dismissible' : '', ( $message->wrapper() ? sprintf( 'data-ppcp-wrapper="%s"', esc_attr( $message->wrapper() ) ) : '' ), + // Use `empty()` in condition, to avoid false phpcs warning. + ( empty( $mute_message_id ) ? '' : sprintf( 'data-ppcp-msg-id="%s"', esc_attr( $mute_message_id ) ) ), wp_kses_post( $message->message() ) ); } return (bool) count( $messages ); } + + /** + * {@inheritDoc} + */ + public function enqueue_admin() : void { + if ( ! $this->can_mute_message ) { + return; + } + + wp_register_style( + 'wc-ppcp-admin-notice', + $this->module_url . '/assets/css/styles.css', + array(), + $this->version + ); + wp_register_script( + 'wc-ppcp-admin-notice', + $this->module_url . '/assets/js/boot-admin.js', + array(), + $this->version, + true + ); + + wp_localize_script( + 'wc-ppcp-admin-notice', + 'wc_admin_notices', + $this->script_data_for_admin() + ); + + wp_enqueue_style( 'wc-ppcp-admin-notice' ); + wp_enqueue_script( 'wc-ppcp-admin-notice' ); + } + + /** + * Data to inject into the current admin page, which is required by JS assets. + * + * @return array + */ + protected function script_data_for_admin() : array { + $ajax_url = admin_url( 'admin-ajax.php' ); + + return array( + 'ajax' => array( + 'mute_message' => array( + 'endpoint' => add_query_arg( + array( 'action' => MuteMessageEndpoint::ENDPOINT ), + $ajax_url + ), + 'nonce' => wp_create_nonce( MuteMessageEndpoint::nonce() ), + ), + ), + ); + } } diff --git a/modules/ppcp-admin-notices/src/Renderer/RendererInterface.php b/modules/ppcp-admin-notices/src/Renderer/RendererInterface.php index 1202b8819..ad0044341 100644 --- a/modules/ppcp-admin-notices/src/Renderer/RendererInterface.php +++ b/modules/ppcp-admin-notices/src/Renderer/RendererInterface.php @@ -20,4 +20,11 @@ interface RendererInterface { * @return bool */ public function render(): bool; + + /** + * Enqueues common assets required for the admin notice behavior. + * + * @return void + */ + public function enqueue_admin() : void; } diff --git a/modules/ppcp-admin-notices/src/Repository/Repository.php b/modules/ppcp-admin-notices/src/Repository/Repository.php index 9573a81a4..72d88c69c 100644 --- a/modules/ppcp-admin-notices/src/Repository/Repository.php +++ b/modules/ppcp-admin-notices/src/Repository/Repository.php @@ -5,11 +5,12 @@ * @package WooCommerce\PayPalCommerce\AdminNotices\Repository */ -declare(strict_types=1); +declare( strict_types = 1 ); namespace WooCommerce\PayPalCommerce\AdminNotices\Repository; use WooCommerce\PayPalCommerce\AdminNotices\Entity\Message; +use WooCommerce\PayPalCommerce\AdminNotices\Entity\PersistentMessage; /** * Class Repository @@ -20,11 +21,11 @@ class Repository implements RepositoryInterface { const PERSISTED_NOTICES_OPTION = 'woocommerce_ppcp-admin-notices'; /** - * Returns the current messages. + * Returns current messages to display, which excludes muted messages. * * @return Message[] */ - public function current_message(): array { + public function current_message() : array { return array_filter( /** * Returns the list of admin messages. @@ -33,7 +34,11 @@ class Repository implements RepositoryInterface { self::NOTICES_FILTER, array() ), - function( $element ) : bool { + function ( $element ) : bool { + if ( $element instanceof PersistentMessage ) { + return ! $element->is_muted(); + } + return is_a( $element, Message::class ); } ); @@ -43,9 +48,10 @@ class Repository implements RepositoryInterface { * Adds a message to persist between page reloads. * * @param Message $message The message. + * * @return void */ - public function persist( Message $message ): void { + public function persist( Message $message ) : void { $persisted_notices = get_option( self::PERSISTED_NOTICES_OPTION ) ?: array(); $persisted_notices[] = $message->to_array(); @@ -58,20 +64,18 @@ class Repository implements RepositoryInterface { * * @return array|Message[] */ - public function get_persisted_and_clear(): array { + public function get_persisted_and_clear() : array { $notices = array(); $persisted_data = get_option( self::PERSISTED_NOTICES_OPTION ) ?: array(); foreach ( $persisted_data as $notice_data ) { - $notices[] = new Message( - (string) ( $notice_data['message'] ?? '' ), - (string) ( $notice_data['type'] ?? '' ), - (bool) ( $notice_data['dismissable'] ?? true ), - (string) ( $notice_data['wrapper'] ?? '' ) - ); + if ( is_array( $notice_data ) ) { + $notices[] = Message::from_array( $notice_data ); + } } update_option( self::PERSISTED_NOTICES_OPTION, array(), true ); + return $notices; } } diff --git a/modules/ppcp-admin-notices/webpack.config.js b/modules/ppcp-admin-notices/webpack.config.js new file mode 100644 index 000000000..0767f84d3 --- /dev/null +++ b/modules/ppcp-admin-notices/webpack.config.js @@ -0,0 +1,38 @@ +const path = require( 'path' ); +const isProduction = process.env.NODE_ENV === 'production'; + +module.exports = { + devtool: isProduction ? 'source-map' : 'eval-source-map', + mode: isProduction ? 'production' : 'development', + target: 'web', + entry: { + 'boot-admin': path.resolve( './resources/js/boot-admin.js' ), + "styles": path.resolve('./resources/css/styles.scss') + }, + output: { + path: path.resolve( __dirname, 'assets/' ), + filename: 'js/[name].js', + }, + module: { + rules: [ + { + test: /\.js?$/, + exclude: /node_modules/, + loader: 'babel-loader', + }, + { + test: /\.scss$/, + exclude: /node_modules/, + use: [ + { + loader: 'file-loader', + options: { + name: 'css/[name].css', + }, + }, + { loader: 'sass-loader' }, + ], + }, + ], + }, +}; diff --git a/modules/ppcp-admin-notices/yarn.lock b/modules/ppcp-admin-notices/yarn.lock new file mode 100644 index 000000000..9afdf6ab8 --- /dev/null +++ b/modules/ppcp-admin-notices/yarn.lock @@ -0,0 +1,2158 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.2.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@babel/code-frame@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== + dependencies: + "@babel/highlight" "^7.24.7" + picocolors "^1.0.0" + +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.2", "@babel/compat-data@^7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.4.tgz#7d2a80ce229890edcf4cc259d4d696cb4dae2fcb" + integrity sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ== + +"@babel/core@^7.19": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.25.2.tgz#ed8eec275118d7613e77a352894cd12ded8eba77" + integrity sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.25.0" + "@babel/helper-compilation-targets" "^7.25.2" + "@babel/helper-module-transforms" "^7.25.2" + "@babel/helpers" "^7.25.0" + "@babel/parser" "^7.25.0" + "@babel/template" "^7.25.0" + "@babel/traverse" "^7.25.2" + "@babel/types" "^7.25.2" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.25.0", "@babel/generator@^7.25.4": + version "7.25.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.25.5.tgz#b31cf05b3fe8c32d206b6dad03bb0aacbde73450" + integrity sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w== + dependencies: + "@babel/types" "^7.25.4" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab" + integrity sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz#37d66feb012024f2422b762b9b2a7cfe27c7fba3" + integrity sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.24.7", "@babel/helper-compilation-targets@^7.24.8", "@babel/helper-compilation-targets@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz#e1d9410a90974a3a5a66e84ff55ef62e3c02d06c" + integrity sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw== + dependencies: + "@babel/compat-data" "^7.25.2" + "@babel/helper-validator-option" "^7.24.8" + browserslist "^4.23.1" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.24.7", "@babel/helper-create-class-features-plugin@^7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz#57eaf1af38be4224a9d9dd01ddde05b741f50e14" + integrity sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-member-expression-to-functions" "^7.24.8" + "@babel/helper-optimise-call-expression" "^7.24.7" + "@babel/helper-replace-supers" "^7.25.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/traverse" "^7.25.4" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.7", "@babel/helper-create-regexp-features-plugin@^7.25.0", "@babel/helper-create-regexp-features-plugin@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz#24c75974ed74183797ffd5f134169316cd1808d9" + integrity sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + regexpu-core "^5.3.1" + semver "^6.3.1" + +"@babel/helper-define-polyfill-provider@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d" + integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== + dependencies: + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + +"@babel/helper-member-expression-to-functions@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz#6155e079c913357d24a4c20480db7c712a5c3fb6" + integrity sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA== + dependencies: + "@babel/traverse" "^7.24.8" + "@babel/types" "^7.24.8" + +"@babel/helper-module-imports@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" + integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-module-transforms@^7.24.7", "@babel/helper-module-transforms@^7.24.8", "@babel/helper-module-transforms@^7.25.0", "@babel/helper-module-transforms@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz#ee713c29768100f2776edf04d4eb23b8d27a66e6" + integrity sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ== + dependencies: + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" + "@babel/traverse" "^7.25.2" + +"@babel/helper-optimise-call-expression@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz#8b0a0456c92f6b323d27cfd00d1d664e76692a0f" + integrity sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.24.8", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz#94ee67e8ec0e5d44ea7baeb51e571bd26af07878" + integrity sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg== + +"@babel/helper-remap-async-to-generator@^7.24.7", "@babel/helper-remap-async-to-generator@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz#d2f0fbba059a42d68e5e378feaf181ef6055365e" + integrity sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-wrap-function" "^7.25.0" + "@babel/traverse" "^7.25.0" + +"@babel/helper-replace-supers@^7.24.7", "@babel/helper-replace-supers@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz#ff44deac1c9f619523fe2ca1fd650773792000a9" + integrity sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.24.8" + "@babel/helper-optimise-call-expression" "^7.24.7" + "@babel/traverse" "^7.25.0" + +"@babel/helper-simple-access@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" + integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz#5f8fa83b69ed5c27adc56044f8be2b3ea96669d9" + integrity sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-string-parser@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" + integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== + +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + +"@babel/helper-validator-option@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" + integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q== + +"@babel/helper-wrap-function@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz#dab12f0f593d6ca48c0062c28bcfb14ebe812f81" + integrity sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ== + dependencies: + "@babel/template" "^7.25.0" + "@babel/traverse" "^7.25.0" + "@babel/types" "^7.25.0" + +"@babel/helpers@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.25.0.tgz#e69beb7841cb93a6505531ede34f34e6a073650a" + integrity sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw== + dependencies: + "@babel/template" "^7.25.0" + "@babel/types" "^7.25.0" + +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/parser@^7.25.0", "@babel/parser@^7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.4.tgz#af4f2df7d02440286b7de57b1c21acfb2a6f257a" + integrity sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA== + dependencies: + "@babel/types" "^7.25.4" + +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.3": + version "7.25.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz#dca427b45a6c0f5c095a1c639dfe2476a3daba7f" + integrity sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/traverse" "^7.25.3" + +"@babel/plugin-bugfix-safari-class-field-initializer-scope@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz#cd0c583e01369ef51676bdb3d7b603e17d2b3f73" + integrity sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz#749bde80356b295390954643de7635e0dffabe73" + integrity sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz#e4eabdd5109acc399b38d7999b2ef66fc2022f89" + integrity sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.7" + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz#3a82a70e7cb7294ad2559465ebcb871dfbf078fb" + integrity sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/traverse" "^7.25.0" + +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-import-assertions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz#2a0b406b5871a20a841240586b1300ce2088a778" + integrity sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz#b4f9ea95a79e6912480c4b626739f86a076624ca" + integrity sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-meta@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-arrow-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz#4f6886c11e423bd69f3ce51dbf42424a5f275514" + integrity sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-async-generator-functions@^7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz#2afd4e639e2d055776c9f091b6c0c180ed8cf083" + integrity sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-remap-async-to-generator" "^7.25.0" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/traverse" "^7.25.4" + +"@babel/plugin-transform-async-to-generator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz#72a3af6c451d575842a7e9b5a02863414355bdcc" + integrity sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA== + dependencies: + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" + +"@babel/plugin-transform-block-scoped-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz#a4251d98ea0c0f399dafe1a35801eaba455bbf1f" + integrity sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-block-scoping@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz#23a6ed92e6b006d26b1869b1c91d1b917c2ea2ac" + integrity sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-class-properties@^7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz#bae7dbfcdcc2e8667355cd1fb5eda298f05189fd" + integrity sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.25.4" + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-class-static-block@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz#c82027ebb7010bc33c116d4b5044fbbf8c05484d" + integrity sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-transform-classes@^7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz#d29dbb6a72d79f359952ad0b66d88518d65ef89a" + integrity sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-compilation-targets" "^7.25.2" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-replace-supers" "^7.25.0" + "@babel/traverse" "^7.25.4" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz#4cab3214e80bc71fae3853238d13d097b004c707" + integrity sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/template" "^7.24.7" + +"@babel/plugin-transform-destructuring@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz#c828e814dbe42a2718a838c2a2e16a408e055550" + integrity sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-dotall-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz#5f8bf8a680f2116a7207e16288a5f974ad47a7a0" + integrity sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-duplicate-keys@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz#dd20102897c9a2324e5adfffb67ff3610359a8ee" + integrity sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz#809af7e3339466b49c034c683964ee8afb3e2604" + integrity sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.0" + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-dynamic-import@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz#4d8b95e3bae2b037673091aa09cd33fecd6419f4" + integrity sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-transform-exponentiation-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz#b629ee22645f412024297d5245bce425c31f9b0d" + integrity sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-export-namespace-from@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz#176d52d8d8ed516aeae7013ee9556d540c53f197" + integrity sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-transform-for-of@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz#f25b33f72df1d8be76399e1b8f3f9d366eb5bc70" + integrity sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + +"@babel/plugin-transform-function-name@^7.25.1": + version "7.25.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz#b85e773097526c1a4fc4ba27322748643f26fc37" + integrity sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA== + dependencies: + "@babel/helper-compilation-targets" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/traverse" "^7.25.1" + +"@babel/plugin-transform-json-strings@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz#f3e9c37c0a373fee86e36880d45b3664cedaf73a" + integrity sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-transform-literals@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz#deb1ad14fc5490b9a65ed830e025bca849d8b5f3" + integrity sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-logical-assignment-operators@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz#a58fb6eda16c9dc8f9ff1c7b1ba6deb7f4694cb0" + integrity sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-transform-member-expression-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz#3b4454fb0e302e18ba4945ba3246acb1248315df" + integrity sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-modules-amd@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz#65090ed493c4a834976a3ca1cde776e6ccff32d7" + integrity sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg== + dependencies: + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-modules-commonjs@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz#ab6421e564b717cb475d6fff70ae7f103536ea3c" + integrity sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA== + dependencies: + "@babel/helper-module-transforms" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-simple-access" "^7.24.7" + +"@babel/plugin-transform-modules-systemjs@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz#8f46cdc5f9e5af74f3bd019485a6cbe59685ea33" + integrity sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw== + dependencies: + "@babel/helper-module-transforms" "^7.25.0" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" + "@babel/traverse" "^7.25.0" + +"@babel/plugin-transform-modules-umd@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz#edd9f43ec549099620df7df24e7ba13b5c76efc8" + integrity sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A== + dependencies: + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz#9042e9b856bc6b3688c0c2e4060e9e10b1460923" + integrity sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-new-target@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz#31ff54c4e0555cc549d5816e4ab39241dfb6ab00" + integrity sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz#1de4534c590af9596f53d67f52a92f12db984120" + integrity sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-transform-numeric-separator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz#bea62b538c80605d8a0fac9b40f48e97efa7de63" + integrity sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-transform-object-rest-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz#d13a2b93435aeb8a197e115221cab266ba6e55d6" + integrity sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q== + dependencies: + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.24.7" + +"@babel/plugin-transform-object-super@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz#66eeaff7830bba945dd8989b632a40c04ed625be" + integrity sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + +"@babel/plugin-transform-optional-catch-binding@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz#00eabd883d0dd6a60c1c557548785919b6e717b4" + integrity sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-transform-optional-chaining@^7.24.7", "@babel/plugin-transform-optional-chaining@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz#bb02a67b60ff0406085c13d104c99a835cdf365d" + integrity sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz#5881f0ae21018400e320fc7eb817e529d1254b68" + integrity sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-private-methods@^7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz#9bbefbe3649f470d681997e0b64a4b254d877242" + integrity sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.25.4" + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-private-property-in-object@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz#4eec6bc701288c1fab5f72e6a4bbc9d67faca061" + integrity sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-transform-property-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz#f0d2ed8380dfbed949c42d4d790266525d63bbdc" + integrity sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-regenerator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz#021562de4534d8b4b1851759fd7af4e05d2c47f8" + integrity sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + regenerator-transform "^0.15.2" + +"@babel/plugin-transform-reserved-words@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz#80037fe4fbf031fc1125022178ff3938bb3743a4" + integrity sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-shorthand-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz#85448c6b996e122fa9e289746140aaa99da64e73" + integrity sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz#e8a38c0fde7882e0fb8f160378f74bd885cc7bb3" + integrity sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + +"@babel/plugin-transform-sticky-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz#96ae80d7a7e5251f657b5cf18f1ea6bf926f5feb" + integrity sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-template-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz#a05debb4a9072ae8f985bcf77f3f215434c8f8c8" + integrity sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-typeof-symbol@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz#383dab37fb073f5bfe6e60c654caac309f92ba1c" + integrity sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-unicode-escapes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz#2023a82ced1fb4971630a2e079764502c4148e0e" + integrity sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-property-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz#9073a4cd13b86ea71c3264659590ac086605bbcd" + integrity sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz#dfc3d4a51127108099b19817c0963be6a2adf19f" + integrity sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-sets-regex@^7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz#be664c2a0697ffacd3423595d5edef6049e8946c" + integrity sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.2" + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/preset-env@^7.19": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.25.4.tgz#be23043d43a34a2721cd0f676c7ba6f1481f6af6" + integrity sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw== + dependencies: + "@babel/compat-data" "^7.25.4" + "@babel/helper-compilation-targets" "^7.25.2" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-validator-option" "^7.24.8" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.25.3" + "@babel/plugin-bugfix-safari-class-field-initializer-scope" "^7.25.0" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.25.0" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.7" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.25.0" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.24.7" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.24.7" + "@babel/plugin-transform-async-generator-functions" "^7.25.4" + "@babel/plugin-transform-async-to-generator" "^7.24.7" + "@babel/plugin-transform-block-scoped-functions" "^7.24.7" + "@babel/plugin-transform-block-scoping" "^7.25.0" + "@babel/plugin-transform-class-properties" "^7.25.4" + "@babel/plugin-transform-class-static-block" "^7.24.7" + "@babel/plugin-transform-classes" "^7.25.4" + "@babel/plugin-transform-computed-properties" "^7.24.7" + "@babel/plugin-transform-destructuring" "^7.24.8" + "@babel/plugin-transform-dotall-regex" "^7.24.7" + "@babel/plugin-transform-duplicate-keys" "^7.24.7" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex" "^7.25.0" + "@babel/plugin-transform-dynamic-import" "^7.24.7" + "@babel/plugin-transform-exponentiation-operator" "^7.24.7" + "@babel/plugin-transform-export-namespace-from" "^7.24.7" + "@babel/plugin-transform-for-of" "^7.24.7" + "@babel/plugin-transform-function-name" "^7.25.1" + "@babel/plugin-transform-json-strings" "^7.24.7" + "@babel/plugin-transform-literals" "^7.25.2" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.7" + "@babel/plugin-transform-member-expression-literals" "^7.24.7" + "@babel/plugin-transform-modules-amd" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.8" + "@babel/plugin-transform-modules-systemjs" "^7.25.0" + "@babel/plugin-transform-modules-umd" "^7.24.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.7" + "@babel/plugin-transform-new-target" "^7.24.7" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.7" + "@babel/plugin-transform-numeric-separator" "^7.24.7" + "@babel/plugin-transform-object-rest-spread" "^7.24.7" + "@babel/plugin-transform-object-super" "^7.24.7" + "@babel/plugin-transform-optional-catch-binding" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.8" + "@babel/plugin-transform-parameters" "^7.24.7" + "@babel/plugin-transform-private-methods" "^7.25.4" + "@babel/plugin-transform-private-property-in-object" "^7.24.7" + "@babel/plugin-transform-property-literals" "^7.24.7" + "@babel/plugin-transform-regenerator" "^7.24.7" + "@babel/plugin-transform-reserved-words" "^7.24.7" + "@babel/plugin-transform-shorthand-properties" "^7.24.7" + "@babel/plugin-transform-spread" "^7.24.7" + "@babel/plugin-transform-sticky-regex" "^7.24.7" + "@babel/plugin-transform-template-literals" "^7.24.7" + "@babel/plugin-transform-typeof-symbol" "^7.24.8" + "@babel/plugin-transform-unicode-escapes" "^7.24.7" + "@babel/plugin-transform-unicode-property-regex" "^7.24.7" + "@babel/plugin-transform-unicode-regex" "^7.24.7" + "@babel/plugin-transform-unicode-sets-regex" "^7.25.4" + "@babel/preset-modules" "0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.6" + babel-plugin-polyfill-regenerator "^0.6.1" + core-js-compat "^3.37.1" + semver "^6.3.1" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== + +"@babel/runtime@^7.8.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.4.tgz#6ef37d678428306e7d75f054d5b1bdb8cf8aa8ee" + integrity sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.24.7", "@babel/template@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.0.tgz#e733dc3134b4fede528c15bc95e89cb98c52592a" + integrity sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/parser" "^7.25.0" + "@babel/types" "^7.25.0" + +"@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.4.tgz#648678046990f2957407e3086e97044f13c3e18e" + integrity sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.25.4" + "@babel/parser" "^7.25.4" + "@babel/template" "^7.25.0" + "@babel/types" "^7.25.4" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.25.4", "@babel/types@^7.4.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.4.tgz#6bcb46c72fdf1012a209d016c07f769e10adcb5f" + integrity sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ== + dependencies: + "@babel/helper-string-parser" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" + to-fast-properties "^2.0.0" + +"@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@types/estree@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== + +"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/node@*": + version "22.5.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.0.tgz#10f01fe9465166b4cab72e75f60d8b99d019f958" + integrity sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg== + dependencies: + undici-types "~6.19.2" + +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== + +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== + +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== + +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== + +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" + +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" + integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== + +"@webpack-cli/info@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" + integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" + integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== + +acorn@^8.7.1, acorn@^8.8.2: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv@^6.12.4, ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +babel-loader@^8.2: + version "8.3.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.3.0.tgz#124936e841ba4fe8176786d6ff28add1f134d6a8" + integrity sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q== + dependencies: + find-cache-dir "^3.3.1" + loader-utils "^2.0.0" + make-dir "^3.1.0" + schema-utils "^2.6.5" + +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.11" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33" + integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== + dependencies: + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.6.2" + semver "^6.3.1" + +babel-plugin-polyfill-corejs3@^0.10.6: + version "0.10.6" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz#2deda57caef50f59c525aeb4964d3b2f867710c7" + integrity sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.2" + core-js-compat "^3.38.0" + +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz#addc47e240edd1da1058ebda03021f382bba785e" + integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.2" + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browserslist@^4.21.10, browserslist@^4.23.1, browserslist@^4.23.3: + version "4.23.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.3.tgz#debb029d3c93ebc97ffbc8d9cbb03403e227c800" + integrity sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA== + dependencies: + caniuse-lite "^1.0.30001646" + electron-to-chromium "^1.5.4" + node-releases "^2.0.18" + update-browserslist-db "^1.1.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +caniuse-lite@^1.0.30001646: + version "1.0.30001651" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz#52de59529e8b02b1aedcaaf5c05d9e23c0c28138" + integrity sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +"chokidar@>=3.0.0 <4.0.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chrome-trace-event@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +colorette@^2.0.14: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +core-js-compat@^3.37.1, core-js-compat@^3.38.0: + version "3.38.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.38.1.tgz#2bc7a298746ca5a7bcb9c164bcb120f2ebc09a09" + integrity sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw== + dependencies: + browserslist "^4.23.3" + +core-js@^3.25.0: + version "3.38.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.38.1.tgz#aa375b79a286a670388a1a363363d53677c0383e" + integrity sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw== + +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + +cross-spawn@^7.0.1, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: + version "4.3.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" + integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== + dependencies: + ms "2.1.2" + +electron-to-chromium@^1.5.4: + version "1.5.13" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz#1abf0410c5344b2b829b7247e031f02810d442e6" + integrity sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q== + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +enhanced-resolve@^5.17.1: + version "5.17.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" + integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +envinfo@^7.7.3: + version "7.13.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.13.0.tgz#81fbb81e5da35d74e814941aeab7c325a606fb31" + integrity sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q== + +es-module-lexer@^1.2.1: + version "1.5.4" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" + integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== + +escalade@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +file-loader@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-cache-dir@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +graceful-fs@^4.1.2, graceful-fs@^4.2.11, graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +immutable@^4.0.0: + version "4.3.7" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" + integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== + +import-local@^3.0.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.13.0: + version "2.15.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" + integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== + dependencies: + hasown "^2.0.2" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + +json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json5@^2.1.2, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klona@^2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22" + integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA== + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +loader-utils@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" + integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^3.0.2, make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.27: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +picocolors@^1.0.0, picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pkg-dir@^4.1.0, pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +rechoir@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" + integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== + dependencies: + resolve "^1.9.0" + +regenerate-unicode-properties@^10.1.0: + version "10.1.1" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" + integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== + dependencies: + "@babel/runtime" "^7.8.4" + +regexpu-core@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== + dependencies: + "@babel/regjsgen" "^0.8.0" + regenerate "^1.4.2" + regenerate-unicode-properties "^10.1.0" + regjsparser "^0.9.1" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + +regjsparser@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" + integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== + dependencies: + jsesc "~0.5.0" + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve@^1.14.2, resolve@^1.9.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +sass-loader@^12.1.0: + version "12.6.0" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.6.0.tgz#5148362c8e2cdd4b950f3c63ac5d16dbfed37bcb" + integrity sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA== + dependencies: + klona "^2.0.4" + neo-async "^2.6.2" + +sass@^1.42.1: + version "1.77.8" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.8.tgz#9f18b449ea401759ef7ec1752a16373e296b52bd" + integrity sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + +schema-utils@^2.6.5: + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== + dependencies: + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" + +schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +semver@^6.0.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +"source-map-js@>=0.6.2 <2.0.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +terser-webpack-plugin@^5.3.10: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.20" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" + +terser@^5.26.0: + version "5.31.6" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.6.tgz#c63858a0f0703988d0266a82fcbf2d7ba76422b1" + integrity sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" + integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== + +update-browserslist-db@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== + dependencies: + escalade "^3.1.2" + picocolors "^1.0.1" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +watchpack@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da" + integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +webpack-cli@^4.10: + version "4.10.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" + integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.2.0" + "@webpack-cli/info" "^1.5.0" + "@webpack-cli/serve" "^1.7.0" + colorette "^2.0.14" + commander "^7.0.0" + cross-spawn "^7.0.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + webpack-merge "^5.7.3" + +webpack-merge@^5.7.3: + version "5.10.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" + integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== + dependencies: + clone-deep "^4.0.1" + flat "^5.0.2" + wildcard "^2.0.0" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@^5.76: + version "5.94.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.94.0.tgz#77a6089c716e7ab90c1c67574a28da518a20970f" + integrity sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg== + dependencies: + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" + acorn "^8.7.1" + acorn-import-attributes "^1.9.5" + browserslist "^4.21.10" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.17.1" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.11" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.2.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" + webpack-sources "^3.2.3" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== diff --git a/modules/ppcp-api-client/src/Endpoint/Orders.php b/modules/ppcp-api-client/src/Endpoint/Orders.php index 568a16705..4ba5b71a1 100644 --- a/modules/ppcp-api-client/src/Endpoint/Orders.php +++ b/modules/ppcp-api-client/src/Endpoint/Orders.php @@ -96,9 +96,107 @@ class Orders { } $status_code = (int) wp_remote_retrieve_response_code( $response ); - if ( $status_code !== 200 ) { + if ( ! in_array( $status_code, array( 200, 201 ), true ) ) { + $body = json_decode( $response['body'] ); + + $message = $body->details[0]->description ?? ''; + if ( $message ) { + throw new RuntimeException( $message ); + } + throw new PayPalApiException( - json_decode( $response['body'] ), + $body, + $status_code + ); + } + + return $response; + } + + /** + * Confirms the given order. + * + * @link https://developer.paypal.com/docs/api/orders/v2/#orders_confirm + * + * @param array $request_body The request body. + * @param string $id PayPal order ID. + * @return array + * @throws RuntimeException If something went wrong with the request. + * @throws PayPalApiException If something went wrong with the PayPal API request. + */ + public function confirm_payment_source( array $request_body, string $id ): array { + $bearer = $this->bearer->bearer(); + $url = trailingslashit( $this->host ) . 'v2/checkout/orders/' . $id . '/confirm-payment-source'; + + $args = array( + 'method' => 'POST', + 'headers' => array( + 'Authorization' => 'Bearer ' . $bearer->token(), + 'Content-Type' => 'application/json', + 'PayPal-Request-Id' => uniqid( 'ppcp-', true ), + ), + 'body' => wp_json_encode( $request_body ), + ); + + $response = $this->request( $url, $args ); + if ( $response instanceof WP_Error ) { + throw new RuntimeException( $response->get_error_message() ); + } + + $status_code = (int) wp_remote_retrieve_response_code( $response ); + if ( $status_code !== 200 ) { + $body = json_decode( $response['body'] ); + + $message = $body->details[0]->description ?? ''; + if ( $message ) { + throw new RuntimeException( $message ); + } + + throw new PayPalApiException( + $body, + $status_code + ); + } + + return $response; + } + + /** + * Get PayPal order by id. + * + * @param string $id PayPal order ID. + * @return array + * @throws RuntimeException If something went wrong with the request. + * @throws PayPalApiException If something went wrong with the PayPal API request. + */ + public function order( string $id ): array { + $bearer = $this->bearer->bearer(); + $url = trailingslashit( $this->host ) . 'v2/checkout/orders/' . $id; + + $args = array( + 'headers' => array( + 'Authorization' => 'Bearer ' . $bearer->token(), + 'Content-Type' => 'application/json', + 'PayPal-Request-Id' => uniqid( 'ppcp-', true ), + ), + ); + + $response = $this->request( $url, $args ); + if ( $response instanceof WP_Error ) { + throw new RuntimeException( $response->get_error_message() ); + } + + $status_code = (int) wp_remote_retrieve_response_code( $response ); + if ( $status_code !== 200 ) { + $body = json_decode( $response['body'] ); + + $message = $body->details[0]->description ?? ''; + if ( $message ) { + throw new RuntimeException( $message ); + } + + throw new PayPalApiException( + $body, $status_code ); } diff --git a/modules/ppcp-applepay/resources/js/ApplepayButton.js b/modules/ppcp-applepay/resources/js/ApplepayButton.js index 83b0a95b5..1c77a5c45 100644 --- a/modules/ppcp-applepay/resources/js/ApplepayButton.js +++ b/modules/ppcp-applepay/resources/js/ApplepayButton.js @@ -339,6 +339,12 @@ class ApplePayButton { this.#isInitialized = true; this.applePayConfig = config; + if ( this.isSeparateGateway ) { + document + .querySelectorAll( '#ppc-button-applepay-container' ) + .forEach( ( el ) => el.remove() ); + } + if ( ! this.isEligible ) { this.hide(); } else { diff --git a/modules/ppcp-applepay/services.php b/modules/ppcp-applepay/services.php index 76de2150d..1956d1ee0 100644 --- a/modules/ppcp-applepay/services.php +++ b/modules/ppcp-applepay/services.php @@ -299,14 +299,15 @@ return array( esc_html( $button_text ) ); }, - 'applepay.wc-gateway' => static function ( ContainerInterface $container ): ApplePayGateway { + 'applepay.wc-gateway' => static function ( ContainerInterface $container ): ApplePayGateway { return new ApplePayGateway( $container->get( 'wcgateway.order-processor' ), $container->get( 'api.factory.paypal-checkout-url' ), $container->get( 'wcgateway.processor.refunds' ), $container->get( 'wcgateway.transaction-url-provider' ), $container->get( 'session.handler' ), - $container->get( 'applepay.url' ) + $container->get( 'applepay.url' ), + $container->get( 'woocommerce.logger.woocommerce' ) ); }, diff --git a/modules/ppcp-applepay/src/ApplePayGateway.php b/modules/ppcp-applepay/src/ApplePayGateway.php index 1cccda0f2..7c87258f9 100644 --- a/modules/ppcp-applepay/src/ApplePayGateway.php +++ b/modules/ppcp-applepay/src/ApplePayGateway.php @@ -10,6 +10,7 @@ declare( strict_types = 1 ); namespace WooCommerce\PayPalCommerce\Applepay; use Exception; +use Psr\Log\LoggerInterface; use WC_Order; use WC_Payment_Gateway; use WooCommerce\PayPalCommerce\Session\SessionHandler; @@ -72,6 +73,13 @@ class ApplePayGateway extends WC_Payment_Gateway { */ private $module_url; + /** + * The logger. + * + * @var LoggerInterface + */ + private $logger; + /** * ApplePayGateway constructor. * @@ -84,6 +92,7 @@ class ApplePayGateway extends WC_Payment_Gateway { * view URL based on order. * @param SessionHandler $session_handler The Session Handler. * @param string $module_url The URL to the module. + * @param LoggerInterface $logger The logger. */ public function __construct( OrderProcessor $order_processor, @@ -91,7 +100,8 @@ class ApplePayGateway extends WC_Payment_Gateway { RefundProcessor $refund_processor, TransactionUrlProvider $transaction_url_provider, SessionHandler $session_handler, - string $module_url + string $module_url, + LoggerInterface $logger ) { $this->id = self::ID; @@ -111,6 +121,7 @@ class ApplePayGateway extends WC_Payment_Gateway { $this->refund_processor = $refund_processor; $this->transaction_url_provider = $transaction_url_provider; $this->session_handler = $session_handler; + $this->logger = $logger; add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, diff --git a/modules/ppcp-axo/src/AxoModule.php b/modules/ppcp-axo/src/AxoModule.php index 9b5a6985d..e0398e506 100644 --- a/modules/ppcp-axo/src/AxoModule.php +++ b/modules/ppcp-axo/src/AxoModule.php @@ -78,7 +78,7 @@ class AxoModule implements ModuleInterface { assert( $settings instanceof Settings ); $is_paypal_enabled = $settings->has( 'enabled' ) && $settings->get( 'enabled' ) ?? false; - $is_dcc_enabled = $settings->has( 'dcc_enabled' ) && $settings->get( 'dcc_enabled' ) ?? false; + $is_dcc_enabled = $settings->has( 'dcc_enabled' ) && $settings->get( 'dcc_enabled' ) ?? false; if ( ! $is_paypal_enabled || ! $is_dcc_enabled ) { return $methods; diff --git a/modules/ppcp-button/resources/js/modules/Renderer/PaymentButton.js b/modules/ppcp-button/resources/js/modules/Renderer/PaymentButton.js index 11fe31f79..8da7b6e24 100644 --- a/modules/ppcp-button/resources/js/modules/Renderer/PaymentButton.js +++ b/modules/ppcp-button/resources/js/modules/Renderer/PaymentButton.js @@ -113,6 +113,13 @@ export default class PaymentButton { */ #isInitialized = false; + /** + * Whether the one-time initialization of the payment gateway is complete. + * + * @type {boolean} + */ + #gatewayInitialized = false; + /** * The button's context. * @@ -437,6 +444,17 @@ export default class PaymentButton { return this.wrappers.Default; } + /** + * Whether the button is placed inside a classic gateway context. + * + * Classic gateway contexts are: Classic checkout, Pay for Order page. + * + * @return {boolean} True indicates, the button is located inside a classic gateway. + */ + get isInsideClassicGateway() { + return PaymentContext.Gateways.includes( this.context ); + } + /** * Determines if the current payment button should be rendered as a stand-alone gateway. * The return value `false` usually means, that the payment button is bundled with all available @@ -449,20 +467,21 @@ export default class PaymentButton { get isSeparateGateway() { return ( this.#buttonConfig.is_wc_gateway_enabled && - PaymentContext.Gateways.includes( this.context ) + this.isInsideClassicGateway ); } /** * Whether the currently selected payment gateway is set to the payment method. * - * Only relevant on checkout pages, when `this.isSeparateGateway` is true. + * Only relevant on checkout pages where "classic" payment gateways are rendered. * * @return {boolean} True means that this payment method is selected as current gateway. */ get isCurrentGateway() { - if ( ! this.isSeparateGateway ) { - return false; + if ( ! this.isInsideClassicGateway ) { + // This means, the button's visibility is managed by another script. + return true; } /* @@ -470,7 +489,14 @@ export default class PaymentButton { * module fires the "ButtonEvents.RENDER" event before any PaymentButton instances are * created. I.e. we cannot observe the initial gateway selection event. */ - return this.methodId === getCurrentPaymentMethod(); + const currentMethod = getCurrentPaymentMethod(); + + if ( this.isSeparateGateway ) { + return this.methodId === currentMethod; + } + + // Button is rendered inside the Smart Buttons block. + return PaymentMethods.PAYPAL === currentMethod; } /** @@ -673,7 +699,7 @@ export default class PaymentButton { } ); // Events relevant for buttons inside a payment gateway. - if ( PaymentContext.Gateways.includes( this.context ) ) { + if ( this.isInsideClassicGateway ) { const parentMethod = this.isSeparateGateway ? this.methodId : PaymentMethods.PAYPAL; @@ -703,7 +729,7 @@ export default class PaymentButton { this.applyWrapperStyles(); - if ( this.isEligible && this.isPresent && this.isVisible ) { + if ( this.isEligible && this.isCurrentGateway && this.isVisible ) { if ( ! this.isButtonAttached ) { this.log( 'refresh.addButton' ); this.addButton(); @@ -712,25 +738,33 @@ export default class PaymentButton { } /** - * Makes the custom payment gateway visible by removing initial inline styles from the DOM. + * Makes the payment gateway visible by removing initial inline styles from the DOM. + * Also, removes the button-placeholder container from the smart button block. * * Only relevant on the checkout page, i.e., when `this.isSeparateGateway` is `true` */ showPaymentGateway() { - if ( ! this.isSeparateGateway || ! this.isEligible ) { + if ( + this.#gatewayInitialized || + ! this.isSeparateGateway || + ! this.isEligible + ) { return; } - const styleSelectors = `style[data-hide-gateway="${ this.methodId }"]`; + const styleSelector = `style[data-hide-gateway="${ this.methodId }"]`; + const wrapperSelector = `#${ this.wrappers.Default }`; - const styles = document.querySelectorAll( styleSelectors ); + document + .querySelectorAll( styleSelector ) + .forEach( ( el ) => el.remove() ); + + document + .querySelectorAll( wrapperSelector ) + .forEach( ( el ) => el.remove() ); - if ( ! styles.length ) { - return; - } this.log( 'Show gateway' ); - - styles.forEach( ( el ) => el.remove() ); + this.#gatewayInitialized = true; // This code runs only once, during button initialization, and fixes the initial visibility. this.isVisible = this.isCurrentGateway; diff --git a/modules/ppcp-googlepay/services.php b/modules/ppcp-googlepay/services.php index 110b56937..fb64b2626 100644 --- a/modules/ppcp-googlepay/services.php +++ b/modules/ppcp-googlepay/services.php @@ -267,7 +267,8 @@ return array( $container->get( 'wcgateway.processor.refunds' ), $container->get( 'wcgateway.transaction-url-provider' ), $container->get( 'session.handler' ), - $container->get( 'googlepay.url' ) + $container->get( 'googlepay.url' ), + $container->get( 'woocommerce.logger.woocommerce' ) ); }, ); diff --git a/modules/ppcp-googlepay/src/GooglePayGateway.php b/modules/ppcp-googlepay/src/GooglePayGateway.php index 235a67a85..cef3916d9 100644 --- a/modules/ppcp-googlepay/src/GooglePayGateway.php +++ b/modules/ppcp-googlepay/src/GooglePayGateway.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Googlepay; use Exception; +use Psr\Log\LoggerInterface; use WC_Order; use WC_Payment_Gateway; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; @@ -72,6 +73,13 @@ class GooglePayGateway extends WC_Payment_Gateway { */ private $module_url; + /** + * The logger. + * + * @var LoggerInterface + */ + private $logger; + /** * GooglePayGateway constructor. * @@ -81,6 +89,7 @@ class GooglePayGateway extends WC_Payment_Gateway { * @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order. * @param SessionHandler $session_handler The Session Handler. * @param string $module_url The URL to the module. + * @param LoggerInterface $logger The logger. */ public function __construct( OrderProcessor $order_processor, @@ -88,7 +97,8 @@ class GooglePayGateway extends WC_Payment_Gateway { RefundProcessor $refund_processor, TransactionUrlProvider $transaction_url_provider, SessionHandler $session_handler, - string $module_url + string $module_url, + LoggerInterface $logger ) { $this->id = self::ID; @@ -113,6 +123,7 @@ class GooglePayGateway extends WC_Payment_Gateway { $this->refund_processor = $refund_processor; $this->transaction_url_provider = $transaction_url_provider; $this->session_handler = $session_handler; + $this->logger = $logger; add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/multibanco-payment-method.js b/modules/ppcp-local-alternative-payment-methods/resources/js/multibanco-payment-method.js new file mode 100644 index 000000000..d09f7fd24 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/multibanco-payment-method.js @@ -0,0 +1,18 @@ +import { registerPaymentMethod } from '@woocommerce/blocks-registry'; +import { APM } from './apm-block'; + +const config = wc.wcSettings.getSetting( 'ppcp-multibanco_data' ); + +registerPaymentMethod( { + name: config.id, + label:
, + content: , + edit:
, + ariaLabel: config.title, + canMakePayment: () => { + return true; + }, + supports: { + features: config.supports, + }, +} ); diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index 74796c712..c0a66c11e 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -60,6 +60,11 @@ return array( 'countries' => array( 'AT', 'DE', 'DK', 'EE', 'ES', 'FI', 'GB', 'LT', 'LV', 'NL', 'NO', 'SE' ), 'currencies' => array( 'EUR', 'DKK', 'SEK', 'GBP', 'NOK' ), ), + 'multibanco' => array( + 'id' => MultibancoGateway::ID, + 'countries' => array( 'PT' ), + 'currencies' => array( 'EUR' ), + ), ); }, 'ppcp-local-apms.bancontact.wc-gateway' => static function ( ContainerInterface $container ): BancontactGateway { @@ -118,6 +123,14 @@ return array( $container->get( 'wcgateway.transaction-url-provider' ) ); }, + 'ppcp-local-apms.multibanco.wc-gateway' => static function ( ContainerInterface $container ): MultibancoGateway { + return new MultibancoGateway( + $container->get( 'api.endpoint.orders' ), + $container->get( 'api.factory.purchase-unit' ), + $container->get( 'wcgateway.processor.refunds' ), + $container->get( 'wcgateway.transaction-url-provider' ) + ); + }, 'ppcp-local-apms.bancontact.payment-method' => static function( ContainerInterface $container ): BancontactPaymentMethod { return new BancontactPaymentMethod( $container->get( 'ppcp-local-apms.url' ), @@ -167,4 +180,11 @@ return array( $container->get( 'ppcp-local-apms.trustly.wc-gateway' ) ); }, + 'ppcp-local-apms.multibanco.payment-method' => static function( ContainerInterface $container ): MultibancoPaymentMethod { + return new MultibancoPaymentMethod( + $container->get( 'ppcp-local-apms.url' ), + $container->get( 'ppcp.asset-version' ), + $container->get( 'ppcp-local-apms.multibanco.wc-gateway' ) + ); + }, ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php index c37be41ec..54204d12d 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php @@ -13,6 +13,7 @@ use WC_Payment_Gateway; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor; @@ -72,7 +73,7 @@ class BancontactGateway extends WC_Payment_Gateway { 'products', ); - $this->method_title = __( 'Bancontact', 'woocommerce-paypal-payments' ); + $this->method_title = __( 'Bancontact (via PayPal)', 'woocommerce-paypal-payments' ); $this->method_description = __( 'A popular and trusted electronic payment method in Belgium, used by Belgian customers with Bancontact cards issued by local banks. Transactions are processed in EUR.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'Bancontact', 'woocommerce-paypal-payments' ) ); @@ -177,6 +178,9 @@ class BancontactGateway extends WC_Payment_Gateway { $body = json_decode( $response['body'] ); + $wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $body->id ); + $wc_order->save_meta_data(); + $payer_action = ''; foreach ( $body->links as $link ) { if ( $link->rel === 'payer-action' ) { diff --git a/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php index d26285df7..94b6cba48 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php @@ -91,7 +91,7 @@ class BancontactPaymentMethod extends AbstractPaymentMethodType { 'id' => $this->name, 'title' => $this->gateway->title, 'description' => $this->gateway->description, - 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_bancontact_color.svg' ), + 'icon' => 'bancontact', ); } } diff --git a/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php b/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php index ec49df338..1538f3f83 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php @@ -13,6 +13,7 @@ use WC_Payment_Gateway; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor; @@ -72,7 +73,7 @@ class BlikGateway extends WC_Payment_Gateway { 'products', ); - $this->method_title = __( 'Blik', 'woocommerce-paypal-payments' ); + $this->method_title = __( 'Blik (via PayPal)', 'woocommerce-paypal-payments' ); $this->method_description = __( 'A widely used mobile payment method in Poland, allowing Polish customers to pay directly via their banking apps. Transactions are processed in PLN.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'Blik', 'woocommerce-paypal-payments' ) ); @@ -178,6 +179,9 @@ class BlikGateway extends WC_Payment_Gateway { $body = json_decode( $response['body'] ); + $wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $body->id ); + $wc_order->save_meta_data(); + $payer_action = ''; foreach ( $body->links as $link ) { if ( $link->rel === 'payer-action' ) { diff --git a/modules/ppcp-local-alternative-payment-methods/src/BlikPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/BlikPaymentMethod.php index 073df2de0..de68baa85 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BlikPaymentMethod.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BlikPaymentMethod.php @@ -91,7 +91,7 @@ class BlikPaymentMethod extends AbstractPaymentMethodType { 'id' => $this->name, 'title' => $this->gateway->title, 'description' => $this->gateway->description, - 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_blik_color.svg' ), + 'icon' => 'blik', ); } } diff --git a/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php b/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php index 4bc74985f..a52674130 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php @@ -13,6 +13,7 @@ use WC_Payment_Gateway; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor; @@ -72,7 +73,7 @@ class EPSGateway extends WC_Payment_Gateway { 'products', ); - $this->method_title = __( 'EPS', 'woocommerce-paypal-payments' ); + $this->method_title = __( 'EPS (via PayPal)', 'woocommerce-paypal-payments' ); $this->method_description = __( 'An online payment method in Austria, enabling Austrian buyers to make secure payments directly through their bank accounts. Transactions are processed in EUR.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'EPS', 'woocommerce-paypal-payments' ) ); @@ -177,6 +178,9 @@ class EPSGateway extends WC_Payment_Gateway { $body = json_decode( $response['body'] ); + $wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $body->id ); + $wc_order->save_meta_data(); + $payer_action = ''; foreach ( $body->links as $link ) { if ( $link->rel === 'payer-action' ) { diff --git a/modules/ppcp-local-alternative-payment-methods/src/EPSPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/EPSPaymentMethod.php index c00abdb7d..4848acf03 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/EPSPaymentMethod.php +++ b/modules/ppcp-local-alternative-payment-methods/src/EPSPaymentMethod.php @@ -91,7 +91,7 @@ class EPSPaymentMethod extends AbstractPaymentMethodType { 'id' => $this->name, 'title' => $this->gateway->title, 'description' => $this->gateway->description, - 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_eps_color.svg' ), + 'icon' => 'eps', ); } } diff --git a/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php b/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php index 7c1d65436..b799527a5 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php @@ -13,6 +13,7 @@ use WC_Payment_Gateway; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor; @@ -72,7 +73,7 @@ class IDealGateway extends WC_Payment_Gateway { 'products', ); - $this->method_title = __( 'iDeal', 'woocommerce-paypal-payments' ); + $this->method_title = __( 'iDeal (via PayPal)', 'woocommerce-paypal-payments' ); $this->method_description = __( 'The most common payment method in the Netherlands, allowing Dutch buyers to pay directly through their preferred bank. Transactions are processed in EUR.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'iDeal', 'woocommerce-paypal-payments' ) ); @@ -134,16 +135,13 @@ class IDealGateway extends WC_Payment_Gateway { $purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order ); $amount = $purchase_unit->amount()->to_array(); - $payment_source = array( - 'country_code' => $wc_order->get_billing_country(), - 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), - ); - // TODO get "bic" from gateway settings. - $request_body = array( 'intent' => 'CAPTURE', 'payment_source' => array( - 'ideal' => $payment_source, + 'ideal' => array( + 'country_code' => $wc_order->get_billing_country(), + 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), + ), ), 'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL', 'purchase_units' => array( @@ -179,6 +177,9 @@ class IDealGateway extends WC_Payment_Gateway { $body = json_decode( $response['body'] ); + $wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $body->id ); + $wc_order->save_meta_data(); + $payer_action = ''; foreach ( $body->links as $link ) { if ( $link->rel === 'payer-action' ) { diff --git a/modules/ppcp-local-alternative-payment-methods/src/IDealPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/IDealPaymentMethod.php index 7f40e90f9..03a9c02f4 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/IDealPaymentMethod.php +++ b/modules/ppcp-local-alternative-payment-methods/src/IDealPaymentMethod.php @@ -91,7 +91,7 @@ class IDealPaymentMethod extends AbstractPaymentMethodType { 'id' => $this->name, 'title' => $this->gateway->title, 'description' => $this->gateway->description, - 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_ideal_color.svg' ), + 'icon' => 'ideal', ); } } diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index 88edf6b31..5dda3b818 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -15,6 +15,8 @@ use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; +use WooCommerce\PayPalCommerce\WcGateway\Helper\FeesUpdater; +use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; /** * Class LocalAlternativePaymentMethodsModule @@ -35,6 +37,13 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { * {@inheritDoc} */ public function run( ContainerInterface $c ): void { + $settings = $c->get( 'wcgateway.settings' ); + assert( $settings instanceof Settings ); + + if ( ! $settings->has( 'allow_local_apm_gateways' ) || $settings->get( 'allow_local_apm_gateways' ) !== true ) { + return; + } + add_filter( 'woocommerce_payment_gateways', /** @@ -150,6 +159,37 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { } } ); + + add_action( + 'woocommerce_paypal_payments_payment_capture_completed_webhook_handler', + function( WC_Order $wc_order, string $order_id ) use ( $c ) { + $payment_methods = $c->get( 'ppcp-local-apms.payment-methods' ); + if ( + ! $this->is_local_apm( $wc_order->get_payment_method(), $payment_methods ) + ) { + return; + } + + $fees_updater = $c->get( 'wcgateway.helper.fees-updater' ); + assert( $fees_updater instanceof FeesUpdater ); + + $fees_updater->update( $order_id, $wc_order ); + }, + 10, + 2 + ); + + add_filter( + 'woocommerce_paypal_payments_allowed_refund_payment_methods', + function( array $payment_methods ) use ( $c ): array { + $local_payment_methods = $c->get( 'ppcp-local-apms.payment-methods' ); + foreach ( $local_payment_methods as $payment_method ) { + $payment_methods[] = $payment_method['id']; + } + + return $payment_methods; + } + ); } /** diff --git a/modules/ppcp-local-alternative-payment-methods/src/MultibancoGateway.php b/modules/ppcp-local-alternative-payment-methods/src/MultibancoGateway.php new file mode 100644 index 000000000..264e208a4 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/MultibancoGateway.php @@ -0,0 +1,236 @@ +id = self::ID; + + $this->supports = array( + 'refunds', + 'products', + ); + + $this->method_title = __( 'Multibanco (via PayPal)', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'An online payment method in Portugal, enabling Portuguese buyers to make secure payments directly through their bank accounts. Transactions are processed in EUR.', 'woocommerce-paypal-payments' ); + + $this->title = $this->get_option( 'title', __( 'Multibanco', 'woocommerce-paypal-payments' ) ); + $this->description = $this->get_option( 'description', '' ); + + $this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_multibanco_color.svg' ); + + $this->init_form_fields(); + $this->init_settings(); + + add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); + + $this->orders_endpoint = $orders_endpoint; + $this->purchase_unit_factory = $purchase_unit_factory; + $this->refund_processor = $refund_processor; + $this->transaction_url_provider = $transaction_url_provider; + } + + /** + * Initialize the form fields. + */ + public function init_form_fields() { + $this->form_fields = array( + 'enabled' => array( + 'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'label' => __( 'Multibanco', 'woocommerce-paypal-payments' ), + 'default' => 'no', + 'desc_tip' => true, + 'description' => __( 'Enable/Disable Multibanco payment gateway.', 'woocommerce-paypal-payments' ), + ), + 'title' => array( + 'title' => __( 'Title', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->title, + 'desc_tip' => true, + 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + 'description' => array( + 'title' => __( 'Description', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->description, + 'desc_tip' => true, + 'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + ); + } + + /** + * Processes the order. + * + * @param int $order_id The WC order ID. + * @return array + */ + public function process_payment( $order_id ) { + $wc_order = wc_get_order( $order_id ); + $wc_order->update_status( 'pending', __( 'Awaiting for the buyer to complete the payment.', 'woocommerce-paypal-payments' ) ); + + $purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order ); + $amount = $purchase_unit->amount()->to_array(); + + $request_body = array( + 'intent' => 'CAPTURE', + 'purchase_units' => array( + array( + 'reference_id' => $purchase_unit->reference_id(), + 'amount' => array( + 'currency_code' => $amount['currency_code'], + 'value' => $amount['value'], + ), + 'custom_id' => $purchase_unit->custom_id(), + 'invoice_id' => $purchase_unit->invoice_id(), + ), + ), + ); + + try { + $response = $this->orders_endpoint->create( $request_body ); + $body = json_decode( $response['body'] ); + + $request_body = array( + 'payment_source' => array( + 'multibanco' => array( + 'country_code' => $wc_order->get_billing_country(), + 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), + ), + ), + 'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL', + 'application_context' => array( + 'locale' => 'en-PT', + 'return_url' => $this->get_return_url( $wc_order ), + 'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ), + ), + ); + + $response = $this->orders_endpoint->confirm_payment_source( $request_body, $body->id ); + $body = json_decode( $response['body'] ); + + $payer_action = ''; + foreach ( $body->links as $link ) { + if ( $link->rel === 'payer-action' ) { + $payer_action = $link->href; + } + } + + WC()->cart->empty_cart(); + + $wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $body->id ); + $wc_order->save_meta_data(); + + return array( + 'result' => 'success', + 'redirect' => esc_url( $payer_action ), + ); + + } catch ( RuntimeException $exception ) { + $wc_order->update_status( + 'failed', + $exception->getMessage() + ); + + return array( + 'result' => 'failure', + 'redirect' => wc_get_checkout_url(), + ); + } + } + + /** + * Process refund. + * + * If the gateway declares 'refunds' support, this will allow it to refund. + * a passed in amount. + * + * @param int $order_id Order ID. + * @param float $amount Refund amount. + * @param string $reason Refund reason. + * @return boolean True or false based on success, or a WP_Error object. + */ + public function process_refund( $order_id, $amount = null, $reason = '' ) { + $order = wc_get_order( $order_id ); + if ( ! is_a( $order, \WC_Order::class ) ) { + return false; + } + return $this->refund_processor->process( $order, (float) $amount, (string) $reason ); + } + + /** + * Return transaction url for this gateway and given order. + * + * @param \WC_Order $order WC order to get transaction url by. + * + * @return string + */ + public function get_transaction_url( $order ): string { + $this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order ); + + return parent::get_transaction_url( $order ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/src/MultibancoPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/MultibancoPaymentMethod.php new file mode 100644 index 000000000..556badc3f --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/MultibancoPaymentMethod.php @@ -0,0 +1,97 @@ +module_url = $module_url; + $this->version = $version; + $this->gateway = $gateway; + + $this->name = MultibancoGateway::ID; + } + + /** + * {@inheritDoc} + */ + public function initialize() {} + + /** + * {@inheritDoc} + */ + public function is_active() { + return true; + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_script_handles() { + wp_register_script( + 'ppcp-multibanco-payment-method', + trailingslashit( $this->module_url ) . 'assets/js/multibanco-payment-method.js', + array(), + $this->version, + true + ); + + return array( 'ppcp-multibanco-payment-method' ); + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_data() { + return array( + 'id' => $this->name, + 'title' => $this->gateway->title, + 'description' => $this->gateway->description, + 'icon' => 'multibanco', + ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php b/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php index ec33430b8..710e4d5b8 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php @@ -13,6 +13,7 @@ use WC_Payment_Gateway; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor; @@ -72,7 +73,7 @@ class MyBankGateway extends WC_Payment_Gateway { 'products', ); - $this->method_title = __( 'MyBank', 'woocommerce-paypal-payments' ); + $this->method_title = __( 'MyBank (via PayPal)', 'woocommerce-paypal-payments' ); $this->method_description = __( 'A European online banking payment solution primarily used in Italy, enabling customers to make secure bank transfers during checkout. Transactions are processed in EUR.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'MyBank', 'woocommerce-paypal-payments' ) ); @@ -177,6 +178,9 @@ class MyBankGateway extends WC_Payment_Gateway { $body = json_decode( $response['body'] ); + $wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $body->id ); + $wc_order->save_meta_data(); + $payer_action = ''; foreach ( $body->links as $link ) { if ( $link->rel === 'payer-action' ) { diff --git a/modules/ppcp-local-alternative-payment-methods/src/MyBankPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/MyBankPaymentMethod.php index 132f918ac..b3bb2d515 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/MyBankPaymentMethod.php +++ b/modules/ppcp-local-alternative-payment-methods/src/MyBankPaymentMethod.php @@ -91,7 +91,7 @@ class MyBankPaymentMethod extends AbstractPaymentMethodType { 'id' => $this->name, 'title' => $this->gateway->title, 'description' => $this->gateway->description, - 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_mybank_color.svg' ), + 'icon' => 'mybank', ); } } diff --git a/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php b/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php index 97e23f7c0..65151c31f 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php @@ -13,6 +13,7 @@ use WC_Payment_Gateway; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor; @@ -72,7 +73,7 @@ class P24Gateway extends WC_Payment_Gateway { 'products', ); - $this->method_title = __( 'Przelewy24', 'woocommerce-paypal-payments' ); + $this->method_title = __( 'Przelewy24 (via PayPal)', 'woocommerce-paypal-payments' ); $this->method_description = __( 'A popular online payment gateway in Poland, offering various payment options for Polish customers. Transactions can be processed in PLN or EUR.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'Przelewy24', 'woocommerce-paypal-payments' ) ); @@ -178,6 +179,9 @@ class P24Gateway extends WC_Payment_Gateway { $body = json_decode( $response['body'] ); + $wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $body->id ); + $wc_order->save_meta_data(); + $payer_action = ''; foreach ( $body->links as $link ) { if ( $link->rel === 'payer-action' ) { diff --git a/modules/ppcp-local-alternative-payment-methods/src/P24PaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/P24PaymentMethod.php index d9fe2b3b8..4cb89b393 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/P24PaymentMethod.php +++ b/modules/ppcp-local-alternative-payment-methods/src/P24PaymentMethod.php @@ -91,7 +91,7 @@ class P24PaymentMethod extends AbstractPaymentMethodType { 'id' => $this->name, 'title' => $this->gateway->title, 'description' => $this->gateway->description, - 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_przelewy24_color.svg' ), + 'icon' => 'p24', ); } } diff --git a/modules/ppcp-local-alternative-payment-methods/src/TrustlyGateway.php b/modules/ppcp-local-alternative-payment-methods/src/TrustlyGateway.php index 7d34e02d7..0bc4e7e19 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/TrustlyGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/TrustlyGateway.php @@ -13,6 +13,7 @@ use WC_Payment_Gateway; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor; @@ -72,7 +73,7 @@ class TrustlyGateway extends WC_Payment_Gateway { 'products', ); - $this->method_title = __( 'Trustly', 'woocommerce-paypal-payments' ); + $this->method_title = __( 'Trustly (via PayPal)', 'woocommerce-paypal-payments' ); $this->method_description = __( 'A European payment method that allows buyers to make payments directly from their bank accounts, suitable for customers across multiple European countries. Supported currencies include EUR, DKK, SEK, GBP, and NOK.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'Trustly', 'woocommerce-paypal-payments' ) ); @@ -177,6 +178,9 @@ class TrustlyGateway extends WC_Payment_Gateway { $body = json_decode( $response['body'] ); + $wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $body->id ); + $wc_order->save_meta_data(); + $payer_action = ''; foreach ( $body->links as $link ) { if ( $link->rel === 'payer-action' ) { diff --git a/modules/ppcp-local-alternative-payment-methods/src/TrustlyPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/TrustlyPaymentMethod.php index 87ba625a2..c7a501cf0 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/TrustlyPaymentMethod.php +++ b/modules/ppcp-local-alternative-payment-methods/src/TrustlyPaymentMethod.php @@ -91,7 +91,7 @@ class TrustlyPaymentMethod extends AbstractPaymentMethodType { 'id' => $this->name, 'title' => $this->gateway->title, 'description' => $this->gateway->description, - 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_trustly_color.svg' ), + 'icon' => 'trustly', ); } } diff --git a/modules/ppcp-local-alternative-payment-methods/webpack.config.js b/modules/ppcp-local-alternative-payment-methods/webpack.config.js index a4366ebd8..d3410c95e 100644 --- a/modules/ppcp-local-alternative-payment-methods/webpack.config.js +++ b/modules/ppcp-local-alternative-payment-methods/webpack.config.js @@ -30,6 +30,9 @@ module.exports = { 'trustly-payment-method': path.resolve( './resources/js/trustly-payment-method.js' ), + 'multibanco-payment-method': path.resolve( + './resources/js/multibanco-payment-method.js' + ), }, output: { path: path.resolve( __dirname, 'assets/' ), diff --git a/modules/ppcp-paylater-configurator/services.php b/modules/ppcp-paylater-configurator/services.php index 8be798d24..b5b8fd441 100644 --- a/modules/ppcp-paylater-configurator/services.php +++ b/modules/ppcp-paylater-configurator/services.php @@ -13,6 +13,8 @@ use WooCommerce\PayPalCommerce\PayLaterConfigurator\Endpoint\SaveConfig; use WooCommerce\PayPalCommerce\PayLaterConfigurator\Endpoint\GetConfig; use WooCommerce\PayPalCommerce\PayLaterConfigurator\Factory\ConfigFactory; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; +use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply; +use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; return array( 'paylater-configurator.url' => static function ( ContainerInterface $container ): string { @@ -44,4 +46,34 @@ return array( $container->get( 'woocommerce.logger.woocommerce' ) ); }, + 'paylater-configurator.is-available' => static function ( ContainerInterface $container ) : bool { + // Test, if Pay-Later is available; depends on the shop country and Vaulting status. + $messages_apply = $container->get( 'button.helper.messages-apply' ); + assert( $messages_apply instanceof MessagesApply ); + + $settings = $container->get( 'wcgateway.settings' ); + assert( $settings instanceof Settings ); + + $vault_enabled = $settings->has( 'vault_enabled' ) && $settings->get( 'vault_enabled' ); + + return ! $vault_enabled && $messages_apply->for_country(); + }, + 'paylater-configurator.messaging-locations' => static function ( ContainerInterface $container ) : array { + // Get an array of locations that display the Pay-Later message. + $settings = $container->get( 'wcgateway.settings' ); + assert( $settings instanceof Settings ); + + $is_enabled = $settings->has( 'pay_later_messaging_enabled' ) && $settings->get( 'pay_later_messaging_enabled' ); + + if ( ! $is_enabled ) { + return array(); + } + + $selected_locations = $settings->has( 'pay_later_messaging_locations' ) ? $settings->get( 'pay_later_messaging_locations' ) : array(); + if ( is_array( $selected_locations ) ) { + return $selected_locations; + } + + return array(); + }, ); diff --git a/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php b/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php index 1aa35462c..4ec4ed394 100644 --- a/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php +++ b/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php @@ -9,7 +9,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\PayLaterConfigurator; -use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply; use WooCommerce\PayPalCommerce\PayLaterConfigurator\Endpoint\GetConfig; use WooCommerce\PayPalCommerce\PayLaterConfigurator\Endpoint\SaveConfig; use WooCommerce\PayPalCommerce\PayLaterConfigurator\Factory\ConfigFactory; @@ -18,6 +17,8 @@ use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; +use WooCommerce\PayPalCommerce\AdminNotices\Repository\Repository; +use WooCommerce\PayPalCommerce\AdminNotices\Entity\PersistentMessage; /** * Class PayLaterConfiguratorModule @@ -47,19 +48,22 @@ class PayLaterConfiguratorModule implements ModuleInterface { /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void { - $messages_apply = $c->get( 'button.helper.messages-apply' ); - assert( $messages_apply instanceof MessagesApply ); + public function run( ContainerInterface $c ) : void { + $is_available = $c->get( 'paylater-configurator.is-available' ); + + if ( ! $is_available ) { + return; + } + + $current_page_id = $c->get( 'wcgateway.current-ppcp-settings-page-id' ); + $is_wc_settings_page = $c->get( 'wcgateway.is-wc-settings-page' ); + $messaging_locations = $c->get( 'paylater-configurator.messaging-locations' ); + + $this->add_paylater_update_notice( $messaging_locations, $is_wc_settings_page, $current_page_id ); $settings = $c->get( 'wcgateway.settings' ); assert( $settings instanceof Settings ); - $vault_enabled = $settings->has( 'vault_enabled' ) && $settings->get( 'vault_enabled' ); - - if ( $vault_enabled || ! $messages_apply->for_country() ) { - return; - } - add_action( 'wc_ajax_' . SaveConfig::ENDPOINT, static function () use ( $c ) { @@ -78,8 +82,6 @@ class PayLaterConfiguratorModule implements ModuleInterface { } ); - $current_page_id = $c->get( 'wcgateway.current-ppcp-settings-page-id' ); - if ( $current_page_id !== Settings::PAY_LATER_TAB_ID ) { return; } @@ -149,4 +151,62 @@ class PayLaterConfiguratorModule implements ModuleInterface { */ public function getKey() { } + + /** + * Conditionally registers a new admin notice to highlight the new Pay-Later UI. + * + * The notice appears on any PayPal-Settings page, except for the Pay-Later settings page, + * when no Pay-Later messaging is used yet. + * + * @param array $message_locations PayLater messaging locations. + * @param bool $is_settings_page Whether the current page is a WC settings page. + * @param string $current_page_id ID of current settings page tab. + * + * @return void + */ + private function add_paylater_update_notice( array $message_locations, bool $is_settings_page, string $current_page_id ) : void { + // The message must be registered on any WC-Settings page, except for the Pay Later page. + if ( ! $is_settings_page || Settings::PAY_LATER_TAB_ID === $current_page_id ) { + return; + } + + // Don't display the notice when Pay-Later messaging is already used. + if ( count( $message_locations ) ) { + return; + } + + add_filter( + Repository::NOTICES_FILTER, + /** + * Notify the user about the new Pay-Later UI. + * + * @param array $notices The notices. + * @return array + * + * @psalm-suppress MissingClosureParamType + */ + static function ( $notices ) : array { + $settings_url = admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcp-tab=ppcp-pay-later' ); + + $message = sprintf( + // translators: %1$s and %2$s are the opening and closing of HTML tag directing to the Pay-Later settings page. + __( + 'NEW: Check out the recently revamped %1$sPayPal Pay Later messaging experience here%2$s. Get paid in full at checkout while giving your customers the flexibility to pay in installments over time.', + 'woocommerce-paypal-payments' + ), + '', + '' + ); + + $notices[] = new PersistentMessage( + 'pay-later-messaging', + $message, + 'info', + 'ppcp-notice-wrapper' + ); + + return $notices; + } + ); + } } diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index e92b7ee6a..9cb8dc0c0 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -27,6 +27,7 @@ use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Admin\RenderReauthorizeAction; use WooCommerce\PayPalCommerce\WcGateway\Endpoint\CaptureCardPayment; use WooCommerce\PayPalCommerce\WcGateway\Endpoint\RefreshFeatureStatusEndpoint; +use WooCommerce\PayPalCommerce\WcGateway\Helper\FeesUpdater; use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Admin\FeesRenderer; @@ -172,10 +173,14 @@ return array( return new DisableGateways( $session_handler, $settings, $settings_status, $subscription_helper ); }, - 'wcgateway.is-wc-payments-page' => static function ( ContainerInterface $container ): bool { + 'wcgateway.is-wc-settings-page' => static function ( ContainerInterface $container ): bool { $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; + return 'wc-settings' === $page; + }, + 'wcgateway.is-wc-payments-page' => static function ( ContainerInterface $container ): bool { + $is_wc_settings_page = $container->get( 'wcgateway.is-wc-settings-page' ); $tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : ''; - return 'wc-settings' === $page && 'checkout' === $tab; + return $is_wc_settings_page && 'checkout' === $tab; }, 'wcgateway.is-wc-gateways-list-page' => static function ( ContainerInterface $container ): bool { return $container->get( 'wcgateway.is-wc-payments-page' ) && ! isset( $_GET['section'] ); @@ -776,6 +781,20 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), + 'allow_local_apm_gateways' => array( + 'title' => __( 'Create gateway for alternative payment methods', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'desc_tip' => true, + 'label' => __( 'Moves the alternative payment methods from the PayPal gateway into their own dedicated gateways.', 'woocommerce-paypal-payments' ), + 'description' => __( 'By default, alternative payment methods are displayed in the Standard Payments payment gateway. This setting creates a gateway for each alternative payment method.', 'woocommerce-paypal-payments' ), + 'default' => false, + 'screens' => array( + State::STATE_START, + State::STATE_ONBOARDED, + ), + 'requirements' => array(), + 'gateway' => 'paypal', + ), 'disable_cards' => array( 'title' => __( 'Disable specific credit cards', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-multiselect', @@ -1165,6 +1184,13 @@ return array( $logger = $container->get( 'woocommerce.logger.woocommerce' ); return new RefundFeesUpdater( $order_endpoint, $logger ); }, + 'wcgateway.helper.fees-updater' => static function ( ContainerInterface $container ): FeesUpdater { + return new FeesUpdater( + $container->get( 'api.endpoint.orders' ), + $container->get( 'api.factory.capture' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); + }, 'button.helper.messages-disclaimers' => static function ( ContainerInterface $container ): MessagesDisclaimers { return new MessagesDisclaimers( diff --git a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoice.php b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoice.php index 9da44d069..94ed7240a 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoice.php +++ b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoice.php @@ -195,7 +195,7 @@ class PayUponInvoice { ); add_action( - 'ppcp_payment_capture_completed_webhook_handler', + 'woocommerce_paypal_payments_payment_capture_completed_webhook_handler', function ( WC_Order $wc_order, string $order_id ) { try { if ( $wc_order->get_payment_method() !== PayUponInvoiceGateway::ID ) { diff --git a/modules/ppcp-wc-gateway/src/Helper/FeesUpdater.php b/modules/ppcp-wc-gateway/src/Helper/FeesUpdater.php new file mode 100644 index 000000000..3bffeaeaa --- /dev/null +++ b/modules/ppcp-wc-gateway/src/Helper/FeesUpdater.php @@ -0,0 +1,98 @@ +orders_endpoint = $orders_endpoint; + $this->capture_factory = $capture_factory; + $this->logger = $logger; + } + + /** + * Updates the fees meta for a given order. + * + * @param string $order_id PayPal order ID. + * @param WC_Order $wc_order WC order. + * @return void + */ + public function update( string $order_id, WC_Order $wc_order ): void { + try { + $order = $this->orders_endpoint->order( $order_id ); + } catch ( RuntimeException $exception ) { + $this->logger->warning( + sprintf( + 'Could not get PayPal order %1$s when trying to update fees for WC order #%2$s', + $order_id, + $wc_order->get_id() + ) + ); + + return; + } + + $body = json_decode( $order['body'] ); + + $capture = $this->capture_factory->from_paypal_response( $body->purchase_units[0]->payments->captures[0] ); + $breakdown = $capture->seller_receivable_breakdown(); + if ( $breakdown ) { + $wc_order->update_meta_data( PayPalGateway::FEES_META_KEY, $breakdown->to_array() ); + $paypal_fee = $breakdown->paypal_fee(); + if ( $paypal_fee ) { + $wc_order->update_meta_data( 'PayPal Transaction Fee', (string) $paypal_fee->value() ); + } + + $wc_order->save_meta_data(); + } + } +} diff --git a/modules/ppcp-wc-gateway/src/Processor/PaymentsStatusHandlingTrait.php b/modules/ppcp-wc-gateway/src/Processor/PaymentsStatusHandlingTrait.php index e6186badf..22ad3c5df 100644 --- a/modules/ppcp-wc-gateway/src/Processor/PaymentsStatusHandlingTrait.php +++ b/modules/ppcp-wc-gateway/src/Processor/PaymentsStatusHandlingTrait.php @@ -35,9 +35,25 @@ trait PaymentsStatusHandlingTrait { WC_Order $wc_order ): void { if ( $order->intent() === 'CAPTURE' ) { - $this->handle_capture_status( $order->purchase_units()[0]->payments()->captures()[0], $wc_order ); + $purchase_units = $order->purchase_units(); + + if ( ! empty( $purchase_units ) && isset( $purchase_units[0] ) ) { + $payments = $purchase_units[0]->payments(); + + if ( $payments && ! empty( $payments->captures() ) ) { + $this->handle_capture_status( $payments->captures()[0], $wc_order ); + } + } } elseif ( $order->intent() === 'AUTHORIZE' ) { - $this->handle_authorization_status( $order->purchase_units()[0]->payments()->authorizations()[0], $wc_order ); + $purchase_units = $order->purchase_units(); + + if ( ! empty( $purchase_units ) && isset( $purchase_units[0] ) ) { + $payments = $purchase_units[0]->payments(); + + if ( $payments && ! empty( $payments->authorizations() ) ) { + $this->handle_authorization_status( $payments->authorizations()[0], $wc_order ); + } + } } } diff --git a/modules/ppcp-wc-gateway/src/Processor/RefundProcessor.php b/modules/ppcp-wc-gateway/src/Processor/RefundProcessor.php index 91e73866c..25e4c5eed 100644 --- a/modules/ppcp-wc-gateway/src/Processor/RefundProcessor.php +++ b/modules/ppcp-wc-gateway/src/Processor/RefundProcessor.php @@ -109,7 +109,11 @@ class RefundProcessor { */ public function process( WC_Order $wc_order, float $amount = null, string $reason = '' ) : bool { try { - if ( ! in_array( $wc_order->get_payment_method(), array( PayPalGateway::ID, CreditCardGateway::ID, CardButtonGateway::ID, PayUponInvoiceGateway::ID ), true ) ) { + $allowed_refund_payment_methods = apply_filters( + 'woocommerce_paypal_payments_allowed_refund_payment_methods', + array( PayPalGateway::ID, CreditCardGateway::ID, CardButtonGateway::ID, PayUponInvoiceGateway::ID ) + ); + if ( ! in_array( $wc_order->get_payment_method(), $allowed_refund_payment_methods, true ) ) { return true; } diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index f01084da9..f2b250a5f 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -497,6 +497,19 @@ class WCGatewayModule implements ModuleInterface { return $fields; } ); + + add_action( + 'woocommerce_paypal_payments_gateway_migrate', + function( string $installed_plugin_version ) use ( $c ) { + $settings = $c->get( 'wcgateway.settings' ); + assert( $settings instanceof Settings ); + + if ( ! $installed_plugin_version ) { + $settings->set( 'allow_local_apm_gateways', true ); + $settings->persist(); + } + } + ); } /** diff --git a/modules/ppcp-webhooks/src/Handler/PaymentCaptureCompleted.php b/modules/ppcp-webhooks/src/Handler/PaymentCaptureCompleted.php index d8f927b42..da291c123 100644 --- a/modules/ppcp-webhooks/src/Handler/PaymentCaptureCompleted.php +++ b/modules/ppcp-webhooks/src/Handler/PaymentCaptureCompleted.php @@ -105,7 +105,7 @@ class PaymentCaptureCompleted implements RequestHandler { /** * Allow access to the webhook logic before updating the WC order. */ - do_action( 'ppcp_payment_capture_completed_webhook_handler', $wc_order, $order_id ); + do_action( 'woocommerce_paypal_payments_payment_capture_completed_webhook_handler', $wc_order, $order_id ); if ( $wc_order->get_status() !== 'on-hold' ) { return $this->success_response(); diff --git a/package.json b/package.json index b628c76b3..b5dec8450 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,13 @@ { "name": "woocommerce-paypal-payments", - "version": "2.8.3", + "version": "2.9.0", "description": "WooCommerce PayPal Payments", "repository": "https://github.com/woocommerce/woocommerce-paypal-payments", "license": "GPL-2.0", "author": "WooCommerce", "scripts": { "postinstall": "run-s install:modules:* && run-s build:modules", + "install:modules:ppcp-admin-notices": "cd modules/ppcp-admin-notices && yarn install", "install:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn install", "install:modules:ppcp-blocks": "cd modules/ppcp-blocks && yarn install", "install:modules:ppcp-paylater-block": "cd modules/ppcp-paylater-block && yarn install", @@ -25,6 +26,7 @@ "install:modules:ppcp-card-fields": "cd modules/ppcp-card-fields && yarn install", "install:modules:ppcp-compat": "cd modules/ppcp-compat && yarn install", "install:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn install", + "build:modules:ppcp-admin-notices": "cd modules/ppcp-admin-notices && yarn run build", "build:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run build", "build:modules:ppcp-blocks": "cd modules/ppcp-blocks && yarn run build", "build:modules:ppcp-paylater-block": "cd modules/ppcp-paylater-block && yarn run build", @@ -44,6 +46,7 @@ "build:modules:ppcp-compat": "cd modules/ppcp-compat && yarn run build", "build:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn run build", "build:modules": "run-p build:modules:*", + "watch:modules:ppcp-admin-notices": "cd modules/ppcp-admin-notices && yarn run watch", "watch:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run watch", "watch:modules:ppcp-blocks": "cd modules/ppcp-blocks && yarn run watch", "watch:modules:ppcp-paylater-block": "cd modules/ppcp-paylater-block && yarn run watch", @@ -93,7 +96,7 @@ "prearchive": "rm -rf $npm_package_name.zip", "archive": "zip -r $npm_package_name.zip . -x **.git/\\* **node_modules/\\*", "postarchive": "yarn run archive:cleanup && rm -rf $npm_package_name && unzip $npm_package_name.zip -d $npm_package_name && rm $npm_package_name.zip && zip -r $npm_package_name.zip $npm_package_name && rm -rf $npm_package_name", - "archive:cleanup": "zip -d $npm_package_name.zip .env* .ddev/\\* \\*.idea/\\* .editorconfig .eslintrc babel.config.json tests/\\* \\*test/\\* .github/\\* .psalm/\\* wordpress_org_assets/\\* \\*.DS_Store \\*README.md \\*.gitattributes \\*.gitignore \\*composer.json \\*composer.lock patchwork.json phpunit.xml.dist .phpunit.result.cache phpcs.xml* psalm*.xml* playwright.config.js wp-cli.yml \\*.babelrc \\*package.json \\*webpack.config.js \\*yarn.lock \\*.travis.yml\\" + "archive:cleanup": "zip -d $npm_package_name.zip .env* .ddev/\\* \\*.idea/\\* .editorconfig tests/\\* .github/\\* .psalm/\\* wordpress_org_assets/\\* \\*.DS_Store \\*README.md \\*.gitattributes \\*.gitignore \\*composer.json \\*composer.lock patchwork.json phpunit.xml.dist .phpunit.result.cache phpcs.xml* psalm*.xml* playwright.config.js wp-cli.yml \\*.babelrc \\*package.json \\*webpack.config.js \\*yarn.lock \\*.travis.yml\\" }, "config": { "wp_org_slug": "woocommerce-paypal-payments" diff --git a/readme.txt b/readme.txt index 1aed175cb..180629a68 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: woocommerce, paypal, payments, ecommerce, checkout, cart, pay later, apple Requires at least: 5.3 Tested up to: 6.6 Requires PHP: 7.2 -Stable tag: 2.8.3 +Stable tag: 2.9.0 License: GPLv2 License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -179,6 +179,26 @@ If you encounter issues with the PayPal buttons not appearing after an update, p == Changelog == += 2.9.0 - 2024-09-02 = +* Fix - Fatal error in Block Editor when using WooCommerce blocks #2534 +* Fix - Can't pay from block pages when the shipping callback is enabled and no shipping methods defined #2429 +* Fix - Various Google Pay button fixes #2496 +* Fix - Buying a free trial subscription with ACDC results in a $1 charge in the API call #2465 +* Fix - Problem with Google Pay and Apple Pay button placement on Pay for Order page #2542 +* Fix - When there isn't any shipping option for the address the order is still created from classic cart #2437 +* Fix - Patch the order with no shipping methods, instead of throwing an error #2435 +* Enhancement - Separate Apple Pay button for Classic Checkout #2457 +* Enhancement - Remove AMEX support for ACDC when store location is set to China #2526 +* Enhancement - Inform users of Pay Later messaging configuration when Pay Later wasn't recently enabled #2529 +* Enhancement - Update ACDC signup URLs #2475 +* Enhancement - Implement country based APMs via Orders API #2511 +* Enhancement - Update PaymentsStatusHandlingTrait.php (author @callmeahmedr) #2523 +* Enhancement - Disable PayPal Shipping callback by default #2527 +* Enhancement - Change Apple Pay and Google Pay default button labels to plain #2476 +* Enhancement - Add Package Tracking compatibility with DHL Shipping plugin #2463 +* Enhancement - Add support for WC Bookings when skipping checkout confirmation #2452 +* Enhancement - Remove currencies from country-currency matrix in card fields module #2441 + = 2.8.3 - 2024-08-12 = * Fix - Google Pay: Prevent field validation from being triggered on checkout page load #2474 * Fix - Do not add tax info into order meta during order creation #2471 diff --git a/woocommerce-paypal-payments.php b/woocommerce-paypal-payments.php index fcf66ae12..afae61309 100644 --- a/woocommerce-paypal-payments.php +++ b/woocommerce-paypal-payments.php @@ -3,14 +3,14 @@ * Plugin Name: WooCommerce PayPal Payments * Plugin URI: https://woocommerce.com/products/woocommerce-paypal-payments/ * Description: PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, credit/debit cards, alternative digital wallets local payment types and bank accounts. Turn on only PayPal options or process a full suite of payment methods. Enable global transaction with extensive currency and country coverage. - * Version: 2.8.3 + * Version: 2.9.0 * Author: WooCommerce * Author URI: https://woocommerce.com/ * License: GPL-2.0 * Requires PHP: 7.2 * Requires Plugins: woocommerce * WC requires at least: 3.9 - * WC tested up to: 9.1 + * WC tested up to: 9.2 * Text Domain: woocommerce-paypal-payments * * @package WooCommerce\PayPalCommerce @@ -26,7 +26,7 @@ define( 'PAYPAL_API_URL', 'https://api-m.paypal.com' ); define( 'PAYPAL_URL', 'https://www.paypal.com' ); define( 'PAYPAL_SANDBOX_API_URL', 'https://api-m.sandbox.paypal.com' ); define( 'PAYPAL_SANDBOX_URL', 'https://www.sandbox.paypal.com' ); -define( 'PAYPAL_INTEGRATION_DATE', '2024-08-07' ); +define( 'PAYPAL_INTEGRATION_DATE', '2024-08-28' ); define( 'PPCP_PAYPAL_BN_CODE', 'Woo_PPCP' ); ! defined( 'CONNECT_WOO_CLIENT_ID' ) && define( 'CONNECT_WOO_CLIENT_ID', 'AcCAsWta_JTL__OfpjspNyH7c1GGHH332fLwonA5CwX4Y10mhybRZmHLA0GdRbwKwjQIhpDQy0pluX_P' ); @@ -106,7 +106,7 @@ define( 'PPCP_PAYPAL_BN_CODE', 'Woo_PPCP' ); /** * The hook fired when the plugin is installed or updated. */ - do_action( 'woocommerce_paypal_payments_gateway_migrate' ); + do_action( 'woocommerce_paypal_payments_gateway_migrate', $installed_plugin_version ); if ( $installed_plugin_version ) { /** diff --git a/wordpress_org_assets/screenshot-1.png b/wordpress_org_assets/screenshot-1.png index 8d86b396a..9783183c6 100644 Binary files a/wordpress_org_assets/screenshot-1.png and b/wordpress_org_assets/screenshot-1.png differ diff --git a/wordpress_org_assets/screenshot-2.png b/wordpress_org_assets/screenshot-2.png index a77634b98..0861a47cf 100644 Binary files a/wordpress_org_assets/screenshot-2.png and b/wordpress_org_assets/screenshot-2.png differ diff --git a/wordpress_org_assets/screenshot-3.jpg b/wordpress_org_assets/screenshot-3.jpg deleted file mode 100644 index c996e8fcc..000000000 Binary files a/wordpress_org_assets/screenshot-3.jpg and /dev/null differ diff --git a/wordpress_org_assets/screenshot-3.png b/wordpress_org_assets/screenshot-3.png new file mode 100644 index 000000000..8a24c736b Binary files /dev/null and b/wordpress_org_assets/screenshot-3.png differ diff --git a/wordpress_org_assets/screenshot-4.png b/wordpress_org_assets/screenshot-4.png index 28bff48f0..83644227d 100644 Binary files a/wordpress_org_assets/screenshot-4.png and b/wordpress_org_assets/screenshot-4.png differ diff --git a/wordpress_org_assets/screenshot-5.jpg b/wordpress_org_assets/screenshot-5.jpg deleted file mode 100644 index 8b7df54a1..000000000 Binary files a/wordpress_org_assets/screenshot-5.jpg and /dev/null differ diff --git a/wordpress_org_assets/screenshot-5.png b/wordpress_org_assets/screenshot-5.png new file mode 100644 index 000000000..5f72c0a06 Binary files /dev/null and b/wordpress_org_assets/screenshot-5.png differ diff --git a/wordpress_org_assets/screenshot-6.jpg b/wordpress_org_assets/screenshot-6.jpg deleted file mode 100644 index 0ebce54ba..000000000 Binary files a/wordpress_org_assets/screenshot-6.jpg and /dev/null differ diff --git a/wordpress_org_assets/screenshot-6.png b/wordpress_org_assets/screenshot-6.png new file mode 100644 index 000000000..5c1f7dbea Binary files /dev/null and b/wordpress_org_assets/screenshot-6.png differ